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:
merlokk 2018-08-14 15:11:56 +03:00
commit 843373d47e
145 changed files with 3781 additions and 6271 deletions

2
.gitignore vendored
View file

@ -18,8 +18,10 @@
!client/hardnested/tables/*.z
usb_cmd.lua
version.c
armsrc/fpga_version_info.c
client/ui/ui_overlays.h
*.Td
.DS_Store
*.exe
hardnested_stats.txt

View file

@ -6,6 +6,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
### Changed
- Adjusted `lf cmdread` to respond to client when complete and the client will then automatically call `data samples`
- Improved backdoor detection missbehaving magic s50/1k tag (Fl0-0)
- Deleted wipe functionality from `hf mf csetuid` (Merlok)
- Changed `hf mf nested` logic (Merlok)
@ -20,8 +21,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
### Fixed
- Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok)
- Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi)
### Added
- Added a bitbang mode to `lf cmdread` if delay is 0 the cmd bits turn off and on the antenna with 0 and 1 respectively (marshmellow)
- Added PAC/Stanley detection to lf search (marshmellow)
- Added lf pac demod and lf pac read - extracts the raw blocks from a PAC/Stanley tag (marshmellow)
- Added hf mf c* commands compatibity for 4k and gen1b backdoor (Fl0-0)
@ -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` SDA, DDA, fast DDA, CDA calculations for VISA and Mastercard and some other compatible EMV cards (Merlok)
- Added `hf emv test` - crypto tests for DES, AES, SHA, RSA, SDA, DDA, CDA and some other crypto functions (Merlok)
- Added `hf list mf` - deciphers crypto1 stream and works with first authentication and weak nested authentications (Merlok)
## [3.0.1][2017-06-08]
@ -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
- Added hf mf hardnested, an attack working for hardened Mifare cards (EV1, Mifare Plus SL1) where hf mf nested fails
- Added hf mf hardnested, an attack working for hardened Mifare cards (EV1, Mifare Plus SL1) where hf mf nested fails (piwi)
- Added experimental testmode write option for t55xx (danger) (marshmellow)
- Added t55xx p1detect to `lf search` chip detections (marshmellow)
- Added lf t55xx p1detect, detect page 1 of a t55xx tag based on E015 mfg code (marshmellow)

55
CI/.travis.yml Normal file
View 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
View 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

View file

@ -0,0 +1,3 @@
hf mf hardnested t 1 000000000000
hf emv test
exit

View file

@ -28,6 +28,7 @@ The Proxmark3 is available for purchase (assembled and tested) from the
following locations:
* [RyscCorp](https://proxmark3.com/) (US)
* [Hackerwarehouse](https://hackerwarehouse.com/) (US)
* [Elechouse](http://www.elechouse.com/) (HK)
* [Lab401](https://lab401.com/) (FR)
* [RFxSecure](http://www.rfxsecure.com/) (SG)

View file

@ -10,10 +10,16 @@ APP_INCLUDES = apps.h
#remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation
APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DWITH_HFSNOOP \
APP_CFLAGS = -DON_DEVICE \
-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_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
SRC_ISO15693 = iso15693.c iso15693tools.c
@ -21,7 +27,6 @@ SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c mifares
SRC_ISO14443b = iso14443b.c
SRC_CRAPTO1 = crypto1.c des.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c
#the FPGA bitstream files. Note: order matters!
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
@ -59,6 +64,9 @@ ARMSRC = fpgaloader.c \
optimized_cipher.c \
hfsnoop.c
VERSIONSRC = version.c \
fpga_version_info.c
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common
@ -69,6 +77,14 @@ all: $(OBJS)
.DELETE_ON_ERROR:
# version.c should be remade on every compilation
.PHONY: version.c
version.c: default_version.c
perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@

View file

@ -16,6 +16,7 @@
#include "cmd.h"
#include "proxmark3.h"
#include "apps.h"
#include "fpga.h"
#include "util.h"
#include "printf.h"
#include "string.h"
@ -31,7 +32,7 @@
#endif
// Craig Young - 14a stand-alone code
#ifdef WITH_ISO14443a_StandAlone
#ifdef WITH_ISO14443a
#include "iso14443a.h"
#endif
@ -136,34 +137,27 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
//-----------------------------------------------------------------------------
static int ReadAdc(int ch)
{
uint32_t d;
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_MR =
ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz
ADC_MODE_STARTUP_TIME(1 /* was 16 */) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us
ADC_MODE_SAMPLE_HOLD_TIME(15 /* was 8 */); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us
// Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value.
// Both AMPL_LO and AMPL_HI are very high impedance (10MOhm) outputs, the input capacitance of the ADC is 12pF (typical). This results in a time constant
// of RC = 10MOhm * 12pF = 120us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged.
// AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
// of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged.
//
// The maths are:
// If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be
//
// v_cap = v_in * (1 - exp(-RC/SHTIM)) = v_in * (1 - exp(-3)) = v_in * 0,95 (i.e. an error of 5%)
//
// Note: with the "historic" values in the comments above, the error was 34% !!!
// v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%)
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_MR =
ADC_MODE_PRESCALE(63) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz
ADC_MODE_STARTUP_TIME(1) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us
ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us
AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch)))
;
d = AT91C_BASE_ADC->ADC_CDR[ch];
while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {};
return d;
return AT91C_BASE_ADC->ADC_CDR[ch];
}
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);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
SpinDelay(50);
for (i=255; i>=19; i--) {
WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
@ -201,7 +197,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv
if (i==95) *vLf125 = adcval; // voltage at 125Khz
if (i==89) *vLf134 = adcval; // voltage at 134Khz
LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes
LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes
if(LF_Results[i] > peak) {
*peakv = adcval;
peak = LF_Results[i];
@ -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);
LED_B_OFF();
return;
@ -291,6 +287,7 @@ void ReadMem(int addr)
extern struct version_information version_information;
/* bootrom version information is pointed to from _bootphase1_version_pointer */
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
void SendVersion(void)
{
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
@ -311,10 +308,12 @@ void SendVersion(void)
FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
FpgaGatherVersion(FPGA_BITSTREAM_LF, temp, sizeof(temp));
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
FpgaGatherVersion(FPGA_BITSTREAM_HF, temp, sizeof(temp));
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
for (int i = 0; i < fpga_bitstream_num; i++) {
strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1);
if (i < fpga_bitstream_num - 1) {
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
}
}
// Send Chip ID and used flash memory
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
@ -368,7 +367,7 @@ void SendStatus(void)
cmd_send(CMD_ACK,1,0,0,0,0);
}
#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF)
#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF_StandAlone)
#define OPTS 2
@ -399,8 +398,8 @@ void StandAloneMode14a()
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
int selected = 0;
int playing = 0, iGotoRecord = 0, iGotoClone = 0;
int cardRead[OPTS] = {0};
bool playing = false, GotoRecord = false, GotoClone = false;
bool cardRead[OPTS] = {false};
uint8_t readUID[10] = {0};
uint32_t uid_1st[OPTS]={0};
uint32_t uid_2nd[OPTS]={0};
@ -416,9 +415,9 @@ void StandAloneMode14a()
WDT_HIT();
SpinDelay(300);
if (iGotoRecord == 1 || cardRead[selected] == 0)
if (GotoRecord || !cardRead[selected])
{
iGotoRecord = 0;
GotoRecord = false;
LEDsoff();
LED(selected + 1, 0);
LED(LED_RED2, 0);
@ -443,7 +442,7 @@ void StandAloneMode14a()
else if (cardRead[(selected+1)%OPTS]) {
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
selected = (selected+1)%OPTS;
break; // playing = 1;
break;
}
else {
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
@ -493,14 +492,14 @@ void StandAloneMode14a()
LED(selected + 1, 0);
// Next state is replay:
playing = 1;
playing = true;
cardRead[selected] = 1;
cardRead[selected] = true;
}
/* MF Classic UID clone */
else if (iGotoClone==1)
else if (GotoClone)
{
iGotoClone=0;
GotoClone=false;
LEDsoff();
LED(selected + 1, 0);
LED(LED_ORANGE, 250);
@ -551,7 +550,7 @@ void StandAloneMode14a()
MifareCGetBlock(0x3F, 1, 0, oldBlock0);
if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
playing = 1;
playing = true;
}
else {
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]);
@ -569,14 +568,14 @@ void StandAloneMode14a()
if (memcmp(testBlock0,newBlock0,16)==0)
{
DbpString("Cloned successfull!");
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
playing = 0;
iGotoRecord = 1;
cardRead[selected] = false; // Only if the card was cloned successfully should we clear it
playing = false;
GotoRecord = true;
selected = (selected+1) % OPTS;
}
else {
Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
playing = 1;
playing = true;
}
}
LEDsoff();
@ -584,14 +583,12 @@ void StandAloneMode14a()
}
// Change where to record (or begin playing)
else if (playing==1) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
else if (playing) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
{
LEDsoff();
LED(selected + 1, 0);
// Begin transmitting
if (playing)
{
LED(LED_GREEN, 0);
DbpString("Playing");
for ( ; ; ) {
@ -620,12 +617,12 @@ void StandAloneMode14a()
else if (button_action == BUTTON_SINGLE_CLICK) {
selected = (selected + 1) % OPTS;
Dbprintf("Done playing. Switching to record mode on bank %d",selected);
iGotoRecord = 1;
GotoRecord = true;
break;
}
else if (button_action == BUTTON_HOLD) {
Dbprintf("Playtime over. Begin cloning...");
iGotoClone = 1;
GotoClone = true;
break;
}
WDT_HIT();
@ -636,13 +633,9 @@ void StandAloneMode14a()
LEDsoff();
LED(selected + 1, 0);
}
else
while(BUTTON_PRESS())
WDT_HIT();
}
}
}
#elif WITH_LF
#elif WITH_LF_StandAlone
// samy's sniff and repeat routine
void SamyRun()
{
@ -1435,7 +1428,7 @@ void __attribute__((noreturn)) AppMain(void)
}
WDT_HIT();
#ifdef WITH_LF
#ifdef WITH_LF_StandAlone
#ifndef WITH_ISO14443a_StandAlone
if (BUTTON_HELD(1000) > 0)
SamyRun();

View file

