mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
initial commit to be in sync the-soon-defunct repo pm3rdv40.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- inside proxmark3 client run the following commands and paste the output here.
|
||||
- hw version
|
||||
- hw status
|
||||
- data tune
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# Travis-CI Build for IcemanFork/Proxmark3
|
||||
# Travis-CI Build for RfidResearchGroup/Proxmark3
|
||||
language: c
|
||||
|
||||
#default linux build env is: Ubuntu 14.04 trusty
|
||||
@@ -28,7 +28,7 @@ before_install:
|
||||
sudo apt-get install -y gcc-arm-none-eabi;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update;
|
||||
brew tap iceman1001/proxmark3;
|
||||
brew tap RfidResearchGroup/proxmark3;
|
||||
fi
|
||||
|
||||
install:
|
||||
|
||||
+10
-1
@@ -2,7 +2,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
## [unreleased][unreleased]
|
||||
- Fix 'hf legic' enhancement of rx / tx in legic commands (@drandreas)
|
||||
- Fix 'data buffclear' - now frees bigbuff also (@iceman)
|
||||
- Fix GET_TICKS and signess while shifting (@drandreas)
|
||||
- Added 'hf 14b dump' - now dumps to file (bin & eml) (@iceman)
|
||||
- Fix fixed xcorrelation for strong signal (@drandreas)
|
||||
- Fix 'hf mf chk' - keytype was reversed (@TomHarkness)
|
||||
- Added strange vid/pid found in wild. Could be pm3 easy clones. (@iceman)
|
||||
- Fix 'make udev' - udev filename could be in conflict, renamed. (@blshkv)
|
||||
- Fix 'lf t55xx config' - wrong sized array disabled FSK1a/FSK2a as options (@grauerfuchs)
|
||||
- Added more default keys (@j8048188) (@iceman)
|
||||
- Added 'sc list/info/raw/reader/upgrade' - (RDV40) smart card module functionality (@iceman)
|
||||
- Fix 'download eml buffer' (@drandreas)
|
||||
|
||||
@@ -30,64 +30,6 @@ Links
|
||||
https://github.com/Gator96100/ProxSpace/archive/master.zip
|
||||
|
||||
|
||||
-- OR --
|
||||
|
||||
Use the following list of packages required to setup the compile environment yourself.
|
||||
|
||||
1 - Install QT SDK for Windows [1]
|
||||
|
||||
In the following instructions, we'll assume you installed it to C:\QT
|
||||
|
||||
2 - MSYS-1.0.11 [2]
|
||||
|
||||
Just follow the installation procedure.
|
||||
When asked if you have MinGW installed and for its path, provide:
|
||||
C:/QT/mingw
|
||||
|
||||
3 - readline-5.0-1-bin [5]
|
||||
|
||||
From this archive, copy:
|
||||
bin/* to C:\QT\mingw\bin
|
||||
include/* to C:\QT\mingw\include
|
||||
lib/*.a to C:\QT\mingw\lib
|
||||
|
||||
4 - libusb-win32-device-bin-0.1.12.2 [6]
|
||||
|
||||
Be careful here, it is *NOT* working with the filter version!
|
||||
Likewise copy:
|
||||
include/usb.h to C:\QT\mingw\include
|
||||
lib/gcc/libusb.a to C:\QT\mingw\lib
|
||||
|
||||
|
||||
5 - Install DevkitPro [5]
|
||||
|
||||
You'll need it to compile the firmware (ARM) side.
|
||||
You only need devkitARM, nothing more (no extra lib or anything else)
|
||||
Assuming you installed it to C:\devkitpro, make sure you set
|
||||
the DEVKITARM environment variable to /c/devkitPro/devkitARM :
|
||||
export DEVKITARM=/c/devkitPro/devkitARM
|
||||
Also, add its bin to your PATH:
|
||||
export PATH=$PATH:$DEVKITARM/bin
|
||||
|
||||
6 - Install Strawberry Perl [6]
|
||||
|
||||
7 - Setup a few variables
|
||||
|
||||
In your shell from MSYS, make sure you set QTDIR to your QT installation:
|
||||
export QTDIR=/c/QT/qt
|
||||
And add its bin to your path as well:
|
||||
export PATH=$PATH:$QTDIR/bin
|
||||
|
||||
Download links:
|
||||
|
||||
[1] http://qt.nokia.com/downloads/sdk-windows-cpp
|
||||
[2] http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe
|
||||
[3] http://sourceforge.net/projects/gnuwin32/files/readline/5.0-1/readline-5.0-1-bin.zip/download
|
||||
[4] http://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/0.1.12.2/libusb-win32-device-bin-0.1.12.2.tar.gz/download
|
||||
[5] http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitProUpdater-1.5.0.exe/download
|
||||
[6] http://strawberry-perl.googlecode.com/files/strawberry-perl-5.10.1.1.msi
|
||||
|
||||
|
||||
============
|
||||
= Mac OS X =
|
||||
============
|
||||
|
||||
@@ -77,7 +77,7 @@ tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin
|
||||
# you may need to logout, relogin to get this access right correct.
|
||||
# Finally, you might need to run the proxmark3 client under SUDO on some systems
|
||||
udev:
|
||||
sudo cp -rf driver/77-mm-usb-device-blacklist.rules /etc/udev/rules.d/77-mm-usb-device-blacklist.rules
|
||||
sudo cp -rf driver/77-pm3-usb-device-blacklist.rules /etc/udev/rules.d/77-pm3-usb-device-blacklist.rules
|
||||
sudo udevadm control --reload-rules
|
||||
ifneq ($(wildcard /etc/arch-release),) #If user is running ArchLinux
|
||||
sudo usermod -aG uucp $(USER) #Use specific command and group
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
Iceman fork
|
||||
===============
|
||||
[](https://travis-ci.org/iceman1001/proxmark3)[](https://scan.coverity.com/project/proxmark3_iceman_fork)[](https://github.com/iceman1001/proxmark3/releases/latest)
|
||||
[](https://github.com/RfidResearchGroup/proxmark3/releases/latest)
|
||||
|
||||
## This fork is HIGHLY experimental and bleeding edge
|
||||
|
||||
|
||||
The kickstarter for the latest revision of proxmark is out.
|
||||
[proxmark3 rdv4.0](https://www.kickstarter.com/projects/1408815241/proxmark3-rdv-40)
|
||||
|
||||
That one is a beauty!
|
||||
|
||||
|
||||
|
||||
|
||||
## Nothing says thank you as much as a donation
|
||||
https://paypal.me/iceman1001/ Feel free to donate. All support is welcome.
|
||||
|
||||
monereo: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP
|
||||
## Proxmark3 RDV40 dedicated
|
||||
|
||||
## Notice
|
||||
There is so much in this fork, with all fixes and additions its basically the most enhanced fork to this day for the Proxmark3 device. Which makes it so awesum to play with. Do please play with it. Get excited and experiment. As a side note with all coverity scan fixes this client is much more stable than PM3 Master even if I tend to break it sometimes. I'll try to make a release when this fork becomes stable between my experiments.
|
||||
This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device.
|
||||
|
||||
## Coverity Scan Config & Run
|
||||
Download the Coverity Scan Self-buld and install it.
|
||||
@@ -41,40 +27,20 @@ You will need to configure ARM-NON-EABI- Compiler for it to use:
|
||||
|
||||
|
||||
## Whats changed?
|
||||
Whats so special with this fork? I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch.
|
||||
Among the stuff is
|
||||
|
||||
* Jonor's hf 14a raw timing patch
|
||||
* Piwi's updates. (usually gets into the master)
|
||||
* Piwi's "topaz" branch
|
||||
* Piwi's "hardnested" branch
|
||||
* Holiman's iclass, (usually gets into the master)
|
||||
* Marshmellow's fixes (usually gets into the master)
|
||||
* Midnitesnake's Ultralight, Ultralight-c enhancements
|
||||
* Izsh's lf peak modification / iir-filtering
|
||||
* Aspers's tips and tricks from inside the PM3-gui-tool, settings.xml and other stuff.
|
||||
* My own desfire, Ultralight extras, LF T55xx enhancements, bugs fixes (filelength, hf mf commands ), TNP3xxx lua scripts, Awid26, skidata scripts (will come)
|
||||
* other obscure patches like for the sammy-mode, (offline you know), tagidentifications, defaultkeys.
|
||||
* Minor textual changes here and there.
|
||||
* Simulation of Ultralight/Ntag.
|
||||
* Marshmellow's and my "RevEng" addon for the client. Ref: http://reveng.sourceforge.net/ Now using reveng1.44
|
||||
* J-Run alternative bruteforce Mifare nested auths.. (you need one other exe to make it work)
|
||||
* A Bruteforce for T55XX passwords against tag.
|
||||
* A Bruteforce for AWID 26, starting w a facilitycode then trying all 0xFFFF cardnumbers via simulation. To be used against a AWID Reader.
|
||||
* A Bruteforce for HID, starting w a facilitycode then trying all 0xFFFF cardnumbers via simulation. To be used against a HID Reader.
|
||||
* Blaposts Crapto1 v3.3
|
||||
* Icsom's legic script and legic enhancements
|
||||
* Aczid's bitsliced bruteforce solver in 'hf mf hardnested'
|
||||
* added flash memory 256kb.
|
||||
* added smart card module
|
||||
* added FPC connector
|
||||
|
||||
---
|
||||
## Why don't you merged with offical PM3 Master?
|
||||
Me fiddling with the code so much, there is a nightmare in merging a PR. I will never find time to do PR because of it. Much of what you find here is not in the interest for offical PM3. However and luckily I have @marshmellow42 who takes some stuff and push PR's back. The separation from offical pm3 repo gives me very much freedom to create a firmware/client in the way I want to use the PM3.
|
||||
## Why didn't you based it on offical PM3 Master?
|
||||
The separation from offical pm3 repo gives us very much freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the offical pm3 repo with RDV40 specific code.
|
||||
|
||||
## Why don't you add this or that functionality?
|
||||
Give me a hint, and I'll see if I can't merge in the stuff you have.
|
||||
Give us a hint, and we'll see if we can't merge in the stuff you have.
|
||||
|
||||
## PM3 GUI
|
||||
I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*
|
||||
The official PM3-GUI from Gaucho will not work.
|
||||
The new universial GUI will work.
|
||||
|
||||
## Development
|
||||
This fork now compiles just fine on
|
||||
@@ -90,13 +56,13 @@ See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux
|
||||
A nice and cool install script made by @daveio is found here:
|
||||
https://github.com/daveio/attacksurface/blob/master/proxmark3/pm3-setup.sh
|
||||
I have also added this script to the fork.
|
||||
https://github.com/iceman1001/proxmark3/blob/master/install.sh
|
||||
https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
|
||||
|
||||
- Run
|
||||
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi`
|
||||
|
||||
- Clone iceman fork
|
||||
`git clone https://github.com/iceman1001/proxmark3.git`
|
||||
- Clone fork
|
||||
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
|
||||
|
||||
- Get the latest commits
|
||||
`git pull`
|
||||
@@ -121,8 +87,8 @@ https://github.com/iceman1001/proxmark3/blob/master/install.sh
|
||||
`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed`
|
||||
`yaourt -S termcap`
|
||||
|
||||
- Clone iceman fork
|
||||
`git clone https://github.com/iceman1001/proxmark3.git`
|
||||
- Clone fork
|
||||
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
|
||||
|
||||
- Get the latest commits
|
||||
`git pull`
|
||||
@@ -148,7 +114,7 @@ Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/c
|
||||
|
||||
1. Install homebrew if you haven't yet already done so: http://brew.sh/
|
||||
|
||||
2. Tap this repo: `brew tap iceman1001/proxmark3`
|
||||
2. Tap this repo: `brew tap RfidResearchGroup/proxmark3`
|
||||
|
||||
3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub.
|
||||
|
||||
@@ -161,7 +127,7 @@ Tested on macOS High Sierra 10.13.2
|
||||
*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above*
|
||||
|
||||
1. Force HomeBrew to pull the latest source from github
|
||||
`brew upgrade --fetch-HEAD iceman1001/proxmark3/proxmark3`
|
||||
`brew upgrade --fetch-HEAD RfidResearchGroup/proxmark3`
|
||||
|
||||
2. Flash the bootloader & fullimage.elf
|
||||
* With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. Continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"*
|
||||
@@ -172,16 +138,6 @@ Tested on macOS High Sierra 10.13.2
|
||||
|
||||
4. Enjoy the update
|
||||
|
||||
## Docker container
|
||||
I recently added a docker container on Docker HUB. You find it here: https://hub.docker.com/r/iceman1001/proxmark3/
|
||||
Follow those instructions to get it up and running. No need for the old proxspace-environment anymore.
|
||||
|
||||
-[1.6.0] How to start: https://www.youtube.com/watch?v=b5Zta89Cf6Q
|
||||
-[1.6.0] How to connect: https://youtu.be/0ZS2t5C-caI
|
||||
-[1.6.1] How to flash: https://www.youtube.com/watch?v=WXouhuGYEiw
|
||||
|
||||
Recommendations: Use only latest container.
|
||||
|
||||
|
||||
## Building on Windows
|
||||
|
||||
@@ -196,13 +152,12 @@ Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxS
|
||||
Links
|
||||
- https://github.com/Gator96100/ProxSpace/archive/master.zip
|
||||
- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0)
|
||||
- https://github.com/Gator96100/ProxSpace/releases/tag/v2.1 (release v2.1 with gcc v5.3.0)
|
||||
|
||||
|
||||
### 7. Build and run
|
||||
|
||||
- Clone iceman fork
|
||||
`git clone https://github.com/iceman1001/proxmark3.git`
|
||||
- Clone fork
|
||||
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
|
||||
|
||||
- Get the latest commits
|
||||
`git pull`
|
||||
@@ -222,4 +177,4 @@ Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark s
|
||||
`proxmark3.exe comX`
|
||||
|
||||
iceman at host iuse.se
|
||||
January 2015, Sweden
|
||||
July 2018, Sweden
|
||||
|
||||
@@ -1070,6 +1070,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
||||
#endif
|
||||
case CMD_BUFF_CLEAR:
|
||||
BigBuf_Clear();
|
||||
BigBuf_free();
|
||||
break;
|
||||
|
||||
case CMD_MEASURE_ANTENNA_TUNING:
|
||||
|
||||
+5
-9
@@ -320,7 +320,6 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
|
||||
|
||||
static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
||||
|
||||
volatile uint16_t b;
|
||||
uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
|
||||
|
||||
if ( power )
|
||||
@@ -340,25 +339,23 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing
|
||||
// sending 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
uint16_t c = 0;
|
||||
while (c < 6) {
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
c++;
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b;
|
||||
}
|
||||
}
|
||||
// sending sync code
|
||||
|
||||
// sending data
|
||||
c = 0;
|
||||
while (c < len) {
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = frame[c++];
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
@@ -436,7 +433,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||
// Set up FeliCa communication (similar to iso14443a_setup)
|
||||
// field is setup for "Sending as Reader"
|
||||
static void felica_setup(uint8_t fpga_minor_mode) {
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_setup Enter");
|
||||
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
@@ -471,7 +468,6 @@ static void felica_setup(uint8_t fpga_minor_mode) {
|
||||
StartCountSspClk();
|
||||
|
||||
LED_D_ON();
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_setup Exit");
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// RAW FeliCa commands. Send out commands and store answers.
|
||||
|
||||
+11
-9
@@ -29,28 +29,31 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
|
||||
BigBuf_free(); BigBuf_Clear();
|
||||
|
||||
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
|
||||
int trigger_cnt;
|
||||
int trigger_cnt = 0;
|
||||
|
||||
LED_D_ON();
|
||||
// Select correct configs
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Setting Frame Mode For better performance on high speed data transfer.
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
SpinDelay(100);
|
||||
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame Mode For better performance on high speed data transfer.
|
||||
|
||||
trigger_cnt = 0;
|
||||
uint16_t r = 0;
|
||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
r = MAX(r & 0xff, r >> 8);
|
||||
if (r >= 180) {
|
||||
if (r >= 180) { // 0xB4 ??
|
||||
if (++trigger_cnt > triggersToSkip)
|
||||
break;
|
||||
}
|
||||
@@ -75,4 +78,3 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
||||
|
||||
+45
-46
@@ -38,9 +38,9 @@ struct hitag2_tag {
|
||||
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
|
||||
} state;
|
||||
unsigned int active_sector;
|
||||
byte_t crypto_active;
|
||||
uint8_t crypto_active;
|
||||
uint64_t cs;
|
||||
byte_t sectors[12][4];
|
||||
uint8_t sectors[12][4];
|
||||
};
|
||||
|
||||
static struct hitag2_tag tag = {
|
||||
@@ -71,14 +71,14 @@ static enum {
|
||||
// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
|
||||
// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
|
||||
#define AUTH_TABLE_LENGTH 2744
|
||||
static byte_t* auth_table;
|
||||
static uint8_t* auth_table;
|
||||
static size_t auth_table_pos = 0;
|
||||
static size_t auth_table_len = AUTH_TABLE_LENGTH;
|
||||
|
||||
static byte_t password[4];
|
||||
static byte_t NrAr[8];
|
||||
static byte_t key[8];
|
||||
static byte_t writedata[4];
|
||||
static uint8_t password[4];
|
||||
static uint8_t NrAr[8];
|
||||
static uint8_t key[8];
|
||||
static uint8_t writedata[4];
|
||||
static uint64_t cipher_state;
|
||||
|
||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||
@@ -177,7 +177,7 @@ static int hitag2_init(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
|
||||
static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv)
|
||||
{
|
||||
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
|
||||
((uint64_t)tag->sectors[2][3] << 8) |
|
||||
@@ -196,9 +196,9 @@ static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
|
||||
tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_));
|
||||
}
|
||||
|
||||
static int hitag2_cipher_authenticate(uint64_t* cs, const byte_t *authenticator_is)
|
||||
static int hitag2_cipher_authenticate(uint64_t* cs, const uint8_t *authenticator_is)
|
||||
{
|
||||
byte_t authenticator_should[4];
|
||||
uint8_t authenticator_should[4];
|
||||
authenticator_should[0] = ~_hitag2_byte(cs);
|
||||
authenticator_should[1] = ~_hitag2_byte(cs);
|
||||
authenticator_should[2] = ~_hitag2_byte(cs);
|
||||
@@ -206,7 +206,7 @@ static int hitag2_cipher_authenticate(uint64_t* cs, const byte_t *authenticator_
|
||||
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
|
||||
}
|
||||
|
||||
static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int bytes, unsigned int bits)
|
||||
static int hitag2_cipher_transcrypt(uint64_t* cs, uint8_t *data, unsigned int bytes, unsigned int bits)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<bytes; i++) data[i] ^= _hitag2_byte(cs);
|
||||
@@ -271,7 +271,7 @@ static void hitag_send_bit(int bit) {
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
||||
static void hitag_send_frame(const uint8_t* frame, size_t frame_len)
|
||||
{
|
||||
// Send start of frame
|
||||
for(size_t i=0; i<5; i++) {
|
||||
@@ -288,9 +288,9 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
||||
}
|
||||
|
||||
|
||||
static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
||||
static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen)
|
||||
{
|
||||
byte_t rx_air[HITAG_FRAME_LEN];
|
||||
uint8_t rx_air[HITAG_FRAME_LEN];
|
||||
|
||||
// Copy the (original) received frame how it is send over the air
|
||||
memcpy(rx_air,rx,nbytes(rxlen));
|
||||
@@ -435,17 +435,17 @@ static void hitag_reader_send_bit(int bit) {
|
||||
|
||||
if(bit == 0) {
|
||||
// Zero bit: |_-|
|
||||
while(AT91C_BASE_TC0->TC_CV < T0*22);
|
||||
while (AT91C_BASE_TC0->TC_CV < T0*22) {};
|
||||
|
||||
} else {
|
||||
// One bit: |_--|
|
||||
while(AT91C_BASE_TC0->TC_CV < T0*28);
|
||||
while (AT91C_BASE_TC0->TC_CV < T0*28) {};
|
||||
}
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
|
||||
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||
static void hitag_reader_send_frame(const uint8_t* frame, size_t frame_len)
|
||||
{
|
||||
// Send the content of the frame
|
||||
for(size_t i=0; i<frame_len; i++) {
|
||||
@@ -463,7 +463,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||
|
||||
size_t blocknr;
|
||||
|
||||
static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||
static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) {
|
||||
// Reset the transmission frame length
|
||||
*txlen = 0;
|
||||
|
||||
@@ -518,7 +518,7 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t*
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
||||
static bool hitag2_write_page(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen)
|
||||
{
|
||||
switch (writestate) {
|
||||
case WRITE_STATE_START:
|
||||
@@ -560,22 +560,19 @@ static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen, bool write) {
|
||||
static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen, bool write) {
|
||||
// Reset the transmission frame length
|
||||
*txlen = 0;
|
||||
|
||||
if(bCrypto) {
|
||||
hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8);
|
||||
|
||||
}
|
||||
|
||||
if (bCrypto && !bAuthenticating && write) {
|
||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
// Try to find out which command was send by selecting on length (in bits)
|
||||
switch (rxlen) {
|
||||
@@ -670,7 +667,7 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
|
||||
}
|
||||
|
||||
|
||||
static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||
static bool hitag2_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) {
|
||||
// Reset the transmission frame length
|
||||
*txlen = 0;
|
||||
|
||||
@@ -710,7 +707,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size
|
||||
}
|
||||
|
||||
|
||||
static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||
static bool hitag2_test_auth_attempts(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) {
|
||||
|
||||
// Reset the transmission frame length
|
||||
*txlen = 0;
|
||||
@@ -766,7 +763,7 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||
static bool hitag2_read_uid(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) {
|
||||
// Reset the transmission frame length
|
||||
*txlen = 0;
|
||||
|
||||
@@ -812,7 +809,7 @@ void SnoopHitag(uint32_t type) {
|
||||
int lastbit;
|
||||
bool bSkip;
|
||||
int tag_sof;
|
||||
byte_t rx[HITAG_FRAME_LEN];
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen=0;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
@@ -827,7 +824,7 @@ void SnoopHitag(uint32_t type) {
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
|
||||
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
DbpString("Starting Hitag2 snoop");
|
||||
@@ -1020,13 +1017,13 @@ void SnoopHitag(uint32_t type) {
|
||||
// DbpString("All done");
|
||||
}
|
||||
|
||||
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||
void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) {
|
||||
int frame_count;
|
||||
int response;
|
||||
int overflow;
|
||||
byte_t rx[HITAG_FRAME_LEN];
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen=0;
|
||||
byte_t tx[HITAG_FRAME_LEN];
|
||||
uint8_t tx[HITAG_FRAME_LEN];
|
||||
size_t txlen=0;
|
||||
bool bQuitTraceFull = false;
|
||||
bQuiet = false;
|
||||
@@ -1042,9 +1039,9 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
byte_t* auth_table;
|
||||
uint8_t* auth_table;
|
||||
|
||||
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
DbpString("Starting Hitag2 simulation");
|
||||
@@ -1053,7 +1050,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||
|
||||
if (tag_mem_supplied) {
|
||||
DbpString("Loading hitag2 memory...");
|
||||
memcpy((byte_t*)tag.sectors,data,48);
|
||||
memcpy((uint8_t*)tag.sectors,data,48);
|
||||
}
|
||||
|
||||
uint32_t block = 0;
|
||||
@@ -1213,10 +1210,10 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||
void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||
int frame_count = 0;
|
||||
int response = 0;
|
||||
byte_t rx[HITAG_FRAME_LEN];
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
byte_t txbuf[HITAG_FRAME_LEN];
|
||||
byte_t* tx = txbuf;
|
||||
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||
uint8_t* tx = txbuf;
|
||||
size_t txlen = 0;
|
||||
int lastbit = 1;
|
||||
bool bSkip;
|
||||
@@ -1349,6 +1346,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||
} else {
|
||||
Dbprintf("Error, unknown hitag reader type: %d",htf);
|
||||
set_tracing(false);
|
||||
LED_D_OFF();
|
||||
return;
|
||||
}
|
||||
uint8_t attempt_count=0;
|
||||
@@ -1388,11 +1386,13 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||
case RHT2F_UID_ONLY: {
|
||||
bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
|
||||
attempt_count++; //attempt 3 times to get uid then quit
|
||||
if (!bStop && attempt_count == 3) bStop = true;
|
||||
if (!bStop && attempt_count == 3)
|
||||
bStop = true;
|
||||
} break;
|
||||
default: {
|
||||
Dbprintf("Error, unknown function: %d",htf);
|
||||
set_tracing(false);
|
||||
LED_D_OFF();
|
||||
return;
|
||||
} break;
|
||||
}
|
||||
@@ -1501,22 +1501,21 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
if ( bSuccessful )
|
||||
cmd_send(CMD_ACK, bSuccessful, 0, 0, (byte_t*)tag.sectors, 48);
|
||||
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t*)tag.sectors, 48);
|
||||
else
|
||||
cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||
int frame_count;
|
||||
int response;
|
||||
byte_t rx[HITAG_FRAME_LEN];
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen=0;
|
||||
byte_t txbuf[HITAG_FRAME_LEN];
|
||||
byte_t* tx = txbuf;
|
||||
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||
uint8_t* tx = txbuf;
|
||||
size_t txlen=0;
|
||||
int lastbit;
|
||||
bool bSkip;
|
||||
@@ -1788,5 +1787,5 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
// Dbprintf("frame received: %d",frame_count);
|
||||
// DbpString("All done");
|
||||
cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
|
||||
cmd_send(CMD_ACK,bSuccessful,0,0,(uint8_t*)tag.sectors,48);
|
||||
}
|
||||
|
||||
+15
-6
@@ -990,9 +990,11 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
|
||||
while (!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
|
||||
// wait for byte to become available in rx holding register
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
@@ -1127,13 +1129,10 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
||||
LEDsoff();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// this will clear out bigbuf memory, the eload command must select this before!
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
FpgaSetupSsc();
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Enable and clear the trace
|
||||
clear_trace();
|
||||
@@ -1586,11 +1585,17 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
|
||||
volatile uint8_t b = 0;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
// Prevent rx holding register from overflowing
|
||||
if ( (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){
|
||||
b = AT91C_BASE_SSC->SSC_RHR; (void) b;
|
||||
}
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)){
|
||||
b = 0x00;
|
||||
if ( i < respLen){
|
||||
@@ -1630,6 +1635,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
|
||||
// DOUBLE THE SAMPLES!
|
||||
@@ -1649,6 +1655,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
||||
if (c >= len) break;
|
||||
}
|
||||
|
||||
// Prevent rx holding register from overflowing
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = AT91C_BASE_SSC->SSC_RHR; (void)b;
|
||||
}
|
||||
@@ -1750,12 +1757,14 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples,
|
||||
while (!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
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)++;
|
||||
}
|
||||
|
||||
// Wait for byte be become available in rx holding register
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
if (c >= timeout) return false;
|
||||
|
||||
@@ -1802,10 +1811,10 @@ void setupIclassReader() {
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Reset trace buffer
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
+83
-158
@@ -449,14 +449,12 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
|
||||
// loop is a wait/delay ?
|
||||
/*
|
||||
for(uint8_t c = 0; c < 10;) {
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0xFF;
|
||||
++c;
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Now run a `software UART' on the stream of incoming samples.
|
||||
@@ -466,8 +464,16 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
|
||||
while( !BUTTON_PRESS() ) {
|
||||
WDT_HIT();
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
}
|
||||
|
||||
// Wait for byte be become available in rx holding register
|
||||
if ( AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY ) {
|
||||
|
||||
b = (uint8_t) AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
for ( mask = 0x80; mask != 0; mask >>= 1) {
|
||||
if ( Handle14443bReaderUartBit(b & mask)) {
|
||||
*len = Uart.byteCnt;
|
||||
@@ -494,7 +500,7 @@ void ClearFpgaShiftingRegisters(void){
|
||||
|
||||
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
|
||||
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
|
||||
while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
|
||||
if (AT91C_BASE_SSC->SSC_RHR) break;
|
||||
}
|
||||
|
||||
@@ -531,9 +537,13 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
|
||||
|
||||
// Transmit the response.
|
||||
for(uint16_t i = 0; i < len;) {
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = response[++i];
|
||||
}
|
||||
|
||||
// Prevent rx holding register from overflowing
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = AT91C_BASE_SSC->SSC_RHR;(void)b;
|
||||
}
|
||||
@@ -550,10 +560,10 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
||||
|
||||
// setup device.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
|
||||
// allocate command receive buffer
|
||||
BigBuf_free(); BigBuf_Clear_ext(false);
|
||||
@@ -786,6 +796,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
|
||||
CHECK_FOR_SUBCARRIER();
|
||||
|
||||
// subcarrier detected
|
||||
|
||||
if (v > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
||||
Demod.sumI = ci;
|
||||
@@ -987,10 +998,6 @@ static void GetTagSamplesFor14443bDemod() {
|
||||
if ( upTo )
|
||||
upTo = NULL;
|
||||
|
||||
// print the last batch of IQ values from FPGA
|
||||
if (MF_DBGLEVEL == 4)
|
||||
Dbhexdump(ISO14443B_DMA_BUFFER_SIZE, (uint8_t *)dmaBuf, false);
|
||||
|
||||
if ( Demod.len > 0 )
|
||||
LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false);
|
||||
}
|
||||
@@ -999,20 +1006,10 @@ static void GetTagSamplesFor14443bDemod() {
|
||||
// Transmit the command (to the tag) that was placed in ToSend[].
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TransmitFor14443b_AsReader(void) {
|
||||
|
||||
// we could been in following mode:
|
||||
// FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ
|
||||
// if its second call or more
|
||||
|
||||
// while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
// AT91C_BASE_SSC->SSC_THR = 0XFF;
|
||||
// }
|
||||
|
||||
int c;
|
||||
volatile uint32_t b;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||
SpinDelay(40);
|
||||
SpinDelay(60);
|
||||
|
||||
// What does this loop do? Is it TR1?
|
||||
// 0xFF = 8 bits of 1. 1 bit == 1Etu,..
|
||||
@@ -1020,27 +1017,21 @@ static void TransmitFor14443b_AsReader(void) {
|
||||
// 80*9 = 720us.
|
||||
|
||||
for(c = 0; c < 50;) {
|
||||
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0xFF;
|
||||
c++;
|
||||
}
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = AT91C_BASE_SSC->SSC_RHR; (void)b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Send frame loop
|
||||
for(c = 0; c < ToSendMax;) {
|
||||
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = ToSend[c++];
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = AT91C_BASE_SSC->SSC_RHR; (void)b;
|
||||
}
|
||||
}
|
||||
//WaitForFpgaDelayQueueIsEmpty(delay);
|
||||
// We should wait here for the FPGA to send all bits.
|
||||
WDT_HIT();
|
||||
}
|
||||
|
||||
@@ -1188,7 +1179,8 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
|
||||
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx));
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
|
||||
if (Demod.len == 0) return 2;
|
||||
if (Demod.len == 0)
|
||||
return 2;
|
||||
|
||||
// Randomly generated Chip ID
|
||||
if (card) card->chipid = Demod.output[0];
|
||||
@@ -1200,16 +1192,16 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
|
||||
CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx));
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
|
||||
if (Demod.len != 3) return 2;
|
||||
if (Demod.len != 3)
|
||||
return 2;
|
||||
|
||||
// Check the CRC of the answer:
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("crc fail ice2");
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Check response from the tag: should be the same UID as the command we just sent:
|
||||
if (select_srx[1] != Demod.output[0]) return 1;
|
||||
if (select_srx[1] != Demod.output[0])
|
||||
return 1;
|
||||
|
||||
// First get the tag's UID:
|
||||
select_srx[0] = ISO14443B_GET_UID;
|
||||
@@ -1218,13 +1210,12 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
|
||||
CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
|
||||
if (Demod.len != 10) return 2;
|
||||
if (Demod.len != 10)
|
||||
return 2;
|
||||
|
||||
// The check the CRC of the answer
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("crc fail ice3");
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
card->uidlen = 8;
|
||||
@@ -1251,13 +1242,12 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
|
||||
GetTagSamplesFor14443bDemod(); //select_card
|
||||
|
||||
// ATQB too short?
|
||||
if (Demod.len < 14) return 2;
|
||||
if (Demod.len < 14)
|
||||
return 2;
|
||||
|
||||
// VALIDATE CRC
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup crc fail");
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
card->uidlen = 4;
|
||||
@@ -1276,13 +1266,12 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
|
||||
GetTagSamplesFor14443bDemod();//select_card
|
||||
|
||||
// Answer to ATTRIB too short?
|
||||
if(Demod.len < 3) return 2;
|
||||
if(Demod.len < 3)
|
||||
return 2;
|
||||
|
||||
// VALIDATE CRC
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len) ) {
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup crc2 fail");
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len) )
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
|
||||
@@ -1314,11 +1303,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
|
||||
// Set up ISO 14443 Type B communication (similar to iso14443a_setup)
|
||||
// field is setup for "Sending as Reader"
|
||||
void iso14443b_setup() {
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup Enter");
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
//BigBuf_free();
|
||||
//BigBuf_Clear_ext(false);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
@@ -1332,13 +1318,12 @@ void iso14443b_setup() {
|
||||
|
||||
// Signal field is on with the appropriate LED
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||
SpinDelay(300);
|
||||
SpinDelay(100);
|
||||
|
||||
// Start the timer
|
||||
StartCountSspClk();
|
||||
|
||||
LED_D_ON();
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup Exit");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1350,91 +1335,42 @@ void iso14443b_setup() {
|
||||
//
|
||||
// I tried to be systematic and check every answer of the tag, every CRC, etc...
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool ReadSTBlock(uint8_t block) {
|
||||
uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00};
|
||||
AddCrc14B(cmd, 2);
|
||||
CodeAndTransmit14443bAsReader(cmd, sizeof(cmd));
|
||||
GetTagSamplesFor14443bDemod();
|
||||
|
||||
// Check if we got an answer from the tag
|
||||
if (Demod.len != 6) {
|
||||
DbpString("[!] expected 6 bytes from tag, got less...");
|
||||
return false;
|
||||
}
|
||||
// The check the CRC of the answer
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
DbpString("[!] CRC Error block!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void ReadSTMemoryIso14443b(uint8_t numofblocks) {
|
||||
// Make sure that we start from off, since the tags are stateful;
|
||||
// confusing things will happen if we don't reset them between reads.
|
||||
switch_off();
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
set_tracing(true);
|
||||
|
||||
// Now give it time to spin up.
|
||||
// Signal field is on with the appropriate LED
|
||||
LED_D_ON();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
|
||||
SpinDelay(100);
|
||||
//switch_off();
|
||||
|
||||
uint8_t i = 0x00;
|
||||
uint8_t *buf = BigBuf_malloc(sizeof(iso14b_card_select_t));
|
||||
|
||||
// First command: wake up the tag using the INITIATE command
|
||||
uint8_t cmd1[] = {ISO14443B_INITIATE, 0x00, 0x97, 0x5b};
|
||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); //no
|
||||
GetTagSamplesFor14443bDemod(); // no
|
||||
|
||||
if (Demod.len == 0) {
|
||||
DbpString("[!] No response from tag");
|
||||
set_tracing(false);
|
||||
return;
|
||||
} else {
|
||||
Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x",
|
||||
Demod.output[0], Demod.output[1], Demod.output[2]);
|
||||
}
|
||||
|
||||
// There is a response, SELECT the uid
|
||||
DbpString("[!] SELECT tag:");
|
||||
cmd1[0] = ISO14443B_SELECT; // 0x0E is SELECT
|
||||
cmd1[1] = Demod.output[0];
|
||||
AddCrc14B(cmd1, 2);
|
||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); //no
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
if (Demod.len != 3) {
|
||||
Dbprintf("[!] expected 3 bytes from tag, got %d", Demod.len);
|
||||
set_tracing(false);
|
||||
return;
|
||||
}
|
||||
// Check the CRC of the answer:
|
||||
iso14443b_setup();
|
||||
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
DbpString("[!] CRC Error reading select response.");
|
||||
set_tracing(false);
|
||||
return;
|
||||
}
|
||||
// Check response from the tag: should be the same UID as the command we just sent:
|
||||
if (cmd1[1] != Demod.output[0]) {
|
||||
Dbprintf("[!] Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]);
|
||||
set_tracing(false);
|
||||
return;
|
||||
}
|
||||
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
|
||||
uint8_t res = iso14443b_select_srx_card(card);
|
||||
|
||||
// Tag is now selected,
|
||||
// First get the tag's UID:
|
||||
cmd1[0] = ISO14443B_GET_UID;
|
||||
AddCrc14B(cmd1, 1);
|
||||
CodeAndTransmit14443bAsReader(cmd1, 3); // no -- Only first three bytes for this one
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
if (Demod.len != 10) {
|
||||
Dbprintf("[!] expected 10 bytes from tag, got %d", Demod.len);
|
||||
set_tracing(false);
|
||||
return;
|
||||
}
|
||||
// The check the CRC of the answer (use cmd1 as temporary variable):
|
||||
// 0: OK 2: attrib fail, 3:crc fail,
|
||||
if ( res > 0 ) goto out;
|
||||
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
Dbprintf("[!] CRC Error reading block! Expected: %04x got: %04x", (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
|
||||
// Do not return;, let's go on... (we should retry, maybe ?)
|
||||
}
|
||||
Dbprintf("[+] Tag UID (64 bits): %08x %08x",
|
||||
(Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
|
||||
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
|
||||
|
||||
// Now loop to read all 16 blocks, address from 0 to last block
|
||||
Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks);
|
||||
cmd1[0] = 0x08;
|
||||
i = 0x00;
|
||||
|
||||
++numofblocks;
|
||||
|
||||
for (;;) {
|
||||
@@ -1442,22 +1378,16 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
|
||||
DbpString("System area block (0xFF):");
|
||||
i = 0xff;
|
||||
}
|
||||
cmd1[1] = i;
|
||||
AddCrc14B(cmd1, 2);
|
||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); //no
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
|
||||
uint8_t retries = 3;
|
||||
do {
|
||||
res = ReadSTBlock(i);
|
||||
} while (!res && --retries);
|
||||
|
||||
if (Demod.len != 6) { // Check if we got an answer from the tag
|
||||
DbpString("[!] expected 6 bytes from tag, got less...");
|
||||
return;
|
||||
}
|
||||
// The check the CRC of the answer (use cmd1 as temporary variable):
|
||||
|
||||
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
|
||||
Dbprintf("[!] CRC Error reading block! Expected: %04x got: %04x",
|
||||
(cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
|
||||
// Do not return;, let's go on... (we should retry, maybe ?)
|
||||
if (!res && !retries) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Now print out the memory location:
|
||||
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
|
||||
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
|
||||
@@ -1467,11 +1397,13 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
|
||||
++i;
|
||||
}
|
||||
|
||||
set_tracing(false);
|
||||
out:
|
||||
switch_off(); // disconnect raw
|
||||
SpinDelay(20);
|
||||
}
|
||||
|
||||
static void iso1444b_setup_sniff(void){
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup_sniff Enter");
|
||||
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
BigBuf_free();
|
||||
@@ -1504,8 +1436,6 @@ static void iso1444b_setup_sniff(void){
|
||||
|
||||
// Start the SSP timer
|
||||
StartCountSspClk();
|
||||
|
||||
if (MF_DBGLEVEL > 3) Dbprintf("iso1443b_setup_sniff Exit");
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -1596,7 +1526,7 @@ void RAMFUNC SniffIso14443b(void) {
|
||||
|
||||
// is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103
|
||||
// LSB is a fpga signal bit.
|
||||
if (Handle14443bTagSamplesDemod(ci >> 1, cq >> 1)) {
|
||||
if (Handle14443bTagSamplesDemod(ci, cq)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||
UartReset();
|
||||
@@ -1647,10 +1577,8 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
|
||||
iso14b_set_trigger(true);
|
||||
|
||||
if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
|
||||
// Make sure that we start from off, since the tags are stateful;
|
||||
// confusing things will happen if we don't reset them between reads.
|
||||
//switch_off(); // before connect in raw
|
||||
iso14443b_setup();
|
||||
clear_trace();
|
||||
}
|
||||
|
||||
set_tracing(true);
|
||||
@@ -1660,15 +1588,15 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
|
||||
status = iso14443b_select_card(card);
|
||||
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
// 0: OK 2: attrib fail, 3:crc fail,
|
||||
if ( status > 0 ) return;
|
||||
if ( status > 0 ) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
|
||||
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
|
||||
status = iso14443b_select_srx_card(card);
|
||||
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
// 0: OK 2: attrib fail, 3:crc fail,
|
||||
if ( status > 0 ) return;
|
||||
// 0: OK 2: demod fail, 3:crc fail,
|
||||
if ( status > 0 ) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
||||
@@ -1690,6 +1618,7 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
|
||||
cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen);
|
||||
}
|
||||
|
||||
out:
|
||||
// turn off trigger (LED_A)
|
||||
if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER)
|
||||
iso14b_set_trigger(false);
|
||||
@@ -1697,11 +1626,7 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
|
||||
// turn off antenna et al
|
||||
// we don't send a HALT command.
|
||||
if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) {
|
||||
if (MF_DBGLEVEL > 2) Dbprintf("disconnect");
|
||||
switch_off(); // disconnect raw
|
||||
SpinDelay(20);
|
||||
} else {
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1930,7 +1930,7 @@ void Cotag(uint32_t arg0) {
|
||||
// Turn the field off
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
LED_A_OFF();
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+10
-3
@@ -399,8 +399,9 @@ uint32_t doCotagAcquisitionManchester() {
|
||||
uint8_t sample = 0, firsthigh = 0, firstlow = 0;
|
||||
uint16_t sample_counter = 0, period = 0;
|
||||
uint8_t curr = 0, prev = 0;
|
||||
uint16_t noise_counter = 0;
|
||||
|
||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) ) {
|
||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
|
||||
WDT_HIT();
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||
@@ -413,14 +414,20 @@ uint32_t doCotagAcquisitionManchester() {
|
||||
|
||||
// find first peak
|
||||
if ( !firsthigh ) {
|
||||
if (sample < COTAG_ONE_THRESHOLD)
|
||||
if (sample < COTAG_ONE_THRESHOLD) {
|
||||
noise_counter++;
|
||||
continue;
|
||||
}
|
||||
noise_counter = 0;
|
||||
firsthigh = 1;
|
||||
}
|
||||
|
||||
if ( !firstlow ){
|
||||
if (sample > COTAG_ZERO_THRESHOLD )
|
||||
if (sample > COTAG_ZERO_THRESHOLD ) {
|
||||
noise_counter++;
|
||||
continue;
|
||||
}
|
||||
noise_counter = 0;
|
||||
firstlow = 1;
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -37,10 +37,11 @@ void StartCountSspClk();
|
||||
void ResetSspClk(void);
|
||||
uint32_t RAMFUNC GetCountSspClk();
|
||||
|
||||
void StartTicks(void);
|
||||
uint32_t GetTicks(void);
|
||||
void WaitTicks(uint32_t ticks);
|
||||
void WaitUS(uint16_t us);
|
||||
void WaitMS(uint16_t ms);
|
||||
void StopTicks(void);
|
||||
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);
|
||||
|
||||
extern void StopTicks(void);
|
||||
#endif
|
||||
+12
-4
@@ -66,7 +66,7 @@ int usage_analyse_nuid(void){
|
||||
return 0;
|
||||
}
|
||||
int usage_analyse_a(void) {
|
||||
PrintAndLogEx(NORMAL, "my personal garbage test command");
|
||||
PrintAndLogEx(NORMAL, "Iceman's personal garbage test command");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: analyse a [h] d <bytes>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
@@ -248,9 +248,17 @@ int CmdAnalyseLCR(const char *Cmd) {
|
||||
if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_lcr();
|
||||
|
||||
int len = 0;
|
||||
param_gethex_ex(Cmd, 0, data, &len);
|
||||
if ( len%2 ) return usage_analyse_lcr();
|
||||
len >>= 1;
|
||||
switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) {
|
||||
case 1:
|
||||
PrintAndLogEx(WARNING, "Invalid HEX value.");
|
||||
return 1;
|
||||
case 2:
|
||||
PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data));
|
||||
return 1;
|
||||
case 3:
|
||||
PrintAndLogEx(WARNING, "Hex must have even number of digits.");
|
||||
return 1;
|
||||
}
|
||||
uint8_t finalXor = calculateLRC(data, len);
|
||||
PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor);
|
||||
return 0;
|
||||
|
||||
@@ -150,6 +150,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){
|
||||
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)) {
|
||||
|
||||
+283
-35
@@ -1,5 +1,6 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
// Modified 2018 iceman
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
@@ -89,12 +90,28 @@ int usage_hf_14b_write_srx(void){
|
||||
PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344");
|
||||
return 0;
|
||||
}
|
||||
int usage_hf_14b_dump(void){
|
||||
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
|
||||
"\n"
|
||||
"Usage: hf 14b dump [h] [card memory] <f filname> \n"
|
||||
"Options:\n"
|
||||
"\th this help\n"
|
||||
"\t[card memory] 1 = SRIX4K (default), 2 = SRI512"
|
||||
"\tf <name> filename, if no <name> UID will be used as filename\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"\thf 14b dump f\n"
|
||||
"\thf 14b dump 2 f mydump");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
static void switch_on_field_14b(void) {
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
}
|
||||
*/
|
||||
|
||||
static int switch_off_field_14b(void) {
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}};
|
||||
@@ -109,11 +126,11 @@ int CmdHF14BList(const char *Cmd) {
|
||||
}
|
||||
|
||||
int CmdHF14BSim(const char *Cmd) {
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H') return usage_hf_14b_sim();
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_sim();
|
||||
|
||||
uint32_t pupi = 0;
|
||||
if (cmdp == 'u' || cmdp == 'U') {
|
||||
if (cmdp == 'u') {
|
||||
pupi = param_get32ex(Cmd, 1, 0, 16);
|
||||
}
|
||||
|
||||
@@ -125,8 +142,8 @@ int CmdHF14BSim(const char *Cmd) {
|
||||
|
||||
int CmdHF14BSniff(const char *Cmd) {
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H') return usage_hf_14b_sniff();
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_sniff();
|
||||
|
||||
UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
@@ -151,26 +168,21 @@ int CmdHF14BCmdRaw (const char *Cmd) {
|
||||
while (Cmd[i]!='\0') {
|
||||
if (Cmd[i]==' ' || Cmd[i]=='\t') { ++i; continue; }
|
||||
if (Cmd[i]=='-') {
|
||||
switch (Cmd[i+1]) {
|
||||
switch (tolower(Cmd[i+1])) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
return usage_hf_14b_raw();
|
||||
case 'r':
|
||||
case 'R':
|
||||
reply = false;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
flags |= ISO14B_APPEND_CRC;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
power = true;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
select = true;
|
||||
if (Cmd[i+2]=='s' || Cmd[i+2]=='S') {
|
||||
if (tolower(Cmd[i+2]) == 's') {
|
||||
flags |= ISO14B_SELECT_SR;
|
||||
++i;
|
||||
} else {
|
||||
@@ -229,6 +241,54 @@ int CmdHF14BCmdRaw (const char *Cmd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||
|
||||
if (!card)
|
||||
return false;
|
||||
|
||||
uint8_t retry = 3;
|
||||
UsbCommand resp;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}};
|
||||
|
||||
// test for 14b SR
|
||||
while (retry--) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
|
||||
uint8_t status = resp.arg[0];
|
||||
if ( status == 0) {
|
||||
memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // retry
|
||||
|
||||
// test 14b standard
|
||||
c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT;
|
||||
retry = 3;
|
||||
while (retry--) {
|
||||
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
|
||||
uint8_t status = resp.arg[0];
|
||||
if ( status == 0) {
|
||||
memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // retry
|
||||
|
||||
if ( !retry )
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// print full atqb info
|
||||
// bytes
|
||||
// 0,1,2,3 = application data
|
||||
@@ -374,8 +434,45 @@ static void print_st_general_info(uint8_t *data, uint8_t len){
|
||||
|
||||
// 14b get and print Full Info (as much as we know)
|
||||
bool HF14B_Std_Info(bool verbose){
|
||||
//add more info here
|
||||
|
||||
bool isSuccess = false;
|
||||
|
||||
// 14b get and print UID only (general info)
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
switch_off_field_14b();
|
||||
return false;
|
||||
}
|
||||
|
||||
iso14b_card_select_t card;
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
|
||||
|
||||
uint64_t status = resp.arg[0];
|
||||
|
||||
switch( status ){
|
||||
case 0:
|
||||
PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
|
||||
PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid);
|
||||
print_atqb_resp(card.atqb, card.cid);
|
||||
isSuccess = true;
|
||||
case 2:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
||||
break;
|
||||
case 3:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
|
||||
break;
|
||||
default:
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
|
||||
break;
|
||||
}
|
||||
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
// SRx get and print full info (needs more info...)
|
||||
@@ -395,7 +492,10 @@ bool HF14B_ST_Info(bool verbose){
|
||||
memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
|
||||
|
||||
uint64_t status = resp.arg[0];
|
||||
if ( status > 0 ) return switch_off_field_14b();
|
||||
if ( status > 0 )
|
||||
return false;
|
||||
|
||||
print_st_general_info(card.uid, card.uidlen);
|
||||
|
||||
//add locking bit information here. uint8_t data[16] = {0x00};
|
||||
// uint8_t datalen = 2;
|
||||
@@ -418,7 +518,6 @@ bool HF14B_ST_Info(bool verbose){
|
||||
|
||||
// if (datalen != resplen || !crc) return rawClose();
|
||||
//print_ST_Lock_info(data[5]>>2);
|
||||
switch_off_field_14b();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -428,7 +527,7 @@ bool HF14BInfo(bool verbose){
|
||||
// try std 14b (atqb)
|
||||
if (HF14B_Std_Info(verbose)) return true;
|
||||
|
||||
// try st 14b
|
||||
// try ST 14b
|
||||
if (HF14B_ST_Info(verbose)) return true;
|
||||
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
@@ -439,10 +538,10 @@ bool HF14BInfo(bool verbose){
|
||||
|
||||
// menu command to get and print all info known about any known 14b tag
|
||||
int CmdHF14Binfo(const char *Cmd){
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H') return usage_hf_14b_info();
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_info();
|
||||
|
||||
bool verbose = !((cmdp == 's') || (cmdp == 'S'));
|
||||
bool verbose = !(cmdp == 's');
|
||||
return HF14BInfo(verbose);
|
||||
}
|
||||
|
||||
@@ -450,16 +549,13 @@ bool HF14B_ST_Reader(bool verbose){
|
||||
|
||||
bool isSuccess = false;
|
||||
|
||||
switch_on_field_14b();
|
||||
|
||||
// SRx get and print general info about SRx chip from UID
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_SELECT_SR, 0, 0}};
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
switch_off_field_14b();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -486,8 +582,6 @@ bool HF14B_ST_Reader(bool verbose){
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed");
|
||||
break;
|
||||
}
|
||||
|
||||
switch_off_field_14b();
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
@@ -503,7 +597,6 @@ bool HF14B_Std_Reader(bool verbose){
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
|
||||
switch_off_field_14b();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -530,8 +623,6 @@ bool HF14B_Std_Reader(bool verbose){
|
||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
|
||||
break;
|
||||
}
|
||||
|
||||
switch_off_field_14b();
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
@@ -613,10 +704,10 @@ bool HF14BReader(bool verbose){
|
||||
|
||||
// menu command to get and print general info about all known 14b chips
|
||||
int CmdHF14BReader(const char *Cmd){
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (cmdp == 'h' || cmdp == 'H') return usage_hf_14b_reader();
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_hf_14b_reader();
|
||||
|
||||
bool verbose = !((cmdp == 's') || (cmdp == 'S'));
|
||||
bool verbose = !(cmdp == 's');
|
||||
return HF14BReader(verbose);
|
||||
}
|
||||
|
||||
@@ -625,8 +716,8 @@ int CmdHF14BReader(const char *Cmd){
|
||||
* this command just dumps the contents of the memory/
|
||||
*/
|
||||
int CmdHF14BReadSri(const char *Cmd){
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_hf_14b_read_srx();
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx();
|
||||
|
||||
uint8_t tagtype = param_get8(Cmd, 0);
|
||||
uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F;
|
||||
@@ -648,14 +739,14 @@ int CmdHF14BWriteSri(const char *Cmd){
|
||||
* Special block FF = otp_lock_reg block.
|
||||
* Data len 4 bytes-
|
||||
*/
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
uint8_t blockno = -1;
|
||||
uint8_t data[4] = {0x00};
|
||||
bool isSrix4k = true;
|
||||
char str[30];
|
||||
memset(str, 0x00, sizeof(str));
|
||||
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_hf_14b_write_srx();
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx();
|
||||
|
||||
if ( cmdp == '2' )
|
||||
isSrix4k = false;
|
||||
@@ -703,6 +794,162 @@ int CmdHF14BWriteSri(const char *Cmd){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// need to write to file
|
||||
int CmdHF14BDump(const char*Cmd) {
|
||||
|
||||
uint8_t fileNameLen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
char * fptr = filename;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0, cardtype = 1;
|
||||
uint16_t cardsize = 0;
|
||||
uint8_t blocks = 0;
|
||||
iso14b_card_select_t card;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_14b_dump();
|
||||
case 'f':
|
||||
fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
if (cmdp == 0) {
|
||||
cardtype = param_get8ex(Cmd, cmdp, 1, 10);
|
||||
cmdp++;
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors) return usage_hf_14b_dump();
|
||||
|
||||
switch (cardtype){
|
||||
case 2:
|
||||
cardsize = (512/8) + 4;
|
||||
blocks = 0x0F;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
cardsize = (4096/8) + 4;
|
||||
blocks = 0x7F;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!get_14b_UID(&card)) {
|
||||
PrintAndLogEx(WARNING, "No tag found.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fileNameLen < 1) {
|
||||
PrintAndLogEx(INFO, "Using UID as filename");
|
||||
fptr += sprintf(fptr, "hf-14b-");
|
||||
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
||||
}
|
||||
|
||||
// detect blocksize from card :)
|
||||
PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen));
|
||||
|
||||
uint8_t data[cardsize];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
int blocknum = 0;
|
||||
uint8_t *recv = NULL;
|
||||
|
||||
UsbCommand resp;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, { ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
|
||||
//select
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (resp.arg[0]) {
|
||||
PrintAndLogEx(INFO, "failed to select %d | %d", resp.arg[0], resp.arg[1]);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW;
|
||||
c.arg[1] = 2;
|
||||
|
||||
uint8_t *req = c.d.asBytes;
|
||||
req[0] = ISO14443B_READ_BLK;
|
||||
|
||||
for (int retry = 0; retry < 5; retry++) {
|
||||
|
||||
req[1] = blocknum;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
||||
uint8_t status = resp.arg[0] & 0xFF;
|
||||
if ( status > 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t len = (resp.arg[1] & 0xFFFF);
|
||||
recv = resp.d.asBytes;
|
||||
|
||||
if ( !check_crc(CRC_14443_B, recv, len) ) {
|
||||
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(data + (blocknum * 4), resp.d.asBytes, 4);
|
||||
|
||||
if ( blocknum == 0xFF) {
|
||||
//last read.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
retry = 0;
|
||||
blocknum++;
|
||||
if ( blocknum > blocks ) {
|
||||
// read config block
|
||||
blocknum = 0xFF;
|
||||
}
|
||||
|
||||
printf("."); fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
if ( blocknum != 0xFF) {
|
||||
PrintAndLogEx(NORMAL, "\n Dump failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n");
|
||||
PrintAndLogEx(NORMAL, "block# | data | ascii");
|
||||
PrintAndLogEx(NORMAL, "---------+--------------+----------");
|
||||
|
||||
for (int i = 0; i <= blocks; i++) {
|
||||
PrintAndLogEx(NORMAL,
|
||||
"%3d/0x%02X | %s | %s",
|
||||
i,
|
||||
i,
|
||||
sprint_hex(data + (i*4), 4 ),
|
||||
sprint_ascii(data + (i*4), 4)
|
||||
);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n");
|
||||
|
||||
|
||||
size_t datalen = (blocks+1) * 4;
|
||||
saveFileEML(filename, "eml", data, datalen, 4);
|
||||
saveFile(filename, "bin", data, datalen);
|
||||
out:
|
||||
return switch_off_field_14b();
|
||||
}
|
||||
|
||||
uint32_t srix4kEncode(uint32_t value) {
|
||||
/*
|
||||
// vv = value
|
||||
@@ -844,6 +1091,7 @@ bool waitCmd14b(bool verbose) {
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"},
|
||||
{"info", CmdHF14Binfo, 0, "Tag information"},
|
||||
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"},
|
||||
{"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
|
||||
|
||||
@@ -45,6 +45,8 @@ extern int CmdHF14BSniff(const char *Cmd);
|
||||
extern int CmdHF14BWrite( const char *cmd);
|
||||
extern int CmdHF14BReader(const char *Cmd);
|
||||
|
||||
extern int CmdHF14BDump(const char *Cmd);
|
||||
|
||||
extern bool HF14BInfo(bool verbose);
|
||||
extern bool HF14BReader(bool verbose);
|
||||
extern int CmdHF14BCmdRaw (const char *Cmd);
|
||||
|
||||
+1
-3
@@ -658,12 +658,10 @@ int CmdHF15Dump(const char*Cmd) {
|
||||
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch(param_getchar(Cmd, cmdp)) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
return usage_15_dump();
|
||||
case 'f':
|
||||
case 'F':
|
||||
fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user