Merge pull request #59 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2020-10-21 19:05:36 +11:00 committed by GitHub
commit f1ed632a1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 1265 additions and 571 deletions

55
.vscode/launch.json vendored Normal file
View file

@ -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",
}
}
]
}

72
.vscode/tasks.json vendored
View file

@ -4,24 +4,82 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "build", "label": "all: Make & run",
"type": "shell", "type": "shell",
"command": "make clean && make all -j$(nproc --all)", "command": "make -j && ./pm3",
"problemMatcher": [ "problemMatcher": [
"$gcc" "$gcc"
] ],
"group": {
"kind": "build",
"isDefault": true
}
}, },
{ {
"label": "flash fullimage", "label": "choose: Make",
"type": "shell", "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": [] "problemMatcher": []
}, },
{ {
"label": "FLASH BOOTROM", "label": "BOOTROM: Make & Flash",
"type": "shell", "type": "shell",
"command": "sudo ./pm3-flash-bootrom", "command": "make bootrom && ./pm3-flash-bootrom",
"problemMatcher": [] "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"
} }
] ]
} }

View file

@ -27,6 +27,9 @@ LD = g++
SH = sh SH = sh
BASH = bash BASH = bash
PERL = perl PERL = perl
CCC =foo
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
PATHSEP=/ PATHSEP=/
PREFIX ?= /usr/local PREFIX ?= /usr/local
@ -48,9 +51,15 @@ else
RANLIB= ranlib RANLIB= ranlib
endif endif
DEFCXXFLAGS = -Wall -Werror -O3 -pipe ifeq ($(DEBUG),1)
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe DEFCXXFLAGS = -g -O0 -pipe
DEFLDFLAGS = 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 # Next ones are activated only if SANITIZE=1
ifeq ($(SANITIZE),1) ifeq ($(SANITIZE),1)
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
@ -62,7 +71,11 @@ DEFCFLAGS += -Wbad-function-cast -Wredundant-decls -Wmissing-prototypes -Wchar-s
# Some more warnings we need first to eliminate, so temporarely tolerated: # Some more warnings we need first to eliminate, so temporarely tolerated:
DEFCFLAGS += -Wcast-align -Wno-error=cast-align DEFCFLAGS += -Wcast-align -Wno-error=cast-align
DEFCFLAGS += -Wswitch-enum -Wno-error=switch-enum 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)
DEFCFLAGS += -Wno-stringop-overflow -Wno-error=stringop-overflow
endif
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
# their readline has strict-prototype issues # their readline has strict-prototype issues
DEFCFLAGS += -Wno-strict-prototypes DEFCFLAGS += -Wno-strict-prototypes

View file

@ -978,6 +978,15 @@ static void PacketReceived(PacketCommandNG *packet) {
EM4xLogin(payload->password); EM4xLogin(payload->password);
break; 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: { case CMD_LF_EM4X_READWORD: {
struct p { struct p {
uint32_t password; uint32_t password;
@ -1250,7 +1259,11 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_HF_ISO14443A_ANTIFUZZ: { 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; break;
} }
case CMD_HF_EPA_COLLECT_NONCE: { case CMD_HF_EPA_COLLECT_NONCE: {
@ -1481,12 +1494,12 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break; break;
} }
case CMD_HF_MFU_COUNTER_TEAROFF: { case CMD_HF_MFU_COUNTER_TEAROFF: {
struct p { struct p {
uint8_t counter; uint8_t counter;
uint32_t tearoff_time; uint32_t tearoff_time;
} PACKED; } 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); MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
break; break;
} }
@ -1520,13 +1533,13 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_HF_ICLASS_SIMULATE: { case CMD_HF_ICLASS_SIMULATE: {
/* /*
struct p { struct p {
uint8_t reader[4]; uint8_t reader[4];
uint8_t mac[4]; uint8_t mac[4];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
*/ */
SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
break; break;
@ -1562,7 +1575,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_HF_ICLASS_RESTORE: { case CMD_HF_ICLASS_RESTORE: {
iClass_Restore( (iclass_restore_req_t *)packet->data.asBytes); iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
break; break;
} }
#endif #endif
@ -1604,7 +1617,11 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_SMART_SETCLOCK: { 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; break;
} }
case CMD_SMART_RAW: { case CMD_SMART_RAW: {

View file

@ -889,18 +889,18 @@ static int write(uint8_t word[4], uint8_t address) {
return PM3_ETEAROFF; return PM3_ETEAROFF;
} else { } else {
// wait for T0 * EM4X50_T_TAG_TWA (write access time) // wait for T0 * EM4X50_T_TAG_TWA (write access time)
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA); wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
// look for ACK sequence // look for ACK sequence
if (check_ack(false)) { if (check_ack(false)) {
// now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time) // now EM4x50 needs T0 * EM4X50_T_TAG_TWEE (EEPROM write time)
// for saving data and should return with ACK // for saving data and should return with ACK
if (check_ack(false)) if (check_ack(false))
return PM3_SUCCESS; return PM3_SUCCESS;
} }
} }
} else { } else {
@ -985,7 +985,7 @@ void em4x50_write(em4x50_data_t *etd) {
lf_finalize(); lf_finalize();
return; return;
} }
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
// to verify result reset EM4x50 // to verify result reset EM4x50
if (reset()) { if (reset()) {
@ -1033,7 +1033,7 @@ void em4x50_write_password(em4x50_data_t *etd) {
// login and change password // login and change password
if (login(etd->password)) { if (login(etd->password)) {
int res = write_password(etd->password, etd->new_password); int res = write_password(etd->password, etd->new_password);
if (res == PM3_ETEAROFF) { if (res == PM3_ETEAROFF) {
lf_finalize(); lf_finalize();

View file

@ -47,12 +47,6 @@ static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
#define I2C_DELAY_2CLK I2CSpinDelayClk(2) #define I2C_DELAY_2CLK I2CSpinDelayClk(2)
#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x)) #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 #define ISO7618_MAX_FRAME 255
// try i2c bus recovery at 100kHz = 5us high, 5us low // try i2c bus recovery at 100kHz = 5us high, 5us low
@ -134,11 +128,11 @@ void I2C_Reset_EnterMainProgram(void) {
StartTicks(); StartTicks();
I2C_init(); I2C_init();
I2C_SetResetStatus(0, 0, 0); I2C_SetResetStatus(0, 0, 0);
I2C_DELAY_30ms; WaitMS(30);
I2C_SetResetStatus(1, 0, 0); I2C_SetResetStatus(1, 0, 0);
I2C_DELAY_30ms; WaitMS(30);
I2C_SetResetStatus(1, 1, 1); I2C_SetResetStatus(1, 1, 1);
I2C_DELAY_10ms; WaitMS(10);
} }
// Reset the SIM_Adapter, then enter the bootloader program // Reset the SIM_Adapter, then enter the bootloader program
@ -147,9 +141,9 @@ void I2C_Reset_EnterBootloader(void) {
StartTicks(); StartTicks();
I2C_init(); I2C_init();
I2C_SetResetStatus(0, 1, 1); I2C_SetResetStatus(0, 1, 1);
I2C_DELAY_100ms; WaitMS(100);
I2C_SetResetStatus(1, 1, 1); I2C_SetResetStatus(1, 1, 1);
I2C_DELAY_10ms; WaitMS(10);
} }
// Wait for the clock to go High. // Wait for the clock to go High.
@ -193,7 +187,7 @@ static bool WaitSCL_L_timeout(void) {
if (!SCL_read) if (!SCL_read)
return true; return true;
I2C_DELAY_100us; WaitMS(1);
} }
return (delay == 0); return (delay == 0);
} }
@ -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) // extra wait 500us (514us measured)
// 200us (xx measured) // 200us (xx measured)
// WaitUS(600); WaitUS(600);
I2C_DELAY_600us;
bool bBreak = true; bool bBreak = true;
uint16_t readcount = 0; uint16_t readcount = 0;
@ -811,8 +804,7 @@ void SmartCardUpgrade(uint64_t arg0) {
} }
// writing takes time. // writing takes time.
// WaitMS(50); WaitMS(100);
I2C_DELAY_100ms;
// read // read
res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
@ -844,12 +836,10 @@ void SmartCardSetClock(uint64_t arg0) {
LED_D_ON(); LED_D_ON();
set_tracing(true); set_tracing(true);
I2C_Reset_EnterMainProgram(); I2C_Reset_EnterMainProgram();
// Send SIM CLC // Send SIM CLC
// start [C0 05 xx] stop // start [C0 05 xx] stop
I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN); I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
reply_ng(CMD_SMART_SETCLOCK, PM3_SUCCESS, NULL, 0);
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
set_tracing(false); set_tracing(false);
LEDsoff(); LEDsoff();
} }

View file

@ -1367,7 +1367,7 @@ static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_
*status |= FLAG_ICLASS_CC; *status |= FLAG_ICLASS_CC;
} else { } else {
// on NON_SECURE_PAGEMODE cards, AIA is on block2.. // on NON_SECURE_PAGEMODE cards, AIA is on block2..
// read App Issuer Area block 2 // read App Issuer Area block 2
@ -1443,7 +1443,7 @@ void ReaderIClass(uint8_t flags) {
// with 0xFF:s in block 3 and 4. // with 0xFF:s in block 3 and 4.
LED_B_ON(); LED_B_ON();
reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t*)&hdr, sizeof(hdr)); 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 - //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) // only useful if looping in arm (not try_once && not abort_after_read)
@ -1489,9 +1489,9 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse)); memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse));
if ( payload->use_replay) { if (payload->use_replay) {
memcpy(pmac, payload->key + 4, 4); memcpy(pmac, payload->key + 4, 4);
memcpy(cmd_check + 1, payload->key, 8); memcpy(cmd_check + 1, payload->key, 8);
} else { } else {
@ -1780,7 +1780,7 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac)
// write command: cmd, 1 blockno, 8 data, 4 mac // write command: cmd, 1 blockno, 8 data, 4 mac
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno }; uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
memcpy(write + 2, data, 8); memcpy(write + 2, data, 8);
memcpy(write + 10, mac, 4); memcpy(write + 10, mac, 4);
AddCrc(write + 1, 13); AddCrc(write + 1, 13);
@ -1872,11 +1872,11 @@ void iClass_WriteBlock(uint8_t *msg) {
iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time); iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
res = false; res = false;
switch_off(); switch_off();
if (payload->req.send_reply) if (payload->req.send_reply)
reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t)); reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
return; return;
} else { } else {
if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) { if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) {
@ -1885,7 +1885,7 @@ void iClass_WriteBlock(uint8_t *msg) {
} }
} }
} }
if (tries == 0) { if (tries == 0) {
res = false; res = false;
goto out; goto out;
@ -1932,7 +1932,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
if (msg->req.send_reply) { if (msg->req.send_reply) {
reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0); reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
} }
return; return;
} }
LED_A_ON(); LED_A_ON();
@ -1942,7 +1942,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
uint32_t eof_time = 0; uint32_t eof_time = 0;
picopass_hdr hdr = {0}; picopass_hdr hdr = {0};
// select // select
bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time); bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time);
if (res == false) { if (res == false) {
goto out; goto out;
@ -1974,7 +1974,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
doMAC_N(wb, sizeof(wb), hdr.key_c, mac); doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
else else
doMAC_N(wb, sizeof(wb), hdr.key_d, mac); doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
// data + mac // data + mac
if (iclass_writeblock_ext(item.blockno, item.data, mac)) { if (iclass_writeblock_ext(item.blockno, item.data, mac)) {
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno); Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno);
@ -1983,7 +1983,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno); Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno);
} }
} }
out: out:
switch_off(); switch_off();

View file