@ -10,20 +10,21 @@
// mode once it is configured.
//-----------------------------------------------------------------------------
#include "fpgaloader.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "fpgaloader.h"
#include "apps.h"
#include "fpga.h"
#include "proxmark3.h"
#include "util.h"
#include "string.h"
#include "BigBuf.h"
#include "zlib.h"
extern void Dbprintf(const char *fmt, ...);
// remember which version of the bitstream we have already downloaded to the FPGA
static int downloaded_bitstream = FPGA_BITSTREAM_ERR;
static int downloaded_bitstream = 0;
// this is where the bitstreams are located in memory:
extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end;
@ -31,10 +32,7 @@ extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end;
static uint8_t *fpga_image_ptr = NULL;
static uint32_t uncompressed_bytes_cnt;
static const uint8_t _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(_bitparse_fixed_header)
#define OUTPUT_BUFFER_LEN 80
#define FPGA_INTERLEAVE_SIZE 288
//-----------------------------------------------------------------------------
// Set up the Serial Peripheral Interface as master
@ -201,7 +199,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8
//----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % FPGA_BITSTREAM_MAX != (bitstream_version - 1)) {
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}
@ -234,7 +232,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
// initialize z_stream structure for inflate:
compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start;
compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_start - &_binary_obj_fpga_all_bit_z_end;
compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start;
compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
@ -248,8 +246,8 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
}
// Check for a valid .bit file (starts with _bitparse_fixed_header)
if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) {
// Check for a valid .bit file (starts with bitparse_fixed_header)
if(memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) {
return true;
} else {
return false;
@ -442,77 +440,6 @@ void FpgaDownloadAndGo(int bitstream_version)
}
//-----------------------------------------------------------------------------
// Gather version information from FPGA image. Needs to decompress the begin
// of the respective (HF or LF) image.
// Note: decompression makes use of (i.e. overwrites) BigBuf[]. It is therefore
// advisable to call this only once and store the results for later use.
//-----------------------------------------------------------------------------
void FpgaGatherVersion(int bitstream_version, char *dst, int len)
{
unsigned int fpga_info_len;
char tempstr[40] = {0x00};
z_stream compressed_fpga_stream;
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
dst[0] = '\0';
// ensure that we can allocate enough memory for decompression:
BigBuf_free(); BigBuf_Clear_ext(false);
if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
return;
if(bitparse_find_section(bitstream_version, 'a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
if (!memcmp("fpga_lf", tempstr, 7))
strncat(dst, "LF ", len-1);
else if (!memcmp("fpga_hf", tempstr, 7))
strncat(dst, "HF ", len-1);
}
strncat(dst, "FPGA image built", len-1);
if(bitparse_find_section(bitstream_version, 'b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " for ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
if(bitparse_find_section(bitstream_version, 'c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " on ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
if(bitparse_find_section(bitstream_version, 'd', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " at ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
strncat(dst, "\n", len-1);
inflateEnd(&compressed_fpga_stream);
}
//-----------------------------------------------------------------------------
// Send a 16 bit command/data pair to the FPGA.
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
@ -562,12 +489,8 @@ void SetAdcMuxFor(uint32_t whichGpio)
}
void Fpga_print_status(void) {
Dbprintf("Fgpa");
switch(downloaded_bitstream) {
case FPGA_BITSTREAM_HF: Dbprintf(" mode....................HF"); break;
case FPGA_BITSTREAM_LF: Dbprintf(" mode....................LF"); break;
default: Dbprintf(" mode....................%d", downloaded_bitstream); break;
}
Dbprintf("Currently loaded FPGA image:");
Dbprintf(" %s", fpga_version_information[downloaded_bitstream-1]);
}
int FpgaGetCurrent() {

View file

@ -10,10 +10,15 @@
// 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 FpgaWriteConfWord(uint8_t v);
void FpgaDownloadAndGo(int bitstream_version);
void FpgaGatherVersion(int bitstream_version, char *dst, int len);
void FpgaSetupSsc(void);
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len);
@ -24,12 +29,9 @@ int FpgaGetCurrent();
void SetAdcMuxFor(uint32_t whichGpio);
// definitions for multiple FPGA config files support
#define FPGA_BITSTREAM_MAX 2 // the total number of FPGA bitstreams (configs)
#define FPGA_BITSTREAM_ERR 0
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
// Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12)
@ -72,3 +74,5 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0)
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
#endif

View file

@ -813,13 +813,13 @@ void SnoopHitag(uint32_t type) {
int lastbit;
bool bSkip;
int tag_sof;
byte_t rx[HITAG_FRAME_LEN];
byte_t rx[HITAG_FRAME_LEN] = {0};
size_t rxlen=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
auth_table_len = 0;
@ -1032,7 +1032,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
auth_table_len = 0;
@ -1225,7 +1225,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
//DbpString("Starting Hitag reader family");
@ -1548,7 +1548,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
//DbpString("Starting Hitag reader family");

View file

@ -210,7 +210,7 @@ static void hitag_send_bit(int bit) {
;
LOW(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < T0 * 32)
;;
;
}
LED_A_OFF();
break;
@ -945,7 +945,6 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
int i, j;
byte_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0;
//bool bQuitTraceFull = false;
bQuiet = false;
byte_t txbuf[HITAG_FRAME_LEN];
byte_t* tx = txbuf;
@ -953,7 +952,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
BigBuf_free();
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
DbpString("Starting HitagS simulation");
@ -985,39 +984,39 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
tag.max_page=0;
//con1
tag.auth=0;
if((tag.pages[1][2]&0x80)==1)
if (tag.pages[1][2]&0x80)
tag.auth=1;
tag.LCON=0;
if((tag.pages[1][2]&0x2)==1)
if (tag.pages[1][2]&0x2)
tag.LCON=1;
tag.LKP=0;
if((tag.pages[1][2]&0x1)==1)
if (tag.pages[1][2]&0x1)
tag.LKP=1;
//con2
//0=read write 1=read only
tag.LCK7=0;
if((tag.pages[1][1]&0x80)==1)
if (tag.pages[1][1]&0x80)
tag.LCK7=1;
tag.LCK6=0;
if((tag.pages[1][1]&0x40)==1)
if (tag.pages[1][1]&0x40)
tag.LCK6=1;
tag.LCK5=0;
if((tag.pages[1][1]&0x20)==1)
if (tag.pages[1][1]&0x20)
tag.LCK5=1;
tag.LCK4=0;
if((tag.pages[1][1]&0x10)==1)
if (tag.pages[1][1]&0x10)
tag.LCK4=1;
tag.LCK3=0;
if((tag.pages[1][1]&0x8)==1)
if (tag.pages[1][1]&0x8)
tag.LCK3=1;
tag.LCK2=0;
if((tag.pages[1][1]&0x4)==1)
if (tag.pages[1][1]&0x4)
tag.LCK2=1;
tag.LCK1=0;
if((tag.pages[1][1]&0x2)==1)
if (tag.pages[1][1]&0x2)
tag.LCK1=1;
tag.LCK0=0;
if((tag.pages[1][1]&0x1)==1)
if (tag.pages[1][1]&0x1)
tag.LCK0=1;
// Set up simulator mode, frequency divisor which will drive the FPGA
@ -1216,7 +1215,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
bQuiet = false;
@ -1560,7 +1559,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
tag.tstate = NO_OP;
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
bQuiet = false;
@ -1847,7 +1846,7 @@ void check_challenges(bool file_given, byte_t* data) {
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
set_tracing(true);
clear_trace();
bQuiet = false;

View file

@ -91,7 +91,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
if(!Uart.bitBuffer) {
Uart.bitBuffer = bit ^ 0xFF0;
return FALSE;
return false;
}
else {
Uart.bitBuffer <<= 4;
@ -102,7 +102,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
Uart.byteCnt++;
Uart.swapper = 0;
if(Uart.byteCnt > 15) { return TRUE; }
if(Uart.byteCnt > 15) { return true; }
}
else {
Uart.swapper = 1;
@ -139,12 +139,12 @@ static RAMFUNC int OutOfNDecoding(int bit)
Uart.highCnt = 0;
if(Uart.byteCnt == 0) {
// Its not straightforward to show single EOFs
// So just leave it and do not return TRUE
// So just leave it and do not return true
Uart.output[0] = 0xf0;
Uart.byteCnt++;
}
else {
return TRUE;
return true;
}
}
else if(Uart.state != STATE_START_OF_COMMUNICATION) {
@ -263,7 +263,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
Uart.byteCnt++;
Uart.output[Uart.byteCnt] = 0xAA;
Uart.byteCnt++;
return TRUE;
return true;
}*/
}
@ -318,7 +318,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
}
}
return FALSE;
return false;
}
//=============================================================================
@ -371,7 +371,7 @@ static RAMFUNC int ManchesterDecoding(int v)
if(Demod.buff < 3) {
Demod.buff++;
return FALSE;
return false;
}
if(Demod.state==DEMOD_UNSYNCD) {
@ -473,7 +473,7 @@ static RAMFUNC int ManchesterDecoding(int v)
Demod.len++;
Demod.state = DEMOD_UNSYNCD;
// error = 0x0f;
return TRUE;
return true;
}
else {
Demod.state = DEMOD_ERROR_WAIT;
@ -557,7 +557,7 @@ static RAMFUNC int ManchesterDecoding(int v)
}
Demod.state = DEMOD_UNSYNCD;
return TRUE;
return true;
}
else {
Demod.output[Demod.len] = 0xad;
@ -612,14 +612,14 @@ static RAMFUNC int ManchesterDecoding(int v)
Demod.len++;
Demod.output[Demod.len] = 0xBB;
Demod.len++;
return TRUE;
return true;
}
}
} // end (state != UNSYNCED)
return FALSE;
return false;
}
//=============================================================================
@ -639,7 +639,7 @@ void RAMFUNC SnoopIClass(void)
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// response from the tag.
//int triggered = FALSE; // FALSE to wait first for card
//int triggered = false; // false to wait first for card
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
@ -656,9 +656,9 @@ void RAMFUNC SnoopIClass(void)
// The DMA buffer, used to stream samples from the FPGA
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
set_tracing(TRUE);
set_tracing(true);
clear_trace();
iso14a_set_trigger(FALSE);
iso14a_set_trigger(false);
int lastRxCounter;
uint8_t *upTo;
@ -749,12 +749,12 @@ void RAMFUNC SnoopIClass(void)
time_stop = (GetCountSspClk()-time_0) << 4;
LED_C_ON();
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,true)) break;
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break;
if(tracing) {
uint8_t parity[MAX_PARITY_SIZE];
GetParity(Uart.output, Uart.byteCnt, parity);
LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, TRUE);
LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, true);
}
@ -782,7 +782,7 @@ void RAMFUNC SnoopIClass(void)
if(tracing) {
uint8_t parity[MAX_PARITY_SIZE];
GetParity(Demod.output, Demod.len, parity);
LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, FALSE);
LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, false);
}
// And ready to receive another response.
@ -830,7 +830,7 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) {
//-----------------------------------------------------------------------------
// Wait for commands from reader
// Stop when button is pressed
// Or return TRUE when command is captured
// Or return true when command is captured
//-----------------------------------------------------------------------------
static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
{
@ -848,7 +848,7 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
for(;;) {
WDT_HIT();
if(BUTTON_PRESS()) return FALSE;
if(BUTTON_PRESS()) return false;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00;
@ -858,7 +858,7 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
if(OutOfNDecoding(b & 0x0f)) {
*len = Uart.byteCnt;
return TRUE;
return true;
}
}
}
@ -993,7 +993,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Enable and clear the trace
set_tracing(TRUE);
set_tracing(true);
clear_trace();
//Use the emulator memory for SIM
uint8_t *emulator = BigBuf_get_EM_addr();
@ -1325,11 +1325,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
if (tracing) {
uint8_t parity[MAX_PARITY_SIZE];
GetParity(receivedCmd, len, parity);
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE);
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, true);
if (trace_data != NULL) {
GetParity(trace_data, trace_data_size, parity);
LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE);
LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, false);
}
if(!tracing) {
DbpString("Trace full");
@ -1420,7 +1420,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
uint8_t sendbyte;
bool firstpart = TRUE;
bool firstpart = true;
c = 0;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
@ -1512,14 +1512,14 @@ void ReaderTransmitIClass(uint8_t* frame, int len)
if (tracing) {
uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len, par);
LogTrace(frame, len, rsamples, rsamples, par, TRUE);
LogTrace(frame, len, rsamples, rsamples, par, true);
}
}
//-----------------------------------------------------------------------------
// Wait a certain time for tag response
// If a response is captured return TRUE
// If it takes too long return FALSE
// If a response is captured return true
// If it takes too long return false
//-----------------------------------------------------------------------------
static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) //uint8_t *buffer
{
@ -1538,27 +1538,27 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
uint8_t b;
if (elapsed) *elapsed = 0;
bool skip = FALSE;
bool skip = false;
c = 0;
for(;;) {
WDT_HIT();
if(BUTTON_PRESS()) return FALSE;
if(BUTTON_PRESS()) return false;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!!
if (elapsed) (*elapsed)++;
}
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
if(c < timeout) { c++; } else { return FALSE; }
if(c < timeout) { c++; } else { return false; }
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
skip = !skip;
if(skip) continue;
if(ManchesterDecoding(b & 0x0f)) {
*samples = c << 3;
return TRUE;
return true;
}
}
}
@ -1567,14 +1567,14 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
int ReaderReceiveIClass(uint8_t* receivedAnswer)
{
int samples = 0;
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return false;
rsamples += samples;
if (tracing) {
uint8_t parity[MAX_PARITY_SIZE];
GetParity(receivedAnswer, Demod.len, parity);
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE);
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,false);
}
if(samples == 0) return FALSE;
if(samples == 0) return false;
return Demod.len;
}
@ -1582,7 +1582,7 @@ void setupIclassReader()
{
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Reset trace buffer
set_tracing(TRUE);
set_tracing(true);
clear_trace();
// Setup SSC
@ -1822,7 +1822,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
uint8_t resp[ICLASS_BUFFER_SIZE];
setupIclassReader();
set_tracing(TRUE);
set_tracing(true);
while(!BUTTON_PRESS()) {

View file

@ -2151,9 +2151,7 @@ void ReaderMifare(bool first_try)
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
if (first_try) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
}
// free eventually allocated BigBuf memory. We want all for tracing.
BigBuf_free();
@ -2161,9 +2159,9 @@ void ReaderMifare(bool first_try)
clear_trace();
set_tracing(true);
byte_t nt_diff = 0;
uint8_t nt_diff = 0;
uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
static byte_t par_low = 0;
static uint8_t par_low = 0;
bool led_on = true;
uint8_t uid[10] ={0};
uint32_t cuid;
@ -2171,11 +2169,11 @@ void ReaderMifare(bool first_try)
uint32_t nt = 0;
uint32_t previous_nt = 0;
static uint32_t nt_attacked = 0;
byte_t par_list[8] = {0x00};
byte_t ks_list[8] = {0x00};
uint8_t par_list[8] = {0x00};
uint8_t ks_list[8] = {0x00};
#define PRNG_SEQUENCE_LENGTH (1 << 16);
static uint32_t sync_time;
uint32_t sync_time = GetCountSspClk() & 0xfffffff8;
static int32_t sync_cycles;
int catch_up_cycles = 0;
int last_catch_up = 0;
@ -2185,10 +2183,9 @@ void ReaderMifare(bool first_try)
if (first_try) {
mf_nr_ar3 = 0;
sync_time = GetCountSspClk() & 0xfffffff8;
par[0] = par_low = 0;
sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces).
nt_attacked = 0;
par[0] = 0;
}
else {
// we were unsuccessful on a previous call. Try another READER nonce (first 3 parity bits remain the same)
@ -2204,6 +2201,7 @@ void ReaderMifare(bool first_try)
#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
#define MAX_SYNC_TRIES 32
#define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle
#define NUM_DEBUG_INFOS 8 // per strategy
#define MAX_STRATEGY 3
uint16_t unexpected_random = 0;
@ -2253,8 +2251,8 @@ void ReaderMifare(bool first_try)
sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
catch_up_cycles = 0;
// if we missed the sync time already, advance to the next nonce repeat
while(GetCountSspClk() > sync_time) {
// if we missed the sync time already or are about to miss it, advance to the next nonce repeat
while(sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) {
elapsed_prng_sequences++;
sync_time = (sync_time & 0xfffffff8) + sync_cycles;
}
@ -2410,14 +2408,14 @@ void ReaderMifare(bool first_try)
}
}
byte_t buf[28];
uint8_t buf[32];
memcpy(buf + 0, uid, 4);
num_to_bytes(nt, 4, buf + 4);
memcpy(buf + 8, par_list, 8);
memcpy(buf + 16, ks_list, 8);
memcpy(buf + 24, mf_nr_ar, 4);
memcpy(buf + 24, mf_nr_ar, 8);
cmd_send(CMD_ACK, isOK, 0, 0, buf, 28);
cmd_send(CMD_ACK, isOK, 0, 0, buf, 32);
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -2482,7 +2480,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
for(uint32_t sniffCounter = 0; true; ) {
if(BUTTON_PRESS()) {
DbpString("cancelled by button");
DbpString("Canceled by button.");
break;
}
@ -2539,7 +2537,9 @@ void RAMFUNC SniffMifare(uint8_t param) {
if(!TagIsActive) { // no need to try decoding tag data if the reader is sending
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
if(MillerDecoding(readerdata, (sniffCounter-1)*4)) {
LED_C_INV();
LED_B_ON();
LED_C_OFF();
if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, true)) break;
/* And ready to receive another command. */
@ -2554,7 +2554,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) {
LED_C_INV();
LED_B_OFF();
LED_C_ON();
if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, false)) break;
@ -2576,7 +2577,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
} // main cycle
DbpString("COMMAND FINISHED");
DbpString("COMMAND FINISHED.");
FpgaDisableSscDma();
MfSniffEnd();

View file

