mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge branch 'master' into smartcard-relay
This commit is contained in:
@@ -70,7 +70,7 @@ jobs:
|
||||
env:
|
||||
V: 1
|
||||
PLATFORM_EXTRAS: BTADDON
|
||||
run: make
|
||||
run: make -j$((`nproc` + 1))
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -50,14 +50,12 @@ jobs:
|
||||
- name: Build
|
||||
env:
|
||||
V: 1
|
||||
run: make
|
||||
run: make -j$((`sysctl -n hw.ncpu` + 1))
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
|
||||
macos-make-btaddon:
|
||||
if: always()
|
||||
needs: [macos-make]
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
@@ -93,14 +91,12 @@ jobs:
|
||||
env:
|
||||
V: 1
|
||||
PLATFORM_EXTRAS: BTADDON
|
||||
run: make
|
||||
run: make -j$((`sysctl -n hw.ncpu` + 1))
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
|
||||
macos-cmake:
|
||||
if: always()
|
||||
needs: [macos-make, macos-make-btaddon]
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
@@ -144,7 +140,7 @@ jobs:
|
||||
- name: Build
|
||||
env:
|
||||
VERBOSE: 1
|
||||
run: make
|
||||
run: make -j$((`sysctl -n hw.ncpu` + 1))
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Test
|
||||
|
||||
@@ -41,14 +41,12 @@ jobs:
|
||||
- name: Build
|
||||
env:
|
||||
V: 1
|
||||
run: make
|
||||
run: make -j$((`nproc` + 1))
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
|
||||
ubuntu-make-btaddon:
|
||||
if: always()
|
||||
needs: [ubuntu-make]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -74,14 +72,12 @@ jobs:
|
||||
env:
|
||||
V: 1
|
||||
PLATFORM_EXTRAS: BTADDON
|
||||
run: make
|
||||
run: make -j$((`nproc` + 1))
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
|
||||
ubuntu-cmake:
|
||||
if: always()
|
||||
needs: [ubuntu-make, ubuntu-make-btaddon]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -115,7 +111,7 @@ jobs:
|
||||
- name: Build
|
||||
env:
|
||||
VERBOSE: 1
|
||||
run: make
|
||||
run: make -j$((`nproc` + 1))
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Test
|
||||
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
run: make clean
|
||||
|
||||
- name: Build
|
||||
run: make V=1
|
||||
run: make -j $([System.Environment]::ProcessorCount + 1) V=1
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
run: make clean
|
||||
|
||||
- name: Build btaddon
|
||||
run: make V=1 PLATFORM_EXTRAS=BTADDON
|
||||
run: make -j $([System.Environment]::ProcessorCount + 1) V=1 PLATFORM_EXTRAS=BTADDON
|
||||
|
||||
- name: Test btaddon
|
||||
run: make check
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Build cmake
|
||||
run: make VERBOSE=1
|
||||
run: make -j $([System.Environment]::ProcessorCount + 1) VERBOSE=1
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Test cmake
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
run: make clean
|
||||
|
||||
- name: Build
|
||||
run: make V=1
|
||||
run: make -j$((`nproc` + 1)) V=1
|
||||
|
||||
- name: Test
|
||||
run: make check
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
run: make clean
|
||||
|
||||
- name: Build btaddon
|
||||
run: make V=1 PLATFORM_EXTRAS=BTADDON
|
||||
run: make -j$((`nproc` + 1)) V=1 PLATFORM_EXTRAS=BTADDON
|
||||
|
||||
- name: Test btaddon
|
||||
run: make check
|
||||
@@ -171,7 +171,7 @@ jobs:
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Build cmake
|
||||
run: make VERBOSE=1
|
||||
run: make -j$((`nproc` + 1)) VERBOSE=1
|
||||
working-directory: client/build/
|
||||
|
||||
- name: Test cmake
|
||||
|
||||
+58
-6
@@ -1,11 +1,61 @@
|
||||
# Change Log
|
||||
Change Log
|
||||
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]
|
||||
- Use proxmark3 as a generic smartcard reader with other software with `smart relay` (@gm3197)
|
||||
- Added `tools\mfkeys\staticnested` - program to recover static nested keys (@iceman1001)
|
||||
- Added `pm3_gen_dictionary.py` - python script to extract and save all keys from MFC dump files. (@iceman1001)
|
||||
- Changed `hf mfu info` - now detect MIFARE Ultralight AES (@iceman1001)
|
||||
- Changed `hf mf autopwn` - now supports multiple user supplied keys (@iceman1001)
|
||||
- Added `hf mf gchpwd` command for change Gen4 GTU card access password (@merlokk)
|
||||
- Added `--ms` option in `hw status` to specify the timeout of connection speed test (@wh201906)
|
||||
- Added `hf mf ginfo` command for get info about Gen4 GTU configuration (@merlokk)
|
||||
- Added support for loading Flipper PICOPASS dump files (@iceman1001)
|
||||
- Fixed unknown chip identification (@jmichelp)
|
||||
- Fixed `nfc decode` - now properly handles MFU dump files (@iceman1001)
|
||||
- Added support for loading Flipper MCT/MFU dump files (@iceman1001)
|
||||
- Changed `data bmap` - now default `-m` is 8 (@iceman1001)
|
||||
- Added support for NTAG424 cards. (@dankar)
|
||||
- Additional fixes to configcard code for keyroll mode based on nfc-iclass output (@Antiklesys)
|
||||
- Changed lf sampling - improved the performance (@yah01)
|
||||
- Added `bind` option for network connections to specify the outbound address and port (@wh201906)
|
||||
- Changed `lf em 4x05 dump` - now supports the `--ns` nosave parameter (@iceman1001)
|
||||
- Fixed some wrong synchronization waits in usb_write() to increase the communication speed (@wh201906)
|
||||
- Added new command `data bmap` - breaks down a hexvalue to a binary template (@iceman1001)
|
||||
- Changed aid_desfire.json - added entreis from the Metrodroid project (@iceman1001)
|
||||
- Changed mad.json - added entries from the Metrodroid project (@iceman1001)
|
||||
- Changed `hf iclass dump` - now allow no save of dumped data (@iceman1001)
|
||||
- Changed `hf iclass calcnewkey` - Added calculations for old key elite and new key non elite (@Antiklesys)
|
||||
- Changed the CLI prompt to show tcp/udp if used (@iceman1001)
|
||||
- Changed `hw ping` - now shows transfer time (@doegox)
|
||||
- Added `hf mf encodehid` - writes HID legacy credential to a empty MFC (@iceman1001)
|
||||
- Added `hf iclass sam` - Added support for HID SAM Picopass communications (@iceman1001)
|
||||
- Add support for quoted arguments in the CLI, allowing spaces in them which
|
||||
are removed automatically (@jmichelp)
|
||||
- Added UDP support on Windows (@wh201906)
|
||||
- Added client communication timeout to preferences (@iceman1001)
|
||||
- Added IPv6 support (@wh201906)
|
||||
- Fixed `lf hid clone --bin` - now correctly handles sentinel bits (@iceman1001)
|
||||
- Experimental UDP support in linux (@iceman1001, @wh201906)
|
||||
- Changed CI scripts to speed up the builds (@wh201906)
|
||||
- Changed the timeout of local TCP connections (@wh201906)
|
||||
- Finalized implementation of configcard generation for keyroll when cardhelper is not present (@Antiklesys)
|
||||
- Added documentation for compiling on iOS (@The-SamminAter)
|
||||
- Fixed `hf iclass wrbl` - pagemap bit map for secured is now handled better (@iceman1001)
|
||||
- Changed `hf iclass view/decrypt` to detect SIO lengths better and show if legacy credentials are encrypted (@nvx)
|
||||
- Changed the json file formats for mfc, 14b, 15, legic, cryptorf, ndef (@iceman1001)
|
||||
- Deprecated the EML file format when saving dump files. (@iceman1001)
|
||||
- Added `sim014.bin` - new sim module firmware v4.42 with improved ISO7816 Protocol T0 support (@gentilkiwi)
|
||||
- Added datasheet for sim module (@iceman1001)
|
||||
- Changed `smart raw --timeout` - allows for a custom timeout (@iceman1001)
|
||||
- Changed `lf t55 detectp1` - now also accepts 0xE039 Silicon Craft Tech as valid card (@iceman1001)
|
||||
- Fixed `utils.lua` library function "convertdectohex" wasn't working (@iceman1001)
|
||||
- Added `hf iclass creditepurse` command to allow crediting the epurse debit value (@nvx)
|
||||
- Modified `hf iclass configcard` to only support online mode (@Antiklesys)
|
||||
- Modified `hf iclass configcard` command to generate config cards without a cardhelper module by porting the contents of blocks 6 & 7 from nfc-iclass (@Antiklesys)
|
||||
- Fixed `hf iclass info` command showing incorrectly in offline mode (@Antiklesys)
|
||||
- The "doc/magic_cards_notes.md" file has been rebuilt, filled up, and so on. (@team-orangeBlue)
|
||||
|
||||
## [Raccoon.4.17140][2023-09-09]
|
||||
- Changed text and adjust pm3_test case for mf_aes_brute (@doegox)
|
||||
@@ -59,7 +109,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Fixed compiling liblua on iOS (@The-SamminAter)
|
||||
- Changed `hf_mf_luxeo_dump.lua` - now have list of keys to iterate (@iceman1001)
|
||||
- Fixed the timeout of TCP connections (@wh201906)
|
||||
- Changed the connection timeout configurable (@wh201906)
|
||||
- Added `hw timeout` - make the connection timeout configurable (@wh201906)
|
||||
|
||||
## [Seven.4.16717][2023-06-25]
|
||||
- Change `hf 14a info` - now identifes QL88 tags (@iceman1001)
|
||||
@@ -81,7 +131,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Changed `hf mfu pwdgen -r` - now generates pwd/pack for Philips Sonicare, thanks @ckuenzi, @atc1441 (@iceman1001)
|
||||
- Changed `hf mfu info` - now detects Philips Sonicare devices (@iceman1001)
|
||||
- Fixed truncated FPGA upload due to incorrect integer size variable (@d18c7db)
|
||||
- Changed `usart btfactory` - handles the new BT board with version "BT SPP V3.0" (@iceman1001)
|
||||
- Changed `usart btfactory` - handles the new BT board with version "BT SPP V3.0" (@iceman1001)
|
||||
- Changed `hf mf eview --sk` - now can extract keys and save to file (@iceman1001)
|
||||
- Changed `hf mf view --sk` - now can extract keys and save to file (@iceman1001)
|
||||
- Changed `hf mf sim` - reduce 6ms threshold to 4ms for reset to idle #1974 (@net147)
|
||||
@@ -108,7 +158,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Added `hf mf gdmcfg` - Support Gen4 GDM read configuration block (@iceman1001)
|
||||
- Changed magic note to include a section about GDM tags (@iceman1001)
|
||||
- Added `hf mf gdmsetblk` - Support Gen4 GDM write block (@iceman1001)
|
||||
- Changed `hf 14a info` - detect Gen GDM magic tags (@iceman1001)
|
||||
- Changed `hf 14a info` - detect Gen GDM magic tags (@iceman1001)
|
||||
- Changed CLI max string argument length limit from 512 to 4096 (@iceman1001)
|
||||
- Fixed `data asn1` - now handles bad input better (@iceman1001)
|
||||
- Added new public key for signature MIFARE Plus Troika (@iceman100)
|
||||
@@ -178,14 +228,14 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Fixed length check in sim module communications (@jmichelp)
|
||||
- Changed timings in i2c.c when communicating with sim module (@iceman1001)
|
||||
- Moved to non-deprecated API to initialize Python interpreter (@jmichelp)
|
||||
- Changed `sc upgrade` updated firmware v4.13 (RDV40) - frame buffer is now 384 bytes (@sentiprox)
|
||||
- Changed `sc upgrade` updated firmware v4.13 (RDV40) - frame buffer is now 384 bytes (@sentiprox)
|
||||
- Fixed contact interface / smartcard APDU chaining logic and allow 256 bytes ADPU payload. Need SIM firmware 4.13 to work (@jmichelp)
|
||||
- Fixed `lf hitag dump` - Should now work as described in the command help (@natmchugh)
|
||||
- Fixed SPI flash overflow when loading dictionnaries into flash. Breaking change: added 1 more sector for Mifare - dictionnaries should be loaded again (@jmichelp)
|
||||
- Added `hf mf gload, gsave, ggetblk, gsetblk` for Gen4 GTU in mifare classic mode (@DidierA)
|
||||
- Fixed `trace list -r` (relative times) not working unless `-u` (microseconds) was specified, and made `--frame` respect `-u` and `-r` options (@nvx)
|
||||
- Added detection of magic Gen4 GTU (@DidierA)
|
||||
- Added luascript `hf_i2c_plus_2k_utils` - Script for dumping/modifying user memory of sectors 0 and 1 (@flamebarke)
|
||||
- Added luascript `hf_i2c_plus_2k_utils` - Script for dumping/modifying user memory of sectors 0 and 1 (@flamebarke)
|
||||
- Added `hf mfu esave` - saves emulator memory to mfu dump file (@DidierA)
|
||||
- Added luascript `hf_mfu_ntag` - Script for configuring NTAG216 configuration pages (@flamebarke)
|
||||
- Changed `hf mf hardnested` - a detection for static encrypted nonces (@iceman1001)
|
||||
@@ -299,6 +349,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Added new standalone mode `lf_em4100rsww` (@zabszk)
|
||||
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
|
||||
- Added `script run hf_mf_hid_sim.lua` (@micsen)
|
||||
- Added flashmem support in `HF_14BSNIFF` standalone mode (@wh201906)
|
||||
- Changed `HF_14ASNIFF` standalone mode - now supports Proxmark3 without flashmem (@wh201906)
|
||||
|
||||
## [Frostbit.4.14831][2022-01-11]
|
||||
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
|
||||
|
||||
@@ -34,7 +34,7 @@ all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfk
|
||||
#all clean install uninstall check: %: hitag2crack/%
|
||||
|
||||
INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py pm3_amii_bin2eml.pl pm3_reblay-emulating.py pm3_reblay-reading.py
|
||||
INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt
|
||||
INSTALLSIMFW=sim011.bin sim011.sha512.txt sim013.bin sim013.sha512.txt sim014.bin sim014.sha512.txt
|
||||
INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage
|
||||
INSTALLSHARES=tools/jtag_openocd traces
|
||||
INSTALLDOCS=doc/*.md doc/md
|
||||
|
||||
@@ -10,8 +10,7 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the
|
||||
|
||||
| Actions OSX CI | Actions Ubuntu CI | Actions Windows CI |
|
||||
|:--------------:|:------------------:|:------------------:|
|
||||
|  |  | [](https://github.com/RfidResearchGroup/proxmark3/actions/workflows/windows.yml) |
|
||||
|
||||
| [](https://github.com/RfidResearchGroup/proxmark3/actions/workflows/macos.yml) | [](https://github.com/RfidResearchGroup/proxmark3/actions/workflows/ubuntu.yml) | [](https://github.com/RfidResearchGroup/proxmark3/actions/workflows/windows.yml) |
|
||||
|
||||
# Table of Contents
|
||||
1. [PROXMARK3 INSTALLATION AND OVERVIEW](#proxmark3-installation-and-overview)
|
||||
@@ -40,6 +39,7 @@ The Proxmark3 is the swiss-army tool of RFID, allowing for interactions with the
|
||||
| [macOS - Setup and Build](/doc/md/Installation_Instructions/macOS-Compile-From-Source-Instructions.md) ||
|
||||
| [Windows - Setup and Build](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md) ||
|
||||
| [Termux / Android - Setup and Build](/doc/termux_notes.md) ||
|
||||
| [iOS - Setup and Build](/doc/md/Installation_Instructions/iOS-Installation-Instructions.md)
|
||||
| [Blue Shark Manual](/doc/bt_manual_v10.md) | [Command Cheat Sheet](/doc/cheatsheet.md)|
|
||||
| [Advanced Compilation Parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) | [More Cheat Sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)|
|
||||
| [Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md) | [Complete Client Command Set](/doc/commands.md) |
|
||||
@@ -77,6 +77,7 @@ We define generic Proxmark3 platforms as following devices.
|
||||
- Ryscorp green PCB version
|
||||
- Radiowar black PCB version
|
||||
- numerous Chinese adapted versions of the RDV3 easy (kkmoon, PiSwords etc)
|
||||
- Proxmark3 SE (Second edition) (BLE enabled)
|
||||
|
||||
**Not supported**
|
||||
- ⚠ Proxmark Evolution (EVO)
|
||||
@@ -96,8 +97,6 @@ We define generic Proxmark3 platforms as following devices.
|
||||
- **Note**: unknown device hw
|
||||
- ⚠ Proxmark3 Ultimate
|
||||
- **Note**: unknown device hw
|
||||
- ⚠ Proxmark3 SE
|
||||
- **Note**: unknown device hw
|
||||
|
||||
When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work.
|
||||
|
||||
@@ -185,6 +184,7 @@ This repo compiles nicely on
|
||||
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
|
||||
- Android / Termux
|
||||
- macOS / Homebrew (or MacPorts, experimental) / Apple Silicon M1
|
||||
- iOS (Jailbroken, rootful)
|
||||
- Docker container
|
||||
- [ Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
|
||||
- [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/)
|
||||
|
||||
+2
-2
@@ -37,13 +37,13 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
||||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
|
||||
SRC_HF = hfops.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_mfc.c sam_seos.c
|
||||
#UNUSED: mifaresniff.c
|
||||
SRC_ISO14443b = iso14443b.c
|
||||
SRC_FELICA = felica.c
|
||||
SRC_CRAPTO1 = crypto1.c des.c desfire_crypto.c mifaredesfire.c aes.c platform_util.c
|
||||
SRC_CRC = crc.c crc16.c crc32.c
|
||||
SRC_ICLASS = iclass.c optimized_cipherutils.c optimized_ikeys.c optimized_elite.c optimized_cipher.c
|
||||
SRC_ICLASS = iclass.c optimized_cipherutils.c optimized_ikeys.c optimized_elite.c optimized_cipher.c sam_picopass.c
|
||||
SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
|
||||
SRC_NFCBARCODE = thinfilm.c
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
#define HF_ICALSSS_READSIM_TEMP_MOD_BIN "iceclass-temp-mod.bin"
|
||||
#define HF_ICLASS_FULLSIM_MOD "iceclass-modified"
|
||||
#define HF_ICLASS_FULLSIM_MOD_BIN HF_ICLASS_FULLSIM_MOD".bin"
|
||||
#define HF_ICLASS_FULLSIM_MOD_EML HF_ICLASS_FULLSIM_MOD".eml"
|
||||
#define HF_ICLASS_ATTACK_BIN "iclass_mac_attack"
|
||||
|
||||
#define HF_ICLASS_CC_A "iceclass_cc_a.bin"
|
||||
@@ -117,10 +116,6 @@ static bool have_aa2(void) {
|
||||
return memcmp(aa2_key, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
|
||||
}
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
static uint8_t csns[8 * NUM_CSNS] = {
|
||||
0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
|
||||
+126
-82
@@ -28,9 +28,10 @@
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
#include "cmd.h"
|
||||
#include "commonutil.h"
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF - Reading Visa cards & Emulating a Visa MSD Transaction(ISO14443) - (Salvador Mendoza)");
|
||||
DbpString(" HF - Reading VISA cards & Emulating a VISA MSD Transaction(ISO14443) - (Salvador Mendoza)");
|
||||
}
|
||||
|
||||
/* This standalone implements two different modes: reading and emulating.
|
||||
@@ -132,9 +133,15 @@ static uint8_t treatPDOL(const uint8_t *apdu) {
|
||||
|
||||
void RunMod(void) {
|
||||
StandAloneMode();
|
||||
DbpString(_YELLOW_(">>") "Reading Visa cards & Emulating a Visa MSD Transaction a.k.a. MSDSal Started " _YELLOW_("<<"));
|
||||
DbpString("");
|
||||
DbpString(_YELLOW_(">>>") " Reading VISA cards & Emulating a VISA MSD Transaction a.k.a. MSDSal Started " _YELLOW_("<<<"));
|
||||
DbpString("");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
// also sets HIGH pointer of BigBuf enabling us to malloc w/o fiddling w the reserved emulator memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
//For reading process
|
||||
iso14a_card_select_t card_a_info;
|
||||
|
||||
@@ -146,10 +153,32 @@ void RunMod(void) {
|
||||
0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44,
|
||||
0x46, 0x30, 0x31, 0x00
|
||||
};
|
||||
uint8_t visa[13] = {
|
||||
0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x03, 0x10, 0x10, 0x00
|
||||
|
||||
uint8_t visa[] = { 0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00 };
|
||||
|
||||
|
||||
/*
|
||||
uint8_t select_aid_hdr[5] = { 0x00, 0xA4, 0x04, 0x00, 0x00 };
|
||||
static const char* aid_list [] = {
|
||||
"A00000000305076010", // VISA ELO Credit
|
||||
"A0000000031010", // VISA Debit/Credit (Classic)
|
||||
"A000000003101001", // VISA Credit
|
||||
"A000000003101002", // VISA Debit
|
||||
"A0000000032010", // VISA Electron
|
||||
"A0000000032020", // VISA
|
||||
"A0000000033010", // VISA Interlink
|
||||
"A0000000034010", // VISA Specific
|
||||
"A0000000035010", // VISA Specific
|
||||
"A0000000036010", // Domestic Visa Cash Stored Value
|
||||
"A0000000036020", // International Visa Cash Stored Value
|
||||
"A0000000038002", // VISA Auth, VisaRemAuthen EMV-CAP (DPA)
|
||||
"A0000000038010", // VISA Plus
|
||||
"A0000000039010", // VISA Loyalty
|
||||
"A000000003999910", // VISA Proprietary ATM
|
||||
"A000000098", // Visa USA Debit Card
|
||||
"A0000000980848", // Visa USA Debit Cardv
|
||||
};
|
||||
*/
|
||||
|
||||
uint8_t processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00};
|
||||
uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00};
|
||||
@@ -161,48 +190,49 @@ void RunMod(void) {
|
||||
|
||||
bool existpdol;
|
||||
|
||||
|
||||
// - MSD token card format -
|
||||
//
|
||||
//Card number: 4412 3456 0578 1234
|
||||
//Expiration date: 17/11
|
||||
//Service code: 201
|
||||
//Discretionary data: 0000030000991
|
||||
//char token[19] = {0x44,0x12,0x34,0x56,0x05,0x78,0x12,0x34,0xd1,0x71,0x12,0x01,0x00,0x00,0x03,0x00,0x00,0x99,0x1f};
|
||||
// Card number.............. 4412 3456 0578 1234
|
||||
// Expiration date.......... 17/11
|
||||
// Service code............. 201
|
||||
// Discretionary data....... 0000030000991
|
||||
// Pin verification value... 0000
|
||||
// CVV / iCvv............... 030
|
||||
// Trailing................. 000991
|
||||
|
||||
// 44 12 34 56 05 78 12 34 D 1711 2 01 00 00 03 00 00 99 1
|
||||
// char token[19] = {0x44,0x12,0x34,0x56,0x05,0x78,0x12,0x34,0xd1,0x71,0x12,0x01,0x00,0x00,0x03,0x00,0x00,0x99,0x1f};
|
||||
//
|
||||
// It is possible to initialize directly the emulation mode, having "token" with data and set "chktoken" = true ;)
|
||||
//
|
||||
char token[19] = {0x00};
|
||||
bool chktoken = false;
|
||||
|
||||
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
|
||||
// Such a response is less time critical, so we can prepare them on the fly
|
||||
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
|
||||
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
|
||||
|
||||
// UID 4 bytes(could be 7 bytes if needed it)
|
||||
uint8_t flags = FLAG_4B_UID_IN_DATA;
|
||||
// in case there is a read command received we shouldn't break
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
|
||||
uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04};
|
||||
uint8_t visauid[7] = {0xE9, 0x66, 0x5D, 0x20};
|
||||
memcpy(data, visauid, 4);
|
||||
|
||||
// to initialize the emulation
|
||||
uint8_t tagType = 11; // 11 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||
tag_response_info_t *responses;
|
||||
|
||||
uint32_t cuid = 0;
|
||||
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
|
||||
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
|
||||
uint8_t pages = 0;
|
||||
|
||||
// command buffers
|
||||
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
|
||||
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
|
||||
|
||||
|
||||
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
|
||||
// Such a response is less time critical, so we can prepare them on the fly
|
||||
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
|
||||
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
|
||||
|
||||
uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE] = {0};
|
||||
uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE] = {0};
|
||||
|
||||
// to know the transaction status
|
||||
uint8_t prevCmd = 0;
|
||||
|
||||
@@ -223,11 +253,11 @@ void RunMod(void) {
|
||||
// Checking if the user wants to go directly to emulation mode using a hardcoded track 2
|
||||
if (chktoken == true && token[0] != 0x00) {
|
||||
state = STATE_EMU;
|
||||
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
|
||||
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
|
||||
DbpString("Initialized [ " _BLUE_("emulation mode") " ]");
|
||||
DbpString("Waiting for a card reader...");
|
||||
} else {
|
||||
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
|
||||
DbpString("\n"_YELLOW_("!!") "Waiting for a Visa card...");
|
||||
DbpString("Initialized [ " _YELLOW_("reading mode") " ]");
|
||||
DbpString("Waiting for a VISA card...");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -240,20 +270,20 @@ void RunMod(void) {
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
|
||||
|
||||
if (button_pressed == BUTTON_HOLD)
|
||||
if (button_pressed == BUTTON_HOLD) {
|
||||
break;
|
||||
else if (button_pressed == BUTTON_SINGLE_CLICK) {
|
||||
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
|
||||
// pressing one time change between reading & emulation
|
||||
if (state == STATE_READ) {
|
||||
if (chktoken == true && token[0] != 0x00) {
|
||||
// only change to emulation if it saved a track 2 in memory
|
||||
state = STATE_EMU;
|
||||
DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]"));
|
||||
DbpString("[ " _BLUE_("Emulation mode") " ]");
|
||||
} else
|
||||
DbpString(_YELLOW_("!!") "Nothing in memory to emulate");
|
||||
DbpString(_YELLOW_("Nothing in memory to emulate"));
|
||||
} else {
|
||||
state = STATE_READ;
|
||||
DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]"));
|
||||
DbpString("[ " _YELLOW_("Reading mode") " ]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,35 +291,40 @@ void RunMod(void) {
|
||||
|
||||
if (state == STATE_READ) {
|
||||
LED_A_ON();
|
||||
if (chktoken)
|
||||
if (chktoken) {
|
||||
LED_C_ON();
|
||||
}
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) {
|
||||
|
||||
DbpString(_YELLOW_("+") "Found ISO 14443 Type A!");
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
chktoken = false;
|
||||
LED_C_OFF();
|
||||
LED_B_ON();
|
||||
|
||||
// add loop visa
|
||||
// for (int i = 0; i < ARRAYLEN(AIDlist); i ++) {
|
||||
// hexstr_to_byte_array("a0da02631a440a44000000a012ad10a00e800200048108", sam_apdu, &sam_len);
|
||||
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, NULL);
|
||||
|
||||
if (apdulen > 0) {
|
||||
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
|
||||
DbpString("[ " _YELLOW_("Proxmark command") " ]");
|
||||
Dbhexdump(apduslen[i], apdus[i], false);
|
||||
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
|
||||
DbpString("[ " _GREEN_("Card answer") " ]");
|
||||
Dbhexdump(apdulen - 2, apdubuffer, false);
|
||||
DbpString("----");
|
||||
DbpString("-------------------------------");
|
||||
|
||||
for (uint8_t u = 0; u < apdulen; u++) {
|
||||
if (i == 1) {
|
||||
|
||||
// check for PDOL
|
||||
if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) {
|
||||
for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++)
|
||||
|
||||
for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++) {
|
||||
pdol[e] = apdubuffer[u + e + 2];
|
||||
}
|
||||
|
||||
// generate a challenge
|
||||
plen = treatPDOL(pdol);
|
||||
@@ -309,25 +344,27 @@ void RunMod(void) {
|
||||
}
|
||||
|
||||
if (i == 1) {
|
||||
DbpString(_GREEN_("[ ") "Challenge generated" _GREEN_(" ]"));
|
||||
DbpString("[ "_GREEN_("Challenge generated") " ]");
|
||||
Dbhexdump(plen, existpdol ? ppdol : processing, false);
|
||||
}
|
||||
} else {
|
||||
DbpString(_YELLOW_("!!") "Error reading the card");
|
||||
DbpString(_RED_("Error reading the card"));
|
||||
}
|
||||
LED_B_OFF();
|
||||
}
|
||||
|
||||
if (chktoken) {
|
||||
DbpString(_RED_("[ ") "Track 2" _RED_(" ]"));
|
||||
DbpString("[ " _GREEN_("Track 2") " ]");
|
||||
Dbhexdump(19, (uint8_t *)token, false);
|
||||
DbpString(_YELLOW_("!!") "Card number");
|
||||
DbpString("[ " _GREEN_("Card Number") " ]");
|
||||
Dbhexdump(8, (uint8_t *)token, false);
|
||||
DbpString("---");
|
||||
DbpString("-------------------------------");
|
||||
DbpString("");
|
||||
DbpString("");
|
||||
LED_C_ON();
|
||||
state = STATE_EMU;
|
||||
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
|
||||
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
|
||||
DbpString("Initialized [ " _BLUE_("emulation mode") " ]");
|
||||
DbpString("Waiting for a card reader...");
|
||||
}
|
||||
}
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
@@ -340,14 +377,15 @@ void RunMod(void) {
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
// tag type: 11 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||
if (SimulateIso14443aInit(11, flags, data, &responses, &cuid, NULL, NULL, NULL) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
DbpString(_YELLOW_("!!") "Error initializing the emulation process!");
|
||||
DbpString(_RED_("Error initializing the emulation process!"));
|
||||
SpinDelay(500);
|
||||
state = STATE_READ;
|
||||
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
|
||||
DbpString("\n" _YELLOW_("!!") "Waiting for a Visa card...");
|
||||
DbpString("Initialized [ "_YELLOW_("reading mode") " ]");
|
||||
DbpString("Waiting for a VISA card...");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -366,11 +404,12 @@ void RunMod(void) {
|
||||
for (;;) {
|
||||
LED_B_OFF();
|
||||
// clean receive command buffer
|
||||
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
|
||||
DbpString(_YELLOW_("!!") "Emulator stopped");
|
||||
if (GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len) == false) {
|
||||
DbpString("Emulator stopped");
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
tag_response_info_t *p_response = NULL;
|
||||
LED_B_ON();
|
||||
|
||||
@@ -387,53 +426,49 @@ void RunMod(void) {
|
||||
|
||||
// received a HALT
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) {
|
||||
//DbpString(_YELLOW_("+") "Received a HALT");
|
||||
p_response = NULL;
|
||||
|
||||
// received a WAKEUP
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) {
|
||||
//DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
prevCmd = 0;
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
|
||||
// received request for UID (cascade 1)
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) {
|
||||
//DbpString(_YELLOW_("+") "Request for UID C1");
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
|
||||
// received a SELECT (cascade 1)
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) {
|
||||
//DbpString(_YELLOW_("+") "Request for SELECT S1");
|
||||
p_response = &responses[RESP_INDEX_SAKC1];
|
||||
|
||||
// received a RATS request
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
|
||||
DbpString(_YELLOW_("+") "Request for RATS");
|
||||
prevCmd = 0;
|
||||
//p_response = &responses[RESP_INDEX_RATS];
|
||||
|
||||
static uint8_t rRATS[] = { 0x13, 0x78, 0x80, 0x72, 0x02, 0x80, 0x31, 0x80, 0x66, 0xb1, 0x84, 0x0c, 0x01, 0x6e, 0x01, 0x83, 0x00, 0x90, 0x00 };
|
||||
|
||||
memcpy(&dynamic_response_info.response[0], rRATS, sizeof(rRATS));
|
||||
dynamic_response_info.response_n = sizeof(rRATS);
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
|
||||
} else {
|
||||
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
|
||||
Dbhexdump(len, receivedCmd, false);
|
||||
if (g_dbglevel == DBG_DEBUG) {
|
||||
DbpString("[ "_YELLOW_("Card reader command") " ]");
|
||||
Dbhexdump(len, receivedCmd, false);
|
||||
}
|
||||
|
||||
// emulate a Visa MSD(Magnetic stripe data) card
|
||||
// emulate a Visa MSD (Magnetic stripe data) card
|
||||
if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) {
|
||||
dynamic_response_info.response[0] = receivedCmd[0];
|
||||
|
||||
// depending on card reader commands, the Proxmark will answer to fool the reader
|
||||
// respond with PPSE
|
||||
if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) {
|
||||
// need to adapt lengths..
|
||||
uint8_t ppsea[39] = {
|
||||
// 0x23 = 35, skip two first bytes then the message - SW 2 is 35 = 0x23
|
||||
0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59,
|
||||
0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46,
|
||||
0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61,
|
||||
0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03,
|
||||
0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00
|
||||
0x0C, 0x4F,
|
||||
// len aid0 aid1 aid2...
|
||||
0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10,
|
||||
0x87, 0x01, 0x01, 0x90, 0x00
|
||||
};
|
||||
memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea));
|
||||
dynamic_response_info.response_n = sizeof(ppsea) + 1;
|
||||
@@ -442,10 +477,14 @@ void RunMod(void) {
|
||||
// respond Visa AID
|
||||
} else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) {
|
||||
uint8_t visauid_long[34] = {
|
||||
0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00,
|
||||
0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56,
|
||||
0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44,
|
||||
0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02,
|
||||
// 0x1E = 30, skip two first bytes then the message - SW 2 is 30 = 0x1E
|
||||
0x6F, 0x1E, 0x84,
|
||||
// len aid0 aid1 aid2....
|
||||
0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10,
|
||||
0xA5, 0x13, 0x50,
|
||||
// len V I S A C R E D I T
|
||||
0x0B, 0x56, 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54,
|
||||
0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02,
|
||||
0x90, 0x00
|
||||
};
|
||||
memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long));
|
||||
@@ -461,18 +500,21 @@ void RunMod(void) {
|
||||
|
||||
// SFI
|
||||
} else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) {
|
||||
uint8_t last[4] = {0x70, 0x15, 0x57, 0x13};
|
||||
uint8_t statusapdu[2] = {0x90, 0x00};
|
||||
uint8_t card[25];
|
||||
memcpy(&card[0], last, sizeof(last));
|
||||
uint8_t card[25] = {
|
||||
0x70, 0x15, 0x57, 0x13, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x90, 0x00
|
||||
};
|
||||
// add token array == Track 2 found before
|
||||
memcpy(&card[4], token, sizeof(token));
|
||||
memcpy(&card[23], statusapdu, sizeof(statusapdu));
|
||||
|
||||
memcpy(&dynamic_response_info.response[1], card, sizeof(card));
|
||||
dynamic_response_info.response_n = sizeof(card) + 1;
|
||||
prevCmd++;
|
||||
|
||||
} else {
|
||||
uint8_t finished[2] = {0x6f, 0x00};
|
||||
uint8_t finished[2] = {0x6F, 0x00};
|
||||
memcpy(&dynamic_response_info.response[1], finished, sizeof(finished));
|
||||
dynamic_response_info.response_n = sizeof(finished) + 1;
|
||||
if (prevCmd == 5) {
|
||||
@@ -480,7 +522,7 @@ void RunMod(void) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DbpString(_YELLOW_("!!") "Received unknown command!");
|
||||
DbpString(_RED_("Received unknown command!"));
|
||||
if (prevCmd < 4) {
|
||||
memcpy(dynamic_response_info.response, receivedCmd, len);
|
||||
dynamic_response_info.response_n = len;
|
||||
@@ -491,7 +533,7 @@ void RunMod(void) {
|
||||
}
|
||||
|
||||
if (dynamic_response_info.response_n > 0) {
|
||||
DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]"));
|
||||
DbpString("[ " _GREEN_("Proxmark3 answer") " ]");
|
||||
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);
|
||||
DbpString("----");
|
||||
|
||||
@@ -501,7 +543,7 @@ void RunMod(void) {
|
||||
|
||||
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
||||
SpinDelay(500);
|
||||
DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!");
|
||||
DbpString(_RED_("Error preparing Proxmark to answer!"));
|
||||
continue;
|
||||
}
|
||||
p_response = &dynamic_response_info;
|
||||
@@ -511,13 +553,15 @@ void RunMod(void) {
|
||||
EmSendPrecompiledCmd(p_response);
|
||||
}
|
||||
}
|
||||
switch_off();
|
||||
|
||||
switch_off();
|
||||
set_tracing(false);
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||
}
|
||||
}
|
||||
DbpString(_YELLOW_("[=]") "exiting");
|
||||
DbpString("Exit standalone mode!");
|
||||
DbpString("");
|
||||
SpinErr(15, 200, 3);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
@@ -73,29 +73,25 @@ void ModInfo(void) {
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(_YELLOW_(">>") "Relaying ISO/14443A data over Bluetooth a.k.a. reblay Started<<");
|
||||
DbpString("");
|
||||
Dbprintf(_YELLOW_(">>> ") " Relaying ISO/14443A data over Bluetooth a.k.a. reblay Started " _YELLOW_("<<<"));
|
||||
DbpString("");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
|
||||
// Such a response is less time critical, so we can prepare them on the fly
|
||||
#define DYNAMIC_RESPONSE_BUFFER_SIZE 512
|
||||
#define DYNAMIC_MODULATION_BUFFER_SIZE 1024
|
||||
|
||||
uint8_t flags = FLAG_4B_UID_IN_DATA; //UID 4 bytes(could be 7 bytes if needed it)
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break
|
||||
|
||||
uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04};
|
||||
// UID 4 bytes(could be 7 bytes if needed it)
|
||||
uint8_t flags = FLAG_4B_UID_IN_DATA;
|
||||
// in case there is a read command received we shouldn't break
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
|
||||
uint8_t visauid[7] = {0xE9, 0x66, 0x5D, 0x20};
|
||||
memcpy(data, visauid, 4);
|
||||
|
||||
// to initialize the emulation
|
||||
uint8_t tagType = 4; // 4 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||
tag_response_info_t *responses;
|
||||
|
||||
uint32_t cuid = 0;
|
||||
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
|
||||
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
|
||||
uint8_t pages = 0;
|
||||
|
||||
|
||||
// For received Bluetooth package
|
||||
uint8_t rpacket[MAX_FRAME_SIZE] = { 0x00 };
|
||||
@@ -126,6 +122,12 @@ void RunMod() {
|
||||
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
|
||||
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
|
||||
|
||||
|
||||
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
|
||||
// Such a response is less time critical, so we can prepare them on the fly
|
||||
#define DYNAMIC_RESPONSE_BUFFER_SIZE 512
|
||||
#define DYNAMIC_MODULATION_BUFFER_SIZE 1024
|
||||
|
||||
uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE] = {0};
|
||||
uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE] = {0};
|
||||
|
||||
@@ -143,9 +145,9 @@ void RunMod() {
|
||||
uint8_t state = STATE_READ;
|
||||
|
||||
if (state == STATE_READ) {
|
||||
DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]"));
|
||||
DbpString("Initialized [ " _YELLOW_("reading mode") " ]");
|
||||
} else {
|
||||
DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]"));
|
||||
DbpString("Initialized [ " _BLUE_("emulation mode") " ]");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -162,10 +164,10 @@ void RunMod() {
|
||||
else if (button_pressed == BUTTON_SINGLE_CLICK) { // Pressing one time change between reading & emulation
|
||||
if (state == STATE_READ) {
|
||||
state = STATE_EMU;
|
||||
DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]"));
|
||||
DbpString("[ " _BLUE_("Emulation mode") " ]");
|
||||
} else {
|
||||
state = STATE_READ;
|
||||
DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]"));
|
||||
DbpString("[ " _YELLOW_("Reading mode") " ]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +180,7 @@ void RunMod() {
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) {
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// Get data to send a ping with UID + ATQA + SAK
|
||||
@@ -208,7 +211,9 @@ void RunMod() {
|
||||
Dbhexdump(uidlen + 4, rdata, false);
|
||||
|
||||
DbpString(_YELLOW_("[ ") "Sending ping" _YELLOW_(" ]"));
|
||||
|
||||
if (usart_writebuffer_sync(rdata, uidlen + 4) == PM3_SUCCESS) {
|
||||
|
||||
DbpString(_YELLOW_("[ ") "Sent!" _YELLOW_(" ]"));
|
||||
|
||||
for (;;) {
|
||||
@@ -261,26 +266,31 @@ void RunMod() {
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
// 4 = ISO/IEC 14443-4 - javacard (JCOP)
|
||||
if (SimulateIso14443aInit(4, flags, data, &responses, &cuid, NULL, NULL, NULL) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
DbpString(_YELLOW_("!!") "Error initializing the emulation process!");
|
||||
DbpString(_RED_("Error initializing the emulation process!"));
|
||||
SpinDelay(500);
|
||||
state = STATE_READ;
|
||||
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
|
||||
DbpString("Initialized [ "_YELLOW_("reading mode") " ]");
|
||||
continue;
|
||||
}
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
|
||||
int len = 0; // Command length
|
||||
int retval = PM3_SUCCESS; // Check emulation status
|
||||
// Command length
|
||||
int len = 0;
|
||||
// Check emulation status
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
uint8_t resp = 0; // Bluetooth response
|
||||
// Bluetooth response
|
||||
uint8_t resp = 0;
|
||||
lenpacket = 0;
|
||||
|
||||
uint8_t prevcmd = 0x00; // Keep track of last terminal type command
|
||||
// Keep track of last terminal type command
|
||||
uint8_t prevcmd = 0x00;
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
@@ -288,11 +298,12 @@ void RunMod() {
|
||||
for (;;) {
|
||||
LED_B_OFF();
|
||||
// Clean receive command buffer
|
||||
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
|
||||
DbpString(_YELLOW_("!!") "Emulator stopped");
|
||||
if (GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len) == false) {
|
||||
DbpString("Emulator stopped");
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
tag_response_info_t *p_response = NULL;
|
||||
LED_B_ON();
|
||||
|
||||
@@ -314,46 +325,42 @@ void RunMod() {
|
||||
}
|
||||
}
|
||||
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
|
||||
// DbpString(_YELLOW_("+") "REQUEST Received");
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||
// DbpString(_YELLOW_("+") "Received a HALT");
|
||||
p_response = NULL;
|
||||
resp = 0;
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
// DbpString(_YELLOW_("+") "WAKEUP Received");
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
resp = 0;
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
|
||||
// DbpString(_YELLOW_("+") "Request for UID C1");
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||
// DbpString(_YELLOW_("+") "Request for SELECT S1");
|
||||
p_response = &responses[RESP_INDEX_SAKC1];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||
// DbpString(_YELLOW_("+") "Request for RATS");
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
resp = 1;
|
||||
} else if (receivedCmd[0] == 0xf2 && len == 4) { // ACKed - Time extension
|
||||
DbpString(_YELLOW_("!!") "Reader accepted time extension!");
|
||||
DbpString(_YELLOW_("!!") " Reader accepted time extension!");
|
||||
p_response = NULL;
|
||||
} else if ((receivedCmd[0] == 0xb2 || receivedCmd[0] == 0xb3) && len == 3) { //NACK - Request more time WTX
|
||||
DbpString(_YELLOW_("!!") "NACK - time extension request?");
|
||||
DbpString(_YELLOW_("!!") " NACK - time extension request?");
|
||||
if (resp == 2 && lenpacket == 0) {
|
||||
DbpString(_YELLOW_("!!") "Requesting more time - WTX");
|
||||
DbpString(_YELLOW_("!!") " Requesting more time - WTX");
|
||||
dynamic_response_info.response_n = 2;
|
||||
dynamic_response_info.response[0] = 0xf2;
|
||||
dynamic_response_info.response[1] = 0x0b; // Requesting the maximum amount of time
|
||||
} else if (lenpacket == 0) {
|
||||
DbpString(_YELLOW_("!!") "NACK - ACK - Resend last command!"); // To burn some time as well
|
||||
DbpString(_YELLOW_("!!") " NACK - ACK - Resend last command!"); // To burn some time as well
|
||||
dynamic_response_info.response[0] = 0xa3;
|
||||
dynamic_response_info.response_n = 1;
|
||||
} else {
|
||||
DbpString(_YELLOW_("!!") "Avoiding request - Bluetooth data already in memory!!");
|
||||
DbpString(_YELLOW_("!!") " Avoiding request - Bluetooth data already in memory!!");
|
||||
}
|
||||
} else {
|
||||
DbpString(_GREEN_("[ ") "Card reader command" _GREEN_(" ]"));
|
||||
Dbhexdump(len - 2, &receivedCmd[1], false);
|
||||
if (g_dbglevel == DBG_DEBUG) {
|
||||
DbpString("[ "_YELLOW_("Card reader command") " ]");
|
||||
Dbhexdump(len - 2, &receivedCmd[1], false);
|
||||
}
|
||||
|
||||
if ((receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) && len > 3) { // Process reader commands
|
||||
|
||||
@@ -379,16 +386,17 @@ void RunMod() {
|
||||
|
||||
} else {
|
||||
if (lenpacket == 0) {
|
||||
DbpString(_YELLOW_("!!") "Received unknown command!");
|
||||
DbpString(_RED_("Received unknown command!"));
|
||||
memcpy(dynamic_response_info.response, receivedCmd, len);
|
||||
dynamic_response_info.response_n = len;
|
||||
} else {
|
||||
DbpString(_YELLOW_("!!") "Avoiding unknown command - Bluetooth data already in memory!!");
|
||||
DbpString(_YELLOW_("!!") " Avoiding unknown command - Bluetooth data already in memory !!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic_response_info.response_n > 0) {
|
||||
DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]"));
|
||||
DbpString("[ " _GREEN_("Proxmark3 answer") " ]");
|
||||
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);
|
||||
DbpString("----");
|
||||
if (lenpacket > 0) {
|
||||
@@ -402,7 +410,7 @@ void RunMod() {
|
||||
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
||||
Dbprintf(_YELLOW_("[ ") "Buffer size: %d "_YELLOW_(" ]"), dynamic_response_info.response_n);
|
||||
SpinDelay(500);
|
||||
DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!");
|
||||
DbpString(_RED_("Error preparing Proxmark to answer!"));
|
||||
continue;
|
||||
}
|
||||
p_response = &dynamic_response_info;
|
||||
@@ -412,13 +420,15 @@ void RunMod() {
|
||||
EmSendPrecompiledCmd(p_response);
|
||||
}
|
||||
}
|
||||
switch_off();
|
||||
|
||||
switch_off();
|
||||
set_tracing(false);
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||
}
|
||||
}
|
||||
DbpString(_YELLOW_("[=]") "exiting");
|
||||
DbpString("Exit standalone mode!");
|
||||
DbpString("");
|
||||
SpinErr(15, 200, 3);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
+30
-8
@@ -62,7 +62,9 @@
|
||||
#include "crc16.h"
|
||||
#include "protocols.h"
|
||||
#include "mifareutil.h"
|
||||
|
||||
#include "sam_picopass.h"
|
||||
#include "sam_seos.h"
|
||||
#include "sam_mfc.h"
|
||||
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD_disabled.h"
|
||||
@@ -367,11 +369,10 @@ static void print_debug_level(void) {
|
||||
|
||||
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
|
||||
// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the PacketCommandNG structure included.
|
||||
static void printConnSpeed(void) {
|
||||
static void printConnSpeed(uint32_t wait) {
|
||||
DbpString(_CYAN_("Transfer Speed"));
|
||||
Dbprintf(" Sending packets to client...");
|
||||
|
||||
#define CONN_SPEED_TEST_MIN_TIME 500 // in milliseconds
|
||||
uint8_t *test_data = BigBuf_get_addr();
|
||||
uint32_t start_time = GetTickCount();
|
||||
uint32_t delta_time = 0;
|
||||
@@ -379,7 +380,7 @@ static void printConnSpeed(void) {
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
while (delta_time < CONN_SPEED_TEST_MIN_TIME) {
|
||||
while (delta_time < wait) {
|
||||
reply_ng(CMD_DOWNLOADED_BIGBUF, PM3_SUCCESS, test_data, PM3_CMD_DATA_SIZE);
|
||||
bytes_transferred += PM3_CMD_DATA_SIZE;
|
||||
delta_time = GetTickCountDelta(start_time);
|
||||
@@ -388,13 +389,15 @@ static void printConnSpeed(void) {
|
||||
|
||||
Dbprintf(" Time elapsed................... %dms", delta_time);
|
||||
Dbprintf(" Bytes transferred.............. %d", bytes_transferred);
|
||||
Dbprintf(" Transfer Speed PM3 -> Client... " _YELLOW_("%d") " bytes/s", 1000 * bytes_transferred / delta_time);
|
||||
if (delta_time) {
|
||||
Dbprintf(" Transfer Speed PM3 -> Client... " _YELLOW_("%llu") " bytes/s", 1000 * (uint64_t)bytes_transferred / delta_time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints runtime information about the PM3.
|
||||
**/
|
||||
static void SendStatus(void) {
|
||||
static void SendStatus(uint32_t wait) {
|
||||
BigBuf_print_status();
|
||||
Fpga_print_status();
|
||||
#ifdef WITH_FLASH
|
||||
@@ -410,7 +413,7 @@ static void SendStatus(void) {
|
||||
#ifdef WITH_ISO14443a
|
||||
printHf14aConfig(); // HF 14a config
|
||||
#endif
|
||||
printConnSpeed();
|
||||
printConnSpeed(wait);
|
||||
DbpString(_CYAN_("Various"));
|
||||
|
||||
print_stack_usage();
|
||||
@@ -1684,6 +1687,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
case CMD_HF_MIFARE_EML_MEMCLR: {
|
||||
MifareEMemClr();
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_MEMSET: {
|
||||
@@ -2038,6 +2042,21 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
fwdata = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_HF_SAM_PICOPASS: {
|
||||
sam_picopass_get_pacs();
|
||||
break;
|
||||
}
|
||||
case CMD_HF_SAM_SEOS: {
|
||||
// sam_seos_get_pacs();
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_HF_SAM_MFC: {
|
||||
// sam_mfc_get_pacs();
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FPC_USART
|
||||
@@ -2645,7 +2664,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_STATUS: {
|
||||
SendStatus();
|
||||
if (packet->length == 4)
|
||||
SendStatus(packet->data.asDwords[0]);
|
||||
else
|
||||
SendStatus(CONN_SPEED_TEST_MIN_TIME_DEFAULT);
|
||||
break;
|
||||
}
|
||||
case CMD_TIA: {
|
||||
|
||||
@@ -37,6 +37,9 @@ int tearoff_hook(void);
|
||||
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
|
||||
#define MAX_ADC_LF_VOLTAGE 140800
|
||||
|
||||
// Default connection speed test timeout, used in hw status
|
||||
#define CONN_SPEED_TEST_MIN_TIME_DEFAULT 500 // in milliseconds
|
||||
|
||||
extern int ToSendMax;
|
||||
extern uint8_t ToSend[];
|
||||
|
||||
|
||||
+21
-13
@@ -76,11 +76,11 @@ void Dbprintf(const char *fmt, ...) {
|
||||
// prints HEX & ASCII
|
||||
void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
|
||||
#if DEBUG
|
||||
char ascii[9];
|
||||
char ascii[17];
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
int l = (len > 8) ? 8 : len;
|
||||
int l = (len > 16) ? 16 : len;
|
||||
|
||||
memcpy(ascii, d, l);
|
||||
ascii[l] = 0;
|
||||
@@ -97,33 +97,41 @@ void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
|
||||
else
|
||||
Dbprintf("%*D", l, d, " ");
|
||||
|
||||
len -= 8;
|
||||
d += 8;
|
||||
len -= 16;
|
||||
d += 16;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_result(const char *name, const uint8_t *buf, size_t len) {
|
||||
void print_result(const char *name, const uint8_t *d, size_t n) {
|
||||
|
||||
const uint8_t *p = buf;
|
||||
uint16_t tmp = len & 0xFFF0;
|
||||
const uint8_t *p = d;
|
||||
uint16_t tmp = n & 0xFFF0;
|
||||
|
||||
for (; p - buf < tmp; p += 16) {
|
||||
for (; p - d < tmp; p += 16) {
|
||||
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
name,
|
||||
p - buf,
|
||||
len,
|
||||
p - d,
|
||||
n,
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
|
||||
);
|
||||
}
|
||||
if (len % 16 != 0) {
|
||||
|
||||
if (n % 16 != 0) {
|
||||
char s[46] = {0};
|
||||
char *sp = s;
|
||||
for (; p - buf < len; p++) {
|
||||
for (; p - d < n; p++) {
|
||||
sprintf(sp, "%02x ", p[0]);
|
||||
sp += 3;
|
||||
}
|
||||
Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s);
|
||||
Dbprintf("[%s: %02d/%02d] %s", name, p - d, n, s);
|
||||
}
|
||||
}
|
||||
|
||||
// Prints message and hexdump
|
||||
void print_dbg(char *msg, uint8_t *d, uint16_t n) {
|
||||
if (g_dbglevel == DBG_DEBUG) {
|
||||
print_result(msg, d, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ void Dbprintf(const char *fmt, ...);
|
||||
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
||||
void Dbhexdump(int len, const uint8_t *d, bool bAsci);
|
||||
void print_result(const char *name, const uint8_t *buf, size_t len);
|
||||
void print_dbg(char *msg, uint8_t *d, uint16_t n);
|
||||
//void PrintToSendBuffer(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -569,7 +569,7 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
|
||||
uint8_t *spaceptr = NULL;
|
||||
|
||||
/*
|
||||
keybits = malloc(2080);
|
||||
keybits = calloc(2080, sizeof(uint8_t));
|
||||
if (!keybits) {
|
||||
UserMessage("cannot malloc keybits\r\n");
|
||||
return false;
|
||||
|
||||
+217
-129
File diff suppressed because it is too large
Load Diff
+10
-1
@@ -30,6 +30,15 @@
|
||||
#define I2C_DEVICE_CMD_GETVERSION 0x06
|
||||
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
||||
|
||||
// The SIM module v4 supports up to 384 bytes for the length.
|
||||
#define ISO7816_MAX_FRAME 270
|
||||
|
||||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1 byte transfer == 1ms with max frame being 256 bytes
|
||||
#define SIM_WAIT_DELAY 88000 // about 270ms delay // 109773 -- about 337.7ms delay
|
||||
|
||||
|
||||
void I2C_recovery(void);
|
||||
void I2C_init(bool has_ticks);
|
||||
void I2C_Reset(void);
|
||||
@@ -48,7 +57,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint16_t len, uint8_t device_cmd, uint8_t
|
||||
int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
bool I2C_WriteFW(const uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
|
||||
|
||||
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen);
|
||||
bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen, uint32_t wait);
|
||||
//
|
||||
bool GetATR(smart_card_atr_t *card_ptr, bool verbose);
|
||||
|
||||
|
||||
+19
-32
@@ -36,9 +36,10 @@
|
||||
#include "protocols.h"
|
||||
#include "ticks.h"
|
||||
#include "iso15693.h"
|
||||
#include "iclass_cmd.h" /* iclass_card_select_t struct */
|
||||
#include "iclass_cmd.h" // iclass_card_select_t struct
|
||||
#include "i2c.h" // i2c defines (SIM module access)
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
@@ -52,23 +53,6 @@ static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
#define ICLASS_16KS_SIZE 0x100 * 8
|
||||
#endif
|
||||
|
||||
// iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after
|
||||
// the reader command. This is measured from end of reader EOF to first modulation of the tag's SOF which starts with a 56,64us unmodulated period.
|
||||
// 330us = 140 ssp_clk cycles @ 423,75kHz when simulating.
|
||||
// 56,64us = 24 ssp_clk_cycles
|
||||
#define DELAY_ICLASS_VCD_TO_VICC_SIM (140 - 26) // (140 - 24)
|
||||
|
||||
// times in ssp_clk_cycles @ 3,3625MHz when acting as reader
|
||||
#define DELAY_ICLASS_VICC_TO_VCD_READER DELAY_ISO15693_VICC_TO_VCD_READER
|
||||
|
||||
// times in samples @ 212kHz when acting as reader
|
||||
#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us
|
||||
#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms
|
||||
#define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us
|
||||
|
||||
#define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
||||
|
||||
/*
|
||||
* CARD TO READER
|
||||
* in ISO15693-2 mode - Manchester
|
||||
@@ -1245,7 +1229,7 @@ send:
|
||||
}
|
||||
|
||||
// THE READER CODE
|
||||
static void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod) {
|
||||
void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod) {
|
||||
CodeIso15693AsReader(frame, len);
|
||||
tosend_t *ts = get_tosend();
|
||||
TransmitTo15693Tag(ts->buf, ts->max, start_time, shallow_mod);
|
||||
@@ -1784,7 +1768,6 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac,
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (blockno == 2) {
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(data + 4, resp, 4) || memcmp(data, resp + 4, 4)) {
|
||||
@@ -1792,6 +1775,7 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac,
|
||||
}
|
||||
} else if (blockno == 3 || blockno == 4) {
|
||||
// check response. Key updates always return 0xffffffffffffffff
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (memcmp(all_ff, resp, 8)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1821,7 +1805,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr_t hdr = {0};
|
||||
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
|
||||
bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
@@ -1881,8 +1865,9 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
res = false;
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
|
||||
if (payload->req.send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(bool));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
||||
@@ -1901,16 +1886,16 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
}
|
||||
|
||||
// verify write
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (pagemap == PICOPASS_SECURE_PAGEMODE && payload->req.blockno == 2) {
|
||||
if ((pagemap != PICOPASS_NON_SECURE_PAGEMODE) && (payload->req.blockno == 2)) {
|
||||
// check response. e-purse update swaps first and second half
|
||||
if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
} else if (pagemap == PICOPASS_SECURE_PAGEMODE && (payload->req.blockno == 3 || payload->req.blockno == 4)) {
|
||||
} else if ((pagemap != PICOPASS_NON_SECURE_PAGEMODE) && (payload->req.blockno == 3 || payload->req.blockno == 4)) {
|
||||
// check response. Key updates always return 0xffffffffffffffff
|
||||
if (memcmp(all_ff, resp, 8)) {
|
||||
uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
if (memcmp(all_ff, resp, sizeof(all_ff))) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
@@ -1925,8 +1910,9 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
out:
|
||||
switch_off();
|
||||
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
|
||||
if (payload->req.send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(bool));
|
||||
}
|
||||
}
|
||||
|
||||
void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
|
||||
@@ -1967,8 +1953,9 @@ void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
|
||||
res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), epurse, sizeof(epurse), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
|
||||
if (!res) {
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
if (payload->req.send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETIMEOUT, (uint8_t *)&res, sizeof(uint8_t));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1977,7 +1964,7 @@ void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
|
||||
|
||||
uint8_t epurse_offset = 0;
|
||||
const uint8_t empty_epurse[] = {0xff, 0xff, 0xff, 0xff};
|
||||
if (!memcmp(epurse, empty_epurse, 4)) {
|
||||
if (memcmp(epurse, empty_epurse, 4) == 0) {
|
||||
// epurse data in stage 2
|
||||
epurse_offset = 4;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,23 @@
|
||||
#include "common.h"
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
// iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after
|
||||
// the reader command. This is measured from end of reader EOF to first modulation of the tag's SOF which starts with a 56,64us unmodulated period.
|
||||
// 330us = 140 ssp_clk cycles @ 423,75kHz when simulating.
|
||||
// 56,64us = 24 ssp_clk_cycles
|
||||
#define DELAY_ICLASS_VCD_TO_VICC_SIM (140 - 26) // (140 - 24)
|
||||
|
||||
// times in ssp_clk_cycles @ 3,3625MHz when acting as reader
|
||||
#define DELAY_ICLASS_VICC_TO_VCD_READER DELAY_ISO15693_VICC_TO_VCD_READER
|
||||
|
||||
|
||||
// times in samples @ 212kHz when acting as reader
|
||||
#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us
|
||||
#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms
|
||||
#define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us
|
||||
|
||||
#define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
void ReaderIClass(uint8_t flags);
|
||||
|
||||
@@ -43,4 +60,7 @@ bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, ui
|
||||
|
||||
bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
|
||||
uint8_t get_pagemap(const picopass_hdr_t *hdr);
|
||||
void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod);
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user