@ -2390,7 +2390,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(); switch_off();
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
} }
@ -2629,7 +2629,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
AddCrc14A(rats, 2); AddCrc14A(rats, 2);
ReaderTransmit(rats, sizeof(rats), NULL); ReaderTransmit(rats, sizeof(rats), NULL);
int len = ReaderReceive(resp, resp_par); int len = ReaderReceive(resp, resp_par);
if (len == 0) if (len == 0)
return 0; return 0;
if (p_card) { if (p_card) {

View file

@ -1474,13 +1474,13 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
int res = 0; int res = 0;
tosend_t *ts = get_tosend(); tosend_t *ts = get_tosend();
TransmitTo15693Tag(ts->buf, ts->max, &start_time); TransmitTo15693Tag(ts->buf, ts->max, &start_time);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
res = PM3_ETEAROFF; res = PM3_ETEAROFF;
} else { } else {
*eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF *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); LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true);
if (recv != NULL) { if (recv != NULL) {
@ -1595,11 +1595,11 @@ void ReaderIso15693(uint32_t parameter) {
uint32_t start_time = 0; uint32_t start_time = 0;
uint32_t eof_time; uint32_t eof_time;
int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time); int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time);
if (recvlen == PM3_ETEAROFF) { // tearoff occured if (recvlen == PM3_ETEAROFF) { // tearoff occured
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0); reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
} else { } else {
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
// we should do a better check than this // we should do a better check than this
@ -1634,7 +1634,7 @@ void ReaderIso15693(uint32_t parameter) {
} }
} else { } else {
DbpString("Failed to select card"); DbpString("Failed to select card");
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
} }
} }
switch_off(); switch_off();
@ -1869,7 +1869,7 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
} }
if (recv) { if (recv) {
recvlen = MIN(recvlen,ISO15693_MAX_RESPONSE_LENGTH); recvlen = MIN(recvlen, ISO15693_MAX_RESPONSE_LENGTH);
reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
} else { } else {
reply_mix(CMD_ACK, 1, 0, 0, NULL, 0); reply_mix(CMD_ACK, 1, 0, 0, NULL, 0);

View file

@ -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) // Requires: forwarLink_data filled with valid bits (1 bit per byte)
// fwd_bit_count set with number of bits to be sent // 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. // iceman, 21.3us increments for the USclock verification.
// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead // 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_write_ptr = forwardLink_data;
fwd_bit_sz = fwd_bit_count; fwd_bit_sz = fwd_bit_count;
// Set up FPGA, 125kHz or 95 divisor if (! fast) {
LFSetupFPGAForADC(LF_DIVISOR_125, true); // Set up FPGA, 125kHz or 95 divisor
LFSetupFPGAForADC(LF_DIVISOR_125, true);
}
// force 1st mod pulse (start gap must be longer for 4305) // force 1st mod pulse (start gap must be longer for 4305)
fwd_bit_sz--; //prepare next bit modulation fwd_bit_sz--; //prepare next bit modulation
fwd_write_ptr++; fwd_write_ptr++;
@ -2490,13 +2491,13 @@ static void SendForward(uint8_t fwd_bit_count) {
TurnReadLF_off(EM_START_GAP); TurnReadLF_off(EM_START_GAP);
TurnReadLFOn(18 * 8); 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 while (fwd_bit_sz-- > 0) { //prepare next bit modulation
if (((*fwd_write_ptr++) & 1) == 1) { if (((*fwd_write_ptr++) & 1) == 1) {
WaitUS(32 * 8); WaitUS(32 * 8);
} else { } else {
TurnReadLF_off(23 * 8); TurnReadLF_off(23 * 8);
TurnReadLFOn((32 - 23) * 8); TurnReadLFOn(18 * 8);
} }
} }
} }
@ -2505,13 +2506,60 @@ static void EM4xLoginEx(uint32_t pwd) {
forward_ptr = forwardLink_data; forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN); uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16); len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
SendForward(len); SendForward(len, false);
//WaitUS(20); // no wait for login command. //WaitUS(20); // no wait for login command.
// should receive // should receive
// 0000 1010 ok // 0000 1010 ok
// 0000 0001 fail // 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) { void EM4xLogin(uint32_t pwd) {
StartTicks(); StartTicks();
@ -2558,7 +2606,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
uint8_t len = Prepare_Cmd(FWD_CMD_READ); uint8_t len = Prepare_Cmd(FWD_CMD_READ);
len += Prepare_Addr(addr); len += Prepare_Addr(addr);
SendForward(len); SendForward(len, false);
WaitUS(400); WaitUS(400);
@ -2594,7 +2642,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
len += Prepare_Addr(addr); len += Prepare_Addr(addr);
len += Prepare_Data(data & 0xFFFF, data >> 16); len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len); SendForward(len, false);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks(); StopTicks();
@ -2636,7 +2684,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT); uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
len += Prepare_Data(data & 0xFFFF, data >> 16); len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len); SendForward(len, false);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks(); StopTicks();

View file

@ -57,6 +57,7 @@ void T55xxDangerousRawTest(uint8_t *data);
void TurnReadLFOn(uint32_t delay); void TurnReadLFOn(uint32_t delay);
void EM4xLogin(uint32_t pwd); 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 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 EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd); void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);

View file

@ -2752,15 +2752,15 @@ void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
// Send MFU counter increase cmd // Send MFU counter increase cmd
uint8_t cmd[] = { uint8_t cmd[] = {
MIFARE_ULEV1_INCR_CNT, MIFARE_ULEV1_INCR_CNT,
counter, counter,
0, // lsb 0, // lsb
0, 0,
0, // msb 0, // msb
0, // rfu 0, // rfu
0, 0,
0, 0,
}; };
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
// anticollision / select card // anticollision / select card

View file

@ -18,6 +18,7 @@
# -DANDROID_NATIVE_API_LEVEL=android-19 \ # -DANDROID_NATIVE_API_LEVEL=android-19 \
# -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 .. # -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 ..
message(STATUS "CMake ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(proxmark3) project(proxmark3)
SET (PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..) SET (PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
@ -496,20 +497,10 @@ if (NOT APPLE)
set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed) set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed)
endif (NOT APPLE) 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) if (NOT JANSSON_FOUND)
find_library(pm3rrg_rdv4_jansson REQUIRED)
set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK})
endif (NOT JANSSON_FOUND) endif (NOT JANSSON_FOUND)
if (NOT WHEREAMI_FOUND) if (NOT WHEREAMI_FOUND)
find_library(pm3rrg_rdv4_whereami REQUIRED)
set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK}) set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK})
endif (NOT WHEREAMI_FOUND) endif (NOT WHEREAMI_FOUND)

View file

@ -1,4 +1,5 @@
# version # version
message(STATUS "CMake ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 3.4.1) cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -fvisibility=hidden -w") 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.*") if (CMAKE_MAKE_PROGRAM MATCHES ".*ninja.*")
set(BZIP2_INCLUDE_DIRS ${BZIP2_ROOT}) set(BZIP2_INCLUDE_DIRS ${BZIP2_ROOT})
set(BZIP2_LIBRARIES pm3rrg_rdv4_bzip2) set(BZIP2_LIBRARIES pm3rrg_rdv4_bzip2)
find_library(pm3rrg_rdv4_bzip2 REQUIRED)
elseif (UNIX) # Cross compile at Unix Makefile System. elseif (UNIX) # Cross compile at Unix Makefile System.
# bzip2 dep. # bzip2 dep.
include(ExternalProject) include(ExternalProject)
@ -190,15 +190,6 @@ target_include_directories(pm3rrg_rdv4 PRIVATE
${PM3_ROOT}/common_fpga ${PM3_ROOT}/common_fpga
${PM3_ROOT}/client/src) ${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 target_link_libraries(pm3rrg_rdv4
${BZIP2_LIBRARIES} ${BZIP2_LIBRARIES}
pm3rrg_rdv4_hardnested pm3rrg_rdv4_hardnested

View file

@ -14,7 +14,6 @@ add_library(pm3rrg_rdv4_amiibo STATIC
if (NOT TARGET pm3rrg_rdv4_mbedtls) if (NOT TARGET pm3rrg_rdv4_mbedtls)
include(mbedtls.cmake) include(mbedtls.cmake)
endif() endif()
find_library(pm3rrg_rdv4_mbedtls REQUIRED)
target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
m m
pm3rrg_rdv4_mbedtls) pm3rrg_rdv4_mbedtls)

View file

@ -3,6 +3,7 @@ add_library(pm3rrg_rdv4_cliparser STATIC
cliparser/cliparser.c cliparser/cliparser.c
) )
target_compile_definitions(pm3rrg_rdv4_cliparser PRIVATE _ISOC99_SOURCE)
target_include_directories(pm3rrg_rdv4_cliparser PRIVATE target_include_directories(pm3rrg_rdv4_cliparser PRIVATE
../../common ../../common
../../include ../../include

View file

@ -9,3 +9,12 @@ MYSRCS = \
LIB_A = libcliparser.a LIB_A = libcliparser.a
include ../../../Makefile.host include ../../../Makefile.host
$(info PLATFORM $(platform))
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
# FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32
# but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html
CFLAGS += -D_ISOC99_SOURCE
endif

View file

@ -11,8 +11,10 @@
#include "cliparser.h" #include "cliparser.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <util.h> // Get color constants #include <util.h> // Get color constants
#include <ui.h> // get PrintAndLogEx #include <ui.h> // get PrintAndLogEx
#include <ctype.h> // tolower
#include <inttypes.h> // PRIu64
#ifndef ARRAYLEN #ifndef ARRAYLEN
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0])) # define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
@ -125,7 +127,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
return 0; return 0;
} }
enum ParserState { enum ParserState {
PS_FIRST, PS_FIRST,
PS_ARGUMENT, PS_ARGUMENT,
@ -205,9 +206,9 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
int tmplen = 0; int tmplen = 0;
uint8_t tmpstr[(256 * 2) + 1] = {0}; uint8_t tmpstr[(256 * 2) + 1] = {0};
// concat all strings in argstr into tmpstr[] // concat all strings in argstr into tmpstr[]
// //
int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen); int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen);
if (res) { if (res) {
return res; return res;
@ -216,7 +217,7 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
return res; return res;
} }
res = param_gethex_to_eol((char*)tmpstr, 0, data, maxdatalen, datalen); res = param_gethex_to_eol((char *)tmpstr, 0, data, maxdatalen, datalen);
switch (res) { switch (res) {
case 1: case 1:
printf("Parameter error: Invalid HEX value\n"); printf("Parameter error: Invalid HEX value\n");
@ -241,20 +242,20 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
int ibuf = 0; int ibuf = 0;
for (int i = 0; i < argstr->count; i++) { for (int i = 0; i < argstr->count; i++) {
int len = strlen(argstr->sval[i]); int len = strlen(argstr->sval[i]);
if (len > ( (sizeof(tmpstr) / 2 ) - ibuf)) { if (len > ((sizeof(tmpstr) / 2) - ibuf)) {
printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2)); printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2));
fflush(stdout); fflush(stdout);
return 2; return 2;
} }
memcpy(&tmpstr[ibuf], argstr->sval[i], len); memcpy(&tmpstr[ibuf], argstr->sval[i], len);
ibuf += len; ibuf += len;
} }
ibuf = MIN(ibuf, (sizeof(tmpstr) / 2)); ibuf = MIN(ibuf, (sizeof(tmpstr) / 2));
tmpstr[ibuf] = 0; tmpstr[ibuf] = 0;
@ -272,4 +273,20 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
return 0; return 0;
} }
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
uint64_t rv = 0;
uint8_t data[8];
int datalen = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), &datalen);
if (res == 0) {
for (uint8_t i = 0; i < datalen; i++) {
rv <<= 8;
rv |= data[i];
}
} else {
rv = def;
}
return rv;
}

View file

@ -66,4 +66,6 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
#endif #endif

View file

@ -1203,3 +1203,9 @@ FEE2A3FBC5B6
# taurus avm # taurus avm
# #
005078565703 005078565703
#
# Ving?
#
0602721E8F06
FC0B50AF8700
F7BA51A9434E

View file