@ -243,7 +243,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit)
LED_A_OFF(); // Finished receiving
Uart.state = STATE_UNSYNCD;
if (Uart.byteCnt != 0) {
return TRUE;
return true;
}
} else {
// this is an error
@ -259,7 +259,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit)
break;
}
return FALSE;
return false;
}
@ -283,7 +283,7 @@ static void UartInit(uint8_t *data)
// Receive a command (from the reader to us, where we are the simulated tag),
// and store it in the given buffer, up to the given maximum length. Keeps
// spinning, waiting for a well-framed command, until either we get one
// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
// (returns true) or someone presses the pushbutton on the board (false).
//
// Assume that we're called with the SSC (to the FPGA) and ADC path set
// correctly.
@ -302,20 +302,20 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
for(;;) {
WDT_HIT();
if(BUTTON_PRESS()) return FALSE;
if(BUTTON_PRESS()) return false;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) {
if(Handle14443bUartBit(b & mask)) {
*len = Uart.byteCnt;
return TRUE;
return true;
}
}
}
}
return FALSE;
return false;
}
//-----------------------------------------------------------------------------
@ -347,7 +347,7 @@ void SimulateIso14443bTag(void)
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
clear_trace();
set_tracing(TRUE);
set_tracing(true);
const uint8_t *resp;
uint8_t *respCode;
@ -387,7 +387,7 @@ void SimulateIso14443bTag(void)
if (tracing) {
uint8_t parity[MAX_PARITY_SIZE];
LogTrace(receivedCmd, len, 0, 0, parity, TRUE);
LogTrace(receivedCmd, len, 0, 0, parity, true);
}
// Good, look at the command now.
@ -464,7 +464,7 @@ void SimulateIso14443bTag(void)
// trace the response:
if (tracing) {
uint8_t parity[MAX_PARITY_SIZE];
LogTrace(resp, respLen, 0, 0, parity, FALSE);
LogTrace(resp, respLen, 0, 0, parity, false);
}
}
@ -702,7 +702,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
LED_C_OFF();
if(s == 0x000) {
// This is EOF (start, stop and all data bits == '0'
return TRUE;
return true;
}
}
}
@ -716,7 +716,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
break;
}
return FALSE;
return false;
}
@ -739,12 +739,12 @@ static void DemodInit(uint8_t *data)
/*
* Demodulate the samples we received from the tag, also log to tracebuffer
* quiet: set to 'TRUE' to disable debug output
* quiet: set to 'true' to disable debug output
*/
static void GetSamplesFor14443bDemod(int n, bool quiet)
{
int max = 0;
bool gotFrame = FALSE;
bool gotFrame = false;
int lastRxCounter, ci, cq, samples = 0;
// Allocate memory from BigBuf for some buffers
@ -792,7 +792,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
samples += 2;
if(Handle14443bSamplesDemod(ci, cq)) {
gotFrame = TRUE;
gotFrame = true;
break;
}
}
@ -808,7 +808,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
//Tracing
if (tracing && Demod.len > 0) {
uint8_t parity[MAX_PARITY_SIZE];
LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE);
LogTrace(Demod.output, Demod.len, 0, 0, parity, false);
}
}
@ -929,7 +929,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
TransmitFor14443b();
if (tracing) {
uint8_t parity[MAX_PARITY_SIZE];
LogTrace(cmd,len, 0, 0, parity, TRUE);
LogTrace(cmd,len, 0, 0, parity, true);
}
}
@ -951,7 +951,7 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo
// send
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
// get response
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, true);
if(Demod.len < 3)
{
return 0;
@ -981,7 +981,7 @@ int iso14443b_select_card()
// first, wake up the tag
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
// ATQB too short?
if (Demod.len < 14)
{
@ -996,7 +996,7 @@ int iso14443b_select_card()
attrib[7] = Demod.output[10] & 0x0F;
ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
// Answer to ATTRIB too short?
if(Demod.len < 3)
{
@ -1056,12 +1056,12 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
SpinDelay(200);
clear_trace();
set_tracing(TRUE);
set_tracing(true);
// First command: wake up the tag using the INITIATE command
uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b};
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
if (Demod.len == 0) {
DbpString("No response from tag");
@ -1077,7 +1077,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
cmd1[1] = Demod.output[0];
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
if (Demod.len != 3) {
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
return;
@ -1099,7 +1099,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
cmd1[0] = 0x0B;
ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
if (Demod.len != 10) {
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
return;
@ -1128,7 +1128,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
cmd1[1] = i;
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
if (Demod.len != 6) { // Check if we got an answer from the tag
DbpString("Expected 6 bytes from tag, got less...");
return;
@ -1174,13 +1174,13 @@ void RAMFUNC SnoopIso14443b(void)
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// response from the tag.
int triggered = TRUE; // TODO: set and evaluate trigger condition
int triggered = true; // TODO: set and evaluate trigger condition
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
BigBuf_free();
clear_trace();
set_tracing(TRUE);
set_tracing(true);
// The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
@ -1217,8 +1217,8 @@ void RAMFUNC SnoopIso14443b(void)
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
uint8_t parity[MAX_PARITY_SIZE];
bool TagIsActive = FALSE;
bool ReaderIsActive = FALSE;
bool TagIsActive = false;
bool ReaderIsActive = false;
// And now we loop, receiving samples.
for(;;) {
@ -1259,7 +1259,7 @@ void RAMFUNC SnoopIso14443b(void)
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
if(Handle14443bUartBit(ci & 0x01)) {
if(triggered && tracing) {
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
}
/* And ready to receive another command. */
UartReset();
@ -1269,7 +1269,7 @@ void RAMFUNC SnoopIso14443b(void)
}
if(Handle14443bUartBit(cq & 0x01)) {
if(triggered && tracing) {
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
}
/* And ready to receive another command. */
UartReset();
@ -1287,9 +1287,9 @@ void RAMFUNC SnoopIso14443b(void)
if(tracing)
{
uint8_t parity[MAX_PARITY_SIZE];
LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE);
LogTrace(Demod.output, Demod.len, samples, samples, parity, false);
}
triggered = TRUE;
triggered = true;
// And ready to receive another response.
DemodReset();
@ -1330,12 +1330,12 @@ void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, u
FpgaSetupSsc();
if (datalen){
set_tracing(TRUE);
set_tracing(true);
CodeAndTransmit14443bAsReader(data, datalen);
if(recv) {
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen);
}

View file

@ -305,7 +305,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
c = 0;
getNext = FALSE;
getNext = false;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x43;
@ -444,7 +444,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
c = 0;
getNext = FALSE;
getNext = false;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x43;
@ -612,7 +612,7 @@ void AcquireRawAdcSamplesIso15693(void)
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
c = 0;
getNext = FALSE;
getNext = false;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x43;
@ -666,7 +666,7 @@ void RecordRawAdcSamplesIso15693(void)
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
c = 0;
getNext = FALSE;
getNext = false;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x43;

View file

@ -4,7 +4,7 @@
// the license.
//-----------------------------------------------------------------------------
// Miscellaneous routines for low frequency tag operations.
// Tags supported here so far are Texas Instruments (TI), HID
// Tags supported here so far are Texas Instruments (TI), HID, EM4x05, EM410x
// Also routines for raw mode reading/simulating of LF waveform
//-----------------------------------------------------------------------------
@ -28,51 +28,103 @@
*/
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command)
{
// start timer
StartTicks();
int divisor_used = 95; // 125 KHz
// see if 'h' was specified
// use lf config settings
sample_config *sc = getSamplingConfig();
if (command[strlen((char *) command) - 1] == 'h')
divisor_used = 88; // 134.8 KHz
sample_config sc = { 0,0,1, divisor_used, 0};
setSamplingConfig(&sc);
//clear read buffer
BigBuf_Clear_keep_EM();
/* Make sure the tag is reset */
// Make sure the tag is reset
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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
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
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 != ' ') {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelayUs(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
WaitUS(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
LED_D_ON();
if(*(command++) == '0')
SpinDelayUs(period_0);
else
SpinDelayUs(period_1);
if(*(command++) == '0') {
WaitUS(period_0);
} else {
WaitUS(period_1);
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelayUs(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
WaitUS(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// now do the read
DoAcquisition_config(false, 0);
// 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
@ -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 mod = clock % fc; //modifier
uint8_t modAdj = fc/mod; //how often to apply modifier
bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=TRUE;
bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=true;
// loop through clock - step field clock
for (uint8_t idx=0; idx < wavesPerClock; idx++){
// put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave)
@ -768,9 +820,9 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
for (i=0; i<size; i++){
if (BitStream[i] == curPhase){
pskSimBit(carrier, &n, clk, &curPhase, FALSE);
pskSimBit(carrier, &n, clk, &curPhase, false);
} 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);

View file

@ -266,7 +266,7 @@ uint32_t SnoopLF()
}
/**
* acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
* acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384
* and is Manchester?, we directly gather the manchester data into bigbuff
**/
#define COTAG_T1 384

View file

@ -20,6 +20,9 @@
#include "parity.h"
#include "crc.h"
#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// the block number for the ISO14443-4 PCB
static uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed
@ -677,7 +680,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
}
if (slow) {
timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME;
timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME;
while(GetCountSspClk() < timeout);
}
@ -694,9 +697,11 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
continue;
}
// send a dummy response in order to trigger the cards authentication failure timeout
uint8_t dummy_answer[8] = {0};
ReaderTransmit(dummy_answer, 8, NULL);
// send an incomplete dummy response in order to trigger the card's authentication failure timeout
uint8_t dummy_answer[1] = {0};
ReaderTransmit(dummy_answer, 1, NULL);
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;
num_nonces++;
if (num_nonces % 2) {
@ -709,6 +714,9 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
i += 9;
}
// wait for the card to become ready again
while(GetCountSspClk() < timeout);
}
LED_C_OFF();
@ -1141,7 +1149,7 @@ static bool isBlockTrailer(int blockN) {
if (blockN >= 128 && blockN <= 256) {
return ((blockN & 0x0F) == 0x0F);
}
return FALSE;
return false;
}
void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){

View file

@ -16,7 +16,6 @@
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "iso14443a.h"

View file

@ -35,7 +35,7 @@ bool MfSniffInit(void){
sniffSAK = 0;
sniffUIDType = SNF_UID_4;
return FALSE;
return false;
}
bool MfSniffEnd(void){
@ -43,7 +43,7 @@ bool MfSniffEnd(void){
cmd_send(CMD_ACK,0,0,0,0,0);
LED_B_OFF();
return FALSE;
return false;
}
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {
@ -59,32 +59,27 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
memset(sniffUID, 0x00, 8);
memset(sniffATQA, 0x00, 2);
sniffSAK = 0;
sniffState = SNF_WUPREQ;
sniffState = SNF_ATQA;
if (data[0] == 0x40)
sniffState = SNF_MAGIC_WUPC2;
}
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
memcpy(sniffATQA, data, 2);
sniffState = SNF_ATQA;
}
break;
}
case SNF_ATQA:{
if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader
sniffState = SNF_ANTICOL1;
}
break;
}
case SNF_ANTICOL1:{
if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // UID from tag (CL1)
memcpy(sniffUID + 3, data, 4);
sniffState = SNF_UID1;
}
break;
}
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
memcpy(sniffUID + 3, &data[2], 4);
sniffState = SNF_SAK;
}
break;
@ -92,25 +87,19 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
case SNF_SAK:{
if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card?
sniffSAK = data[0];
if (sniffUID[3] == 0x88) { // CL2 UID part to be expected
sniffState = SNF_ANTICOL2;
if ((sniffUID[3] == 0x88) && (sniffUIDType == SNF_UID_4)) { // CL2 UID part to be expected
sniffUIDType = SNF_UID_7;
memcpy(sniffUID, sniffUID + 4, 3);
sniffState = SNF_UID2;
} else { // select completed
sniffState = SNF_CARD_IDLE;
}
}
break;
}
case SNF_ANTICOL2:{
if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID
memcpy(sniffUID, sniffUID+4, 3);
memcpy(sniffUID+3, data, 4);
sniffUIDType = SNF_UID_7;
sniffState = SNF_UID2;
}
break;
}
case SNF_UID2:{
if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 2nd part of 7 Byte UID
if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) {
memcpy(sniffUID + 3, &data[2], 4);
sniffState = SNF_SAK;
}
break;
@ -123,17 +112,11 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
sniffBuf[11] = sniffSAK;
sniffBuf[12] = 0xFF;
sniffBuf[13] = 0xFF;
LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE);
LogTrace(sniffBuf, 14, 0, 0, NULL, true);
sniffState = SNF_CARD_CMD;
} // intentionally no break;
case SNF_CARD_CMD:{
LogTrace(data, len, 0, 0, NULL, TRUE);
sniffState = SNF_CARD_RESP;
timerData = GetTickCount();
break;
}
case SNF_CARD_RESP:{
LogTrace(data, len, 0, 0, NULL, FALSE);
sniffState = SNF_CARD_CMD;
LogTrace(data, len, 0, 0, parity, reader);
timerData = GetTickCount();
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) {
if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) {
return intMfSniffSend();
}
return FALSE;
return false;
}
// internal sending function. not a RAMFUNC.
@ -179,5 +162,5 @@ bool intMfSniffSend() {
clear_trace();
return TRUE;
return true;
}

View file

@ -27,6 +27,7 @@
#define SNF_CARD_IDLE 9
#define SNF_CARD_CMD 10
#define SNF_CARD_RESP 11
#define SNF_MAGIC_WUPC2 12
#define SNF_UID_4 0
#define SNF_UID_7 0

View file

@ -405,29 +405,46 @@ int mifare_ultra_auth(uint8_t *keybytes){
return 1;
}
#define MFU_MAX_RETRIES 5
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
{
uint16_t len;
uint8_t bt[2];
uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
uint8_t retries;
int result = 0;
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
result = 1;
continue;
}
if (len != 18) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
return 2;
result = 2;
continue;
}
memcpy(bt, receivedAnswer + 16, 2);
AppendCrc14443a(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error.");
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);

View file

@ -24,8 +24,6 @@
#define CRYPT_REQUEST 2
#define AUTH_FIRST 0
#define AUTH_NESTED 2
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK

View file

@ -22,7 +22,7 @@
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
* by the Free Software Foundation, or, at your option, any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of

View file

