mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge pull request #6 from RfidResearchGroup/master
Update from upstream.
This commit is contained in:
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Attach",
|
||||
"type": "cppdbg",
|
||||
"request": "attach",
|
||||
"program": "${cwd}/client/proxmark3",
|
||||
//"processId": "${command:pickProcess}",
|
||||
"processId": "${input:ProcessID}",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},{
|
||||
"name": "(gdb) Build & Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${cwd}/client/proxmark3",
|
||||
"args": ["/dev/ttyACM0"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "client: Debug: clean & make",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
// Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input
|
||||
"id": "ProcessID",
|
||||
"type": "command",
|
||||
"command": "shellCommand.execute",
|
||||
"args": {
|
||||
"command": "pgrep -n proxmark3",
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+65
-7
@@ -4,24 +4,82 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"label": "all: Make & run",
|
||||
"type": "shell",
|
||||
"command": "make clean && make all -j$(nproc --all)",
|
||||
"command": "make -j && ./pm3",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "flash fullimage",
|
||||
"label": "choose: Make",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-fullimage",
|
||||
"command": "make ${input:componentType} -j",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "client: Debug: make",
|
||||
"type": "shell",
|
||||
"command": "make client -j DEBUG=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "client: Debug: clean & make",
|
||||
"type": "shell",
|
||||
"command": "make client/clean && make client -j DEBUG=1",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build",
|
||||
},
|
||||
{
|
||||
"label": "fullimage: Make & Flash",
|
||||
"type": "shell",
|
||||
"command": "make fullimage && ./pm3-flash-fullimage",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "FLASH BOOTROM",
|
||||
"label": "BOOTROM: Make & Flash",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-bootrom",
|
||||
"command": "make bootrom && ./pm3-flash-bootrom",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Run client",
|
||||
"type": "shell",
|
||||
"command": "./pm3",
|
||||
"problemMatcher": []
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"type": "pickString",
|
||||
"id": "componentType",
|
||||
"description": "What Makefile target do you want to execute?",
|
||||
"options": [
|
||||
"all",
|
||||
"client",
|
||||
"bootrom",
|
||||
"fullimage",
|
||||
"recovery",
|
||||
"clean",
|
||||
"install",
|
||||
"uninstall",
|
||||
"style",
|
||||
"miscchecks",
|
||||
"check",
|
||||
],
|
||||
"default": "all"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,6 +3,7 @@ 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]
|
||||
- Removed 'hf iclass replay' - use the 'hf iclass dump' or 'hf iclass rdbl' with option "n" instead (@iceman1001). Concept taken from official repo (@pwpiwi)
|
||||
- Add low level support for 14b' aka Innovatron (@doegox)
|
||||
- Add doc/cliparser.md (@mwalker33)
|
||||
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
||||
|
||||
+33
-12
@@ -27,6 +27,9 @@ LD = g++
|
||||
SH = sh
|
||||
BASH = bash
|
||||
PERL = perl
|
||||
CCC =foo
|
||||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
|
||||
PATHSEP=/
|
||||
PREFIX ?= /usr/local
|
||||
@@ -40,17 +43,29 @@ INSTALLDOCSRELPATH ?= share/doc/proxmark3
|
||||
platform = $(shell uname)
|
||||
DETECTED_OS=$(platform)
|
||||
|
||||
ifeq ($(platform),Darwin)
|
||||
AR= /usr/bin/ar rcs
|
||||
RANLIB= /usr/bin/ranlib
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
DETECTED_COMPILER = clang
|
||||
else
|
||||
AR= ar rcs
|
||||
RANLIB= ranlib
|
||||
DETECTED_COMPILER = gcc
|
||||
endif
|
||||
|
||||
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
|
||||
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
ifeq ($(platform),Darwin)
|
||||
AR= /usr/bin/ar rcs
|
||||
RANLIB= /usr/bin/ranlib
|
||||
else
|
||||
AR= ar rcs
|
||||
RANLIB= ranlib
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
DEFCXXFLAGS = -g -O0 -pipe
|
||||
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
else
|
||||
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
|
||||
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||
DEFLDFLAGS =
|
||||
endif
|
||||
# Next ones are activated only if SANITIZE=1
|
||||
ifeq ($(SANITIZE),1)
|
||||
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
|
||||
@@ -62,12 +77,18 @@ DEFCFLAGS += -Wbad-function-cast -Wredundant-decls -Wmissing-prototypes -Wchar-s
|
||||
# Some more warnings we need first to eliminate, so temporarely tolerated:
|
||||
DEFCFLAGS += -Wcast-align -Wno-error=cast-align
|
||||
DEFCFLAGS += -Wswitch-enum -Wno-error=switch-enum
|
||||
|
||||
# GCC 10 has issues with false positives on stringop-overflow, let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
|
||||
# beware these flags didn't exist for GCC < 7
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 10), 1)
|
||||
ifneq ($(DETECTED_COMPILER), clang)
|
||||
DEFCFLAGS += -Wno-stringop-overflow -Wno-error=stringop-overflow
|
||||
endif
|
||||
endif
|
||||
ifeq ($(platform),Darwin)
|
||||
# their readline has strict-prototype issues
|
||||
DEFCFLAGS += -Wno-strict-prototypes
|
||||
# their readline has strict-prototype issues
|
||||
DEFCFLAGS += -Wno-strict-prototypes
|
||||
else
|
||||
DEFCFLAGS += -Wstrict-prototypes
|
||||
DEFCFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
|
||||
# Next ones are activated only if GCCEXTRA=1 or CLANGEXTRA=1
|
||||
|
||||
@@ -302,15 +302,17 @@ static int reader_dump_mode(void) {
|
||||
Iso15693InitReader();
|
||||
set_tracing(false);
|
||||
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
bool res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
switch_off();
|
||||
continue;
|
||||
}
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
// sanity check of CSN.
|
||||
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||
switch_off();
|
||||
@@ -366,7 +368,7 @@ static int reader_dump_mode(void) {
|
||||
auth.use_credit_key = true;
|
||||
memcpy(auth.key, aa2_key, sizeof(auth.key));
|
||||
|
||||
res = select_iclass_tag(card_data, auth.use_credit_key, &eof_time);
|
||||
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||
if (res) {
|
||||
|
||||
// sanity check of CSN.
|
||||
|
||||
+38
-24
@@ -970,6 +970,23 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_LOGIN: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EM4xLogin(payload->password);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_BF: {
|
||||
struct p {
|
||||
uint32_t start_pwd;
|
||||
uint32_t n;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EM4xBruteforce(payload->start_pwd, payload->n);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_READWORD: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
@@ -1242,7 +1259,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_ANTIFUZZ: {
|
||||
iso14443a_antifuzz(packet->oldarg[0]);
|
||||
struct p {
|
||||
uint8_t flag;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
iso14443a_antifuzz(payload->flag);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_EPA_COLLECT_NONCE: {
|
||||
@@ -1473,12 +1494,12 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MFU_COUNTER_TEAROFF: {
|
||||
case CMD_HF_MFU_COUNTER_TEAROFF: {
|
||||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
|
||||
break;
|
||||
}
|
||||
@@ -1512,6 +1533,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_SIMULATE: {
|
||||
/*
|
||||
struct p {
|
||||
uint8_t reader[4];
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
*/
|
||||
|
||||
SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
@@ -1519,15 +1548,6 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
ReaderIClass(packet->oldarg[0]);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_REPLAY: {
|
||||
struct p {
|
||||
uint8_t reader[4];
|
||||
uint8_t mac[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
ReaderIClass_Replay(payload->reader, payload->mac);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_EML_MEMSET: {
|
||||
//iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
@@ -1554,18 +1574,8 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
iClass_Dump(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_CLONE: {
|
||||
struct p {
|
||||
uint8_t startblock;
|
||||
uint8_t endblock;
|
||||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
iClass_Clone(payload->startblock, payload->endblock, payload->data);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_RESTORE: {
|
||||
iClass_Restore(packet->data.asBytes);
|
||||
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1607,7 +1617,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_SMART_SETCLOCK: {
|
||||
SmartCardSetClock(packet->oldarg[0]);
|
||||
struct p {
|
||||
uint32_t new_clk;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
SmartCardSetClock(payload->new_clk);
|
||||
break;
|
||||
}
|
||||
case CMD_SMART_RAW: {
|
||||
|
||||
+62
-38
@@ -14,6 +14,7 @@
|
||||
#include "lfadc.h"
|
||||
#include "commonutil.h"
|
||||
#include "em4x50.h"
|
||||
#include "appmain.h" // tear
|
||||
|
||||
// 4 data bytes
|
||||
// + byte with row parities
|
||||
@@ -470,10 +471,12 @@ static bool find_double_listen_window(bool bcommand) {
|
||||
|
||||
if (bcommand) {
|
||||
|
||||
// SpinDelay(10);
|
||||
|
||||
// data transmission from card has to be stopped, because
|
||||
// a commamd shall be issued
|
||||
|
||||
// unfortunately the posititon in listen window (where
|
||||
// unfortunately the position in listen window (where
|
||||
// command request has to be sent) has gone, so if a
|
||||
// second window follows - sync on this to issue a command
|
||||
|
||||
@@ -519,7 +522,7 @@ static bool find_em4x50_tag(void) {
|
||||
static bool request_receive_mode(void) {
|
||||
|
||||
// To issue a command we have to find a listen window first.
|
||||
// Because identification and sychronization at the same time is not
|
||||
// Because identification and synchronization at the same time is not
|
||||
// possible when using pulse lengths a double listen window is used.
|
||||
bool bcommand = true;
|
||||
return find_double_listen_window(bcommand);
|
||||
@@ -556,7 +559,7 @@ static bool check_ack(bool bliw) {
|
||||
// "bit" of listen window)
|
||||
wait_timer(FPGA_TIMER_0, T0 * 2 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
|
||||
// check for listen window (if first bit cannot be inerpreted
|
||||
// check for listen window (if first bit cannot be interpreted
|
||||
// as a valid bit it must belong to a listen window)
|
||||
if (get_next_bit() == EM4X50_BIT_OTHER) {
|
||||
|
||||
@@ -727,7 +730,7 @@ static bool standard_read(int *now) {
|
||||
int fwr = *now;
|
||||
uint8_t bits[EM4X50_TAG_WORD] = {0};
|
||||
|
||||
// start with the identification of two succsessive listening windows
|
||||
// start with the identification of two successive listening windows
|
||||
if (find_double_listen_window(false)) {
|
||||
|
||||
// read and save words until following double listen window is detected
|
||||
@@ -816,7 +819,7 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||
status = (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_INFO, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
void em4x50_read(em4x50_data_t *etd) {
|
||||
@@ -860,14 +863,13 @@ void em4x50_read(em4x50_data_t *etd) {
|
||||
status = (now << 2) + (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_READ, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// write functions
|
||||
//==============================================================================
|
||||
|
||||
static bool write(uint8_t word[4], uint8_t address) {
|
||||
static int write(uint8_t word[4], uint8_t address) {
|
||||
|
||||
// writes <word> to specified <address>
|
||||
|
||||
@@ -882,17 +884,23 @@ static bool write(uint8_t word[4], uint8_t address) {
|
||||
// send data
|
||||
em4x50_send_word(word);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, PM3_ETEAROFF, NULL, 0);
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
|
||||
// look for ACK sequence
|
||||
if (check_ack(false)) {
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
|
||||
// for saving data and should return with ACK
|
||||
if (check_ack(false))
|
||||
return true;
|
||||
// look for ACK sequence
|
||||
if (check_ack(false)) {
|
||||
|
||||
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
|
||||
// for saving data and should return with ACK
|
||||
if (check_ack(false))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -900,10 +908,10 @@ static bool write(uint8_t word[4], uint8_t address) {
|
||||
Dbprintf("error in command request");
|
||||
}
|
||||
|
||||
return false;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
static int write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
|
||||
// changes password from <password> to <new_password>
|
||||
|
||||
@@ -915,23 +923,29 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
// send address data
|
||||
em4x50_send_word(password);
|
||||
|
||||
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, PM3_ETEAROFF, NULL, 0);
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
|
||||
// look for ACK sequence and send rm request
|
||||
// during following listen window
|
||||
if (check_ack(true)) {
|
||||
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
|
||||
|
||||
// send new password
|
||||
em4x50_send_word(new_password);
|
||||
// look for ACK sequence and send rm request
|
||||
// during following listen window
|
||||
if (check_ack(true)) {
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
// send new password
|
||||
em4x50_send_word(new_password);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
if (check_ack(false))
|
||||
if (check_ack(false))
|
||||
return true;
|
||||
if (check_ack(false))
|
||||
return PM3_SUCCESS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -939,7 +953,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
Dbprintf("error in command request");
|
||||
}
|
||||
|
||||
return false;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
void em4x50_write(em4x50_data_t *etd) {
|
||||
@@ -966,8 +980,13 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||
blogin = login(etd->password);
|
||||
|
||||
// write word to given address
|
||||
if (write(etd->word, etd->address)) {
|
||||
int res = write(etd->word, etd->address);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
lf_finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (res == PM3_SUCCESS) {
|
||||
// to verify result reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
@@ -996,14 +1015,13 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||
}
|
||||
|
||||
status = (bsuccess << 1) + blogin;
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_WRITE, status, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
void em4x50_write_password(em4x50_data_t *etd) {
|
||||
|
||||
// sinmple change of password
|
||||
// simple change of password
|
||||
|
||||
bool bsuccess = false;
|
||||
|
||||
@@ -1015,12 +1033,18 @@ void em4x50_write_password(em4x50_data_t *etd) {
|
||||
|
||||
// login and change password
|
||||
if (login(etd->password)) {
|
||||
bsuccess = write_password(etd->password, etd->new_password);
|
||||
|
||||
int res = write_password(etd->password, etd->new_password);
|
||||
if (res == PM3_ETEAROFF) {
|
||||
lf_finalize();
|
||||
return;
|
||||
}
|
||||
bsuccess = (res == PM3_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, 0, 0);
|
||||
reply_ng(CMD_LF_EM4X50_WRITE_PASSWORD, bsuccess, 0, 0);
|
||||
}
|
||||
|
||||
void em4x50_wipe(em4x50_data_t *etd) {
|
||||
@@ -1049,7 +1073,7 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
||||
// to verify result reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
// login not necessary because protectd word has been set to 0
|
||||
// login not necessary because protected word has been set to 0
|
||||
// -> no read protected words
|
||||
// -> selective read can be called immediately
|
||||
if (selective_read(addresses)) {
|
||||
@@ -1078,5 +1102,5 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, (uint8_t *)tag.sectors, 238);
|
||||
reply_ng(CMD_LF_EM4X50_WIPE, bsuccess, (uint8_t *)tag.sectors, 238);
|
||||
}
|
||||
|
||||
+18
-25
@@ -47,12 +47,6 @@ static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
||||
#define I2C_DELAY_2CLK I2CSpinDelayClk(2)
|
||||
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
||||
|
||||
#define I2C_DELAY_100us I2CSpinDelayClk( 100 / 3)
|
||||
#define I2C_DELAY_600us I2CSpinDelayClk( 600 / 3)
|
||||
#define I2C_DELAY_10ms I2CSpinDelayClk( 10 * 1000 / 3 )
|
||||
#define I2C_DELAY_30ms I2CSpinDelayClk( 30 * 1000 / 3 )
|
||||
#define I2C_DELAY_100ms I2CSpinDelayClk( 100 * 1000 / 3)
|
||||
|
||||
#define ISO7618_MAX_FRAME 255
|
||||
|
||||
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||
@@ -134,11 +128,11 @@ void I2C_Reset_EnterMainProgram(void) {
|
||||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_SetResetStatus(0, 0, 0);
|
||||
I2C_DELAY_30ms;
|
||||
WaitMS(30);
|
||||
I2C_SetResetStatus(1, 0, 0);
|
||||
I2C_DELAY_30ms;
|
||||
WaitMS(30);
|
||||
I2C_SetResetStatus(1, 1, 1);
|
||||
I2C_DELAY_10ms;
|
||||
WaitMS(10);
|
||||
}
|
||||
|
||||
// Reset the SIM_Adapter, then enter the bootloader program
|
||||
@@ -147,9 +141,9 @@ void I2C_Reset_EnterBootloader(void) {
|
||||
StartTicks();
|
||||
I2C_init();
|
||||
I2C_SetResetStatus(0, 1, 1);
|
||||
I2C_DELAY_100ms;
|
||||
WaitMS(100);
|
||||
I2C_SetResetStatus(1, 1, 1);
|
||||
I2C_DELAY_10ms;
|
||||
WaitMS(10);
|
||||
}
|
||||
|
||||
// Wait for the clock to go High.
|
||||
@@ -187,13 +181,13 @@ static bool WaitSCL_L(void) {
|
||||
// It timeout reading response from card
|
||||
// Which ever comes first
|
||||
static bool WaitSCL_L_timeout(void) {
|
||||
volatile uint32_t delay = 18000;
|
||||
volatile uint32_t delay = 1800;
|
||||
while (delay--) {
|
||||
// exit on SCL LOW
|
||||
if (!SCL_read)
|
||||
return true;
|
||||
|
||||
I2C_DELAY_100us;
|
||||
WaitMS(1);
|
||||
}
|
||||
return (delay == 0);
|
||||
}
|
||||
@@ -225,7 +219,7 @@ static bool I2C_WaitForSim(void) {
|
||||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
if (!WaitSCL_H_delay(30 * 1000 * 50))
|
||||
if (!WaitSCL_H_delay(20 * 1000 * 50))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -440,8 +434,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
|
||||
|
||||
// extra wait 500us (514us measured)
|
||||
// 200us (xx measured)
|
||||
// WaitUS(600);
|
||||
I2C_DELAY_600us;
|
||||
WaitUS(600);
|
||||
|
||||
bool bBreak = true;
|
||||
uint16_t readcount = 0;
|
||||
@@ -641,6 +634,9 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) {
|
||||
|
||||
len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
if (len > 1) {
|
||||
break;
|
||||
} else if (len == 1) {
|
||||
@@ -674,7 +670,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
// 1byte = 1ms , max frame 256bytes. Should wait 256ms atleast just in case.
|
||||
if (I2C_WaitForSim() == false)
|
||||
return false;
|
||||
|
||||
|
||||
// read bytes from module
|
||||
uint8_t len = sizeof(card_ptr->atr);
|
||||
if (sc_rx_bytes(card_ptr->atr, &len) == false)
|
||||
@@ -713,12 +709,12 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
}
|
||||
|
||||
void SmartCardAtr(void) {
|
||||
smart_card_atr_t card;
|
||||
LED_D_ON();
|
||||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
bool isOK = GetATR(&card, true);
|
||||
reply_mix(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
smart_card_atr_t card;
|
||||
int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT;
|
||||
reply_ng(CMD_SMART_ATR, res, (uint8_t*)&card, sizeof(smart_card_atr_t));
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
@@ -811,8 +807,7 @@ void SmartCardUpgrade(uint64_t arg0) {
|
||||
}
|
||||
|
||||
// writing takes time.
|
||||
// WaitMS(50);
|
||||
I2C_DELAY_100ms;
|
||||
WaitMS(100);
|
||||
|
||||
// read
|
||||
res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
|
||||
@@ -844,12 +839,10 @@ void SmartCardSetClock(uint64_t arg0) {
|
||||
LED_D_ON();
|
||||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
|
||||
// Send SIM CLC
|
||||
// start [C0 05 xx] stop
|
||||
I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
|
||||
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_SMART_SETCLOCK, PM3_SUCCESS, NULL, 0);
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
+132
-149
@@ -1276,7 +1276,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *
|
||||
* @return false = fail
|
||||
* true = Got all.
|
||||
*/
|
||||
static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) {
|
||||
|
||||
static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
|
||||
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
|
||||
@@ -1286,8 +1286,6 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
||||
uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
|
||||
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||
|
||||
// Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) will be used
|
||||
// bit 7: parity.
|
||||
if (use_credit_key)
|
||||
@@ -1370,6 +1368,8 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
||||
|
||||
} else {
|
||||
|
||||
// on NON_SECURE_PAGEMODE cards, AIA is on block2..
|
||||
|
||||
// read App Issuer Area block 2
|
||||
read_aia[1] = 0x02;
|
||||
read_aia[2] = 0x61;
|
||||
@@ -1385,23 +1385,23 @@ static bool select_iclass_tag_ex(uint8_t *card_data, bool use_credit_key, uint32
|
||||
|
||||
if (status) {
|
||||
*status |= FLAG_ICLASS_AIA;
|
||||
memcpy(card_data + (8 * 2), resp, 8);
|
||||
memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) {
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time) {
|
||||
uint8_t result = 0;
|
||||
return select_iclass_tag_ex(card_data, use_credit_key, eof_time, &result);
|
||||
return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result);
|
||||
}
|
||||
|
||||
// Reader iClass Anticollission
|
||||
// turn off afterwards
|
||||
void ReaderIClass(uint8_t flags) {
|
||||
|
||||
uint8_t card_data[6 * 8] = {0xFF};
|
||||
picopass_hdr hdr = {0};
|
||||
// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
@@ -1419,14 +1419,13 @@ void ReaderIClass(uint8_t flags) {
|
||||
|
||||
uint8_t result_status = 0;
|
||||
uint32_t eof_time = 0;
|
||||
bool status = select_iclass_tag_ex(card_data, use_credit_key, &eof_time, &result_status);
|
||||
bool status = select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &result_status);
|
||||
if (status == false) {
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Page mapping for secure mode
|
||||
// 0 : CSN
|
||||
// 1 : Configuration
|
||||
@@ -1444,7 +1443,7 @@ void ReaderIClass(uint8_t flags) {
|
||||
// with 0xFF:s in block 3 and 4.
|
||||
|
||||
LED_B_ON();
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t *)&hdr, sizeof(hdr));
|
||||
|
||||
//Send back to client, but don't bother if we already sent this -
|
||||
// only useful if looping in arm (not try_once && not abort_after_read)
|
||||
@@ -1470,101 +1469,6 @@ void ReaderIClass(uint8_t flags) {
|
||||
switch_off();
|
||||
}
|
||||
|
||||
// turn off afterwards
|
||||
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac) {
|
||||
|
||||
BigBuf_free();
|
||||
|
||||
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
memcpy(check + 1, rnr, 4);
|
||||
memcpy(check + 5, mac, 4);
|
||||
|
||||
uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE);
|
||||
if (card_data == NULL) {
|
||||
DbpString("fail to allocate memory");
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_EMALLOC, NULL, 0);
|
||||
return;
|
||||
}
|
||||
memset(card_data, 0xFF, ICLASS_16KS_SIZE);
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, false, &eof_time);
|
||||
if (res == false) {
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
|
||||
//for now replay captured auth (as cc not updated)
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
res = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
|
||||
if (res == false) {
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t mem = hdr.conf.mem_config;
|
||||
uint8_t cardsize = ((mem & 0x80) == 0x80) ? 255 : 32;
|
||||
|
||||
/*
|
||||
static struct memory_t {
|
||||
int k16;
|
||||
int book;
|
||||
int k2;
|
||||
int lockauth;
|
||||
int keyaccess;
|
||||
} memory;
|
||||
|
||||
// memory.k16 = ((mem & 0x80) == 0x80);
|
||||
// memory.book = ((mem & 0x20) == 0x20);
|
||||
// memory.k2 = ((mem & 0x08) == 0x08);
|
||||
// memory.lockauth = ((mem & 0x02) == 0x02);
|
||||
// memory.keyaccess = ((mem & 0x01) == 0x01);
|
||||
// uint8_t cardsize = memory.k16 ? 255 : 32;
|
||||
*/
|
||||
|
||||
bool dumpsuccess = true;
|
||||
|
||||
// main read loop
|
||||
uint16_t i;
|
||||
for (i = 0; i <= cardsize; i++) {
|
||||
|
||||
uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00};
|
||||
AddCrc(c + 1, 1);
|
||||
|
||||
res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time);
|
||||
if (res) {
|
||||
memcpy(card_data + (8 * i), resp, 8);
|
||||
} else {
|
||||
Dbprintf("failed to read block %u ( 0x%02x)", i, i);
|
||||
dumpsuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct p {
|
||||
bool isOK;
|
||||
uint16_t block_cnt;
|
||||
uint32_t bb_offset;
|
||||
} PACKED response;
|
||||
|
||||
response.isOK = dumpsuccess;
|
||||
response.block_cnt = i;
|
||||
response.bb_offset = card_data - BigBuf_get_addr();
|
||||
reply_ng(CMD_HF_ICLASS_REPLAY, PM3_SUCCESS, (uint8_t *)&response, sizeof(response));
|
||||
|
||||
BigBuf_free();
|
||||
switch_off();
|
||||
}
|
||||
|
||||
// used with function select_and_auth (cmdhficlass.c)
|
||||
// which needs to authenticate before doing more things like read/write
|
||||
// selects and authenticate to a card, sends back div_key and mac to client.
|
||||
@@ -1585,24 +1489,30 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
|
||||
|
||||
memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse));
|
||||
|
||||
if (payload->use_raw)
|
||||
memcpy(div_key, payload->key, 8);
|
||||
else
|
||||
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
|
||||
if (payload->use_replay) {
|
||||
|
||||
if (payload->use_credit_key)
|
||||
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
|
||||
else
|
||||
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
|
||||
memcpy(pmac, payload->key + 4, 4);
|
||||
memcpy(cmd_check + 1, payload->key, 8);
|
||||
|
||||
opt_doReaderMAC(ccnr, div_key, pmac);
|
||||
} else {
|
||||
if (payload->use_raw)
|
||||
memcpy(div_key, payload->key, 8);
|
||||
else
|
||||
iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
|
||||
|
||||
// copy MAC to check command (readersignature)
|
||||
cmd_check[5] = pmac[0];
|
||||
cmd_check[6] = pmac[1];
|
||||
cmd_check[7] = pmac[2];
|
||||
cmd_check[8] = pmac[3];
|
||||
if (payload->use_credit_key)
|
||||
memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
|
||||
else
|
||||
memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
|
||||
|
||||
opt_doReaderMAC(ccnr, div_key, pmac);
|
||||
|
||||
// copy MAC to check command (readersignature)
|
||||
cmd_check[5] = pmac[0];
|
||||
cmd_check[6] = pmac[1];
|
||||
cmd_check[7] = pmac[2];
|
||||
cmd_check[8] = pmac[3];
|
||||
}
|
||||
return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time);
|
||||
}
|
||||
|
||||
@@ -1632,7 +1542,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
||||
readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
|
||||
|
||||
// select card / e-purse
|
||||
uint8_t card_data[6 * 8] = {0};
|
||||
picopass_hdr hdr = {0};
|
||||
|
||||
iclass_premac_t *keys = (iclass_premac_t *)datain;
|
||||
|
||||
@@ -1646,7 +1556,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
|
||||
|
||||
uint32_t start_time = 0, eof_time = 0;
|
||||
|
||||
if (select_iclass_tag(card_data, use_credit_key, &eof_time) == false)
|
||||
if (select_iclass_tag(&hdr, use_credit_key, &eof_time) == false)
|
||||
goto out;
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
@@ -1723,7 +1633,7 @@ void iClass_ReadBlock(uint8_t *msg) {
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, payload->use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (payload->send_reply) {
|
||||
response.isOK = res;
|
||||
@@ -1796,7 +1706,7 @@ void iClass_Dump(uint8_t *msg) {
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, req->use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
if (req->send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
|
||||
@@ -1866,10 +1776,12 @@ void iClass_Dump(uint8_t *msg) {
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data) {
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac) {
|
||||
|
||||
// write command: cmd, 1 blockno, 8 data, 4 mac
|
||||
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
|
||||
memcpy(write + 2, data, 12); // data + mac
|
||||
memcpy(write + 2, data, 8);
|
||||
memcpy(write + 10, mac, 4);
|
||||
AddCrc(write + 1, 13);
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
@@ -1914,7 +1826,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
// select tag.
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
bool res = select_iclass_tag((uint8_t *)&hdr, payload->req.use_credit_key, &eof_time);
|
||||
bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
@@ -1937,10 +1849,14 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
if (payload->req.use_replay) {
|
||||
doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac);
|
||||
} else {
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
}
|
||||
|
||||
memcpy(write + 2, payload->data, 8); // data
|
||||
memcpy(write + 10, mac, sizeof(mac)); // mac
|
||||
@@ -1949,8 +1865,29 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
res = iclass_send_cmd_with_retries(write, sizeof(write), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time);
|
||||
if (res == false) {
|
||||
|
||||
uint8_t tries = 3;
|
||||
while (tries-- > 0) {
|
||||
|
||||
iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
res = false;
|
||||
switch_off();
|
||||
if (payload->req.send_reply)
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
|
||||
return;
|
||||
} else {
|
||||
|
||||
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) {
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tries == 0) {
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1983,29 +1920,75 @@ out:
|
||||
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
// turn off afterwards
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||
}
|
||||
void iClass_Restore(iclass_restore_req_t *msg) {
|
||||
|
||||
void iClass_Restore(uint8_t *msg) {
|
||||
// sanitation
|
||||
if (msg == NULL) {
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
iclass_restore_req_t *cmd = (iclass_restore_req_t *)msg;
|
||||
// iclass_auth_req_t *req = &cmd->req;
|
||||
if (msg->item_cnt == 0) {
|
||||
if (msg->req.send_reply) {
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
uint16_t written = 0;
|
||||
uint16_t total_blocks = (cmd->end_block - cmd->start_block) + 1;
|
||||
for (uint8_t b = cmd->start_block; b < total_blocks; b++) {
|
||||
Iso15693InitReader();
|
||||
|
||||
if (iclass_writeblock_ext(b, cmd->data + ((b - cmd->start_block) * 12))) {
|
||||
Dbprintf("Write block [%02x] successful", b);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] failed", b);
|
||||
uint16_t written = 0;
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr hdr = {0};
|
||||
|
||||
// select
|
||||
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// authenticate
|
||||
uint8_t mac[4] = {0};
|
||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
// authenticate
|
||||
if (msg->req.do_auth) {
|
||||
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// main loop
|
||||
for (uint8_t i = 0; i < msg->item_cnt; i++) {
|
||||
|
||||
iclass_restore_item_t item = msg->blocks[i];
|
||||
|
||||
// calc new mac for data, using 1b blockno, 8b data,
|
||||
uint8_t wb[9] = {0};
|
||||
wb[0] = item.blockno;
|
||||
memcpy(wb + 1, item.data, 8);
|
||||
|
||||
if (msg->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
|
||||
// data + mac
|
||||
if (iclass_writeblock_ext(item.blockno, item.data, mac)) {
|
||||
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
switch_off();
|
||||
uint8_t isOK = (written == total_blocks) ? 1 : 0;
|
||||
reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
|
||||
if (msg->req.send_reply) {
|
||||
int isOK = (written == msg->item_cnt) ? PM3_SUCCESS : PM3_ESOFT;
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, isOK, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -17,13 +17,11 @@
|
||||
|
||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac);
|
||||
|
||||
void iClass_WriteBlock(uint8_t *msg);
|
||||
void iClass_Dump(uint8_t *msg);
|
||||
|
||||
void iClass_Restore(uint8_t *msg);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_Restore(iclass_restore_req_t *msg);
|
||||
|
||||
int do_iclass_simulation_nonsec(void);
|
||||
int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf);
|
||||
@@ -37,6 +35,6 @@ bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
||||
void iClass_ReadBlock(uint8_t *msg);
|
||||
bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time);
|
||||
|
||||
bool select_iclass_tag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time);
|
||||
bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time);
|
||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out);
|
||||
#endif
|
||||
|
||||
+12
-9
@@ -1778,9 +1778,10 @@ static void PrepareDelayedTransfer(uint16_t delay) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||
|
||||
if (!hf_field_active)
|
||||
if (!hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring TransmitFor14443a command");
|
||||
return;
|
||||
|
||||
}
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
if (timing) {
|
||||
@@ -2189,8 +2190,10 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||
|
||||
if (!hf_field_active)
|
||||
if (!hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring GetIso14443aAnswerFromTag_Thinfilm command");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
@@ -2390,7 +2393,7 @@ void iso14443a_antifuzz(uint32_t flags) {
|
||||
}
|
||||
}
|
||||
|
||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_HF_ISO14443A_ANTIFUZZ, PM3_SUCCESS, NULL, 0);
|
||||
switch_off();
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
@@ -2624,13 +2627,13 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||
} // else force RATS
|
||||
|
||||
// RATS, Request for answer to select
|
||||
if (!no_rats) {
|
||||
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
|
||||
if (no_rats == false) {
|
||||
uint8_t rats[] = { ISO14443A_CMD_RATS, 0x80, 0x00, 0x00 }; // FSD=256, FSDI=8, CID=0
|
||||
AddCrc14A(rats, 2);
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
int len = ReaderReceive(resp, resp_par);
|
||||
|
||||
if (!len) return 0;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
if (p_card) {
|
||||
memcpy(p_card->ats, resp, sizeof(p_card->ats));
|
||||
@@ -2932,7 +2935,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
FpgaDisableTracing();
|
||||
reply_old(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
} else {
|
||||
arg0 = ReaderReceive(buf, par);
|
||||
FpgaDisableTracing();
|
||||
|
||||
+10
-5
@@ -1895,12 +1895,17 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
||||
FpgaDisableTracing();
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
FpgaDisableTracing();
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, -2, 0, 0, NULL, 0);
|
||||
} else {
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
status = Get14443bAnswerFromTag(buf, sizeof(buf), 5 * ISO14443B_READER_TIMEOUT, &eof_time); // raw
|
||||
FpgaDisableTracing();
|
||||
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
+81
-72
@@ -290,6 +290,7 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
|
||||
LED_B_OFF();
|
||||
|
||||
*start_time = *start_time + DELAY_ARM_TO_TAG;
|
||||
FpgaDisableTracing();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -732,6 +733,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||
}
|
||||
|
||||
FpgaDisableSscDma();
|
||||
FpgaDisableTracing();
|
||||
|
||||
uint32_t sof_time = *eof_time
|
||||
- (dt->len * 8 * 8 * 16) // time for byte transfers
|
||||
@@ -1469,17 +1471,22 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
|
||||
// low speed (1 out of 256)
|
||||
CodeIso15693AsReader256(send, sendlen);
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
tosend_t *ts = get_tosend();
|
||||
TransmitTo15693Tag(ts->buf, ts->max, &start_time);
|
||||
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
|
||||
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
|
||||
|
||||
int res = 0;
|
||||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
|
||||
res = PM3_ETEAROFF;
|
||||
|
||||
} else {
|
||||
|
||||
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF
|
||||
LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
|
||||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1495,7 +1502,6 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
||||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1588,41 +1594,49 @@ void ReaderIso15693(uint32_t parameter) {
|
||||
BuildIdentifyRequest(cmd);
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time;
|
||||
int answerLen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
|
||||
// we should do a better check than this
|
||||
if (answerLen >= 12) {
|
||||
uint8_t uid[8];
|
||||
uid[0] = answer[9]; // always E0
|
||||
uid[1] = answer[8]; // IC Manufacturer code
|
||||
uid[2] = answer[7];
|
||||
uid[3] = answer[6];
|
||||
uid[4] = answer[5];
|
||||
uid[5] = answer[4];
|
||||
uid[6] = answer[3];
|
||||
uid[7] = answer[2];
|
||||
if (recvlen == PM3_ETEAROFF) { // tearoff occured
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
||||
} else {
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[5], uid[6]
|
||||
);
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
|
||||
// we should do a better check than this
|
||||
if (recvlen >= 12) {
|
||||
uint8_t uid[8];
|
||||
uid[0] = answer[9]; // always E0
|
||||
uid[1] = answer[8]; // IC Manufacturer code
|
||||
uid[2] = answer[7];
|
||||
uid[3] = answer[6];
|
||||
uid[4] = answer[5];
|
||||
uid[5] = answer[4];
|
||||
uid[6] = answer[3];
|
||||
uid[7] = answer[2];
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[5], uid[6]
|
||||
);
|
||||
}
|
||||
// send UID back to client.
|
||||
// arg0 = 1 = OK
|
||||
// arg1 = len of response (12 bytes)
|
||||
// arg2 = rtf
|
||||
// asbytes = uid.
|
||||
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] %d octets read from IDENTIFY request:", recvlen);
|
||||
DbdecodeIso15693Answer(recvlen, answer);
|
||||
Dbhexdump(recvlen, answer, true);
|
||||
}
|
||||
} else {
|
||||
DbpString("Failed to select card");
|
||||
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
}
|
||||
// send UID back to client.
|
||||
// arg0 = 1 = OK
|
||||
// arg1 = len of response (12 bytes)
|
||||
// arg2 = rtf
|
||||
// asbytes = uid.
|
||||
reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen);
|
||||
DbdecodeIso15693Answer(answerLen, answer);
|
||||
Dbhexdump(answerLen, answer, true);
|
||||
}
|
||||
|
||||
switch_off();
|
||||
BigBuf_free();
|
||||
}
|
||||
@@ -1694,6 +1708,11 @@ void SimTagIso15693(uint8_t *uid) {
|
||||
|
||||
bool exit_loop = false;
|
||||
while (exit_loop == false) {
|
||||
|
||||
button_pressed = BUTTON_PRESS();
|
||||
if (button_pressed || data_available())
|
||||
break;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// find reader field
|
||||
@@ -1767,6 +1786,11 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
||||
|
||||
if (recvlen >= 12) {
|
||||
Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2));
|
||||
} else {
|
||||
DbpString("Failed to select card");
|
||||
reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
}
|
||||
|
||||
// now with AFI
|
||||
@@ -1816,10 +1840,9 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
int recvlen = 0;
|
||||
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
|
||||
uint32_t eof_time = 0;
|
||||
uint16_t timeout;
|
||||
uint32_t eof_time = 0;
|
||||
bool request_answer = false;
|
||||
|
||||
switch (data[1]) {
|
||||
@@ -1837,43 +1860,29 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
|
||||
timeout = ISO15693_READER_TIMEOUT;
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
Dbprintf("SEND:");
|
||||
Dbhexdump(datalen, data, false);
|
||||
}
|
||||
|
||||
uint32_t start_time = 0;
|
||||
recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
|
||||
int recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time);
|
||||
|
||||
// send a single EOF to get the tag response
|
||||
if (request_answer) {
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
if (recvlen == PM3_ETEAROFF) { // tearoff occured
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
||||
} else {
|
||||
|
||||
// send a single EOF to get the tag response
|
||||
if (request_answer) {
|
||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||
recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time);
|
||||
}
|
||||
|
||||
if (recv) {
|
||||
recvlen = MIN(recvlen, ISO15693_MAX_RESPONSE_LENGTH);
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
|
||||
} else {
|
||||
reply_mix(CMD_ACK, 1, 0, 0, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// for the time being, switch field off to protect rdv4.0
|
||||
// note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
|
||||
if (recv) {
|
||||
|
||||
if (recvlen > ISO15693_MAX_RESPONSE_LENGTH) {
|
||||
recvlen = ISO15693_MAX_RESPONSE_LENGTH;
|
||||
}
|
||||
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) {
|
||||
|
||||
Dbprintf("RECV:");
|
||||
if (recvlen > 0) {
|
||||
Dbhexdump(recvlen, recvbuf, false);
|
||||
DbdecodeIso15693Answer(recvlen, recvbuf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+86
-15
@@ -2467,7 +2467,7 @@ static uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) {
|
||||
// Requires: forwarLink_data filled with valid bits (1 bit per byte)
|
||||
// fwd_bit_count set with number of bits to be sent
|
||||
//====================================================================
|
||||
static void SendForward(uint8_t fwd_bit_count) {
|
||||
static void SendForward(uint8_t fwd_bit_count, bool fast) {
|
||||
|
||||
// iceman, 21.3us increments for the USclock verification.
|
||||
// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead
|
||||
@@ -2480,9 +2480,10 @@ static void SendForward(uint8_t fwd_bit_count) {
|
||||
fwd_write_ptr = forwardLink_data;
|
||||
fwd_bit_sz = fwd_bit_count;
|
||||
|
||||
// Set up FPGA, 125kHz or 95 divisor
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
|
||||
if (! fast) {
|
||||
// Set up FPGA, 125kHz or 95 divisor
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
}
|
||||
// force 1st mod pulse (start gap must be longer for 4305)
|
||||
fwd_bit_sz--; //prepare next bit modulation
|
||||
fwd_write_ptr++;
|
||||
@@ -2490,28 +2491,98 @@ static void SendForward(uint8_t fwd_bit_count) {
|
||||
TurnReadLF_off(EM_START_GAP);
|
||||
TurnReadLFOn(18 * 8);
|
||||
|
||||
// now start writting with bitbanging the antenna. (each bit should be 32*8 total length)
|
||||
// now start writing with bitbanging the antenna. (each bit should be 32*8 total length)
|
||||
while (fwd_bit_sz-- > 0) { //prepare next bit modulation
|
||||
if (((*fwd_write_ptr++) & 1) == 1) {
|
||||
WaitUS(32 * 8);
|
||||
} else {
|
||||
TurnReadLF_off(23 * 8);
|
||||
TurnReadLFOn((32 - 23) * 8);
|
||||
TurnReadLFOn(18 * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EM4xLogin(uint32_t pwd) {
|
||||
static void EM4xLoginEx(uint32_t pwd) {
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
//WaitUS(20); // no wait for login command.
|
||||
// should receive
|
||||
// 0000 1010 ok
|
||||
// 0000 0001 fail
|
||||
}
|
||||
|
||||
void EM4xBruteforce(uint32_t start_pwd, uint32_t n) {
|
||||
// With current timing, 18.6 ms per test = 53.8 pwds/s
|
||||
reply_ng(CMD_LF_EM4X_BF, PM3_SUCCESS, NULL, 0);
|
||||
StartTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitMS(20);
|
||||
LED_A_ON();
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
uint32_t candidates_found = 0;
|
||||
for (uint32_t pwd = start_pwd; pwd < 0xFFFFFFFF; pwd++) {
|
||||
if (((pwd - start_pwd) & 0x3F) == 0x00) {
|
||||
WDT_HIT();
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
Dbprintf("EM4x05 Bruteforce Interrupted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Report progress every 256 attempts
|
||||
if (((pwd - start_pwd) & 0xFF) == 0x00) {
|
||||
Dbprintf("Trying: %06Xxx", pwd >> 8);
|
||||
}
|
||||
clear_trace();
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||
SendForward(len, true);
|
||||
|
||||
WaitUS(400);
|
||||
DoPartialAcquisition(0, false, 350, 1000);
|
||||
uint8_t *mem = BigBuf_get_addr();
|
||||
if (mem[334] < 128) {
|
||||
candidates_found++;
|
||||
Dbprintf("Password candidate: " _GREEN_("%08X"), pwd);
|
||||
if ((n != 0) && (candidates_found == n)) {
|
||||
Dbprintf("EM4x05 Bruteforce Stopped. %i candidate%s found", candidates_found, candidates_found > 1 ? "s" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Beware: if smaller, tag might not have time to be back in listening state yet
|
||||
WaitMS(1);
|
||||
}
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void EM4xLogin(uint32_t pwd) {
|
||||
|
||||
StartTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitMS(20);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
EM4xLoginEx(pwd);
|
||||
|
||||
WaitUS(400);
|
||||
// We need to acquire more than needed, to help demodulators finding the proper modulation
|
||||
DoPartialAcquisition(0, false, 6000, 1000);
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||
|
||||
StartTicks();
|
||||
@@ -2529,17 +2600,17 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||
* 0000 1010 ok
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
|
||||
len += Prepare_Addr(addr);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
WaitUS(400);
|
||||
|
||||
DoPartialAcquisition(20, false, 6000, 1000);
|
||||
DoPartialAcquisition(0, false, 6000, 1000);
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
@@ -2564,14 +2635,14 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
||||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
|
||||
len += Prepare_Addr(addr);
|
||||
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
StopTicks();
|
||||
@@ -2607,13 +2678,13 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
||||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
|
||||
len += Prepare_Data(data & 0xFFFF, data >> 16);
|
||||
|
||||
SendForward(len);
|
||||
SendForward(len, false);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
StopTicks();
|
||||
|
||||
@@ -56,6 +56,8 @@ void T55xxDangerousRawTest(uint8_t *data);
|
||||
|
||||
void TurnReadLFOn(uint32_t delay);
|
||||
|
||||
void EM4xLogin(uint32_t pwd);
|
||||
void EM4xBruteforce(uint32_t start_pwd, uint32_t n);
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
|
||||
+9
-9
@@ -2752,15 +2752,15 @@ void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
|
||||
|
||||
// Send MFU counter increase cmd
|
||||
uint8_t cmd[] = {
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
// anticollision / select card
|
||||
|
||||
+2
-10
@@ -18,6 +18,7 @@
|
||||
# -DANDROID_NATIVE_API_LEVEL=android-19 \
|
||||
# -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 ..
|
||||
|
||||
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(proxmark3)
|
||||
SET (PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
@@ -248,6 +249,7 @@ set (TARGET_SOURCES
|
||||
${PM3_ROOT}/client/src/cmdlfcotag.c
|
||||
${PM3_ROOT}/client/src/cmdlfdestron.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x05.c
|
||||
${PM3_ROOT}/client/src/cmdlfem4x50.c
|
||||
${PM3_ROOT}/client/src/cmdlffdxb.c
|
||||
${PM3_ROOT}/client/src/cmdlfgallagher.c
|
||||
@@ -495,20 +497,10 @@ if (NOT APPLE)
|
||||
set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed)
|
||||
endif (NOT APPLE)
|
||||
|
||||
|
||||
find_library(pm3rrg_rdv4_cliparser REQUIRED)
|
||||
find_library(pm3rrg_rdv4_tinycbor REQUIRED)
|
||||
find_library(pm3rrg_rdv4_lua REQUIRED)
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
find_library(pm3rrg_rdv4_reveng REQUIRED)
|
||||
find_library(pm3rrg_rdv4_hardnested REQUIRED)
|
||||
|
||||
if (NOT JANSSON_FOUND)
|
||||
find_library(pm3rrg_rdv4_jansson REQUIRED)
|
||||
set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK})
|
||||
endif (NOT JANSSON_FOUND)
|
||||
if (NOT WHEREAMI_FOUND)
|
||||
find_library(pm3rrg_rdv4_whereami REQUIRED)
|
||||
set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK})
|
||||
endif (NOT WHEREAMI_FOUND)
|
||||
|
||||
|
||||
@@ -443,6 +443,7 @@ SRCS = aidsearch.c \
|
||||
cmdlfcotag.c \
|
||||
cmdlfdestron.c \
|
||||
cmdlfem4x.c \
|
||||
cmdlfem4x05.c \
|
||||
cmdlfem4x50.c \
|
||||
cmdlffdxb.c \
|
||||
cmdlfguard.c \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# version
|
||||
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -fvisibility=hidden -w")
|
||||
@@ -12,7 +13,6 @@ add_subdirectory(../deps deps)
|
||||
if (CMAKE_MAKE_PROGRAM MATCHES ".*ninja.*")
|
||||
set(BZIP2_INCLUDE_DIRS ${BZIP2_ROOT})
|
||||
set(BZIP2_LIBRARIES pm3rrg_rdv4_bzip2)
|
||||
find_library(pm3rrg_rdv4_bzip2 REQUIRED)
|
||||
elseif (UNIX) # Cross compile at Unix Makefile System.
|
||||
# bzip2 dep.
|
||||
include(ExternalProject)
|
||||
@@ -190,15 +190,6 @@ target_include_directories(pm3rrg_rdv4 PRIVATE
|
||||
${PM3_ROOT}/common_fpga
|
||||
${PM3_ROOT}/client/src)
|
||||
|
||||
find_library(pm3rrg_rdv4_cliparser REQUIRED)
|
||||
find_library(pm3rrg_rdv4_jansson REQUIRED)
|
||||
find_library(pm3rrg_rdv4_tinycbor REQUIRED)
|
||||
find_library(pm3rrg_rdv4_lua REQUIRED)
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
find_library(pm3rrg_rdv4_reveng REQUIRED)
|
||||
find_library(pm3rrg_rdv4_hardnested REQUIRED)
|
||||
find_library(pm3rrg_rdv4_whereami REQUIRED)
|
||||
|
||||
target_link_libraries(pm3rrg_rdv4
|
||||
${BZIP2_LIBRARIES}
|
||||
pm3rrg_rdv4_hardnested
|
||||
|
||||
@@ -14,7 +14,6 @@ add_library(pm3rrg_rdv4_amiibo STATIC
|
||||
if (NOT TARGET pm3rrg_rdv4_mbedtls)
|
||||
include(mbedtls.cmake)
|
||||
endif()
|
||||
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
|
||||
target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
|
||||
m
|
||||
pm3rrg_rdv4_mbedtls)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user