@ -1338,7 +1338,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
if (!res && datalen > 0) if (!res && datalen > 0)
waitCmd(0, timeout); waitCmd(0, timeout);
} }
return 0; return PM3_SUCCESS;
} }
static int waitCmd(uint8_t iSelect, uint32_t timeout) { static int waitCmd(uint8_t iSelect, uint32_t timeout) {
@ -1398,16 +1398,20 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t arg0 = FLAG_4B_UID_IN_DATA; struct {
uint8_t flag;
} PACKED param;
param.flag = FLAG_4B_UID_IN_DATA;
if (arg_get_lit(ctx, 2)) if (arg_get_lit(ctx, 2))
arg0 = FLAG_7B_UID_IN_DATA; param.flag = FLAG_7B_UID_IN_DATA;
if (arg_get_lit(ctx, 3)) if (arg_get_lit(ctx, 3))
arg0 = FLAG_10B_UID_IN_DATA; param.flag = FLAG_10B_UID_IN_DATA;
CLIParserFree(ctx); CLIParserFree(ctx);
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_ANTIFUZZ, arg0, 0, 0, NULL, 0); SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t*)&param, sizeof(param));
return 0; return PM3_SUCCESS;
} }
static int CmdHF14AChaining(const char *Cmd) { static int CmdHF14AChaining(const char *Cmd) {
@ -1438,7 +1442,7 @@ static int CmdHF14AChaining(const char *Cmd) {
PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled");
return 0; return PM3_SUCCESS;
} }
static void printTag(const char *tag) { static void printTag(const char *tag) {
@ -1681,10 +1685,16 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
} }
getTagLabel(card.uid[0], card.uid[1]); getTagLabel(card.uid[0], card.uid[1]);
break; break;
case 0x57: // Qualcomm case 0x46:
if (memcmp(card.uid, "FSTN10m", 7) == 0) {
isMifareClassic = false;
printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
}
break;
case 0x57:
if (memcmp(card.uid, "WSDZ10m", 7) == 0) { if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
isMifareClassic = false; isMifareClassic = false;
printTag("Waveshare NFC-Powered e-Paper"); printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
} }
break; break;
default: default:
@ -1837,30 +1847,30 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
tip = "-> MIFARE Plus X 2K/4K (SL3)"; tip = "-> MIFARE Plus X 2K/4K (SL3)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
if ((card.atqa[0] & 0x02) == 0x02) if ((card.atqa[0] & 0x02) == 0x02)
tip = "-> MIFARE Plus S 2K (SL3)"; tip = "-> MIFARE Plus S 2K (SL3)";
else if ((card.atqa[0] & 0x04) == 0x04) else if ((card.atqa[0] & 0x04) == 0x04)
tip = "-> MIFARE Plus S 4K (SL3)"; tip = "-> MIFARE Plus S 4K (SL3)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
tip = "-> MIFARE Plus SE 1K (17pF)"; tip = "-> MIFARE Plus SE 1K (17pF)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
tip = "-> MIFARE Plus SE 1K (70pF)"; tip = "-> MIFARE Plus SE 1K (70pF)";
} }
} else { //SAK B4,5,6 } else { //SAK B4,5,6
if ((card.sak & 0x20) == 0x20) { // and no GetVersion().. if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
tip = "-> MIFARE Plus X 2K (SL1)"; tip = "-> MIFARE Plus X 2K (SL1)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
tip = "-> MIFARE Plus S 2K (SL1)"; tip = "-> MIFARE Plus S 2K (SL1)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
tip = "-> MIFARE Plus SE 1K (17pF)"; tip = "-> MIFARE Plus SE 1K (17pF)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
tip = "-> MIFARE Plus SE 1K (70pF)"; tip = "-> MIFARE Plus SE 1K (70pF)";
} }
} else { } else {
@ -1868,7 +1878,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
tip = "-> MIFARE Plus X 4K (SL1)"; tip = "-> MIFARE Plus X 4K (SL1)";
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
tip = "-> MIFARE Plus S 4K (SL1)"; tip = "-> MIFARE Plus S 4K (SL1)";
} }
} }
} }

View file

@ -149,7 +149,7 @@ static int CmdHF14BSim(const char *Cmd) {
PrintAndLogEx(FAILED, "failed to read pupi"); PrintAndLogEx(FAILED, "failed to read pupi");
return PM3_EINVARG; return PM3_EINVARG;
} }
PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi))); PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi)));
PrintAndLogEx(INFO, "Press pm3-button to abort simulation"); PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
clearCommandBuffer(); clearCommandBuffer();

View file

@ -656,13 +656,13 @@ static int CmdHF15Demod(const char *Cmd) {
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx); CLIParserFree(ctx);
// The sampling rate is 106.353 ksps/s, for T = 18.8 us // The sampling rate is 106.353 ksps/s, for T = 18.8 us
int i, j; int i, j;
int max = 0, maxPos = 0; int max = 0, maxPos = 0;
int skip = 4; int skip = 4;
if (GraphTraceLen < 1000) { if (GraphTraceLen < 1000) {
PrintAndLogEx(FAILED, "Too few samples in GraphBuffer. Need more than 1000"); PrintAndLogEx(FAILED, "Too few samples in GraphBuffer. Need more than 1000");
PrintAndLogEx(HINT, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data"); PrintAndLogEx(HINT, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data");
return PM3_ESOFT; return PM3_ESOFT;
@ -733,8 +733,8 @@ static int CmdHF15Demod(const char *Cmd) {
PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)"); PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)");
PrintAndLogEx(INFO, " mask = %02x", mask); PrintAndLogEx(INFO, " mask = %02x", mask);
} }
if ( k == 0 ) { if (k == 0) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -744,7 +744,7 @@ static int CmdHF15Demod(const char *Cmd) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " idx | data"); PrintAndLogEx(SUCCESS, " idx | data");
PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------"); PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------");
if ( k / 16 > 0) { if (k / 16 > 0) {
for (; i < k; i += 16) { for (; i < k; i += 16) {
PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, 16)); PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, 16));
} }
@ -824,7 +824,7 @@ static int NxpSysInfo(uint8_t *uid) {
if (status == PM3_ETEAROFF) { if (status == PM3_ETEAROFF) {
return status; return status;
} }
if (status < 2) { if (status < 2) {
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command");
return PM3_EWRONGANSWER; return PM3_EWRONGANSWER;
@ -1058,7 +1058,7 @@ static int CmdHF15Sniff(const char *Cmd) {
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx); CLIParserFree(ctx);
PacketResponseNG resp; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0); SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0);
@ -1111,7 +1111,7 @@ static int CmdHF15Sim(const char *Cmd) {
struct { struct {
uint8_t uid[8]; uint8_t uid[8];
} PACKED payload; } PACKED payload;
int uidlen = 0; int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -1904,11 +1904,11 @@ static int CmdHF15CSetUID(const char *Cmd) {
struct { struct {
uint8_t uid[8]; uint8_t uid[8];
} PACKED payload; } PACKED payload;
int uidlen = 0; int uidlen = 0;
CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen);
CLIParserFree(ctx); CLIParserFree(ctx);
if (uidlen != 8) { if (uidlen != 8) {
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols got "); PrintAndLogEx(WARNING, "UID must include 16 HEX symbols got ");
return PM3_EINVARG; return PM3_EINVARG;
@ -1936,7 +1936,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) { if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply"); PrintAndLogEx(WARNING, "timeout while waiting for reply");
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(INFO, "getting updated card details..."); PrintAndLogEx(INFO, "getting updated card details...");

View file

@ -427,52 +427,52 @@ static void fuse_config(const picopass_hdr *hdr) {
uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]); uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]);
PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t*)&hdr->conf, 8)); PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t *)&hdr->conf, 8));
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "..................... App limit", hdr->conf.app_limit); PrintAndLogEx(INFO, " " _YELLOW_("%02X") "..................... app limit", hdr->conf.app_limit);
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp); PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ Block write lock", hdr->conf.block_writelock); PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ block write lock", hdr->conf.block_writelock);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... Chip", hdr->conf.chip_config); PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... chip", hdr->conf.chip_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... Mem", hdr->conf.mem_config); PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... mem", hdr->conf.mem_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas); PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " Fuses", hdr->conf.fuses); PrintAndLogEx(INFO, " " _YELLOW_("%02X") " fuses", hdr->conf.fuses);
uint8_t fuses = hdr->conf.fuses; uint8_t fuses = hdr->conf.fuses;
PrintAndLogEx(INFO, " Fuses:"); PrintAndLogEx(INFO, " Fuses:");
if (isset(fuses, FUSE_FPERS)) if (isset(fuses, FUSE_FPERS))
PrintAndLogEx(SUCCESS, " mode..... " _GREEN_("Personalization (programmable)")); PrintAndLogEx(SUCCESS, " mode......... " _GREEN_("Personalization (programmable)"));
else else
PrintAndLogEx(SUCCESS, " mode..... " _YELLOW_("Application (locked)")); PrintAndLogEx(SUCCESS, " mode......... " _YELLOW_("Application (locked)"));
if (isset(fuses, FUSE_CODING1)) { if (isset(fuses, FUSE_CODING1)) {
PrintAndLogEx(SUCCESS, " coding.. RFU"); PrintAndLogEx(SUCCESS, " coding...... RFU");
} else { } else {
if (isset(fuses, FUSE_CODING0)) if (isset(fuses, FUSE_CODING0))
PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-2 B / 15693")); PrintAndLogEx(SUCCESS, " coding....... " _YELLOW_("ISO 14443-2 B / 15693"));
else else
PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-B only")); PrintAndLogEx(SUCCESS, " coding....... " _YELLOW_("ISO 14443-B only"));
} }
uint8_t pagemap = get_pagemap(hdr); uint8_t pagemap = get_pagemap(hdr);
switch (pagemap) { switch (pagemap) {
case 0x0: case 0x0:
PrintAndLogEx(INFO, " crypt.... No auth possible. Read only if RA is enabled"); PrintAndLogEx(INFO, " crypt........ No auth possible. Read only if RA is enabled");
break; break;
case 0x1: case 0x1:
PrintAndLogEx(SUCCESS, " crypt.... Non secured page"); PrintAndLogEx(SUCCESS, " crypt........ Non secured page");
break; break;
case 0x2: case 0x2:
PrintAndLogEx(INFO, " crypt.... Secured page, keys locked"); PrintAndLogEx(INFO, " crypt........ Secured page, keys locked");
break; break;
case 0x03: case 0x03:
PrintAndLogEx(SUCCESS, " crypt.... Secured page, " _GREEN_("keys not locked")); PrintAndLogEx(SUCCESS, " crypt........ Secured page, " _GREEN_("keys not locked"));
break; break;
} }
if (isset(fuses, FUSE_RA)) if (isset(fuses, FUSE_RA))
PrintAndLogEx(SUCCESS, " RA....... Read access enabled (non-secure mode)"); PrintAndLogEx(SUCCESS, " RA........... Read access enabled (non-secure mode)");
else else
PrintAndLogEx(INFO, " RA....... Read access not enabled"); PrintAndLogEx(INFO, " RA........... Read access not enabled");
} }
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) { static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) {
@ -545,23 +545,23 @@ static void mem_app_config(const picopass_hdr *hdr) {
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit, app1_limit + 5, app1_limit + 5); PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit, app1_limit + 5, app1_limit + 5);
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit); PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit);
PrintAndLogEx(INFO, "------------------------ " _CYAN_("KeyAccess") " -------------------------"); PrintAndLogEx(INFO, "------------------------- " _CYAN_("KeyAccess") " ------------------------");
PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)"); PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *");
uint8_t book = isset(mem, 0x20); uint8_t book = isset(mem, 0x20);
if (book) { if (book) {
PrintAndLogEx(INFO, " Read A - Kd"); PrintAndLogEx(INFO, " Read A....... debit");
PrintAndLogEx(INFO, " Read B - Kc"); PrintAndLogEx(INFO, " Read B....... credit");
PrintAndLogEx(INFO, " Write A - Kd"); PrintAndLogEx(INFO, " Write A...... debit");
PrintAndLogEx(INFO, " Write B - Kc"); PrintAndLogEx(INFO, " Write B...... credit");
PrintAndLogEx(INFO, " Debit - Kd or Kc"); PrintAndLogEx(INFO, " Debit........ debit or credit");
PrintAndLogEx(INFO, " Credit - Kc"); PrintAndLogEx(INFO, " Credit....... credit");
} else { } else {
PrintAndLogEx(INFO, " Read A - Kd or Kc"); PrintAndLogEx(INFO, " Read A....... debit or credit");
PrintAndLogEx(INFO, " Read B - Kd or Kc"); PrintAndLogEx(INFO, " Read B....... debit or credit");
PrintAndLogEx(INFO, " Write A - Kc"); PrintAndLogEx(INFO, " Write A...... credit");
PrintAndLogEx(INFO, " Write B - Kc"); PrintAndLogEx(INFO, " Write B...... credit");
PrintAndLogEx(INFO, " Debit - Kd or Kc"); PrintAndLogEx(INFO, " Debit........ debit or credit");
PrintAndLogEx(INFO, " Credit - Kc"); PrintAndLogEx(INFO, " redit........ credit");
} }
} }
@ -1540,7 +1540,7 @@ static int CmdHFiClassDump(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode"));
use_replay = true; use_replay = true;
cmdp++; cmdp++;
break; break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -1552,7 +1552,7 @@ static int CmdHFiClassDump(const char *Cmd) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true; errors = true;
} }
if (errors) return usage_hf_iclass_dump(); if (errors) return usage_hf_iclass_dump();
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
@ -1788,7 +1788,7 @@ write_dump:
} }
static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose) { static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose) {
iclass_writeblock_req_t payload = { iclass_writeblock_req_t payload = {
.req.use_raw = rawkey, .req.use_raw = rawkey,
.req.use_elite = elite, .req.use_elite = elite,
@ -1882,13 +1882,13 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
rawkey = true; rawkey = true;
cmdp++; cmdp++;
break; break;
/* /*
case 'n': case 'n':
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode"));
use_replay = true; use_replay = true;
cmdp++; cmdp++;
break; break;
*/ */
case 'v': case 'v':
verbose = true; verbose = true;
cmdp++; cmdp++;
@ -1910,7 +1910,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); if (errors || cmdp < 6) return usage_hf_iclass_writeblock();
int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose); int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose);
switch(isok) { switch (isok) {
case PM3_SUCCESS: case PM3_SUCCESS:
PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno);
break; break;
@ -2043,24 +2043,24 @@ static int CmdHFiClassRestore(const char *Cmd) {
return PM3_EFILE; return PM3_EFILE;
} }
if (bytes_read < ((endblock - startblock + 1) * 8 )) { if (bytes_read < ((endblock - startblock + 1) * 8)) {
PrintAndLogEx(ERR, "file is smaller than your suggested block range ( " _RED_("0x%02x..0x%02x")" )", PrintAndLogEx(ERR, "file is smaller than your suggested block range ( " _RED_("0x%02x..0x%02x")" )",
startblock, endblock startblock, endblock
); );
free(dump); free(dump);
return PM3_EFILE; return PM3_EFILE;
} }
iclass_restore_req_t *payload = calloc(1, payload_size); iclass_restore_req_t *payload = calloc(1, payload_size);
payload->req.use_raw = rawkey, payload->req.use_raw = rawkey;
payload->req.use_elite = elite, payload->req.use_elite = elite;
payload->req.use_credit_key = use_credit_key, payload->req.use_credit_key = use_credit_key;
payload->req.use_replay = false, payload->req.use_replay = false;
payload->req.blockno = startblock, payload->req.blockno = startblock;
payload->req.send_reply = true, payload->req.send_reply = true;
payload->req.do_auth = true, payload->req.do_auth = true;
memcpy(payload->req.key, KEY, 8); memcpy(payload->req.key, KEY, 8);
payload->item_cnt = (endblock - startblock + 1); payload->item_cnt = (endblock - startblock + 1);
// read data from file from block 6 --- 19 // read data from file from block 6 --- 19
@ -2068,21 +2068,21 @@ static int CmdHFiClassRestore(const char *Cmd) {
// then copy to usbcommand->asbytes; // then copy to usbcommand->asbytes;
// max is 32 - 6 = 28 block. 28 x 12 bytes gives 336 bytes // max is 32 - 6 = 28 block. 28 x 12 bytes gives 336 bytes
for (uint8_t i = 0; i < payload->item_cnt; i++) { for (uint8_t i = 0; i < payload->item_cnt; i++) {
payload->blocks[i].blockno = startblock + i; payload->blocks[i].blockno = startblock + i;
memcpy(payload->blocks[i].data, dump + (startblock * 8) + (i * 8) , sizeof(payload->blocks[i].data)); memcpy(payload->blocks[i].data, dump + (startblock * 8) + (i * 8), sizeof(payload->blocks[i].data));
} }
free(dump); free(dump);
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "Preparing to restore block range 0x%02x..0x%02x", startblock, endblock); PrintAndLogEx(INFO, "Preparing to restore block range 0x%02x..0x%02x", startblock, endblock);
PrintAndLogEx(INFO, "------+----------------------"); PrintAndLogEx(INFO, "------+----------------------");
PrintAndLogEx(INFO, "block | data"); PrintAndLogEx(INFO, "block | data");
PrintAndLogEx(INFO, "------+----------------------"); PrintAndLogEx(INFO, "------+----------------------");
for (uint8_t i = 0; i < payload->item_cnt; i++) { for (uint8_t i = 0; i < payload->item_cnt; i++) {
iclass_restore_item_t item = payload->blocks[i]; iclass_restore_item_t item = payload->blocks[i];
PrintAndLogEx(INFO, " %02X | %s", item.blockno, sprint_hex_inrow(item.data, sizeof(item.data))); PrintAndLogEx(INFO, " %02X | %s", item.blockno, sprint_hex_inrow(item.data, sizeof(item.data)));
} }
@ -2233,7 +2233,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
} }
if (got_blockno == false) if (got_blockno == false)
errors = true; errors = true;
if ((use_replay + rawkey + elite) > 1) { if ((use_replay + rawkey + elite) > 1) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true; errors = true;
@ -2405,7 +2405,7 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
PrintAndLogEx(INFO, " blk| data | ascii |lck| info"); PrintAndLogEx(INFO, " blk| data | ascii |lck| info");
PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------");
PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8));
if (i != 1) if (i != 1)
PrintAndLogEx(INFO, "...."); PrintAndLogEx(INFO, "....");
@ -2455,8 +2455,8 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
const char *s = info_nonks[3]; const char *s = info_nonks[3];
if (i < 3) { if (i < 3) {
s = info_nonks[i]; s = info_nonks[i];
} }
PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s);
} else { } else {
const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"}; const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"};
@ -2978,8 +2978,8 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
free(keyBlock); free(keyBlock);
return res; return res;
} }
// Get CSN / UID and CCNR // Get CSN / UID and CCNR
PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR..."); PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR...");
for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) { for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) {
got_csn = select_only(CSN, CCNR, false); got_csn = select_only(CSN, CCNR, false);
@ -2993,7 +2993,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
} }
iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t)); iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t));
if (pre == NULL) { if (pre == NULL) {
return PM3_EMALLOC; return PM3_EMALLOC;
@ -3449,7 +3449,7 @@ static int CmdHFiClassAutopwn(const char *Cmd) {
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx); CLIParserFree(ctx);
// Check keys. // Check keys.
// dump // dump
@ -3539,33 +3539,33 @@ int info_iclass(void) {
picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)resp.data.asBytes; picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)resp.data.asBytes;
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------"); PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "------------------------------------------------------------");
if (readStatus & FLAG_ICLASS_CSN) { if (readStatus & FLAG_ICLASS_CSN) {
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn))); PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
} }
if (readStatus & FLAG_ICLASS_CONF) { if (readStatus & FLAG_ICLASS_CONF) {
PrintAndLogEx(SUCCESS, " Config: %s (Card configuration)", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
} }
// page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks. // page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks.
// page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf // page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf
uint8_t pagemap = get_pagemap(hdr); uint8_t pagemap = get_pagemap(hdr);
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area))); PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area)));
} else { } else {
if (readStatus & FLAG_ICLASS_CC) { if (readStatus & FLAG_ICLASS_CC) {
PrintAndLogEx(SUCCESS, "E-purse: %s (Card challenge, CC)", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
} }
PrintAndLogEx(SUCCESS, " Kd: %s (Debit key, hidden)", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); PrintAndLogEx(SUCCESS, " Kd: %s debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
PrintAndLogEx(SUCCESS, " Kc: %s (Credit key, hidden)", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); PrintAndLogEx(SUCCESS, " Kc: %s credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
if (readStatus & FLAG_ICLASS_AIA) { if (readStatus & FLAG_ICLASS_AIA) {
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
} }
} }
@ -3573,7 +3573,7 @@ int info_iclass(void) {
print_picopass_info(hdr); print_picopass_info(hdr);
} }
PrintAndLogEx(INFO, "------ " _CYAN_("Fingerprint") " ------"); PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
uint8_t aia[8]; uint8_t aia[8];
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) if (pagemap == PICOPASS_NON_SECURE_PAGEMODE)
@ -3588,18 +3588,17 @@ int info_iclass(void) {
bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
if (isHidRange) { if (isHidRange) {
PrintAndLogEx(SUCCESS, "CSN is in HID range"); PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("HID range"));
if (legacy) if (legacy)
PrintAndLogEx(SUCCESS, "Credential : " _GREEN_("iCLASS legacy")); PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS legacy"));
if (se_enabled) if (se_enabled)
PrintAndLogEx(SUCCESS, "Credential : " _GREEN_("iCLASS SE")); PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE"));
} else { } else {
PrintAndLogEx(SUCCESS, _YELLOW_("PicoPass")" (CSN is not in HID range)"); PrintAndLogEx(SUCCESS, " CSN..-....... " _YELLOW_("outside HID range"));
} }
uint8_t cardtype = get_mem_config(hdr); uint8_t cardtype = get_mem_config(hdr);
PrintAndLogEx(SUCCESS, " Card type : " _GREEN_("%s"), card_types[cardtype]); PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
} }
DropField(); DropField();