@ -1,3 +1,40 @@
/*****************************************************************************
* 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
#include <stdint.h>

View file

@ -175,6 +175,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
padc = '0';
goto reswitch;
}
// intentionally fall through to next case
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) {

View file

@ -453,26 +453,47 @@ uint32_t RAMFUNC GetCountSspClk(){
// -------------------------------------------------------------------------
void StartTicks(void){
// 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_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_TC1->TC_CCR = AT91C_TC_CLKDIS;
// first configure TC1 (higher, 0xFFFF0000) 16 bit counter
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0
// second configure TC0 (lower, 0x0000FFFF) 16 bit counter
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0;
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit)
AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit)
AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit)
AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero
AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from TC0
// synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared)
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TCB->TCB_BCR = 1;
// return to zero
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0);
}
// 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...
void WaitTicks(uint32_t ticks){
if ( ticks == 0 ) return;
ticks += GET_TICKS;
while (GET_TICKS < ticks);
ticks += GetTicks();
while (GetTicks() < ticks);
}
// Wait / Spindelay in us (microseconds)
// 1us = 1.5ticks.
void WaitUS(uint16_t us){
if ( us == 0 ) return;
WaitTicks( (uint32_t)(us * 1.5) );
WaitTicks( (uint32_t)us * 3 / 2 ) ;
}
void WaitMS(uint16_t ms){
if (ms == 0) return;
WaitTicks( (uint32_t)(ms * 1500) );
WaitTicks( (uint32_t)ms * 1500 );
}
// Starts Clock and waits until its reset
void ResetTicks(void){
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC1->TC_CV > 0);
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0);
}

View file

@ -44,7 +44,7 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
//iceman's ticks.h
#ifndef GET_TICKS
# define GET_TICKS (uint32_t)((AT91C_BASE_TC1->TC_CV << 16) | AT91C_BASE_TC0->TC_CV)
# define GET_TICKS GetTicks()
#endif
void SpinDelay(int ms);
@ -62,6 +62,7 @@ void ResetSspClk(void);
uint32_t RAMFUNC GetCountSspClk();
extern void StartTicks(void);
extern uint32_t GetTicks(void);
extern void WaitTicks(uint32_t ticks);
extern void WaitUS(uint16_t us);
extern void WaitMS(uint16_t ms);

View file

@ -10,6 +10,7 @@
ARMSRC =
THUMBSRC = cmd.c usb_cdc.c bootrom.c
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
## 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
APP_CFLAGS = -I.
# version.c should be remade on every compilation
.PHONY: version.c
version.c: default_version.c
perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common

View file

@ -23,6 +23,10 @@ LDFLAGS = $(ENV_LDFLAGS)
CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -Wall -g -O3
CXXFLAGS = -I../include -Wall -O3
APP_CFLAGS =
include ../common/Makefile_Enabled_Options.common
CFLAGS += $(APP_CFLAGS)
LUAPLATFORM = generic
platform = $(shell uname)
ifneq (,$(findstring MINGW,$(platform)))
@ -37,6 +41,7 @@ else
endif
endif
ifneq (,$(findstring WITH_GUI,$(APP_CFLAGS)))
# Check for correctly configured Qt5
QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null)
QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
@ -65,6 +70,7 @@ ifeq ($(QTINCLUDES), )
UIC = $(QTDIR)/bin/uic
endif
endif
endif
ifneq ($(QTLDLIBS), )
@ -79,10 +85,13 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
# make temporary to final dependeny files after successful compilation
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d
CORESRCS = uart_posix.c \
uart_win32.c \
util.c \
util_posix.c
util_posix.c \
ui.c \
comms.c
CMDSRCS = crapto1/crapto1.c\
crapto1/crypto1.c\
@ -107,9 +116,7 @@ CMDSRCS = crapto1/crapto1.c\
crc64.c \
iso14443crc.c \
iso15693tools.c \
data.c \
graph.c \
ui.c \
cmddata.c \
lfdemod.c \
emv/crypto_polarssl.c\
@ -130,6 +137,7 @@ CMDSRCS = crapto1/crapto1.c\
emv/test/cda_test.c\
emv/cmdemv.c\
cmdhf.c \
cmdhflist.c \
cmdhf14a.c \
cmdhf14b.c \
cmdhf15.c \
@ -171,14 +179,7 @@ CMDSRCS = crapto1/crapto1.c\
cmdscript.c\
pm3_binlib.c\
pm3_bitlib.c\
protocols.c\
cmdcrc.c\
reveng/reveng.c\
reveng/cli.c\
reveng/bmpbit.c\
reveng/model.c\
reveng/poly.c\
#reveng/getopt.c\
protocols.c
cpu_arch = $(shell uname -m)
ifneq ($(findstring 86, $(cpu_arch)), )
@ -311,6 +312,7 @@ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBS
$(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
$(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d
$(DEPENDENCY_FILES): ;
.PRECIOUS: $(DEPENDENCY_FILES)

View file

@ -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;
}

View file

@ -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

View file

@ -8,15 +8,15 @@
// Data and Graph commands
//-----------------------------------------------------------------------------
#include "cmddata.h"
#include <stdio.h> // also included in util.h
#include <string.h> // also included in util.h
#include <inttypes.h>
#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
#include "data.h" // also included in util.h
#include "cmddata.h"
#include "util.h"
#include "cmdmain.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h"// already included in cmdmain.h
@ -591,8 +591,7 @@ int CmdBitsamples(const char *Cmd)
int cnt = 0;
uint8_t got[12288];
GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(got, sizeof(got), 0 , NULL, -1, false);
for (int j = 0; j < sizeof(got); j++) {
for (int k = 0; k < 8; k++) {
@ -1131,8 +1130,7 @@ int CmdHexsamples(const char *Cmd)
return 0;
}
GetFromBigBuf(got,requested,offset);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(got, requested, offset, NULL, -1, false);
i = 0;
for (j = 0; j < requested; j++) {
@ -1200,10 +1198,9 @@ int getSamples(int n, bool silent)
n = sizeof(got);
if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n);
GetFromBigBuf(got,n,0);
if (!silent) PrintAndLog("Data fetched");
UsbCommand response;
WaitForResponse(CMD_ACK, &response);
GetFromBigBuf(got, n, 0, &response, -1, false);
if (!silent) PrintAndLog("Data fetched");
uint8_t bits_per_sample = 8;
//Old devices without this feature would send 0 at arg[0]
@ -1281,26 +1278,36 @@ int CmdTuneSamples(const char *Cmd)
peakf = resp.arg[2] & 0xffff;
peakv = resp.arg[2] >> 16;
PrintAndLog("");
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0);
PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1));
if (arg & FLAG_TUNE_LF)
{
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/500.0);
PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/500.0);
PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/500.0, 12000.0/(peakf+1));
}
if (arg & FLAG_TUNE_HF)
PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0);
#define LF_UNUSABLE_V 2948 // was 2000. Changed due to bugfix in voltage measurements. LF results are now 47% higher.
#define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher.
#define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
#define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
#define LF_UNUSABLE_V 3000
#define LF_MARGINAL_V 15000
#define HF_UNUSABLE_V 3200
#define HF_MARGINAL_V 8000
if (peakv < LF_UNUSABLE_V)
if (arg & FLAG_TUNE_LF)
{
if (peakv<<1 < LF_UNUSABLE_V)
PrintAndLog("# Your LF antenna is unusable.");
else if (peakv < LF_MARGINAL_V)
else if (peakv<<1 < LF_MARGINAL_V)
PrintAndLog("# Your LF antenna is marginal.");
}
if (arg & FLAG_TUNE_HF)
{
if (vHf < HF_UNUSABLE_V)
PrintAndLog("# Your HF antenna is unusable.");
else if (vHf < HF_MARGINAL_V)
PrintAndLog("# Your HF antenna is marginal.");
}
if (peakv >= LF_UNUSABLE_V) {
if (peakv<<1 >= LF_UNUSABLE_V) {
for (int i = 0; i < 256; i++) {
GraphBuffer[i] = resp.d.asBytes[i] - 128;
}

View file

@ -1,5 +1,6 @@
//-----------------------------------------------------------------------------
// 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,
// at your option, any later version. See the LICENSE.txt file for the text of
@ -8,18 +9,18 @@
// High frequency commands
//-----------------------------------------------------------------------------
#include "cmdhf.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "util.h"
#include "data.h"
#include "ui.h"
#include "iso14443crc.h"
#include "parity.h"
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmdhf.h"
#include "cmdhf14a.h"
#include "cmdhf14b.h"
#include "cmdhf15.h"
@ -31,6 +32,7 @@
#include "cmdhftopaz.h"
#include "protocols.h"
#include "emv/cmdemv.h"
#include "cmdhflist.h"
static int CmdHelp(const char *Cmd);
@ -41,236 +43,6 @@ int CmdHFTune(const char *Cmd)
return 0;
}
void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
switch(cmd[0])
{
case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break;
case ISO14443A_CMD_ANTICOLL_OR_SELECT:{
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
// 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
if(cmd[1] == 0x70)
{
snprintf(exp,size,"SELECT_UID"); break;
}else
{
snprintf(exp,size,"ANTICOLL"); break;
}
}
case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:{
//95 20 = Anticollision of cascade level2
//95 70 = Select of cascade level2
if(cmd[2] == 0x70)
{
snprintf(exp,size,"SELECT_UID-2"); break;
}else
{
snprintf(exp,size,"ANTICOLL-2"); break;
}
}
case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break;
case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break;
case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break;
case ISO14443A_CMD_HALT: snprintf(exp,size,"HALT"); break;
case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break;
case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break;
case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break;
case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
case MIFARE_AUTH_KEYA:{
if ( cmdsize > 3)
snprintf(exp,size,"AUTH-A(%d)",cmd[1]);
else
// case MIFARE_ULEV1_VERSION : both 0x60.
snprintf(exp,size,"EV1 VERSION");
break;
}
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break;
case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break;
case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break;
case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break;
case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break;
case MIFARE_ULEV1_AUTH:
if ( cmdsize == 7 )
snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
else
snprintf(exp,size,"PWD-AUTH");
break;
case MIFARE_ULEV1_FASTREAD:{
if ( cmdsize >=3 && cmd[2] <= 0xE6)
snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULC_WRITE:{
if ( cmd[1] < 0x21 )
snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_READ_CNT:{
if ( cmd[1] < 5 )
snprintf(exp,size,"READ CNT(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_INCR_CNT:{
if ( cmd[1] < 5 )
snprintf(exp,size,"INCR(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break;
case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break;
default: snprintf(exp,size,"?"); break;
}
return;
}
void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
switch(cmd[0])
{
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
* @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];
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
char explanation[30] = {0};
uint8_t mfData[32] = {0};
size_t mfDataLen = 0;
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
@ -466,6 +240,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
case TOPAZ:
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
break;
case PROTO_MIFARE:
crcStatus = mifare_CRC_check(isResponse, frame, data_len);
break;
case ISO_14443A:
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
break;
@ -514,6 +291,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
EndOfTransmissionTimestamp = timestamp + duration;
if (protocol == PROTO_MIFARE)
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse);
if(!isResponse)
{
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 (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
@ -562,27 +355,52 @@ int CmdHFList(const char *Cmd)
{
bool showWaitCycles = false;
bool markCRCBytes = false;
bool loadFromFile = false;
bool saveToFile = false;
char param1 = '\0';
char param2 = '\0';
char param3 = '\0';
char type[40] = {0};
int tlen = param_getstr(Cmd,0,type, sizeof(type));
char param1 = param_getchar(Cmd, 1);
char param2 = param_getchar(Cmd, 2);
bool errors = false;
char filename[FILE_PATH_SIZE] = {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) {
errors = true;
}
if(param1 == 'h'
|| (param1 != 0 && param1 != 'f' && param1 != 'c')
|| (param2 != 0 && param2 != 'f' && param2 != 'c')) {
|| (param1 != 0 && param1 != 'f' && param1 != 'c' && param1 != 'l')
|| (param2 != 0 && param2 != 'f' && param2 != 'c' && param2 != 'l')
|| (param3 != 0 && param3 != 'f' && param3 != 'c' && param3 != 'l')) {
errors = true;
}
if(!errors) {
if(strcmp(type, "iclass") == 0) {
protocol = ICLASS;
} else if(strcmp(type, "mf") == 0) {
protocol = PROTO_MIFARE;
} else if(strcmp(type, "14a") == 0) {
protocol = ISO_14443A;
} else if(strcmp(type, "14b") == 0) {
@ -591,46 +409,96 @@ int CmdHFList(const char *Cmd)
protocol = TOPAZ;
} else if(strcmp(type,"raw") == 0) {
protocol = -1; //No crc, no annotations
} else if (strcmp(type, "save") == 0) {
saveToFile = true;
} else {
errors = true;
}
}
if (param1 == 'f' || param2 == 'f' || param3 == 'f') {
showWaitCycles = true;
}
if (param1 == 'c' || param2 == 'c' || param3 == 'c') {
markCRCBytes = true;
}
if (param1 == 'l' || param2 == 'l' || param3 == 'l') {
loadFromFile = true;
}
if ((loadFromFile || saveToFile) && strlen(filename) == 0) {
errors = true;
}
if (loadFromFile && saveToFile) {
errors = true;
}
if (errors) {
PrintAndLog("List protocol data in trace buffer.");
PrintAndLog("Usage: hf list <protocol> [f][c]");
PrintAndLog("List or save protocol data.");
PrintAndLog("Usage: hf list <protocol> [f] [c] [l <filename>]");
PrintAndLog(" hf list save <filename>");
PrintAndLog(" f - show frame delay times as well");
PrintAndLog(" c - mark CRC bytes");
PrintAndLog(" l - load data from file instead of trace buffer");
PrintAndLog(" save - save data to file");
PrintAndLog("Supported <protocol> values:");
PrintAndLog(" raw - just show raw data without annotations");
PrintAndLog(" 14a - interpret data as iso14443a communications");
PrintAndLog(" mf - interpret data as iso14443a communications and decrypt crypto1 stream");
PrintAndLog(" 14b - interpret data as iso14443b communications");
PrintAndLog(" iclass - interpret data as iclass communications");
PrintAndLog(" topaz - interpret data as topaz communications");
PrintAndLog("");
PrintAndLog("example: hf list 14a f");
PrintAndLog("example: hf list iclass");
PrintAndLog("example: hf list save myCardTrace.trc");
PrintAndLog("example: hf list 14a l myCardTrace.trc");
return 0;
}
if (param1 == 'f' || param2 == 'f') {
showWaitCycles = true;
}
if (param1 == 'c' || param2 == 'c') {
markCRCBytes = true;
}
uint8_t *trace;
uint16_t tracepos = 0;
trace = malloc(USB_CMD_DATA_SIZE);
uint32_t tracepos = 0;
uint32_t traceLen = 0;
if (loadFromFile) {
#define TRACE_CHUNK_SIZE (1<<16) // 64K to start with. Will be enough for BigBuf and some room for future extensions
FILE *tracefile = NULL;
size_t bytes_read;
trace = malloc(TRACE_CHUNK_SIZE);
if (trace == NULL) {
PrintAndLog("Cannot allocate memory for trace");
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
UsbCommand response;
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
WaitForResponse(CMD_ACK, &response);
uint16_t traceLen = response.arg[2];
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0, &response, -1, false);
traceLen = response.arg[2];
if (traceLen > USB_CMD_DATA_SIZE) {
uint8_t *p = realloc(trace, traceLen);
if (p == NULL) {
@ -639,10 +507,20 @@ int CmdHFList(const char *Cmd)
return 2;
}
trace = p;
GetFromBigBuf(trace, traceLen, 0);
WaitForResponse(CMD_ACK, NULL);
GetFromBigBuf(trace, traceLen, 0, NULL, -1, false);
}
}
if (saveToFile) {
FILE *tracefile = NULL;
if ((tracefile = fopen(filename,"wb")) == NULL) {
PrintAndLog("Could not create file %s", filename);
return 1;
}
fwrite(trace, 1, traceLen, tracefile);
PrintAndLog("Recorded Activity (TraceLen = %d bytes) written to file %s", traceLen, filename);
fclose(tracefile);
} else {
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
PrintAndLog("");
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
@ -652,10 +530,12 @@ int CmdHFList(const char *Cmd)
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
ClearAuthData();
while(tracepos < traceLen)
{
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
}
}
free(trace);
return 0;

View file

@ -20,8 +20,7 @@
#include "util.h"
#include "util_posix.h"
#include "iso14443crc.h"
#include "data.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "common.h"
@ -36,8 +35,13 @@
static int CmdHelp(const char *Cmd);
static int waitCmd(uint8_t iLen);
// structure and database for uid -> tagtype lookups
typedef struct {
uint8_t uid;
char* desc;
} manufactureName;
const manufactureName manufactureMapping[] = {
static const manufactureName manufactureMapping[] = {
// ID, "Vendor Country"
{ 0x01, "Motorola UK" },
{ 0x02, "ST Microelectronics SA France" },
@ -187,7 +191,7 @@ int CmdHF14AReader(const char *Cmd) {
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
PrintAndLog(" SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]);
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len));
}
@ -239,7 +243,7 @@ int CmdHF14AInfo(const char *Cmd)
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
PrintAndLog(" SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]);
bool isMifareClassic = true;
switch (card.sak) {
@ -477,12 +481,12 @@ int CmdHF14AInfo(const char *Cmd)
// try to see if card responses to "chinese magic backdoor" commands.
mfCIdentify();
(void)mfCIdentify();
if (isMifareClassic) {
switch(DetectClassicPrng()) {
case 0:
PrintAndLog("Prng detection: HARDEND (hardnested)");
PrintAndLog("Prng detection: HARDENED (hardnested)");
break;
case 1:
PrintAndLog("Prng detection: WEAK");
@ -949,10 +953,7 @@ static command_t CommandTable[] =
};
int CmdHF14A(const char *Cmd) {
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
// parse
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}

View file

@ -15,12 +15,6 @@
#include <stdint.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 CmdHF14AList(const char *Cmd);
int CmdHF14AMifare(const char *Cmd);

View file

@ -8,19 +8,19 @@
// High frequency ISO14443B commands
//-----------------------------------------------------------------------------
#include "cmdhf14b.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include "iso14443crc.h"
#include "proxmark3.h"
#include "data.h"
#include "comms.h"
#include "graph.h"
#include "util.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhf14b.h"
#include "cmdmain.h"
#include "cmdhf14a.h"

View file

@ -11,6 +11,8 @@
#ifndef CMDHF14B_H__
#define CMDHF14B_H__
#include <stdbool.h>
int CmdHF14B(const char *Cmd);
int CmdHF14BList(const char *Cmd);
int CmdHF14BInfo(const char *Cmd);

View file

@ -22,18 +22,18 @@
// the client. Signal Processing & decoding is done on the pc. This is the slowest
// variant, but offers the possibility to analyze the waveforms directly.
#include "cmdhf15.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "proxmark3.h"
#include "data.h"
#include "comms.h"
#include "graph.h"
#include "ui.h"
#include "util.h"
#include "cmdparser.h"
#include "cmdhf15.h"
#include "iso15693tools.h"
#include "cmdmain.h"

View file

@ -11,6 +11,8 @@
#ifndef CMDHF15_H__
#define CMDHF15_H__
#include <stdbool.h>
int CmdHF15(const char *Cmd);
int CmdHF15Demod(const char *Cmd);

View file

@ -17,7 +17,7 @@
#include <stdio.h>
#include "util.h"
#include "util_posix.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "common.h"
@ -202,10 +202,7 @@ int CmdHelp(const char *Cmd)
int CmdHFEPA(const char *Cmd)
{
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
// parse
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}

View file

@ -16,8 +16,7 @@
#include <sys/stat.h>
#include <ctype.h>
#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
#include "data.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhficlass.h"
@ -750,8 +749,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
blocksRead = (sizeof(tag_data)/8) - blockno;
}
// response ok - now get bigbuf content of the dump
GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
size_t gotBytes = blocksRead*8 + blockno*8;
// try AA2
@ -793,8 +791,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
blocksRead = (sizeof(tag_data) - gotBytes)/8;
}
// get dumped data from bigbuf
GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
gotBytes += blocksRead*8;
} else { //field is still on - turn it off...

View file

@ -8,16 +8,17 @@
// High frequency Legic commands
//-----------------------------------------------------------------------------
#include "cmdhflegic.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "proxmark3.h"
#include "data.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhflegic.h"
#include "cmdmain.h"
#include "util.h"
static int CmdHelp(const char *Cmd);
static command_t CommandTable[] =
@ -64,8 +65,7 @@ int CmdLegicDecode(const char *Cmd)
char token_type[4];
// copy data from proxmark into buffer
GetFromBigBuf(data_buf,sizeof(data_buf),0);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(data_buf, sizeof(data_buf), 0, NULL, -1, false);
// Output CDF System area (9 bytes) plus remaining header area (12 bytes)
@ -294,8 +294,7 @@ int CmdLegicSave(const char *Cmd)
return -1;
}
GetFromBigBuf(got,requested,offset);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(got, requested, offset, NULL, -1, false);
for (int j = 0; j < requested; j += 8) {
fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n",

606
client/cmdhflist.c Normal file
View 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
View 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

View file

@ -15,9 +15,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "proxmark3.h"
#include "comms.h"
#include "cmdmain.h"
#include "cmdhfmfhard.h"
#include "parity.h"
#include "util.h"
#include "util_posix.h"
#include "usb_cmd.h"
@ -25,6 +26,7 @@
#include "mifarehost.h"
#include "mifare.h"
#include "mfkey.h"
#include "hardnested/hardnested_bf_core.h"
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
@ -682,9 +684,9 @@ int CmdHF14AMfNested(const char *Cmd)
if (transferToEml) {
uint8_t sectortrailer;
if (trgBlockNo < 32*4) { // 4 block sector
sectortrailer = (trgBlockNo & 0x03) + 3;
sectortrailer = trgBlockNo | 0x03;
} else { // 16 block sector
sectortrailer = (trgBlockNo & 0x0f) + 15;
sectortrailer = trgBlockNo | 0x0f;
}
mfEmlGetMem(keyBlock, sectortrailer, 1);
@ -724,7 +726,6 @@ int CmdHF14AMfNested(const char *Cmd)
blockNo = i * 4;
keyType = j;
num_to_bytes(e_sector[i].Key[j], 6, key);
keyFound = true;
break;
}
@ -735,6 +736,7 @@ int CmdHF14AMfNested(const char *Cmd)
// Can't found a key....
if (!keyFound) {
PrintAndLog("Can't found any of the known keys.");
free(e_sector);
return 4;
}
PrintAndLog("--auto key. block no:%3d, key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
@ -862,6 +864,13 @@ int CmdHF14AMfNestedHard(const char *Cmd)
PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin");
PrintAndLog(" s: Slower acquisition (required by some non standard cards)");
PrintAndLog(" r: Read nonces.bin and start attack");
PrintAndLog(" iX: set type of SIMD instructions. Without this flag programs autodetect it.");
PrintAndLog(" i5: AVX512");
PrintAndLog(" i2: AVX2");
PrintAndLog(" ia: AVX");
PrintAndLog(" is: SSE2");
PrintAndLog(" im: MMX");
PrintAndLog(" in: none (use CPU regular instruction set)");
PrintAndLog(" ");
PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A");
PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w");
@ -880,15 +889,20 @@ int CmdHF14AMfNestedHard(const char *Cmd)
int tests = 0;
uint16_t iindx = 0;
if (ctmp == 'R' || ctmp == 'r') {
nonce_file_read = true;
iindx = 1;
if (!param_gethex(Cmd, 1, trgkey, 12)) {
know_target_key = true;
iindx = 2;
}
} else if (ctmp == 'T' || ctmp == 't') {
tests = param_get32ex(Cmd, 1, 100, 10);
iindx = 2;
if (!param_gethex(Cmd, 2, trgkey, 12)) {
know_target_key = true;
iindx = 3;
}
} else {
blockNo = param_get8(Cmd, 0);
@ -922,20 +936,55 @@ int CmdHF14AMfNestedHard(const char *Cmd)
know_target_key = true;
i++;
}
iindx = i;
while ((ctmp = param_getchar(Cmd, i))) {
if (ctmp == 's' || ctmp == 'S') {
slow = true;
} else if (ctmp == 'w' || ctmp == 'W') {
nonce_file_write = true;
} else if (param_getlength(Cmd, i) == 2 && ctmp == 'i') {
iindx = i;
} else {
PrintAndLog("Possible options are w and/or s");
PrintAndLog("Possible options are w , s and/or iX");
return 1;
}
i++;
}
}
SetSIMDInstr(SIMD_AUTO);
if (iindx > 0) {
while ((ctmp = param_getchar(Cmd, iindx))) {
if (param_getlength(Cmd, iindx) == 2 && ctmp == 'i') {
switch(param_getchar_indx(Cmd, 1, iindx)) {
case '5':
SetSIMDInstr(SIMD_AVX512);
break;
case '2':
SetSIMDInstr(SIMD_AVX2);
break;
case 'a':
SetSIMDInstr(SIMD_AVX);
break;
case 's':
SetSIMDInstr(SIMD_SSE2);
break;
case 'm':
SetSIMDInstr(SIMD_MMX);
break;
case 'n':
SetSIMDInstr(SIMD_NONE);
break;
default:
PrintAndLog("Unknown SIMD type. %c", param_getchar_indx(Cmd, 1, iindx));
return 1;
}
}
iindx++;
}
}
PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ",
trgBlockNo,
trgKeyType?'B':'A',
@ -1138,7 +1187,10 @@ int CmdHF14AMfChk(const char *Cmd)
// initialize storage for found keys
e_sector = calloc(SectorsCnt, sizeof(sector_t));
if (e_sector == NULL) return 1;
if (e_sector == NULL) {
free(keyBlock);
return 1;
}
for (uint8_t keyAB = 0; keyAB < 2; keyAB++) {
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
e_sector[sectorNo].Key[keyAB] = 0xffffffffffff;
@ -1637,10 +1689,7 @@ int CmdHF14AMfESet(const char *Cmd)
}
// 1 - blocks count
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNo, 1, 0}};
memcpy(c.d.asBytes, memBlock, 16);
SendCommand(&c);
return 0;
return mfEmlSetMem(memBlock, blockNo, 1);
}
@ -1859,7 +1908,7 @@ int CmdHF14AMfECFill(const char *Cmd)
default: numSectors = 16;
}
printf("--params: numSectors: %d, keyType:%d", numSectors, keyType);
printf("--params: numSectors: %d, keyType:%d\n", numSectors, keyType);
UsbCommand c = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}};
SendCommand(&c);
return 0;
@ -2425,6 +2474,7 @@ int CmdHF14AMfSniff(const char *Cmd){
//var
int res = 0;
int len = 0;
int parlen = 0;
int blockLen = 0;
int pckNum = 0;
int num = 0;
@ -2436,6 +2486,7 @@ int CmdHF14AMfSniff(const char *Cmd){
uint8_t *buf = NULL;
uint16_t bufsize = 0;
uint8_t *bufPtr = NULL;
uint8_t parity[16];
char ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'h' || ctmp == 'H' ) {
@ -2479,14 +2530,13 @@ int CmdHF14AMfSniff(const char *Cmd){
}
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) {
res = resp.arg[0] & 0xff;
uint16_t traceLen = resp.arg[1];
len = resp.arg[2];
if (res == 0) { // we are done
free(buf);
return 0;
break;
}
if (res == 1) { // there is (more) data to be transferred
@ -2528,6 +2578,7 @@ int CmdHF14AMfSniff(const char *Cmd){
} else {
isTag = false;
}
parlen = (len - 1) / 8 + 1;
bufPtr += 2;
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
memcpy(uid, bufPtr + 2, 7);
@ -2546,15 +2597,22 @@ int CmdHF14AMfSniff(const char *Cmd){
if (wantDecrypt)
mfTraceInit(uid, atqa, sak, wantSaveToEmlFile);
} else {
PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len));
oddparitybuf(bufPtr, len, parity);
PrintAndLog("%s(%d):%s [%s] c[%s]%c",
isTag ? "TAG":"RDR",
num,
sprint_hex(bufPtr, len),
printBitsPar(bufPtr + len, len),
printBitsPar(parity, len),
memcmp(bufPtr + len, parity, len / 8 + 1) ? '!' : ' ');
if (wantLogToFile)
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
if (wantDecrypt)
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
mfTraceDecode(bufPtr, len, bufPtr[len], wantSaveToEmlFile);
num++;
}
bufPtr += len;
bufPtr += ((len-1)/8+1); // ignore parity
bufPtr += parlen; // ignore parity
}
pckNum = 0;
}
@ -2562,6 +2620,9 @@ int CmdHF14AMfSniff(const char *Cmd){
} // while (true)
free(buf);
msleep(300); // wait for exiting arm side.
PrintAndLog("Done.");
return 0;
}
@ -2608,9 +2669,7 @@ static command_t CommandTable[] =
int CmdHFMF(const char *Cmd)
{
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}

View file

@ -25,6 +25,7 @@
#include <locale.h>
#include <math.h>
#include "proxmark3.h"
#include "comms.h"
#include "cmdmain.h"
#include "ui.h"
#include "util.h"
@ -32,6 +33,7 @@
#include "crapto1/crapto1.h"
#include "parity.h"
#include "hardnested/hardnested_bruteforce.h"
#include "hardnested/hardnested_bf_core.h"
#include "hardnested/hardnested_bitarray_core.h"
#include "zlib.h"
@ -71,27 +73,32 @@ static float brute_force_per_second;
static void get_SIMD_instruction_set(char* instruction_set) {
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
if (__builtin_cpu_supports("avx512f")) strcpy(instruction_set, "AVX512F");
else if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
#else
if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
#endif
else if (__builtin_cpu_supports("avx")) strcpy(instruction_set, "AVX");
else if (__builtin_cpu_supports("sse2")) strcpy(instruction_set, "SSE2");
else if (__builtin_cpu_supports("mmx")) strcpy(instruction_set, "MMX");
else
#endif
#endif
switch(GetSIMDInstrAuto()) {
case SIMD_AVX512:
strcpy(instruction_set, "AVX512F");
break;
case SIMD_AVX2:
strcpy(instruction_set, "AVX2");
break;
case SIMD_AVX:
strcpy(instruction_set, "AVX");
break;
case SIMD_SSE2:
strcpy(instruction_set, "SSE2");
break;
case SIMD_MMX:
strcpy(instruction_set, "MMX");
break;
default:
strcpy(instruction_set, "no");
break;
}
}
static void print_progress_header(void) {
char progress_text[80];
char instr_set[12] = "";
char instr_set[12] = {0};
get_SIMD_instruction_set(instr_set);
sprintf(progress_text, "Start using %d threads and %s SIMD core", num_CPUs(), instr_set);
PrintAndLog("\n\n");
@ -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)
{
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
@ -309,7 +276,6 @@ static void init_bitflip_bitarrays(void)
if (bytesread != filesize) {
printf("File read error with %s. Aborting...\n", state_file_name);
fclose(statesfile);
inflateEnd(&compressed_stream);
exit(5);
}
fclose(statesfile);
@ -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 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_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 instr_set[12] = {0};
get_SIMD_instruction_set(instr_set);
PrintAndLog("Using %s SIMD core.", instr_set);
srand((unsigned) time(NULL));
brute_force_per_second = brute_force_benchmark();
write_stats = false;

View file

@ -12,7 +12,7 @@
#include <stdint.h>
#include <stdio.h>
#include "proxmark3.h"
#include "comms.h"
#include "usb_cmd.h"
#include "cmdmain.h"
#include "ui.h"
@ -22,7 +22,6 @@
#include "mifare.h"
#include "util.h"
#include "protocols.h"
#include "data.h"
#define MAX_UL_BLOCKS 0x0f
#define MAX_ULC_BLOCKS 0x2b
@ -1325,8 +1324,7 @@ int CmdHF14AMfUDump(const char *Cmd){
PrintAndLog("Data exceeded Buffer size!");
bufferSize = sizeof(data);
}
GetFromBigBuf(data, bufferSize, startindex);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(data, bufferSize, startindex, NULL, -1, false);
Pages = bufferSize/4;
// Load lock bytes.
@ -1836,7 +1834,7 @@ static command_t CommandTable[] =
};
int CmdHFMFUltra(const char *Cmd){
WaitForResponseTimeout(CMD_ACK,NULL,100);
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}

View file

@ -8,17 +8,18 @@
// High frequency Topaz (NFC Type 1) commands
//-----------------------------------------------------------------------------
#include "cmdhftopaz.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmdhftopaz.h"
#include "cmdhf14a.h"
#include "ui.h"
#include "mifare.h"
#include "proxmark3.h"
#include "comms.h"
#include "iso14443crc.h"
#include "protocols.h"
@ -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],
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
(rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic");
(rid_response[0] & 0x0F) == 0x01 ? "static" : "dynamic");
PrintAndLog("HR1 : %02x", rid_response[1]);
status = topaz_rall(uid_echo, rall_response);
@ -553,10 +554,7 @@ static command_t CommandTable[] =
int CmdHFTopaz(const char *Cmd) {
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
// parse
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}

View file

@ -8,17 +8,17 @@
// Hardware commands
//-----------------------------------------------------------------------------
#include "cmdhw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "ui.h"
#include "proxmark3.h"
#include "comms.h"
#include "cmdparser.h"
#include "cmdhw.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "data.h"
/* low-level hardware control */
@ -408,30 +408,19 @@ int CmdVersion(const char *Cmd)
clearCommandBuffer();
UsbCommand c = {CMD_VERSION};
static UsbCommand resp = {0, {0, 0, 0}};
UsbCommand resp = {0, {0, 0, 0}};
if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
}
} else {
PrintAndLog("[[[ Cached information ]]]\n");
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
PrintAndLog("");
}
return 0;
}
int CmdStatus(const char *Cmd)
{
uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
sample_buf = speed_test_buffer;
clearCommandBuffer();
UsbCommand c = {CMD_STATUS};
SendCommand(&c);

View file

@ -8,21 +8,21 @@
// Low frequency commands
//-----------------------------------------------------------------------------
#include "cmdlf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include "proxmark3.h"
#include "cmdlf.h"
#include "comms.h"
#include "lfdemod.h" // for psk2TOpsk1
#include "util.h" // for parsing cli command utils
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h" // for getting cli commands included in cmdmain.h
#include "cmdmain.h" // for sending cmds to device
#include "data.h" // for GetFromBigBuf
#include "cmddata.h" // for `lf search`
#include "cmdlfawid.h" // for awid menu
#include "cmdlfem4x.h" // for em4x menu
@ -54,26 +54,24 @@ static int CmdHelp(const char *Cmd);
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(" h This help");
PrintAndLog(" L Low frequency (125 KHz)");
PrintAndLog(" H High frequency (134 KHz)");
PrintAndLog(" d <delay> delay OFF period");
PrintAndLog(" z <zero> time period ZERO");
PrintAndLog(" o <one> time period ONE");
PrintAndLog(" d <delay> delay OFF period between bits (0 for bitbang mode)");
PrintAndLog(" z <zero> time period ZERO (antenna off in bitbang mode)");
PrintAndLog(" o <one> time period ONE (antenna on in bitbang mode)");
PrintAndLog(" c <cmd> Command bytes");
PrintAndLog(" ************* All periods in microseconds");
PrintAndLog(" ************* Use lf config to configure options.");
PrintAndLog("Examples:");
PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000");
PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000 H");
PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000");
return 0;
}
/* send a command before reading */
int CmdLFCommandRead(const char *Cmd)
{
static char dummy[3] = {0x20,0x00,0x00};
UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
bool errors = false;
//uint8_t divisor = 95; //125khz
@ -84,14 +82,6 @@ int CmdLFCommandRead(const char *Cmd)
{
case 'h':
return usage_lf_cmdread();
case 'H':
//divisor = 88;
dummy[1]='h';
cmdp++;
break;
case 'L':
cmdp++;
break;
case 'c':
param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes));
cmdp+=2;
@ -121,11 +111,13 @@ int CmdLFCommandRead(const char *Cmd)
//Validations
if(errors) return usage_lf_cmdread();
// in case they specified 'H'
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
getSamples(0, true);
return 0;
}
@ -335,7 +327,7 @@ int CmdLFSetConfig(const char *Cmd)
}
bool lf_read(bool silent, uint32_t samples) {
if (offline) return false;
if (IsOffline()) return false;
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {silent,samples,0}};
clearCommandBuffer();
//And ship it to device
@ -878,7 +870,7 @@ int CmdVchDemod(const char *Cmd)
int CheckChipType(char cmdp) {
uint32_t wordData = 0;
if (offline || cmdp == '1') return 0;
if (IsOffline() || cmdp == '1') return 0;
save_restoreGB(GRAPH_SAVE);
save_restoreDB(GRAPH_SAVE);
@ -923,7 +915,7 @@ int CmdLFfind(const char *Cmd)
return 0;
}
if (!offline && (cmdp != '1')) {
if (!IsOffline() && (cmdp != '1')) {
lf_read(true, 30000);
} else if (GraphTraceLen < minLength) {
PrintAndLog("Data in Graphbuffer was too small.");
@ -939,7 +931,7 @@ int CmdLFfind(const char *Cmd)
// only run if graphbuffer is just noise as it should be for hitag/cotag
if (graphJustNoise(GraphBuffer, testLen)) {
// only run these tests if we are in online mode
if (!offline && (cmdp != '1')) {
if (!IsOffline() && (cmdp != '1')) {
// test for em4x05 in reader talk first mode.
if (EM4x05Block0Test(&wordData)) {
PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n");
@ -955,6 +947,7 @@ int CmdLFfind(const char *Cmd)
return 1;
}
}
PrintAndLog("\nNo Data Found! - maybe not an LF tag?\n");
return 0;
}

View file

@ -11,10 +11,11 @@
// FSK2a, RF/50, 96 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfawid.h"
#include <string.h>
#include <stdio.h> // sscanf
#include "proxmark3.h" // Definitions, USB controls, etc
#include "cmdlfawid.h"
#include "comms.h" // Definitions, USB controls, etc
#include "ui.h" // PrintAndLog
#include "cmdparser.h" // CmdsParse, CmdsHelp
#include "lfdemod.h" // parityTest +

View file

@ -7,14 +7,15 @@
//-----------------------------------------------------------------------------
// Low frequency COTAG commands
//-----------------------------------------------------------------------------
#include "cmdlfcotag.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "cmddata.h"
#include "data.h"
#include "cmdlfcotag.h"
#include "lfdemod.h"
#include "usb_cmd.h"
#include "cmdmain.h"
@ -99,10 +100,9 @@ int CmdCOTAGRead(const char *Cmd) {
getSamples(0, true); break;
}
case 1: {
GetFromBigBuf(DemodBuffer, COTAG_BITS, 0);
DemodBufferLen = COTAG_BITS;
UsbCommand response;
if ( !WaitForResponseTimeout(CMD_ACK, &response, 1000) ) {
DemodBufferLen = COTAG_BITS;
if (!GetFromBigBuf(DemodBuffer, COTAG_BITS, 0, &response, 1000, true)) {
PrintAndLog("timeout while waiting for reply.");
return -1;
}

View file

@ -8,14 +8,14 @@
// Low frequency EM4x commands
//-----------------------------------------------------------------------------
#include "cmdlfem4x.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "cmdlfem4x.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "data.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
@ -804,8 +804,7 @@ int usage_lf_em_read(void) {
bool downloadSamplesEM() {
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
uint8_t got[6000];
GetFromBigBuf(got, sizeof(got), 0);
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) {
if (!GetFromBigBuf(got, sizeof(got), 0, NULL, 4000, true)) {
PrintAndLog("command execution time out");
return false;
}

View file

@ -13,7 +13,7 @@
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h" // for PrintAndLog
#include "util.h"
#include "cmdparser.h"

View file

@ -6,20 +6,193 @@
// the license.
//-----------------------------------------------------------------------------
// Low frequency HID commands (known)
//
// Useful resources:
// RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
// http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
//
// "Understanding Card Data Formats"
// https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
//
// "What Format Do You Need?"
// https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
//-----------------------------------------------------------------------------
#include "cmdlfhid.h"
#include <stdio.h>
#include <string.h>
#include "cmdlfhid.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h" //for g_debugMode, demodbuff cmds
#include "lfdemod.h" // for HIDdemodFSK
#include "parity.h" // for parity
#include "util.h" // for param_get8,32
static int CmdHelp(const char *Cmd);
/**
* Packs a "short" (<38-bit) HID ID from component parts.
*
* This only works with 26, 34, 35 and 37 bit card IDs.
*
* NOTE: Parity calculation is only supported on 26-bit tags. Other card lengths
* may have invalid parity.
*
* Returns false on invalid inputs.
*/
bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info) {
uint32_t high = 0, low = 0;
switch (info->fmtLen) {
case 26: // HID H10301
low |= (info->cardnum & 0xffff) << 1;
low |= (info->fc & 0xff) << 17;
if (info->parityValid) {
// Calculate parity
low |= oddparity32((low >> 1) & 0xfff) & 1;
low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25;
}
break;
case 34:
low |= (info->cardnum & 0xffff) << 1;
low |= (info->fc & 0x7fff) << 17;
high |= (info->fc & 0x8000) >> 15;
// TODO: Calculate parity
break;
case 35:
low |= (info->cardnum & 0xfffff) << 1;
low |= (info->fc & 0x7ff) << 21;
high |= (info->fc & 0x800) >> 11;
// TODO: Calculate parity
break;
case 37:
low |= (info->cardnum & 0x7ffff) << 1;
low |= (info->fc & 0xfff) << 20;
high |= (info->fc & 0xf000) >> 12;
// TODO: Calculate parity
break;
default:
// Invalid / unsupported length
return false;
}
// Set the highest bit
if (info->fmtLen != 37) {
// Bit 37 is always set
high |= 0x20;
// Set the bit corresponding to the length.
if (info->fmtLen < 32) {
low |= 1 << info->fmtLen;
} else {
high |= 1 << (info->fmtLen - 32);
}
}
// Return result only if successful.
*hi = high;
*lo = low;
return true;
}
/**
* Unpacks a "short" (<38-bit) HID ID into its component parts.
*
* This only works with 26, 34, 35 and 37 bit card IDs.
*
* NOTE: Parity checking is only supported on 26-bit tags.
*
* Returns false on invalid inputs.
*/
bool unpack_short_hid(short_hid_info *out, uint32_t hi, uint32_t lo) {
memset(out, 0, sizeof(short_hid_info));
if (((hi >> 5) & 1) == 1) {
// if bit 38 is set then < 37 bit format is used
uint32_t lo2 = 0;
// get bits 21-37 to check for format len bit
lo2 = (((hi & 31) << 12) | (lo >> 20));
uint8_t idx3 = 1;
// find last bit set to 1 (format len bit)
while (lo2 > 1) {
lo2 = lo2 >> 1;
idx3++;
}
out->fmtLen = idx3 + 19;
switch (out->fmtLen) {
case 26: // HID H10301
out->cardnum = (lo >> 1) & 0xFFFF;
out->fc = (lo >> 17) & 0xFF;
if (g_debugMode) {
PrintAndLog("oddparity : input=%x, calculated=%d, provided=%d",
(lo >> 1) & 0xFFF, oddparity32((lo >> 1) & 0xFFF), lo & 1);
PrintAndLog("evenparity: input=%x, calculated=%d, provided=%d",
(lo >> 13) & 0xFFF, evenparity32((lo >> 13) & 0xFFF) & 1, (lo >> 25) & 1);
}
out->parityValid =
(oddparity32((lo >> 1) & 0xFFF) == (lo & 1)) &&
((evenparity32((lo >> 13) & 0xFFF) & 1) == ((lo >> 25) & 1));
break;
case 34:
out->cardnum = (lo >> 1) & 0xFFFF;
out->fc = ((hi & 1) << 15) | (lo >> 17);
// TODO: Calculate parity
break;
case 35:
out->cardnum = (lo >> 1) & 0xFFFFF;
out->fc = ((hi & 1) << 11) | (lo >> 21);
// TODO: Calculate parity
break;
default:
return false;
}
} else {
// If bit 38 is not set, then 37 bit format is used
out->fmtLen = 37;
out->cardnum = (lo >> 1) & 0x7FFFF;
out->fc = ((hi & 0xF) << 12) | (lo >> 20);
// TODO: Calculate parity
}
return true;
}
/**
* Converts a hex string to component "hi" and "lo" 32-bit integers, one nibble
* at a time.
*
* Returns the number of nibbles (4 bits) entered.
*/
int hexstring_to_int64(/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) {
// TODO: Replace this with param_gethex when it supports arbitrary length
// inputs.
int n = 0, i = 0;
while (sscanf(&str[i++], "%1x", &n ) == 1) {
*hi = (*hi << 4) | (*lo >> 28);
*lo = (*lo << 4) | (n & 0xf);
}
return i - 1;
}
//by marshmellow (based on existing demod + holiman's refactor)
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
//print full HID Prox ID and some bit format details if found
@ -59,45 +232,19 @@ int CmdFSKdemodHID(const char *Cmd)
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
}
else { //standard HID tags <38 bits
uint8_t fmtLen = 0;
uint32_t fc = 0;
uint32_t cardnum = 0;
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
uint32_t lo2=0;
lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
uint8_t idx3 = 1;
while(lo2>1){ //find last bit set to 1 (format len bit)
lo2=lo2>>1;
idx3++;
}
fmtLen =idx3+19;
fc =0;
cardnum=0;
if(fmtLen==26){
cardnum = (lo>>1)&0xFFFF;
fc = (lo>>17)&0xFF;
}
if(fmtLen==34){
cardnum = (lo>>1)&0xFFFF;
fc= ((hi&1)<<15)|(lo>>17);
}
if(fmtLen==35){
cardnum = (lo>>1)&0xFFFFF;
fc = ((hi&1)<<11)|(lo>>21);
}
}
else { //if bit 38 is not set then 37 bit format is used
fmtLen = 37;
fc = 0;
cardnum = 0;
if(fmtLen == 37){
cardnum = (lo>>1)&0x7FFFF;
fc = ((hi&0xF)<<12)|(lo>>20);
}
}
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
short_hid_info card_info;
bool ret = unpack_short_hid(&card_info, (uint32_t)hi, (uint32_t)lo);
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
(unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum);
card_info.fmtLen, card_info.fc, card_info.cardnum);
if (card_info.fmtLen == 26) {
PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
}
if (!ret) {
PrintAndLog("Invalid or unsupported tag length.");
}
}
setDemodBuf(BitStream,BitLen,idx);
setClockGrid(50, waveIdx + (idx*50));
@ -121,11 +268,10 @@ int CmdHIDReadFSK(const char *Cmd)
int CmdHIDSim(const char *Cmd)
{
uint32_t hi = 0, lo = 0;
int n = 0, i = 0;
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
hi = (hi << 4) | (lo >> 28);
lo = (lo << 4) | (n & 0xf);
hexstring_to_int64(&hi, &lo, Cmd);
if (hi >= 0x40) {
PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!");
return 0;
}
PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
@ -139,10 +285,11 @@ int CmdHIDSim(const char *Cmd)
int CmdHIDClone(const char *Cmd)
{
unsigned int hi2 = 0, hi = 0, lo = 0;
int n = 0, i = 0;
UsbCommand c;
if (strchr(Cmd,'l') != 0) {
int n = 0, i = 0;
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
hi2 = (hi2 << 4) | (hi >> 28);
hi = (hi << 4) | (lo >> 28);
@ -154,9 +301,10 @@ int CmdHIDClone(const char *Cmd)
c.d.asBytes[0] = 1;
}
else {
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
hi = (hi << 4) | (lo >> 28);
lo = (lo << 4) | (n & 0xf);
hexstring_to_int64(&hi, &lo, Cmd);
if (hi >= 0x40) {
PrintAndLog("This looks like a long tag ID. Aborting!");
return 0;
}
PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
@ -174,6 +322,73 @@ int CmdHIDClone(const char *Cmd)
return 0;
}
int CmdHIDPack(const char *Cmd) {
uint32_t hi = 0, lo = 0;
short_hid_info card_info;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: lf hid pack <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[] =
{
{"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)"},
{"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)"},
{"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}
};

View file

@ -11,10 +11,39 @@
#ifndef 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 CmdFSKdemodHID(const char *Cmd);
int CmdHIDReadDemod(const char *Cmd);
int CmdHIDSim(const char *Cmd);
int CmdHIDClone(const char *Cmd);
int CmdHIDPack(const char *Cmd);
int CmdHIDUnpack(const char *Cmd);
#endif

View file

@ -8,11 +8,12 @@
// Low frequency Hitag support
//-----------------------------------------------------------------------------
#include "cmdlfhitag.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "data.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "common.h"
@ -34,8 +35,7 @@ int CmdLFHitagList(const char *Cmd)
// Query for the actual size of the trace
UsbCommand response;
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
WaitForResponse(CMD_ACK, &response);
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false);
uint16_t traceLen = response.arg[2];
if (traceLen > USB_CMD_DATA_SIZE) {
uint8_t *p = realloc(got, traceLen);
@ -45,8 +45,7 @@ int CmdLFHitagList(const char *Cmd)
return 2;
}
got = p;
GetFromBigBuf(got, traceLen, 0);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(got, traceLen, 0, NULL, -1, false);
}
PrintAndLog("recorded activity (TraceLen = %d bytes):");
@ -67,6 +66,7 @@ int CmdLFHitagList(const char *Cmd)
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"wb")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
free(got);
return 1;
}
}
@ -167,7 +167,7 @@ int CmdLFHitagSim(const char *Cmd) {
return 1;
}
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");
fclose(pf);
return 1;
@ -290,7 +290,7 @@ int CmdLFHitagSimS(const char *Cmd) {
return 1;
}
tag_mem_supplied = true;
if (fread(c.d.asBytes, 4*64, 1, pf) == 0) {
if (fread(c.d.asBytes, 1, 4*64, pf) != 4*64) {
PrintAndLog("Error: File reading error");
fclose(pf);
return 1;
@ -322,7 +322,7 @@ int CmdLFHitagCheckChallenges(const char *Cmd) {
return 1;
}
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");
fclose(pf);
return 1;

View file

@ -8,10 +8,11 @@
// PSK1, rf/32, 64 or 224 bits (known)
//-----------------------------------------------------------------------------
#include "cmdlfindala.h"
#include <stdio.h>
#include <string.h>
#include "cmdlfindala.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"
@ -286,7 +287,7 @@ int CmdIndalaDemod(const char *Cmd) {
}
int CmdIndalaClone(const char *Cmd) {
UsbCommand c;
UsbCommand c = {0};
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;

View file

@ -8,14 +8,14 @@
// FSK2a, rf/64, 64 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <limits.h>
#include "cmdlfio.h"
#include "proxmark3.h"
#include "data.h"
#include "comms.h"
#include "graph.h"
#include "ui.h"
#include "cmdparser.h"

View file

@ -9,10 +9,11 @@
//-----------------------------------------------------------------------------
#include "cmdlfjablotron.h"
#include <string.h>
#include <inttypes.h>
#include <stdbool.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,12 +7,14 @@
// Low frequency Honeywell NexWatch tag commands
// PSK1 RF/16, RF/2, 128 bits long (known)
//-----------------------------------------------------------------------------
#include "cmdlfnexwatch.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdbool.h>
#include "cmdlfnexwatch.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,11 +7,13 @@
// Low frequency Noralsy tag commands
// ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown)
//-----------------------------------------------------------------------------
#include "cmdlfnoralsy.h"
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,10 +7,12 @@
// Low frequency Stanley/PAC tag commands
// NRZ, RF/32, 128 bits long (unknown cs)
//-----------------------------------------------------------------------------
#include "cmdlfpac.h"
#include <string.h>
#include <inttypes.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -8,9 +8,12 @@
//-----------------------------------------------------------------------------
// Low frequency PCF7931 commands
//-----------------------------------------------------------------------------
#include "cmdlfpcf7931.h"
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
@ -18,7 +21,6 @@
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "cmdlfpcf7931.h"
static int CmdHelp(const char *Cmd);

View file

@ -12,6 +12,8 @@
#ifndef CMDLFPCF7931_H__
#define CMDLFPCF7931_H__
#include <stdint.h>
struct pcf7931_config{
uint8_t Pwd[7];
uint16_t InitDelay;

View file

@ -7,11 +7,13 @@
// Low frequency Presco tag commands
// ASK/Manchester, rf/32, 128 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfpresco.h"
#include <string.h>
#include <inttypes.h>
#include <stdio.h>
#include "cmdlfpresco.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,11 +7,13 @@
// Low frequency Farpoint / Pyramid tag commands
// FSK2a, rf/50, 128 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfpyramid.h"
#include <string.h>
#include <inttypes.h>
#include <stdio.h>
#include "cmdlfpyramid.h"
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,11 +7,13 @@
// Low frequency Securakey tag commands
// ASK/Manchester, RF/40, 96 bits long (unknown cs)
//-----------------------------------------------------------------------------
#include "cmdlfsecurakey.h"
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -7,21 +7,21 @@
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#include "cmdlft55xx.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <ctype.h>
#include <time.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlft55xx.h"
#include "util.h"
#include "data.h"
#include "lfdemod.h"
#include "cmdhf14a.h" //for getTagInfo
#include "protocols.h"
@ -207,7 +207,7 @@ void printT5xxHeader(uint8_t page){
int CmdT55xxSetConfig(const char *Cmd) {
uint8_t offset = 0;
char modulation[5] = {0x00};
char modulation[6] = {0x00};
char tmp = 0x00;
uint8_t bitRate = 0;
uint8_t rates[9] = {8,16,32,40,50,64,100,128,0};
@ -1355,8 +1355,7 @@ int CmdResetRead(const char *Cmd) {
}
uint8_t got[BIGBUF_SIZE-1];
GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL);
GetFromBigBuf(got, sizeof(got), 0, NULL, -1 , 0);
setGraphBuf(got, sizeof(got));
return 1;
}

View file

@ -10,6 +10,9 @@
#ifndef CMDLFT55XX_H__
#define CMDLFT55XX_H__
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint32_t bl1;
uint32_t bl2;

View file

@ -8,16 +8,17 @@
// Low frequency TI commands
//-----------------------------------------------------------------------------
#include "cmdlfti.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "crc16.h"
#include "proxmark3.h"
#include "data.h"
#include "comms.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmdlfti.h"
#include "util.h"
static int CmdHelp(const char *Cmd);

View file

@ -7,11 +7,13 @@
// Low frequency Viking tag commands (AKA FDI Matalec Transit)
// ASK/Manchester, RF/32, 64 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfviking.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "proxmark3.h"
#include "cmdlfviking.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -13,7 +13,7 @@
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "comms.h"
#include "ui.h"
#include "util.h"
#include "graph.h"

View file

@ -17,7 +17,6 @@
#include <string.h>
#include "cmdparser.h"
#include "proxmark3.h"
#include "data.h"
#include "usb_cmd.h"
#include "ui.h"
#include "cmdhf.h"
@ -27,24 +26,11 @@
#include "util.h"
#include "util_posix.h"
#include "cmdscript.h"
#include "cmdcrc.h"
unsigned int current_command = CMD_UNKNOWN;
static int CmdHelp(const char *Cmd);
static int CmdQuit(const char *Cmd);
static int CmdRev(const char *Cmd);
//For storing command that are received from the device
#define CMD_BUFFER_SIZE 50
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[] =
{
@ -53,7 +39,6 @@ static command_t CommandTable[] =
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
{"hw", CmdHW, 1, "{ Hardware commands... }"},
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
{"reveng",CmdRev, 1, "Crc calculations from the software reveng1-30"},
{"script",CmdScript,1, "{ Scripting commands }"},
{"quit", CmdQuit, 1, "Exit program"},
{"exit", CmdQuit, 1, "Exit program"},
@ -64,130 +49,18 @@ command_t* getTopLevelCommandTable()
{
return CommandTable;
}
int CmdHelp(const char *Cmd)
static int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}
int CmdQuit(const char *Cmd)
static int CmdQuit(const char *Cmd)
{
return 99;
}
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
// then presses Enter, which the full command line that they typed.
@ -196,38 +69,3 @@ int CommandReceived(char *Cmd) {
return CmdsParse(CommandTable, Cmd);
}
//-----------------------------------------------------------------------------
// Entry point into our code: called whenever we received a packet over USB
// that we weren't necessarily expecting, for example a debug print.
//-----------------------------------------------------------------------------
void UsbCommandReceived(UsbCommand *UC)
{
switch(UC->cmd) {
// First check if we are handling a debug message
case CMD_DEBUG_PRINT_STRING: {
char s[USB_CMD_DATA_SIZE+1];
memset(s, 0x00, sizeof(s));
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
memcpy(s,UC->d.asBytes,len);
PrintAndLog("#db# %s", s);
return;
} break;
case CMD_DEBUG_PRINT_INTEGERS: {
PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
return;
} break;
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
return;
} break;
default:
storeCommand(UC);
break;
}
}

View file

@ -11,17 +11,9 @@
#ifndef CMDMAIN_H__
#define CMDMAIN_H__
#include <stdint.h>
#include <stddef.h>
#include "usb_cmd.h"
#include "cmdparser.h"
extern void UsbCommandReceived(UsbCommand *UC);
extern int CommandReceived(char *Cmd);
extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning);
extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
extern bool WaitForResponse(uint32_t cmd, UsbCommand* response);
extern void clearCommandBuffer();
extern command_t* getTopLevelCommandTable();
#endif

View file

@ -8,12 +8,14 @@
// Command parser
//-----------------------------------------------------------------------------
#include "cmdparser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ui.h"
#include "cmdparser.h"
#include "proxmark3.h"
#include "comms.h"
void CmdsHelp(const command_t Commands[])
@ -23,7 +25,7 @@ void CmdsHelp(const command_t Commands[])
int i = 0;
while (Commands[i].Name)
{
if (!offline || Commands[i].Offline)
if (!IsOffline() || Commands[i].Offline)
PrintAndLog("%-16s %s", Commands[i].Name, Commands[i].Help);
++i;
}

View file

@ -17,7 +17,6 @@
#include "proxmark3.h"
#include "scripting.h"
#include "data.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"

411
client/comms.c Normal file
View 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 = &rx;
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 = &rx;
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
View 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_

View file

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

View file

@ -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

View file

@ -132,7 +132,7 @@ const APDUCode APDUCodeTable[] = {
{"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
{"6F--", APDUCODE_TYPE_ERROR, "Internal exception"},
{"6F00", APDUCODE_TYPE_ERROR, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
{"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse, )"},
{"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse, ...)"},
{"6FXX", APDUCODE_TYPE_ERROR, "No precise diagnosis (procedure byte), (ISO 7816-3)"},
{"9---", APDUCODE_TYPE_NONE, ""},
{"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."},

View file

@ -105,7 +105,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl)
int res = rsa_check_pubkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
@ -150,6 +150,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl)
int res = rsa_check_privkey(&cp->ctx);
if(res != 0) {
fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
free(cp);
return NULL;
}
@ -184,6 +185,7 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl)
int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
if (res) {
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
free(cp);
return NULL;
}
@ -215,7 +217,8 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co
res = rsa_public(&cp->ctx, buf, result);
if(res) {
printf("RSA encrypt failed. Error: %x data len: %d key len: %d\n", res * -1, len, keylen);
printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen);
free(result);
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???
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;
}

View file

@ -53,7 +53,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk,
}
if (cert_tlv->len != enc_pk->mlen) {
printf("ERROR: Certificate length (%d) not equal key length (%d)\n", cert_tlv->len, enc_pk->mlen);
printf("ERROR: Certificate length (%zd) not equal key length (%zd)\n", cert_tlv->len, enc_pk->mlen);
return NULL;
}
kcp = crypto_pk_open(enc_pk->pk_algo,
@ -451,7 +451,7 @@ struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct t
un_tlv,
NULL);
if (!data || data_len < 3) {
printf("ERROR: can't decode message. len %d\n", data_len);
printf("ERROR: can't decode message. len %zd\n", data_len);
return NULL;
}

View file

@ -221,7 +221,7 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) {
return tlvdb_fixed(0x02, dCVVlen, dCVV);
}
int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
uint8_t data[APDU_RES_LEN] = {0};
*ResultLen = 0;
@ -237,10 +237,10 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Re
memcpy(&data[5], apdu.data, apdu.Lc);
if (APDULogging)
PrintAndLog(">>>> %s", sprint_hex(data, 6 + apdu.Lc));
PrintAndLog(">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc));
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le
int res = ExchangeAPDU14a(data, 6 + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe)
int res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res) {
return res;
@ -270,11 +270,11 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Re
}
int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(false, LeaveFieldON, apdu, Result, MaxResultLen, ResultLen, sw, tlv);
return EMVExchangeEx(false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv);
}
int EMVSelect(bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, Result, MaxResultLen, ResultLen, sw, tlv);
return EMVExchangeEx(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv);
}
int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
@ -453,7 +453,12 @@ int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, si
}
int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) {
PrintAndLog(">>> trying to reissue command withouth Le...");
res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
}
return res;
}
int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
@ -461,7 +466,12 @@ int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen,
}
int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) {
PrintAndLog(">>> trying to reissue command withouth Le...");
res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
}
return res;
}
int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {

View file

@ -219,7 +219,7 @@ static int test_pk(bool verbose)
tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %d len %d\n", tmp_len, sizeof(pk_N));
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zd len %zd\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close_pub;
}
@ -256,7 +256,7 @@ static int test_pk(bool verbose)
tmp = crypto_pk_get_parameter(privk, 0, &tmp_len);
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) {
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %d len %d\n", tmp_len, sizeof(pk_N));
fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zd len %zd\n", tmp_len, sizeof(pk_N));
free(tmp);
goto close;
}