View file

@ -294,9 +294,9 @@ static int CmdHFMFPInfo(const char *Cmd) {
} else { } else {
// info about 14a part // info about 14a part
infoHF14A(false, false, false); infoHF14A(false, false, false);
// Historical bytes. // Historical bytes.
} }

View file

@ -242,7 +242,7 @@ static int usage_hf_mfu_otp_tearoff(void) {
PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us"); PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us");
PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00"); PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00"); PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value"); PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3"); PrintAndLogEx(NORMAL, " hf mfu otptear b 3");
@ -362,7 +362,7 @@ static bool ul_select(iso14a_card_select_t *card) {
return false; return false;
} }
if (card) if (card)
memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
} }
return true; return true;
@ -2897,7 +2897,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
} }
use_match = true; use_match = true;
cmdp += 2; cmdp += 2;
break; break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -2947,9 +2947,9 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8); SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8);
// we be getting ACK that we are silently ignoring here.. // we be getting ACK that we are silently ignoring here..
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) { if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
PrintAndLogEx(WARNING, "Failed"); PrintAndLogEx(WARNING, "Failed");
return PM3_ESOFT; return PM3_ESOFT;
@ -3061,7 +3061,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
/* /*
static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) { static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
PrintAndLogEx(INFO, "Reset tear check"); PrintAndLogEx(INFO, "Reset tear check");
uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00}; uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
@ -3081,7 +3081,7 @@ static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
return PM3_ESOFT; return PM3_ESOFT;
} }
DropField(); DropField();
if (ct[0] != 0xBD) { if (ct[0] != 0xBD) {
PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?"); PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
return PM3_ESOFT; return PM3_ESOFT;
@ -3106,13 +3106,13 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"), arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"), arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"), arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
arg_int0("s", "start", "<dec>", "test start time - default 0 us"), arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"), arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"), arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int interval = 0; int interval = 0;
int time_limit, start_time = 0; int time_limit, start_time = 0;
int counter = arg_get_int_def(ctx, 1, 0); int counter = arg_get_int_def(ctx, 1, 0);
@ -3124,15 +3124,15 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
start_time = arg_get_int_def(ctx, 4, 0); start_time = arg_get_int_def(ctx, 4, 0);
} else { } else {
start_time = fixed; start_time = fixed;
interval = 0; interval = 0;
time_limit = fixed; time_limit = fixed;
} }
uint8_t newvalue[5] = {0}; uint8_t newvalue[5] = {0};
int newvaluelen = 0; int newvaluelen = 0;
CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen); CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
CLIParserFree(ctx); CLIParserFree(ctx);
// Validations // Validations
if (start_time > (time_limit - interval)) { if (start_time > (time_limit - interval)) {
PrintAndLogEx(WARNING, "Wrong start time number"); PrintAndLogEx(WARNING, "Wrong start time number");
@ -3163,14 +3163,14 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
PrintAndLogEx(INFO, "failed to select card, exiting..."); PrintAndLogEx(INFO, "failed to select card, exiting...");
return PM3_ESOFT; return PM3_ESOFT;
} }
uint8_t inital_cnt[3] = {0, 0, 0}; uint8_t inital_cnt[3] = {0, 0, 0};
int len = ulev1_readCounter(cnt_no, inital_cnt, sizeof(inital_cnt)); int len = ulev1_readCounter(cnt_no, inital_cnt, sizeof(inital_cnt));
if ( len != sizeof(inital_cnt) ) { if ( len != sizeof(inital_cnt) ) {
PrintAndLogEx(WARNING, "failed to read counter"); PrintAndLogEx(WARNING, "failed to read counter");
return PM3_ESOFT; return PM3_ESOFT;
} }
uint8_t inital_tear[1] = {0}; uint8_t inital_tear[1] = {0};
len = ulev1_readTearing(cnt_no, inital_tear, sizeof(inital_tear)); len = ulev1_readTearing(cnt_no, inital_tear, sizeof(inital_tear));
DropField(); DropField();
@ -3184,7 +3184,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------"); PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter); PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(inital_cnt, sizeof(inital_cnt))); PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(inital_cnt, sizeof(inital_cnt)));
PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", inital_tear[0]); PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", inital_tear[0]);
PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen)); PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
PrintAndLogEx(INFO, "----------------------------------------------------"); PrintAndLogEx(INFO, "----------------------------------------------------");
@ -3197,7 +3197,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
uint32_t loop = 0; uint32_t loop = 0;
uint16_t late = 0; uint16_t late = 0;
while (actual_time <= (time_limit - interval)) { while (actual_time <= (time_limit - interval)) {
@ -3217,7 +3217,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
continue; continue;
} }
uint8_t cntresp[3] = {0, 0, 0}; uint8_t cntresp[3] = {0, 0, 0};
int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp)); int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
if ( rlen == sizeof(cntresp) ) { if ( rlen == sizeof(cntresp) ) {
memcpy(pre, cntresp, sizeof(pre)); memcpy(pre, cntresp, sizeof(pre));
@ -3226,19 +3226,19 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting..."); PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
break; break;
} }
uint8_t tear[1] = {0}; uint8_t tear[1] = {0};
int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear)); int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
if ( tlen == sizeof(tear) ) { if ( tlen == sizeof(tear) ) {
pre_tear = tear[0]; pre_tear = tear[0];
} else { } else {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen); PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
break; break;
} }
DropField(); DropField();
struct p { struct p {
uint8_t counter; uint8_t counter;
uint32_t tearoff_time; uint32_t tearoff_time;
@ -3269,7 +3269,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting..."); PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
break; break;
} }
tear[0] = 0; tear[0] = 0;
tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear)); tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
if ( tlen == sizeof(tear) ) { if ( tlen == sizeof(tear) ) {
@ -3279,7 +3279,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting..."); PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
break; break;
} }
DropField(); DropField();
char prestr[20] = {0}; char prestr[20] = {0};
@ -3290,15 +3290,15 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
bool post_tear_check = (post_tear == 0xBD); bool post_tear_check = (post_tear == 0xBD);
a = (pre[0] | pre[1] << 8 | pre[2] << 16); a = (pre[0] | pre[1] << 8 | pre[2] << 16);
b = (post[0] | post[1] << 8 | post[2] << 16); b = (post[0] | post[1] << 8 | post[2] << 16);
// A != B // A != B
if (memcmp(pre, post, sizeof(pre)) != 0) { if (memcmp(pre, post, sizeof(pre)) != 0) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (inital_value != a ) { if (inital_value != a ) {
if ( inital_value != b ) if ( inital_value != b )
PrintAndLogEx(INFO, "pre %08x, post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear); PrintAndLogEx(INFO, "pre %08x, post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
else else
@ -3319,7 +3319,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
); );
break; break;
} }
if ( a > b ) { if ( a > b ) {
PrintAndLogEx(INFO, _CYAN_("Tear off occured " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )" PrintAndLogEx(INFO, _CYAN_("Tear off occured " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
, prestr , prestr
@ -3347,14 +3347,14 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
newvalue[2] = 0; newvalue[2] = 0;
PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar); PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value); PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b); PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen)); PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
continue; continue;
} else { } else {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, _CYAN_("Tear off occured (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )" PrintAndLogEx(INFO, _CYAN_("Tear off occured (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
, prestr , prestr
, poststr , poststr
@ -3368,23 +3368,23 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
break; break;
} }
if ( wr_value != 0 ) { if ( wr_value != 0 ) {
//uint32_t bar = (0x1000000 - b) + 2; //uint32_t bar = (0x1000000 - b) + 2;
wr_value = 0; wr_value = 0;
newvalue[0] = 0; newvalue[0] = 0;
newvalue[1] = 0; newvalue[1] = 0;
newvalue[2] = 0; newvalue[2] = 0;
if ( b >= (inital_value + (2 * wr_value))) { if ( b >= (inital_value + (2 * wr_value))) {
PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected"); PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
// wr_value = bar; // wr_value = bar;
// newvalue[0] = (bar) & 0xFF; // newvalue[0] = (bar) & 0xFF;
// newvalue[1] = ((bar >> 8) & 0xFF); // newvalue[1] = ((bar >> 8) & 0xFF);
// newvalue[2] = ((bar >> 16) & 0xFF); // newvalue[2] = ((bar >> 16) & 0xFF);
} else { } else {
// wr_value = bar; // wr_value = bar;
// newvalue[0] = (bar) & 0xFF; // newvalue[0] = (bar) & 0xFF;
// newvalue[1] = ((bar >> 8) & 0xFF); // newvalue[1] = ((bar >> 8) & 0xFF);
@ -3397,7 +3397,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
} }
PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen)); PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
//actual_time--; //actual_time--;
late++; late++;
} }
@ -3410,19 +3410,19 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
, post_tear , post_tear
, post_tear_check ? _GREEN_("OK") : _RED_("DETECTED") , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
); );
if ( post_tear_check ) { if ( post_tear_check ) {
if ( a == b ) { if ( a == b ) {
//actual_time--; //actual_time--;
continue; continue;
} }
if ( b == inital_value ) { if ( b == inital_value ) {
PrintAndLogEx(INFO, "Reverted to previous value"); PrintAndLogEx(INFO, "Reverted to previous value");
break; break;
} }
} else { } else {
if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){ if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
PrintAndLogEx(FAILED, "failed to reset tear, exiting..."); PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
break; break;
@ -3436,7 +3436,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
DropField(); DropField();
PrintAndLogEx(INFO, " Sent %u tear offs ", loop); PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
counter_reset_tear(&card, cnt_no); counter_reset_tear(&card, cnt_no);
@ -3584,7 +3584,7 @@ static command_t CommandTable[] = {
{"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"}, {"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"},
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"}, {"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"}, {"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
// {"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"}, // {"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"},
{"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, {"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View file

@ -523,14 +523,14 @@ static int cmd_hf_st_protect(const char *Cmd) {
if (enable_protection && disable_protection) { if (enable_protection && disable_protection) {
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both"); PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (enable_protection) { if (enable_protection) {
state[0] = 0x28; state[0] = 0x28;
} }
if (disable_protection) { if (disable_protection) {
state[0] = 0x26; state[0] = 0x26;
} }
if (read_protection && write_protection) { if (read_protection && write_protection) {
PrintAndLogEx(ERR, "Must specify either read or write protection, not both"); PrintAndLogEx(ERR, "Must specify either read or write protection, not both");
return PM3_EINVARG; return PM3_EINVARG;
@ -681,7 +681,7 @@ static int cmd_hf_st_pwd(const char *Cmd) {
if (change_write_password) { if (change_write_password) {
changePwd[2] = 0x02; changePwd[2] = 0x02;
} }
if (pwdlen != 16) { if (pwdlen != 16) {
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes"); PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
return PM3_EINVARG; return PM3_EINVARG;

View file

@ -351,7 +351,7 @@ static void map8to1(uint8_t *colormap, uint16_t width, uint16_t height, uint8_t
static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, uint8_t **black, uint8_t **red, char *filename, bool save_conversions) { static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, uint8_t **black, uint8_t **red, char *filename, bool save_conversions) {
BMP_HEADER *pbmpheader = (BMP_HEADER *)bmp; BMP_HEADER *pbmpheader = (BMP_HEADER *)bmp;
// check file is full color // check file is full color
if (pbmpheader->bpp != 24) { if ((pbmpheader->bpp != 24) && (pbmpheader->bpp != 32)) {
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -400,6 +400,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
chanB[X + (height - Y - 1) * width] = bmp[offset++]; chanB[X + (height - Y - 1) * width] = bmp[offset++];
chanG[X + (height - Y - 1) * width] = bmp[offset++]; chanG[X + (height - Y - 1) * width] = bmp[offset++];
chanR[X + (height - Y - 1) * width] = bmp[offset++]; chanR[X + (height - Y - 1) * width] = bmp[offset++];
if (pbmpheader->bpp == 32) // Skip Alpha chan
offset++;
} }
// Skip line padding // Skip line padding
offset += width % 4; offset += width % 4;
@ -436,6 +438,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
bmp[offset++] = chanB[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanB[X + (height - Y - 1) * width] & 0xFF;
bmp[offset++] = chanG[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanG[X + (height - Y - 1) * width] & 0xFF;
bmp[offset++] = chanR[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanR[X + (height - Y - 1) * width] & 0xFF;
if (pbmpheader->bpp == 32) // Fill Alpha chan
bmp[offset++] = 0xFF;
} }
// Skip line padding // Skip line padding
offset += width % 4; offset += width % 4;
@ -500,6 +504,8 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF; bmp[offset++] = chanGrey[X + (height - Y - 1) * width] & 0xFF;
if (pbmpheader->bpp == 32) // Fill Alpha chan
bmp[offset++] = 0xFF;
} }
// Skip line padding // Skip line padding
offset += width % 4; offset += width % 4;
@ -536,7 +542,8 @@ static void read_black(uint32_t i, uint8_t *l, uint8_t model_nr, uint8_t *black)
} }
} }
static void read_red(uint32_t i, uint8_t *l, uint8_t model_nr, uint8_t *red) { static void read_red(uint32_t i, uint8_t *l, uint8_t model_nr, uint8_t *red) {
for (uint8_t j = 0; j < models[model_nr].len; j++) { // spurious warning with GCC10 (-Wstringop-overflow) when j is uint8_t, even if all len are < 128
for (uint16_t j = 0; j < models[model_nr].len; j++) {
if (model_nr == M1in54B) { if (model_nr == M1in54B) {
//1.54B needs to flip the red picture data, other screens do not need to flip data //1.54B needs to flip the red picture data, other screens do not need to flip data
l[3 + j] = ~red[i * models[model_nr].len + j]; l[3 + j] = ~red[i * models[model_nr].len + j];
@ -693,11 +700,21 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
return PM3_ESOFT; return PM3_ESOFT;
} }
if ((card.uidlen != 7) || (memcmp(card.uid, "WSDZ10m", 7) != 0)) { if ((card.uidlen != 7) || ((memcmp(card.uid, "FSTN10m", 7) != 0) && (memcmp(card.uid, "WSDZ10m", 7) != 0))) {
PrintAndLogEx(WARNING, "Card doesn't look like Waveshare tag"); PrintAndLogEx(WARNING, "Card doesn't look like Waveshare tag");
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
} }
if (((model_nr != M1in54B) && (memcmp(card.uid, "FSTN10m", 7) == 0))) {
PrintAndLogEx(WARNING, "Card is a Waveshare tag 1.54\", not %s", models[model_nr].desc);
DropField();
return PM3_ESOFT;
}
if (((model_nr == M1in54B) && (memcmp(card.uid, "FSTN10m", 7) != 0))) {
PrintAndLogEx(WARNING, "Card is not a Waveshare tag 1.54\", check your model number");
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(DEBUG, "model_nr = %d", model_nr); PrintAndLogEx(DEBUG, "model_nr = %d", model_nr);
int ret; int ret;
PrintAndLogEx(DEBUG, "Step0"); PrintAndLogEx(DEBUG, "Step0");
@ -921,6 +938,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
msleep(200); msleep(200);
} }
PrintAndLogEx(DEBUG, "Step11: Wait tag to be ready"); PrintAndLogEx(DEBUG, "Step11: Wait tag to be ready");
PrintAndLogEx(INPLACE, "E-paper Reflashing, Waiting");
if (model_nr == M2in13B || model_nr == M1in54B) { // Black, white and red screen refresh time is longer, wait first if (model_nr == M2in13B || model_nr == M1in54B) { // Black, white and red screen refresh time is longer, wait first
msleep(9000); msleep(9000);
} else if (model_nr == M7in5HD) { } else if (model_nr == M7in5HD) {
@ -950,7 +968,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
} else { } else {
fail_num++; fail_num++;
PrintAndLogEx(INPLACE, "E-paper Reflashing, Waiting"); PrintAndLogEx(INPLACE, "E-paper Reflashing, Waiting");
msleep(100); msleep(400);
} }
} }
} }
@ -1048,11 +1066,13 @@ static int CmdHF14AWSLoadBmp(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
} else if (depth == 32) { } else if (depth == 32) {
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Remove alpha channel.", depth); PrintAndLogEx(DEBUG, "BMP file is a RGBA, we will ignore the Alpha channel");
free(bmp); if (read_bmp_rgb(bmp, bytes_read, model_nr, &black, &red, filename, save_conversions) != PM3_SUCCESS) {
return PM3_ESOFT; free(bmp);
return PM3_ESOFT;
}
} else { } else {
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Must be 1 (BW) or 24 (RGB)", depth); PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Must be 1 (BW), 24 (RGB) or 32 (RGBA)", depth);
free(bmp); free(bmp);
return PM3_ESOFT; return PM3_ESOFT;
} }

View file

@ -792,18 +792,18 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("PROXMARK3") " ]"); PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("PROXMARK3") " ]");
if (IfPm3Rdv4Fw() == false) { if (IfPm3Rdv4Fw() == false) {
PrintAndLogEx(NORMAL, " firmware.........................%s", _GREEN_("PM3OTHER")); PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3OTHER"));
if (IfPm3FpcUsartHost()) { if (IfPm3FpcUsartHost()) {
PrintAndLogEx(NORMAL, " FPC USART for BT add-on..........%s", _GREEN_("present")); PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
} }
} else { } else {
PrintAndLogEx(NORMAL, " firmware.........................%s", _GREEN_("PM3RDV4")); PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3RDV4"));
PrintAndLogEx(NORMAL, " external flash...................%s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " smartcard reader.................%s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " FPC USART for BT add-on..........%s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
} }
if (IfPm3FpcUsartDevFromUsb()) { if (IfPm3FpcUsartDevFromUsb()) {
PrintAndLogEx(NORMAL, " FPC USART for developer..........%s", _GREEN_("present")); PrintAndLogEx(NORMAL, " FPC USART for developer... %s", _GREEN_("present"));
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");

View file

@ -31,7 +31,7 @@
#include "cmdlfawid.h" // for awid menu #include "cmdlfawid.h" // for awid menu
#include "cmdlfem4x.h" // for em4x menu #include "cmdlfem4x.h" // for em4x menu
#include "cmdlfem4x05.h" // for em4x05 / 4x69 #include "cmdlfem4x05.h" // for em4x05 / 4x69
#include "cmdlfem4x50.h" // for em4x50 #include "cmdlfem4x50.h" // for em4x50
#include "cmdlfhid.h" // for hid menu #include "cmdlfhid.h" // for hid menu
#include "cmdlfhitag.h" // for hitag menu #include "cmdlfhitag.h" // for hitag menu
#include "cmdlfidteck.h" // for idteck menu #include "cmdlfidteck.h" // for idteck menu
@ -1348,7 +1348,7 @@ static bool CheckChipType(bool getDeviceData) {
//check for em4x05/em4x69 chips first //check for em4x05/em4x69 chips first
uint32_t word = 0; uint32_t word = 0;
if (EM4x05IsBlock0(&word)) { if (em4x05_isblock0(&word)) {
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05 / EM4x69")); PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05 / EM4x69"));
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands");
retval = true; retval = true;

View file

@ -66,7 +66,7 @@ int demodDestron(bool verbose) {
uint8_t data[5] = {0}; uint8_t data[5] = {0};
uint8_t parity_err = 0; uint8_t parity_err = 0;
for (int i=0; i < sizeof(data); i++) { for (int i = 0; i < sizeof(data); i++) {
data[i] = bytebits_to_byte(bits + i * 8, 8); data[i] = bytebits_to_byte(bits + i * 8, 8);
parity_err += oddparity8(data[i]); parity_err += oddparity8(data[i]);
data[i] &= 0x7F; data[i] &= 0x7F;
@ -113,11 +113,11 @@ static int CmdDestronClone(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint8_t data_ex[12 + 24] = {0}; // ManchesterEncode need extra room uint8_t data_ex[12 + 24] = {0}; // ManchesterEncode need extra room
for (int i=0; i < datalen; i++) { for (int i = 0; i < datalen; i++) {
data_ex[i + 1] = ~data [i] | (evenparity8(data[i]) << 7); data_ex[i + 1] = ~data [i] | (evenparity8(data[i]) << 7);
} }
for (int i=0; i < 3; i++) { for (int i = 0; i < 3; i++) {
blocks[i+1] = manchesterEncode2Bytes((data_ex[i*2]<<8)+data_ex[i*2+1]); blocks[i + 1] = manchesterEncode2Bytes((data_ex[i * 2] << 8) + data_ex[i * 2 + 1]);
} }
// inject preamble // inject preamble
blocks[1] = (blocks[1] & 0xFFFF) | 0xAAE20000; blocks[1] = (blocks[1] & 0xFFFF) | 0xAAE20000;

View file

@ -646,6 +646,8 @@ static command_t CommandTable[] = {
{"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"}, {"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
{"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"}, {"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
{"4x05_unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"}, {"4x05_unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"},
{"4x05_sniff", CmdEM4x05Sniff, AlwaysAvailable, "Attempt to recover em4x05 commands from sample buffer"},
{"4x05_brute", CmdEM4x05Brute, IfPm3Lf, "Bruteforce password"},
{"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"}, {"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"},
{"4x50_dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"}, {"4x50_dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"},
{"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"}, {"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"},

File diff suppressed because it is too large Load diff

View file

@ -13,11 +13,57 @@
#include "common.h" #include "common.h"
#define EM_SERIAL_BLOCK 1
#define EM_CONFIG_BLOCK 4
#define EM4305_PROT1_BLOCK 14
#define EM4305_PROT2_BLOCK 15
#define EM4469_PROT_BLOCK 3
// config blocks
#define EM4305_DEFAULT_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/MAN , data rate 32, 4 data blocks
//#define EM4305_DEFAULT_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/BIPHASE , data rate 32, 4 data blocks
#define EM4305_EM_UNIQUE_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, EM4x02/unique - data rate 64, 2 data blocks
#define EM4305_PAXTON_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, EM4x02/paxton - data rate 64, 2 data blocks
#define EM4305_VISA2000_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK, data rate 64, 3 data blocks
#define EM4305_VIKING_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2) ) // ASK/MAN, data rate 32, 2 data blocks
#define EM4305_NORALSY_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK, data rate 32, 3 data blocks
#define EM4305_PRESCO_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/MAN, data rate 32, 4 data blocks
#define EM4305_SECURAKEY_CONFIG_BLOCK (EM4x05_SET_BITRATE(40) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK/MAN, data rate 40, 3 data blocks
#define EM4305_HID_26_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
#define EM4305_PARADOX_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
#define EM4305_AWID_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
#define EM4305_PYRAMID_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(4) ) // FSK2a, Pyramid 26 bit, data rate 50, 4 data blocks
#define EM4305_IOPROX_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(2) ) // FSK2a, data rate 64, 2 data blocks
#define EM4305_INDALA_64_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, indala 64 bit, psk carrier FC * 2, data rate 32, maxblock 2
#define EM4305_INDALA_224_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(7) ) // PSK1, indala 224 bit, psk carrier FC * 2, data rate 32, maxblock 7
#define EM4305_MOTOROLA_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, data rate 32, 2 data blocks
#define EM4305_NEXWATCH_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(3) ) // PSK1 data rate 16, psk carrier FC * 2, 3 data blocks
#define EM4305_KERI_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_PSK1 | EM4x05_PSK_RF_2 | EM4x05_SET_NUM_BLOCKS(2) ) // PSK1, 2 data blocks
#define EM4305_JABLOTRON_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(2) ) // Biphase, data rate 64, 2 data blocks
#define EM4305_GUARDPROXII_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(3) ) // Biphase, data rate 64, Direct modulation, 3 data blocks
#define EM4305_NEDAP_64_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(2) ) // Biphase, data rate 64, 2 data blocks
#define EM4305_NEDAP_128_CONFIG_BLOCK (EM4x05_SET_BITRATE(64) | EM4x05_MODULATION_BIPHASE | EM4x05_SET_NUM_BLOCKS(4) ) // Biphase, data rate 64, 4 data blocks
#define EM4305_PAC_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_NRZ | EM4x05_SET_NUM_BLOCKS(4) ) // NRZ, data rate 32, 4 data blocks
#define EM4305_VERICHIP_CONFIG_BLOCK (EM4x05_SET_BITRATE(40) | EM4x05_MODULATION_NRZ | EM4x05_SET_NUM_BLOCKS(4) ) // NRZ, data rate 40, 4 data blocks
typedef enum {
EM_UNKNOWN,
EM_4205,
EM_4305,
EM_4X69,
} em_tech_type_t;
int CmdLFEM4X05(const char *Cmd); int CmdLFEM4X05(const char *Cmd);
bool EM4x05IsBlock0(uint32_t *word); bool em4x05_isblock0(uint32_t *word);
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word); int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t *word);
int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data);
int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool use_pwd);
int CmdEM4x05Demod(const char *Cmd); int CmdEM4x05Demod(const char *Cmd);
int CmdEM4x05Dump(const char *Cmd); int CmdEM4x05Dump(const char *Cmd);
@ -27,5 +73,7 @@ int CmdEM4x05Wipe(const char *Cmd);
int CmdEM4x05Info(const char *Cmd); int CmdEM4x05Info(const char *Cmd);
int CmdEM4x05Chk(const char *Cmd); int CmdEM4x05Chk(const char *Cmd);
int CmdEM4x05Unlock(const char *Cmd); int CmdEM4x05Unlock(const char *Cmd);
int CmdEM4x05Sniff(const char *Cmd);
int CmdEM4x05Brute(const char *Cmd);
#endif #endif

View file

@ -77,7 +77,7 @@ static int usage_lf_em4x50_dump(void) {
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] [f <filename prefix>] [p <pwd>]"); PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] [f <filename prefix>] [p <pwd>]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " h - this help");
PrintAndLogEx(NORMAL, " f <filename prefix> - overide filename prefix (optional). Default is based on UID"); PrintAndLogEx(NORMAL, " f <filename prefix> - override filename prefix (optional). Default is based on UID");
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)"); PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump")); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump"));
@ -493,7 +493,7 @@ int CmdEM4x50WritePassword(const char *Cmd) {
if (resp.status == PM3_ETEAROFF) if (resp.status == PM3_ETEAROFF)
return PM3_SUCCESS; return PM3_SUCCESS;
success = (bool)resp.status; success = (bool)resp.status;
// get, prepare and print response // get, prepare and print response

View file

@ -470,7 +470,7 @@ const fdxbCountryMapping_t fdxbCountryMapping[] = {
{ 0, "N/A" } // must be the last entry { 0, "N/A" } // must be the last entry
}; };
static const char* mapFDBX(uint16_t countryCode) { static const char *mapFDBX(uint16_t countryCode) {
uint16_t i = 0; uint16_t i = 0;
while (fdxbCountryMapping[i].code > 0) { while (fdxbCountryMapping[i].code > 0) {
if (countryCode == fdxbCountryMapping[i].code) { if (countryCode == fdxbCountryMapping[i].code) {
@ -572,8 +572,8 @@ int demodFDXB(bool verbose) {
PrintAndLogEx(SUCCESS, " Animal bit set? %s", animalBit ? _YELLOW_("True") : "False"); PrintAndLogEx(SUCCESS, " Animal bit set? %s", animalBit ? _YELLOW_("True") : "False");
PrintAndLogEx(SUCCESS, " Data block? %s [value 0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended); PrintAndLogEx(SUCCESS, " Data block? %s [value 0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
PrintAndLogEx(SUCCESS, " RUDI bit? %s", rudiBit ? _YELLOW_("True") " (advanced transponder)" : "False"); PrintAndLogEx(SUCCESS, " RUDI bit? %s", rudiBit ? _YELLOW_("True") " (advanced transponder)" : "False");
PrintAndLogEx(SUCCESS, " User Info? %u %s", userInfo, userInfo == 0 ? "(RFU)":""); PrintAndLogEx(SUCCESS, " User Info? %u %s", userInfo, userInfo == 0 ? "(RFU)" : "");
PrintAndLogEx(SUCCESS, " Replacement No? %u %s", replacementNr, replacementNr == 0 ? "(RFU)":""); PrintAndLogEx(SUCCESS, " Replacement No? %u %s", replacementNr, replacementNr == 0 ? "(RFU)" : "");
uint8_t c[] = {0, 0}; uint8_t c[] = {0, 0};
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]); compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);

View file

@ -601,7 +601,7 @@ static int CmdIndalaClone(const char *Cmd) {
CLIGetHexWithReturn(ctx, 3, data, &datalen); CLIGetHexWithReturn(ctx, 3, data, &datalen);
bool is_t5555 = arg_get_lit(ctx, 4); bool is_t5555 = arg_get_lit(ctx, 4);
bool got_cn = false, got_26 = false; bool got_cn = false, got_26 = false;
if (is_long_uid == false) { if (is_long_uid == false) {
@ -616,7 +616,7 @@ static int CmdIndalaClone(const char *Cmd) {
} }
CLIParserFree(ctx); CLIParserFree(ctx);
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7"); PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
if (is_long_uid) { if (is_long_uid) {

View file

@ -8,23 +8,21 @@
// PSK1, RF/128, RF/2, 64 bits long // PSK1, RF/128, RF/2, 64 bits long
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdlfkeri.h" #include "cmdlfkeri.h"
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include "commonutil.h" // ARRAYLEN
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "cliparser.h" #include "cliparser.h"
#include "comms.h" #include "comms.h"
#include "ui.h" #include "ui.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // preamble test #include "lfdemod.h" // preamble test
#include "cmdlft55xx.h" // verifywrite #include "cmdlft55xx.h" // verifywrite
#include "cmdlfem4x05.h" //
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t; typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t;
@ -125,17 +123,6 @@ int demodKeri(bool verbose) {
setDemodBuff(DemodBuffer, size, idx); setDemodBuff(DemodBuffer, size, idx);
setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock));
//got a good demod
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
//get internal id
// uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32);
// Due to the 3 sync bits being at the start of the capture
// We can take the last 32bits as the internal ID.
uint32_t ID = raw2;
ID &= 0x7FFFFFFF;
/* /*
000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111 000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1###############################^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1###############################^^^
@ -150,25 +137,40 @@ int demodKeri(bool verbose) {
Might be a hash of FC & CN to generate Internal ID Might be a hash of FC & CN to generate Internal ID
*/ */
PrintAndLogEx(SUCCESS, "KERI - Internal ID: " _GREEN_("%u") ", Raw: %08X%08X", ID, raw1, raw2);
/* /*
Descramble Data. Descramble Data.
*/ */
uint32_t fc = 0; uint32_t fc = 0;
uint32_t cardid = 0; uint32_t cardid = 0;
//got a good demod
// Just need to the low 32 bits without the 111 trailer uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2); uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
PrintAndLogEx(SUCCESS, "Descrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d"), fc, cardid);
if (invert) { if (invert) {
PrintAndLogEx(INFO, "Had to Invert - probably KERI"); PrintAndLogEx(INFO, "Had to Invert - probably KERI");
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
DemodBuffer[i] ^= 1; DemodBuffer[i] ^= 1;
raw1 = bytebits_to_byte(DemodBuffer, 32);
raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
CmdPrintDemodBuff("x"); CmdPrintDemodBuff("x");
} }
//get internal id
// uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32);
// Due to the 3 sync bits being at the start of the capture
// We can take the last 32bits as the internal ID.
uint32_t ID = raw2;
ID &= 0x7FFFFFFF;
PrintAndLogEx(SUCCESS, "KERI - Internal ID: " _GREEN_("%u") ", Raw: %08X%08X", ID, raw1, raw2);
// Just need to the low 32 bits without the 111 trailer
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2);
PrintAndLogEx(SUCCESS, "Descrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d"), fc, cardid);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -185,7 +187,7 @@ static int CmdKeriRead(const char *Cmd) {
static int CmdKeriClone(const char *Cmd) { static int CmdKeriClone(const char *Cmd) {
bool q5 = false; bool q5 = false, em4305 = false;
uint8_t keritype[2] = {'i'}; // default to internalid uint8_t keritype[2] = {'i'}; // default to internalid
int typeLen = 0; int typeLen = 0;
@ -207,7 +209,7 @@ static int CmdKeriClone(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "lf keri clone", CLIParserInit(&ctx, "lf keri clone",
"clone a KERI tag to a T55x7 or Q5/T5555 tag", "clone a KERI tag to a T55x7, Q5/T5555 or EM4305/4469 tag",
"lf keri clone -t i --id 12345\n" "lf keri clone -t i --id 12345\n"
"lf keri clone -t m --fc 6 --id 12345\n"); "lf keri clone -t m --fc 6 --id 12345\n");
@ -217,20 +219,34 @@ static int CmdKeriClone(const char *Cmd) {
arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"), arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"),
arg_int0(NULL, "fc", "<dec>", "Facility Code"), arg_int0(NULL, "fc", "<dec>", "Facility Code"),
arg_int1(NULL, "id", "<dec>", "Keri ID"), arg_int1(NULL, "id", "<dec>", "Keri ID"),
arg_lit0(NULL, "em", "specify writing to EM4305/4469 tag"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
char cardtype[16] = {"T55x7"};
if (arg_get_lit(ctx, 1)) { if (arg_get_lit(ctx, 1)) {
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
q5 = true; q5 = true;
} }
if (arg_get_lit(ctx, 5)) {
blocks[0] = EM4305_KERI_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
em4305 = true;
}
typeLen = sizeof(keritype); typeLen = sizeof(keritype);
CLIGetStrWithReturn(ctx, 2, keritype, &typeLen); CLIGetStrWithReturn(ctx, 2, keritype, &typeLen);
fc = arg_get_int_def(ctx, 3, 0); fc = arg_get_int_def(ctx, 3, 0);
cid = arg_get_int_def(ctx, 4, 0); cid = arg_get_int_def(ctx, 4, 0);
CLIParserFree(ctx); CLIParserFree(ctx);
if (q5 && em4305) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
// Setup card data/build internal id // Setup card data/build internal id
switch (keritype[0]) { switch (keritype[0]) {
@ -249,14 +265,20 @@ static int CmdKeriClone(const char *Cmd) {
// Prepare and write to card // Prepare and write to card
// 3 LSB is ONE // 3 LSB is ONE
uint64_t data = ((uint64_t)internalid << 3) + 7; uint64_t data = ((uint64_t)internalid << 3) + 7;
PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), (q5) ? "Q5/T5555" : "T55x7", internalid); PrintAndLogEx(INFO, "Preparing to clone KERI to " _YELLOW_("%s") " with Internal Id " _YELLOW_("%" PRIx32), cardtype, internalid);
blocks[1] = data >> 32; blocks[1] = data >> 32;
blocks[2] = data & 0xFFFFFFFF; blocks[2] = data & 0xFFFFFFFF;
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res;
if (em4305) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify");
return res; return res;

View file

@ -173,18 +173,18 @@ static int CmdMotorolaClone(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
//TODO add selection of chip for Q5 or T55x7 //TODO add selection of chip for Q5 or T55x7
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7"); PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2) // config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag"); PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag");
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
if (is_t5555) if (is_t5555)
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
else else
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
blocks[1] = bytes_to_num(data, 4); blocks[1] = bytes_to_num(data, 4);
blocks[2] = bytes_to_num(data + 4, 4); blocks[2] = bytes_to_num(data + 4, 4);

View file

@ -186,7 +186,7 @@ static int usage_t55xx_dump(void) {
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password 4bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password 4bytes (8 hex symbols)");
PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card");
PrintAndLogEx(NORMAL, " f <prefix> - overide filename prefix (optional). Default is based on blk 0"); PrintAndLogEx(NORMAL, " f <prefix> - override filename prefix (optional). Default is based on blk 0");
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");

View file

@ -10,23 +10,23 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdlfvisa2000.h" #include "cmdlfvisa2000.h"
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h>
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "common.h" #include "common.h"
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "comms.h" #include "comms.h"
#include "ui.h" #include "ui.h"
#include "graph.h" #include "graph.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest #include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // write verify #include "cmdlft55xx.h" // write verify
#include "cmdlfem4x05.h" //
#define BL0CK1 0x56495332 #define BL0CK1 0x56495332
@ -39,10 +39,12 @@ static int usage_lf_visa2k_clone(void) {
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID"); PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag"); PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, " <em4305> : specify writing to EM4305/4469 tag");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233")); PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555"); PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 em4305") " -- encode for EM4305/4469");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -180,18 +182,38 @@ static int CmdVisa2kClone(const char *Cmd) {
id = param_get32ex(Cmd, 0, 0, 10); id = param_get32ex(Cmd, 0, 0, 10);
//Q5 char cardtype[16] = {"T55x7"};
// Q5
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q'; bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
if (q5) if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
}
// EM4305
bool em4305 = tolower(param_getchar(Cmd, 1)) == 'e';
if (em4305) {
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
}
if (q5 && em4305) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
blocks[2] = id; blocks[2] = id;
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id); blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, (q5) ? "Q5/T5555" : "T55x7", id); PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, cardtype, id);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res;
if (em4305) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify");
return res; return res;