View file

@ -20,14 +20,7 @@
#include "elf.h"
#include "proxendian.h"
#include "usb_cmd.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;
#include "comms.h"
#define FLASH_START 0x100000
#define FLASH_SIZE (256*1024)
@ -44,9 +37,10 @@ static const uint8_t elf_ident[] = {
EV_CURRENT
};
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
// unaligned segments if needed
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs)
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint16_t num_phdrs)
{
Elf32_Phdr *phdr = phdrs;
flash_seg_t *seg;
@ -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
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl)
int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl)
{
FILE *fd = NULL;
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs = NULL;
int num_phdrs;
uint16_t num_phdrs;
int res;
fd = fopen(name, "rb");
@ -276,11 +270,11 @@ fail:
// Get the state of the proxmark, backwards compatible
static int get_proxmark_state(uint32_t *state)
{
UsbCommand c;
UsbCommand c = {0};
c.cmd = CMD_DEVICE_INFO;
SendCommand(&c);
UsbCommand resp;
ReceiveCommand(&resp);
WaitForResponse(CMD_UNKNOWN, &resp); // wait for any response. No timeout.
// Three outcomes:
// 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
@ -338,17 +332,18 @@ static int enter_bootloader(char *serial_port_name)
SendCommand(&c);
fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n");
}
msleep(100);
CloseProxmark();
fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name);
do {
sleep(1);
fprintf(stderr, ".");
} while (!OpenProxmark(0));
bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes
if (opened) {
fprintf(stderr," Found.\n");
return 0;
} else {
fprintf(stderr,"Error: Proxmark not found.\n");
return -1;
}
}
fprintf(stderr, "Error: Unknown Proxmark mode\n");
@ -358,7 +353,7 @@ static int enter_bootloader(char *serial_port_name)
static int wait_for_ack(void)
{
UsbCommand ack;
ReceiveCommand(&ack);
WaitForResponse(CMD_UNKNOWN, &ack);
if (ack.cmd != CMD_ACK) {
printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd);
return -1;

View file

@ -10,7 +10,7 @@
#define __FLASH_H__
#include <stdint.h>
#include "elf.h"
#include <stdbool.h>
typedef struct {
void *data;
@ -25,11 +25,10 @@ typedef struct {
flash_seg_t *segments;
} flash_file_t;
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl);
int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl);
int flash_start_flashing(int enable_bl_writes, char *serial_port_name);
int flash_write(flash_file_t *ctx);
void flash_free(flash_file_t *ctx);
int flash_stop_flashing(void);
#endif

View file

@ -10,21 +10,14 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <pthread.h>
#include "proxmark3.h"
#include "util.h"
#include "util_posix.h"
#include "flash.h"
#include "uart.h"
#include "comms.h"
#include "usb_cmd.h"
#ifdef _WIN32
# define unlink(x)
#else
# include <unistd.h>
#endif
static serial_port sp;
static char* serial_port_name;
void cmd_debug(UsbCommand* UC) {
// Debug
@ -40,62 +33,24 @@ void cmd_debug(UsbCommand* UC) {
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)
{
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");
//Is the example below really true? /Martin
fprintf(stderr, "Example:\n\n\t %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0);
fprintf(stderr, "\nExample (Linux):\n\n\t %s /dev/ttyACM0 armsrc/obj/fullimage.elf\n", argv0);
fprintf(stderr, "\nNote (Linux): if the flasher gets stuck in 'Waiting for Proxmark to reappear on <DEVICE>',\n");
fprintf(stderr, " you need to blacklist proxmark for modem-manager - see wiki for more details:\n");
fprintf(stderr, " http://code.google.com/p/proxmark3/wiki/Linux\n\n");
fprintf(stderr, "\nExample:\n\n\t %s "SERIAL_PORT_H" armsrc/obj/fullimage.elf\n", argv0);
#ifdef __linux__
fprintf(stderr, "\nNote (Linux): if the flasher gets stuck at 'Waiting for Proxmark to reappear',\n");
fprintf(stderr, " you may need to blacklist proxmark for modem-manager. v1.4.14 and later\n");
fprintf(stderr, " include this configuration patch already. The change can be found at:\n");
fprintf(stderr, " https://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=6e7ff47\n\n");
#endif
}
#define MAX_FILES 4
int main(int argc, char **argv)
{
int can_write_bl = 0;
int can_write_bl = false;
int num_files = 0;
int res;
flash_file_t files[MAX_FILES];
@ -110,7 +65,7 @@ int main(int argc, char **argv)
for (int i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
if (!strcmp(argv[i], "-b")) {
can_write_bl = 1;
can_write_bl = true;
} else {
usage(argv[0]);
return -1;
@ -126,14 +81,14 @@ 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);
do {
msleep(1000);
fprintf(stderr, ".");
} while (!OpenProxmark(0));
if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes
fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
return -1;
} else {
fprintf(stderr," Found.\n");
}
res = flash_start_flashing(can_write_bl, serial_port_name);
if (res < 0)
@ -155,6 +110,7 @@ int main(int argc, char **argv)
if (res < 0)
return -1;
// Stop the command thread.
CloseProxmark();
fprintf(stderr, "All done.\n\n");

View file

@ -1,4 +1,6 @@
//-----------------------------------------------------------------------------
// piwi, 2017, 2018
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
@ -11,9 +13,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "fpga.h"
#include "zlib.h"
#define MAX(a,b) ((a)>(b)?(a):(b))
@ -37,18 +41,18 @@
#define COMPRESS_MAX_NICE_LENGTH 258
#define COMPRESS_MAX_CHAIN 8192
#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
#define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
#define HARDNESTED_TABLE_SIZE (sizeof(uint32_t) * ((1L<<19)+1))
static void usage(void)
{
fprintf(stdout, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
fprintf(stdout, " Combine n FPGA bitstream files and compress them into one.\n\n");
fprintf(stdout, " fpga_compress -d <infile> <outfile>");
fprintf(stdout, " Decompress <infile>. Write result to <outfile>");
fprintf(stdout, " fpga_compress -t <infile> <outfile>");
fprintf(stdout, " Compress hardnested table <infile>. Write result to <outfile>");
fprintf(stdout, " fpga_compress -v <infile1> <infile2> ... <infile_n> <outfile>\n");
fprintf(stdout, " Extract Version Information from FPGA bitstream files and write it to <outfile>\n\n");
fprintf(stdout, " fpga_compress -d <infile> <outfile>\n");
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)
{
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 k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
c = fgetc(infile[j]);
c = (uint8_t)fgetc(infile[j]);
if (!feof(infile[j])) {
fpga_config[i++] = c;
} else if (num_infiles > 1) {
@ -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)
{
FILE **infiles;
char **infile_names;
FILE *outfile;
if (argc == 1 || argc == 2) {
@ -271,43 +428,56 @@ int main(int argc, char **argv)
}
infiles[0] = fopen(argv[2], "rb");
if (infiles[0] == NULL) {
fprintf(stderr, "Error. Cannot open input file %s", argv[2]);
fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]);
return(EXIT_FAILURE);
}
outfile = fopen(argv[3], "wb");
if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s", argv[3]);
fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[3]);
return(EXIT_FAILURE);
}
return zlib_decompress(infiles[0], outfile);
} else { // Compress
} else { // Compress or gemerate version info
bool hardnested_mode = false;
bool generate_version_file = false;
int num_input_files = 0;
if (!strcmp(argv[1], "-t")) { // hardnested table
if (!strcmp(argv[1], "-t")) { // compress one hardnested table
if (argc != 4) {
usage();
return(EXIT_FAILURE);
}
hardnested_mode = true;
num_input_files = 1;
} else {
} else if (!strcmp(argv[1], "-v")) { // generate version info
generate_version_file = true;
num_input_files = argc-3;
} else { // compress 1..n fpga files
num_input_files = argc-2;
}
infiles = calloc(num_input_files, sizeof(FILE*));
infile_names = calloc(num_input_files, sizeof(char*));
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) {
fprintf(stderr, "Error. Cannot open input file %s", argv[i+hardnested_mode?2:1]);
fprintf(stderr, "Error. Cannot open input file %s\n\n", infile_names[i]);
return(EXIT_FAILURE);
}
}
outfile = fopen(argv[argc-1], "wb");
if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[argc-1]);
return(EXIT_FAILURE);
}
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);
}
}
}