View file

@ -791,14 +791,14 @@ static int CmdSmartReader(const char *Cmd) {
static int CmdSmartSetClock(const char *Cmd) { static int CmdSmartSetClock(const char *Cmd) {
uint8_t cmdp = 0; uint8_t cmdp = 0;
bool errors = false; bool errors = false;
uint8_t clock1 = 0; uint8_t new_clk = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
return usage_sm_setclock(); return usage_sm_setclock();
case 'c': case 'c':
clock1 = param_get8ex(Cmd, cmdp + 1, 2, 10); new_clk = param_get8ex(Cmd, cmdp + 1, 2, 10);
if (clock1 > 2) if (new_clk > 2)
errors = true; errors = true;
cmdp += 2; cmdp += 2;
@ -813,21 +813,26 @@ static int CmdSmartSetClock(const char *Cmd) {
//Validations //Validations
if (errors || cmdp == 0) return usage_sm_setclock(); if (errors || cmdp == 0) return usage_sm_setclock();
struct {
uint32_t new_clk;
} PACKED payload;
payload.new_clk = new_clk;
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_SMART_SETCLOCK, clock1, 0, 0, NULL, 0); SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t*)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500)) {
PrintAndLogEx(WARNING, "smart card select failed"); PrintAndLogEx(WARNING, "smart card select failed");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
uint8_t isok = resp.oldarg[0] & 0xFF; if (resp.status != PM3_SUCCESS) {
if (!isok) {
PrintAndLogEx(WARNING, "smart card set clock failed"); PrintAndLogEx(WARNING, "smart card set clock failed");
return PM3_ESOFT; return PM3_ESOFT;
} }
switch (clock1) { switch (new_clk) {
case 0: case 0:
PrintAndLogEx(SUCCESS, "Clock changed to 16MHz giving 10800 baudrate"); PrintAndLogEx(SUCCESS, "Clock changed to 16MHz giving 10800 baudrate");
break; break;

View file

@ -1106,7 +1106,7 @@ static int l_em4x05_read(lua_State *L) {
// get password // get password
const char *p_pwd = luaL_checkstring(L, 2); const char *p_pwd = luaL_checkstring(L, 2);
if (p_pwd == NULL || strlen(p_pwd) == 0 ) { if (p_pwd == NULL || strlen(p_pwd) == 0) {
use_pwd = false; use_pwd = false;
} else { } else {
if (strlen(p_pwd) != 8) if (strlen(p_pwd) != 8)
@ -1121,7 +1121,7 @@ static int l_em4x05_read(lua_State *L) {
PrintAndLogEx(DEBUG, " Pwd %08X", password); PrintAndLogEx(DEBUG, " Pwd %08X", password);
uint32_t word = 0; uint32_t word = 0;
int res = EM4x05ReadWord_ext(addr, password, use_pwd, &word); int res = em4x05_read_word_ext(addr, password, use_pwd, &word);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
return returnToLuaWithError(L, "Failed to read EM4x05 data"); return returnToLuaWithError(L, "Failed to read EM4x05 data");
} }
@ -1138,7 +1138,7 @@ static int l_em4x50_read(lua_State *L) {
const char *p_addr = luaL_checklstring(L, 1, &size); const char *p_addr = luaL_checklstring(L, 1, &size);
uint32_t addr = 0; uint32_t addr = 0;
sscanf(p_addr, "%u", &addr); sscanf(p_addr, "%u", &addr);
if (addr > 31) if (addr > 31)
return returnToLuaWithError(L, "Address out-of-range (0..31) got %u", addr); return returnToLuaWithError(L, "Address out-of-range (0..31) got %u", addr);
@ -1159,9 +1159,9 @@ static int l_em4x50_read(lua_State *L) {
uint32_t pwd = 0; uint32_t pwd = 0;
sscanf(p_pwd, "%08x", &pwd); sscanf(p_pwd, "%08x", &pwd);
PrintAndLogEx(DEBUG, " Pwd %08X", pwd); PrintAndLogEx(DEBUG, " Pwd %08X", pwd);
etd.password[0] = pwd & 0xFF; etd.password[0] = pwd & 0xFF;
etd.password[1] = (pwd >> 8) & 0xFF; etd.password[1] = (pwd >> 8) & 0xFF;
etd.password[2] = (pwd >> 16) & 0xFF; etd.password[2] = (pwd >> 16) & 0xFF;
@ -1181,11 +1181,11 @@ static int l_em4x50_read(lua_State *L) {
} }
uint32_t word = ( uint32_t word = (
words[etd.address].byte[0] << 24 | words[etd.address].byte[0] << 24 |
words[etd.address].byte[1] << 16 | words[etd.address].byte[1] << 16 |
words[etd.address].byte[2] << 8 | words[etd.address].byte[2] << 8 |
words[etd.address].byte[3] words[etd.address].byte[3]
); );
lua_pushinteger(L, word); lua_pushinteger(L, word);
return 1; return 1;
} }

View file

@ -177,13 +177,13 @@ Check column "offline" for their availability.
|`hf 15 info `|N |`Tag information` |`hf 15 info `|N |`Tag information`
|`hf 15 sniff `|N |`Sniff ISO15693 traffic` |`hf 15 sniff `|N |`Sniff ISO15693 traffic`
|`hf 15 raw `|N |`Send raw hex data to tag` |`hf 15 raw `|N |`Send raw hex data to tag`
|`hf 15 read `|N |`Read a block` |`hf 15 rdbl `|N |`Read a block`
|`hf 15 reader `|N |`Act like an ISO15693 reader` |`hf 15 reader `|N |`Act like an ISO15693 reader`
|`hf 15 readmulti `|N |`Reads multiple Blocks` |`hf 15 readmulti `|N |`Reads multiple Blocks`
|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag` |`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag`
|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)` |`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)`
|`hf 15 sim `|N |`Fake an ISO15693 tag` |`hf 15 sim `|N |`Fake an ISO15693 tag`
|`hf 15 write `|N |`Write a block` |`hf 15 wrbl `|N |`Write a block`
|`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag` |`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag`
|`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag` |`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag`
|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag` |`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag`
@ -233,7 +233,7 @@ Check column "offline" for their availability.
|command |offline |description |command |offline |description
|------- |------- |----------- |------- |------- |-----------
|`hf fido help `|Y |`This help.` |`hf fido help `|Y |`This help.`
|`hf fido info `|N |`List ISO 14443A history` |`hf fido list `|N |`List ISO 14443A history`
|`hf fido info `|N |`Info about FIDO tag.` |`hf fido info `|N |`Info about FIDO tag.`
|`hf fido reg `|N |`FIDO U2F Registration Message.` |`hf fido reg `|N |`FIDO U2F Registration Message.`
|`hf fido auth `|N |`FIDO U2F Authentication Message.` |`hf fido auth `|N |`FIDO U2F Authentication Message.`
@ -256,10 +256,10 @@ Check column "offline" for their availability.
|`hf iclass restore `|N |`[options..] Restore a dump file onto a Picopass / iCLASS tag` |`hf iclass restore `|N |`[options..] Restore a dump file onto a Picopass / iCLASS tag`
|`hf iclass sniff `|N |` Eavesdrop Picopass / iCLASS communication` |`hf iclass sniff `|N |` Eavesdrop Picopass / iCLASS communication`
|`hf iclass wrbl `|N |`[options..] Write Picopass / iCLASS block` |`hf iclass wrbl `|N |`[options..] Write Picopass / iCLASS block`
|`hf iclass chk `|Y |`[options..] Check keys` |`hf iclass autopwn `|N |`[options..] Automatic key recovery tool for iCLASS`
|`hf iclass chk `|N |`[options..] Check keys`
|`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack` |`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack`
|`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file` |`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file`
|`hf iclass replay `|N |`<mac> Read Picopass / iCLASS tag via replay attack`
|`hf iclass sim `|N |`[options..] Simulate iCLASS tag` |`hf iclass sim `|N |`[options..] Simulate iCLASS tag`
|`hf iclass eload `|N |`[f <fn> ] Load Picopass / iCLASS dump file into emulator memory` |`hf iclass eload `|N |`[f <fn> ] Load Picopass / iCLASS dump file into emulator memory`
|`hf iclass esave `|N |`[f <fn> ] Save emulator memory to file` |`hf iclass esave `|N |`[f <fn> ] Save emulator memory to file`
@ -556,6 +556,19 @@ Check column "offline" for their availability.
|`lf cotag read `|N |`Attempt to read and extract tag data` |`lf cotag read `|N |`Attempt to read and extract tag data`
### lf destron
{ FDX-A Destron RFIDs... }
|command |offline |description
|------- |------- |-----------
|`lf destron help `|Y |`This help`
|`lf destron demod `|Y |`Demodulate an Destron tag from the GraphBuffer`
|`lf destron read `|N |`Attempt to read and extract tag data from the antenna`
|`lf destron clone `|N |`Clone Destron tag to T55x7`
|`lf destron sim `|N |`Simulate Destron tag`
### lf em ### lf em
{ EM4X CHIPs & RFIDs... } { EM4X CHIPs & RFIDs... }
@ -570,12 +583,14 @@ Check column "offline" for their availability.
|`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` |`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)`
|`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` |`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)`
|`lf em 410x_clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag` |`lf em 410x_clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag`
|`lf em 4x05_chk `|N |`Check passwords from dictionary`
|`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer` |`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer`
|`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag` |`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag`
|`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag` |`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag`
|`lf em 4x05_info `|N |`tag information EM4x05/EM4x69` |`lf em 4x05_info `|N |`tag information EM4x05/EM4x69`
|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69` |`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69`
|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69` |`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69`
|`lf em 4x05_unlock `|N |`execute tear off against EM4x05/EM4x69`
|`lf em 4x50_dump `|N |`dump EM4x50 tag` |`lf em 4x50_dump `|N |`dump EM4x50 tag`
|`lf em 4x50_info `|N |`tag information EM4x50` |`lf em 4x50_info `|N |`tag information EM4x50`
|`lf em 4x50_write `|N |`write word data to EM4x50` |`lf em 4x50_write `|N |`write word data to EM4x50`

View file

@ -13,7 +13,8 @@ At the moment both are maintained because they don't perfectly overlap yet.
| Feature | Makefile | CMake | Remarks | | Feature | Makefile | CMake | Remarks |
|-----|---|---|---| |-----|---|---|---|
| verbose | V=1 | VERBOSE=1 | | | verbose | `V=1` | `VERBOSE=1` | |
| debug build | `DEBUG=1` | `-DCMAKE_BUILD_TYPE=Debug` | client only |
| warnings management | yes (1) | **no** | (1) cf Makefile.defs | | warnings management | yes (1) | **no** | (1) cf Makefile.defs |
| extra GCC warnings | GCCEXTRA=1 | **no** | | | extra GCC warnings | GCCEXTRA=1 | **no** | |
| extra Clang warnings | CLANGEXTRA=1 | **no** | only on host | | extra Clang warnings | CLANGEXTRA=1 | **no** | only on host |
@ -32,7 +33,7 @@ At the moment both are maintained because they don't perfectly overlap yet.
| bzip2 detection | **none** | find_package, Cross:gitclone | | | bzip2 detection | **none** | find_package, Cross:gitclone | |
| dep cliparser | in_deps | in_deps | | | dep cliparser | in_deps | in_deps | |
| dep hardnested | in_deps | in_deps | | | dep hardnested | in_deps | in_deps | |
| hardn arch autodetect | `uname -m` =? 86 or amd64; `$(CC) -E -mavx512f`? +AVX512` | `CMAKE_SYSTEM_PROCESSOR` =? x86 or x86_64 or i686 or AMD64 (1) | (1) currently it always includes AVX512 on Intel arch | | hardn arch autodetect | `uname -m` =? 86 or amd64; `$(CC) -E -mavx512f`? +`AVX512` | `CMAKE_SYSTEM_PROCESSOR` =? x86 or x86_64 or i686 or AMD64 (1) | (1) currently it always includes AVX512 on Intel arch |
| `cpu_arch` | yes | **no/auto?** | e.g. `cpu_arch=generic` for cross-compilation | `cpu_arch` | yes | **no/auto?** | e.g. `cpu_arch=generic` for cross-compilation
| dep jansson | sys / in_deps | sys / in_deps | | | dep jansson | sys / in_deps | sys / in_deps | |
| jansson detection | pc | pc/find* | | | jansson detection | pc | pc/find* | |

View file

@ -342,7 +342,7 @@ typedef struct {
typedef struct { typedef struct {
iclass_auth_req_t req; iclass_auth_req_t req;
uint8_t item_cnt; uint8_t item_cnt;
iclass_restore_item_t blocks[]; iclass_restore_item_t blocks[];
} PACKED iclass_restore_req_t; } PACKED iclass_restore_req_t;
@ -500,6 +500,7 @@ typedef struct {
#define CMD_LF_EM4X_READWORD 0x0218 #define CMD_LF_EM4X_READWORD 0x0218
#define CMD_LF_EM4X_WRITEWORD 0x0219 #define CMD_LF_EM4X_WRITEWORD 0x0219
#define CMD_LF_EM4X_PROTECTWORD 0x021B #define CMD_LF_EM4X_PROTECTWORD 0x021B
#define CMD_LF_EM4X_BF 0x022A
#define CMD_LF_IO_WATCH 0x021A #define CMD_LF_IO_WATCH 0x021A
#define CMD_LF_EM410X_WATCH 0x021C #define CMD_LF_EM410X_WATCH 0x021C
#define CMD_LF_EM4X50_INFO 0x0240 #define CMD_LF_EM4X50_INFO 0x0240

View file

@ -541,8 +541,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define T55XX_WRITE_TIMEOUT 1500 #define T55XX_WRITE_TIMEOUT 1500
// em4x05 & em4x69 chip configuration register definitions // em4x05 & em4x69 chip configuration register definitions
#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) #define EM4x05_GET_BITRATE(x) ((((x) & 0x3F) * 2) + 2)
#define EM4x05_SET_BITRATE(x) ((x-2)/2) #define EM4x05_SET_BITRATE(x) (((x) - 2) / 2)
#define EM4x05_MODULATION_NRZ 0x00000000 #define EM4x05_MODULATION_NRZ 0x00000000
#define EM4x05_MODULATION_MANCHESTER 0x00000040 #define EM4x05_MODULATION_MANCHESTER 0x00000040
#define EM4x05_MODULATION_BIPHASE 0x00000080 #define EM4x05_MODULATION_BIPHASE 0x00000080
@ -557,15 +557,15 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define EM4x05_PSK_RF_8 0x00000800 #define EM4x05_PSK_RF_8 0x00000800
#define EM4x05_MAXBLOCK_SHIFT 14 #define EM4x05_MAXBLOCK_SHIFT 14
#define EM4x05_FIRST_USER_BLOCK 5 #define EM4x05_FIRST_USER_BLOCK 5
#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode #define EM4x05_SET_NUM_BLOCKS(x) (( (x) + 4) << 14) //# of blocks sent during default read mode
#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1) #define EM4x05_GET_NUM_BLOCKS(x) ((( (x) >> 14) & 0xF) - 4)
#define EM4x05_READ_LOGIN_REQ 1<<18 #define EM4x05_READ_LOGIN_REQ (1 << 18)
#define EM4x05_READ_HK_LOGIN_REQ 1<<19 #define EM4x05_READ_HK_LOGIN_REQ (1 << 19)
#define EM4x05_WRITE_LOGIN_REQ 1<<20 #define EM4x05_WRITE_LOGIN_REQ (1 << 20)
#define EM4x05_WRITE_HK_LOGIN_REQ 1<<21 #define EM4x05_WRITE_HK_LOGIN_REQ (1 << 21)
#define EM4x05_READ_AFTER_WRITE 1<<22 #define EM4x05_READ_AFTER_WRITE (1 << 22)
#define EM4x05_DISABLE_ALLOWED 1<<23 #define EM4x05_DISABLE_ALLOWED (1 << 23)
#define EM4x05_READER_TALK_FIRST 1<<24 #define EM4x05_READER_TALK_FIRST (1 << 24)
// FeliCa protocol // FeliCa protocol