View file

@ -548,44 +548,105 @@ out:
crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch;
bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch;
// determine the available instruction set at runtime and call the correct function
const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) {
static SIMDExecInstr intSIMDInstr = SIMD_AUTO;
void SetSIMDInstr(SIMDExecInstr instr) {
intSIMDInstr = instr;
crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch;
bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch;
}
SIMDExecInstr GetSIMDInstr() {
SIMDExecInstr instr = SIMD_NONE;
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
if (__builtin_cpu_supports("avx512f")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512;
else if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512;
else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
#else
if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
#endif
else if (__builtin_cpu_supports("avx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX;
else if (__builtin_cpu_supports("sse2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2;
else if (__builtin_cpu_supports("mmx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX;
else if (__builtin_cpu_supports("avx")) instr = SIMD_AVX;
else if (__builtin_cpu_supports("sse2")) instr = SIMD_SSE2;
else if (__builtin_cpu_supports("mmx")) instr = SIMD_MMX;
else
#endif
#endif
instr = SIMD_NONE;
return instr;
}
SIMDExecInstr GetSIMDInstrAuto() {
SIMDExecInstr instr = intSIMDInstr;
if (instr == SIMD_AUTO)
return GetSIMDInstr();
return instr;
}
// 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;
break;
}
// call the most optimized function for this CPU
return (*crack_states_bitsliced_function_p)(cuid, best_first_bytes, p, keys_found, num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, nonces);
}
void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) {
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)
if (__builtin_cpu_supports("avx512f")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
else if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
#else
if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
case SIMD_AVX512:
bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
break;
#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
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;
break;
}
// call the most optimized function for this CPU
(*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par);

View file

@ -52,6 +52,18 @@ THE SOFTWARE.
#include "hardnested_bruteforce.h" // statelist_t
typedef enum {
SIMD_AUTO,
SIMD_AVX512,
SIMD_AVX2,
SIMD_AVX,
SIMD_SSE2,
SIMD_MMX,
SIMD_NONE,
} SIMDExecInstr;
extern void SetSIMDInstr(SIMDExecInstr instr);
extern SIMDExecInstr GetSIMDInstrAuto();
extern const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces);
extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par);

View file

@ -139,8 +139,13 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u
return true;
}
static void* crack_states_thread(void* x){
static void*
#ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer)
__attribute__((force_align_arg_pointer))
#endif
#endif
crack_states_thread(void* x){
struct arg {
bool silent;

View file

@ -31,7 +31,6 @@ usb_dev_handle *devh = NULL;
static unsigned int claimed_iface = 0;
unsigned char return_on_error = 0;
unsigned char error_occured = 0;
extern unsigned int current_command;
void SendCommand(UsbCommand *c)
{
@ -40,7 +39,6 @@ void SendCommand(UsbCommand *c)
#if 0
printf("Sending %d bytes\n", sizeof(UsbCommand));
#endif
current_command = c->cmd;
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
if (ret<0) {
error_occured = 1;

View file

@ -2,7 +2,7 @@
This is a library to read 14443a tags. It can be used something like this
local reader = require('read14a')
result, err = reader.read1443a()
result, err = reader.read14443a()
if not result then
print(err)
return
@ -43,11 +43,11 @@ ISO14443a_TYPES[0x88] = "Infineon MIFARE CLASSIC 1K"
ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
local function tostring_1443a(sak)
local function tostring_14443a(sak)
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
end
local function parse1443a(data)
local function parse14443a(data)
--[[
Based on this struct :
@ -66,8 +66,8 @@ local function parse1443a(data)
local count,uid,uidlen, atqa, sak, ats_len, ats= bin.unpack('H10CH2CC',data)
uid = uid:sub(1,2*uidlen)
--print("uid, atqa, sak: ",uid, atqa, sak)
--print("TYPE: ", tostring_1443a(sak))
return { uid = uid, atqa = atqa, sak = sak, name = tostring_1443a(sak)}
--print("TYPE: ", tostring_14443a(sak))
return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak)}
end
--- Sends a USBpacket to the device
@ -114,7 +114,7 @@ local function read14443a(dont_disconnect, no_rats)
return nil, "iso14443a card select failed"
end
data = string.sub(result,count)
info, err = parse1443a(data)
info, err = parse14443a(data)
else
err ="No response from card"
end
@ -139,12 +139,12 @@ local function waitFor14443a()
end
return nil, "Aborted by user"
end
local library = {
read1443a = read14443a,
local library = {
read14443a = read14443a,
read = read14443a,
waitFor14443a = waitFor14443a,
parse1443a = parse1443a,
parse14443a = parse14443a,
sendToDevice = sendToDevice,
ISO14A_COMMAND = ISO14A_COMMAND,
}

View file

@ -16,10 +16,11 @@
#include <pthread.h>
#include "crapto1/crapto1.h"
#include "proxmark3.h"
#include "comms.h"
#include "usb_cmd.h"
#include "cmdmain.h"
#include "ui.h"
#include "parity.h"
#include "util.h"
#include "iso14443crc.h"
@ -73,13 +74,12 @@ static uint32_t intersection(uint64_t *list1, uint64_t *list2)
// Darkside attack (hf mf mifare)
static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
struct Crypto1State *states;
uint32_t i, pos, rr; //nr_diff;
uint32_t i, pos;
uint8_t bt, ks3x[8], par[8][8];
uint64_t key_recovered;
static uint64_t *keylist;
rr = 0;
uint64_t *keylist;
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
@ -92,7 +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) {
*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)
{
uint32_t uid = 0;
uint32_t nt = 0, nr = 0;
uint32_t nt = 0, nr = 0, ar = 0;
uint64_t par_list = 0, ks_list = 0;
uint64_t *keylist = NULL, *last_keylist = NULL;
uint32_t keycount = 0;
@ -159,18 +159,18 @@ int mfDarkside(uint64_t *key)
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
nr = bytes_to_num(resp.d.asBytes + 24, 4);
nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4);
ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4);
break;
}
}
if (par_list == 0 && c.arg[0] == true) {
PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication.");
PrintAndLog("Attack will take a few seconds longer because we need two consecutive successful runs.");
}
c.arg[0] = false;
keycount = nonce2key(uid, nt, nr, par_list, ks_list, &keylist);
keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist);
if (keycount == 0) {
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
@ -178,6 +178,7 @@ int mfDarkside(uint64_t *key)
continue;
}
if (par_list == 0) {
qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
keycount = intersection(last_keylist, keylist);
if (keycount == 0) {
@ -185,6 +186,7 @@ int mfDarkside(uint64_t *key)
last_keylist = keylist;
continue;
}
}
if (keycount > 1) {
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) {
int size = keycount - i > max_keys ? max_keys : keycount - i;
for (int j = 0; j < size; j++) {
if (last_keylist == NULL) {
num_to_bytes(keylist[i*max_keys + j], 6, keyBlock);
if (par_list == 0) {
num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock+(j*6));
} 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)) {
@ -295,7 +297,13 @@ typedef
// wrapper function for multi-threaded lfsr_recovery32
void* nested_worker_thread(void *arg)
void
#ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer)
__attribute__((force_align_arg_pointer))
#endif
#endif
*nested_worker_thread(void *arg)
{
struct Crypto1State *p1;
StateList_t *statelist = arg;
@ -309,6 +317,7 @@ void* nested_worker_thread(void *arg)
return statelist->head.slhead;
}
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate)
{
uint16_t i;
@ -319,7 +328,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
struct Crypto1State *p1, *p2, *p3, *p4;
// flush queue
WaitForResponseTimeout(CMD_ACK, NULL, 100);
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
memcpy(c.d.asBytes, key, 6);
@ -574,14 +583,19 @@ struct Crypto1State *traceCrypto1 = NULL;
struct Crypto1State *revstate;
uint64_t lfsr;
uint64_t ui64Key;
uint32_t ks2;
uint32_t ks3;
uint32_t uid; // serial number
uint32_t nt; // tag challenge
uint32_t nt_enc; // encrypted tag challenge
uint8_t nt_enc_par; // encrypted tag challenge parity
uint32_t nr_enc; // encrypted reader challenge
uint32_t ar_enc; // encrypted reader response
uint8_t ar_enc_par; // encrypted reader response parity
uint32_t at_enc; // encrypted tag response
uint8_t at_enc_par; // encrypted tag response parity
int isTraceCardEmpty(void) {
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));
@ -609,6 +623,7 @@ int saveTraceCard(void) {
for (int i = 0; i < 64; i++) { // blocks
for (int j = 0; j < 16; j++) // bytes
fprintf(f, "%02x", *(traceCard + i * 16 + j));
if (i < 63)
fprintf(f,"\n");
}
fclose(f);
@ -699,8 +714,36 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i
return;
}
bool NTParityCheck(uint32_t ntx) {
if (
(oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((nt_enc_par >> 5) & 0x01) ^ (nt_enc & 0x01)) ||
(oddparity8(ntx >> 16 & 0xff) ^ (ntx >> 8 & 0x01) ^ ((nt_enc_par >> 6) & 0x01) ^ (nt_enc >> 8 & 0x01)) ||
(oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((nt_enc_par >> 7) & 0x01) ^ (nt_enc >> 16 & 0x01))
)
return false;
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];
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);
if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {
mf_crypto1_decrypt(traceCrypto1, data, len, 0);
PrintAndLog("dec> %s", sprint_hex(data, len));
uint8_t parity[16];
oddparitybuf(data, len, parity);
PrintAndLog("dec> %s [%s]", sprint_hex(data, len), printBitsPar(parity, len));
AddLogHex(logHexFileName, "dec> ", data, len);
}
@ -801,7 +846,12 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
case TRACE_AUTH1:
if (len == 4) {
traceState = TRACE_AUTH2;
if (!traceCrypto1) {
nt = bytes_to_num(data, 4);
} else {
nt_enc = bytes_to_num(data, 4);
nt_enc_par = parity;
}
return 0;
} else {
traceState = TRACE_ERROR;
@ -815,6 +865,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
nr_enc = bytes_to_num(data, 4);
ar_enc = bytes_to_num(data + 4, 4);
ar_enc_par = parity << 4;
return 0;
} else {
traceState = TRACE_ERROR;
@ -827,6 +878,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
traceState = TRACE_IDLE;
at_enc = bytes_to_num(data, 4);
at_enc_par = parity;
if (!traceCrypto1) {
// decode key here)
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);
crypto1_get_lfsr(revstate, &lfsr);
printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF));
crypto1_destroy(revstate);
ui64Key = lfsr;
printf("key> probable key:%x%x Prng:%s ks2:%08x ks3:%08x\n",
(unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF),
validate_prng_nonce(nt) ? "WEAK": "HARDEND",
ks2,
ks3);
AddLogUint64(logHexFileName, "key> ", lfsr);
} else {
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;
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
traceCrypto1 = lfsr_recovery64(ks2, ks3);
// nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt;
/* traceCrypto1 = crypto1_create(lfsr); // key in lfsr
crypto1_word(traceCrypto1, nt ^ uid, 0);
crypto1_word(traceCrypto1, ar, 1);
crypto1_word(traceCrypto1, 0, 0);
crypto1_word(traceCrypto1, 0, 0);*/
return 0;
} else {
traceState = TRACE_ERROR;

View file

@ -13,7 +13,8 @@
#include <stdint.h>
#include <stdbool.h>
#include "data.h"
#include "crapto1/crapto1.h"
#include "util.h"
// defaults
// 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 mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile);
extern int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile);
extern int mfTraceDecode(uint8_t *data_src, int len, uint8_t parity, bool wantSaveToEmlFile);
extern int isTraceCardEmpty(void);
extern int isBlockEmpty(int blockN);
@ -61,5 +62,7 @@ extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t
extern int mfCIdentify();
extern int DetectClassicPrng(void);
extern bool validate_prng_nonce(uint32_t nonce);
extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted);
#endif

Some files were not shown because too many files have changed in this diff Show more