mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
commit
5a3a1fcc0f
25 changed files with 699 additions and 222 deletions
|
@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added hf felica rdunencrypted (@7homasSutter)
|
||||||
|
- Added hf felica rqresponse (@7homasSutter)
|
||||||
|
- Added hf felica rqservice (@7homasSutter)
|
||||||
|
- Added polling for felica standard (@7homasSutter)
|
||||||
- Added lf t55xx dump save and lf t55xx restore for .bin and .eml files (@mwalker33)
|
- Added lf t55xx dump save and lf t55xx restore for .bin and .eml files (@mwalker33)
|
||||||
- Added lf t55xx detected to try without password first (@mwalker33)
|
- Added lf t55xx detected to try without password first (@mwalker33)
|
||||||
- Chg `lf indala read` - added indala 26bit decoding (@martinbeier)
|
- Chg `lf indala read` - added indala 26bit decoding (@martinbeier)
|
||||||
|
|
|
@ -1589,9 +1589,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
}
|
}
|
||||||
uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset);
|
uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset);
|
||||||
|
|
||||||
|
// need to copy len bytes of data, not PM3_CMD_DATA_SIZE - 3 - offset
|
||||||
|
// ensure len bytes copied wont go past end of bigbuf
|
||||||
|
uint16_t len = MIN(BIGBUF_SIZE - offset,PM3_CMD_DATA_SIZE - 3);
|
||||||
|
|
||||||
uint8_t *mem = BigBuf_get_addr();
|
uint8_t *mem = BigBuf_get_addr();
|
||||||
memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset);
|
memcpy(mem + offset, &payload->data, len);
|
||||||
|
// memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset);
|
||||||
reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0);
|
reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
156
armsrc/felica.c
156
armsrc/felica.c
|
@ -3,7 +3,7 @@
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "crc16.h" // crc16 ccitt
|
#include "crc16.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
|
@ -14,17 +14,17 @@
|
||||||
// FeliCa timings
|
// FeliCa timings
|
||||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
||||||
#ifndef FELICA_REQUEST_GUARD_TIME
|
#ifndef FELICA_REQUEST_GUARD_TIME
|
||||||
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1)
|
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426
|
||||||
#endif
|
#endif
|
||||||
// FRAME DELAY TIME 2672 carrier cycles
|
// FRAME DELAY TIME 2672 carrier cycles
|
||||||
#ifndef FELICA_FRAME_DELAY_TIME
|
#ifndef FELICA_FRAME_DELAY_TIME
|
||||||
# define FELICA_FRAME_DELAY_TIME (2672/16 + 1)
|
# define FELICA_FRAME_DELAY_TIME (2672/16 + 1) // 168
|
||||||
#endif
|
#endif
|
||||||
#ifndef DELAY_AIR2ARM_AS_READER
|
#ifndef DELAY_AIR2ARM_AS_READER
|
||||||
#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16)
|
#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // 91
|
||||||
#endif
|
#endif
|
||||||
#ifndef DELAY_ARM2AIR_AS_READER
|
#ifndef DELAY_ARM2AIR_AS_READER
|
||||||
#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1)
|
#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// CRC skips two first sync bits in data buffer
|
// CRC skips two first sync bits in data buffer
|
||||||
|
@ -229,21 +229,21 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
|
|
||||||
// timed-out
|
// timed-out
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("Error: Time out card selection!");
|
Dbprintf("Error: Time out card selection!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrong answer
|
// wrong answer
|
||||||
if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) {
|
if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) {
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("Error: Wrong answer selecting card!");
|
Dbprintf("Error: Wrong answer selecting card!");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VALIDATE CRC residue is 0, hence if crc is a value it failed.
|
// VALIDATE CRC residue is 0, hence if crc is a value it failed.
|
||||||
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2)) {
|
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2)) {
|
||||||
if (DBGLEVEL > 3) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("Error: CRC check failed!");
|
Dbprintf("Error: CRC check failed!");
|
||||||
Dbprintf("CRC check was done on Frame: ");
|
Dbprintf("CRC check was done on Frame: ");
|
||||||
Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0);
|
Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0);
|
||||||
|
@ -251,7 +251,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("Card selection successful!");
|
Dbprintf("Card selection successful!");
|
||||||
// copy UID
|
// copy UID
|
||||||
// idm 8
|
// idm 8
|
||||||
|
@ -263,7 +263,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
memcpy(card->uid, card->IDm + 2, 6);
|
memcpy(card->uid, card->IDm + 2, 6);
|
||||||
memcpy(card->iccode, card->PMm, 2);
|
memcpy(card->iccode, card->PMm, 2);
|
||||||
memcpy(card->mrt, card->PMm + 2, 6);
|
memcpy(card->mrt, card->PMm + 2, 6);
|
||||||
if (DBGLEVEL > 3) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("Received Frame: ");
|
Dbprintf("Received Frame: ");
|
||||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||||
}
|
}
|
||||||
|
@ -337,9 +337,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
||||||
|
|
||||||
uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
|
uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
|
||||||
|
|
||||||
if (power)
|
if (power)
|
||||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||||
if (highspeed)
|
if (highspeed)
|
||||||
|
@ -357,7 +355,6 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
||||||
// sending 0x00 0x00 0x00 0x00 0x00 0x00
|
// sending 0x00 0x00 0x00 0x00 0x00 0x00
|
||||||
uint16_t c = 0;
|
uint16_t c = 0;
|
||||||
while (c < 6) {
|
while (c < 6) {
|
||||||
|
|
||||||
// keep tx buffer in a defined state anyway.
|
// keep tx buffer in a defined state anyway.
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
|
@ -366,13 +363,12 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
||||||
}
|
}
|
||||||
// sending data with sync bytes
|
// sending data with sync bytes
|
||||||
c = 0;
|
c = 0;
|
||||||
if (DBGLEVEL > 3) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("Sending frame:");
|
Dbprintf("Sending frame:");
|
||||||
Dbhexdump(len, frame, 0);
|
Dbhexdump(len, frame, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (c < len) {
|
while (c < len) {
|
||||||
|
|
||||||
// Put byte into tx holding register as soon as it is ready
|
// Put byte into tx holding register as soon as it is ready
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = frame[c++];
|
AT91C_BASE_SSC->SSC_THR = frame[c++];
|
||||||
|
@ -404,7 +400,7 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
||||||
// stop when button is pressed
|
// stop when button is pressed
|
||||||
// or return TRUE when command is captured
|
// or return TRUE when command is captured
|
||||||
bool WaitForFelicaReply(uint16_t maxbytes) {
|
bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("WaitForFelicaReply Start");
|
Dbprintf("WaitForFelicaReply Start");
|
||||||
uint32_t c = 0;
|
uint32_t c = 0;
|
||||||
// power, no modulation
|
// power, no modulation
|
||||||
|
@ -414,22 +410,18 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
// clear RXRDY:
|
// clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
uint32_t timeout = iso18092_get_timeout();
|
uint32_t timeout = iso18092_get_timeout();
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("timeout set: %i", timeout);
|
Dbprintf("timeout set: %i", timeout);
|
||||||
//TODO FIX THIS METHOD - Race Condition or something: TIMING/MEMORY ISSUES
|
|
||||||
// If you add content here (dbprintf), timing problems appear?! Last Bytes (CRC) of frame will be cutoff.
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||||
Process18092Byte(b);
|
Process18092Byte(b);
|
||||||
if (FelicaFrame.state == STATE_FULL) {
|
if (FelicaFrame.state == STATE_FULL) {
|
||||||
felica_nexttransfertime =
|
felica_nexttransfertime = MAX(felica_nexttransfertime,
|
||||||
MAX(
|
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
||||||
felica_nexttransfertime,
|
);
|
||||||
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
|
||||||
);
|
|
||||||
|
|
||||||
LogTrace(
|
LogTrace(
|
||||||
FelicaFrame.framebytes,
|
FelicaFrame.framebytes,
|
||||||
FelicaFrame.len,
|
FelicaFrame.len,
|
||||||
|
@ -438,10 +430,10 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
NULL,
|
NULL,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
if (DBGLEVEL > 3) Dbprintf("All bytes received! STATE_FULL");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL");
|
||||||
return true;
|
return true;
|
||||||
} else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) {
|
} else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) {
|
||||||
if (DBGLEVEL > 3) Dbprintf("Error: Timeout! STATE_UNSYNCD");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,7 +443,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
// Set up FeliCa communication (similar to iso14443a_setup)
|
// Set up FeliCa communication (similar to iso14443a_setup)
|
||||||
// field is setup for "Sending as Reader"
|
// field is setup for "Sending as Reader"
|
||||||
static void iso18092_setup(uint8_t fpga_minor_mode) {
|
static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||||
if (DBGLEVEL > 3) Dbprintf("Start iso18092_setup");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Start iso18092_setup");
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
@ -504,7 +496,7 @@ void felica_reset_frame_mode() {
|
||||||
// arg1 len of commandbytes
|
// arg1 len of commandbytes
|
||||||
// d.asBytes command bytes to send
|
// d.asBytes command bytes to send
|
||||||
void felica_sendraw(PacketCommandNG *c) {
|
void felica_sendraw(PacketCommandNG *c) {
|
||||||
if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter");
|
||||||
|
|
||||||
felica_command_t param = c->oldarg[0];
|
felica_command_t param = c->oldarg[0];
|
||||||
size_t len = c->oldarg[1] & 0xffff;
|
size_t len = c->oldarg[1] & 0xffff;
|
||||||
|
@ -514,7 +506,7 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
felica_card_select_t card;
|
felica_card_select_t card;
|
||||||
|
|
||||||
if ((param & FELICA_CONNECT))
|
if ((param & FELICA_CONNECT))
|
||||||
if (DBGLEVEL > 3) Dbprintf("Clear trace");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Clear trace");
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
@ -527,13 +519,13 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
arg0 = felica_select_card(&card);
|
arg0 = felica_select_card(&card);
|
||||||
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||||
if (arg0 > 0) {
|
if (arg0 > 0) {
|
||||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Failed selecting card! ");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Failed selecting card! ");
|
||||||
felica_reset_frame_mode();
|
felica_reset_frame_mode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL > 3) Dbprintf("No card selection");
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("No card selection");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & FELICA_RAW)) {
|
if ((param & FELICA_RAW)) {
|
||||||
|
@ -554,17 +546,18 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
AddCrc(buf, len);
|
AddCrc(buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DBGLEVEL > 3) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("Transmit Frame (no CRC shown):");
|
Dbprintf("Transmit Frame (no CRC shown):");
|
||||||
Dbhexdump(len, buf, 0);
|
Dbhexdump(len, buf, 0);
|
||||||
Dbprintf("Buffer Length: %i", buf[2] + 4);
|
Dbprintf("Buffer Length: %i", buf[2] + 4);
|
||||||
};
|
};
|
||||||
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
|
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
|
||||||
arg0 = WaitForFelicaReply(1024);
|
arg0 = WaitForFelicaReply(1024);
|
||||||
if (DBGLEVEL > 3) {
|
if (DBGLEVEL >= DBG_DEBUG) {
|
||||||
Dbprintf("Received Frame Code: %d", arg0);
|
Dbprintf("Received Frame Code: %d", arg0);
|
||||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len);
|
uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len);
|
||||||
if (result) {
|
if (result) {
|
||||||
Dbprintf("Reply to Client Error Code: %i", result);
|
Dbprintf("Reply to Client Error Code: %i", result);
|
||||||
|
@ -573,7 +566,7 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
if ((param & FELICA_NO_DISCONNECT)) {
|
if ((param & FELICA_NO_DISCONNECT)) {
|
||||||
Dbprintf("Disconnect");
|
Dbprintf("Disconnect");
|
||||||
}
|
}
|
||||||
if (DBGLEVEL > 3)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("FeliCa_sendraw Exit");
|
Dbprintf("FeliCa_sendraw Exit");
|
||||||
felica_reset_frame_mode();
|
felica_reset_frame_mode();
|
||||||
return;
|
return;
|
||||||
|
@ -758,99 +751,6 @@ void felica_sim_lite(uint64_t uid) {
|
||||||
|
|
||||||
#define RES_SVC_LEN 11 + 3
|
#define RES_SVC_LEN 11 + 3
|
||||||
|
|
||||||
void felica_dump() {
|
|
||||||
uint8_t ndef[8];
|
|
||||||
uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21}; // B24D0600FFFF00000921
|
|
||||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
|
||||||
|
|
||||||
TransmitFor18092_AsReader(poll, 10, NULL, 1, 0);
|
|
||||||
|
|
||||||
// iceman, no exit path in this loop
|
|
||||||
while (!BUTTON_PRESS() && !data_available()) {
|
|
||||||
WDT_HIT();
|
|
||||||
TransmitFor18092_AsReader(poll, 10, NULL, 1, 0);
|
|
||||||
if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) {
|
|
||||||
memcpy(ndef, FelicaFrame.framebytes + 4, 8);
|
|
||||||
uint8_t *request_service = felica_create_request_service_frame(0x01, ndef);
|
|
||||||
felica_send_request_service(request_service);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void felica_send_request_service(uint8_t *request_service) {
|
|
||||||
Dbprintf("Send Service Request - len: d%", RES_SVC_LEN);
|
|
||||||
TransmitFor18092_AsReader(request_service, RES_SVC_LEN, NULL, 1, 0);
|
|
||||||
if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_REQSRV_ACK) {
|
|
||||||
Dbprintf("Got Service Response!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create Request Service Frame
|
|
||||||
// Use this command to verify the existence of Area and Service, and to acquire Key Version.
|
|
||||||
// When the specified Area or Service exists, the card returns Key Version.
|
|
||||||
// When the specified Area or Service does not exist, the card returns FFFFh as Key Version.
|
|
||||||
*/
|
|
||||||
uint8_t *felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm) {
|
|
||||||
if (nodeNumber < 1 && nodeNumber > 32) {
|
|
||||||
Dbprintf("Node number out of range: 1 <= %d <= 32 - set node number to 1");
|
|
||||||
nodeNumber = 1;
|
|
||||||
}
|
|
||||||
// Sync 2-Byte, Length 1-Byte, CMD 1-Byte, IDm 8-Byte, nodeNumber 1 <= n <= 32 1-Byte, Node Code List <Little Endian>
|
|
||||||
uint8_t *request_service = BigBuf_malloc(sizeof(uint8_t) * RES_SVC_LEN);
|
|
||||||
//{ 0xb2, 0x4d, 0x06, FELICA_REQSRV_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
|
|
||||||
request_service[0] = 0xb2; //Sync
|
|
||||||
request_service[1] = 0x4d; //Sync
|
|
||||||
request_service[2] = 0x0B; // Length
|
|
||||||
request_service[3] = FELICA_REQSRV_REQ; // CMD
|
|
||||||
request_service[4] = idm[0];
|
|
||||||
request_service[5] = idm[1];
|
|
||||||
request_service[6] = idm[2];
|
|
||||||
request_service[7] = idm[3];
|
|
||||||
request_service[8] = idm[4];
|
|
||||||
request_service[9] = idm[5];
|
|
||||||
request_service[10] = idm[6];
|
|
||||||
request_service[11] = idm[7];
|
|
||||||
request_service[12] = nodeNumber; // Node we like to ask for services
|
|
||||||
request_service[13] = 0x00; // Node Code List // TODO FIND OUT WHAT NEEDS TO BE IN HERE
|
|
||||||
return request_service;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Frame for authentication1 CMD
|
|
||||||
void felica_create_authentication1_frame() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Frame for authentication2 CMD
|
|
||||||
void felica_create_authentication2_frame() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a Frame for Read without encryption CMD as Payload
|
|
||||||
void felica_create_read_block_frame(uint16_t blockNr) {
|
|
||||||
if (blockNr < 1 || blockNr > 567) {
|
|
||||||
Dbprintf("Block number out of range!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8_t c = 0;
|
|
||||||
// First Byte of SYNC
|
|
||||||
frameSpace[c++] = 0xb2;
|
|
||||||
frameSpace[c++] = 0x4d;
|
|
||||||
// skip Length of Frame
|
|
||||||
c++;
|
|
||||||
// Payload
|
|
||||||
frameSpace[c++] = FELICA_RDBLK_REQ; //command number
|
|
||||||
|
|
||||||
// Set frame length
|
|
||||||
|
|
||||||
// CRC
|
|
||||||
}
|
|
||||||
|
|
||||||
void felica_read_block(uint8_t *idm, uint16_t blockNr) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void felica_dump_lite_s() {
|
void felica_dump_lite_s() {
|
||||||
uint8_t ndef[8];
|
uint8_t ndef[8];
|
||||||
uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
|
uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
|
||||||
|
|
|
@ -18,12 +18,7 @@ void felica_sendraw(PacketCommandNG *c);
|
||||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||||
void felica_sim_lite(uint64_t uid);
|
void felica_sim_lite(uint64_t uid);
|
||||||
void felica_dump_lite_s();
|
void felica_dump_lite_s();
|
||||||
void felica_dump();
|
|
||||||
void felica_create_read_block_frame(uint16_t blockNr);
|
void felica_create_read_block_frame(uint16_t blockNr);
|
||||||
void felica_create_authentication1_frame();
|
|
||||||
void felica_create_authentication2_frame();
|
|
||||||
void felica_send_request_service(uint8_t *request_service);
|
void felica_send_request_service(uint8_t *request_service);
|
||||||
void felica_reset_frame_mode();
|
|
||||||
uint8_t *felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2418,7 +2418,7 @@ because of this, we can "sample" the data signal but we interpreate it to Manche
|
||||||
This behavior looks very similar to old ancient Motorola Flexpass
|
This behavior looks very similar to old ancient Motorola Flexpass
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
According to patent:
|
According to patent EP0040544B1:
|
||||||
Operating freq
|
Operating freq
|
||||||
reader 132 kHz
|
reader 132 kHz
|
||||||
tag 66 kHz
|
tag 66 kHz
|
||||||
|
@ -2453,7 +2453,7 @@ void Cotag(uint32_t arg0) {
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
LFSetupFPGAForADC(LF_DIVISOR(132), true);
|
LFSetupFPGAForADC(LF_FREQ2DIV(132), true);
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
//clear buffer now so it does not interfere with timing later
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
|
@ -508,7 +508,7 @@ int CmdGetBitStream(const char *Cmd) {
|
||||||
RepaintGraphWindow();
|
RepaintGraphWindow();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
int CmdConvertBitStream(const char *Cmd) {
|
static int CmdConvertBitStream(const char *Cmd) {
|
||||||
|
|
||||||
if (isGraphBitstream()) {
|
if (isGraphBitstream()) {
|
||||||
convertGraphFromBitstream();
|
convertGraphFromBitstream();
|
||||||
|
@ -1676,16 +1676,16 @@ int CmdTuneSamples(const char *Cmd) {
|
||||||
struct p *package = (struct p *)resp.data.asBytes;
|
struct p *package = (struct p *)resp.data.asBytes;
|
||||||
|
|
||||||
if (package->v_lf125 > NON_VOLTAGE)
|
if (package->v_lf125 > NON_VOLTAGE)
|
||||||
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf125 * ANTENNA_ERROR) / 1000.0, 12000.0 / (LF_DIVISOR_125 + 1));
|
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf125 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_125));
|
||||||
|
|
||||||
if (package->v_lf134 > NON_VOLTAGE)
|
if (package->v_lf134 > NON_VOLTAGE)
|
||||||
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf134 * ANTENNA_ERROR) / 1000.0, 12000.0 / (LF_DIVISOR_134 + 1));
|
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf134 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_134));
|
||||||
|
|
||||||
if (package->v_lfconf > NON_VOLTAGE && package->divisor > 0 && package->divisor != LF_DIVISOR_125 && package->divisor != LF_DIVISOR_134)
|
if (package->v_lfconf > NON_VOLTAGE && package->divisor > 0 && package->divisor != LF_DIVISOR_125 && package->divisor != LF_DIVISOR_134)
|
||||||
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lfconf * ANTENNA_ERROR) / 1000.0, 12000.0 / (package->divisor + 1));
|
PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lfconf * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->divisor));
|
||||||
|
|
||||||
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
|
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
|
||||||
PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, 12000.0 / (package->peak_f + 1));
|
PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f));
|
||||||
|
|
||||||
char judgement[20];
|
char judgement[20];
|
||||||
memset(judgement, 0, sizeof(judgement));
|
memset(judgement, 0, sizeof(judgement));
|
||||||
|
@ -1730,7 +1730,7 @@ int CmdTuneSamples(const char *Cmd) {
|
||||||
|
|
||||||
if (test1 > 0) {
|
if (test1 > 0) {
|
||||||
PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d is %.2f kHz, %d is %.2f kHz.\n\n",
|
PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d is %.2f kHz, %d is %.2f kHz.\n\n",
|
||||||
LF_DIVISOR_134, 12000.0 / (LF_DIVISOR_134 + 1), LF_DIVISOR_125, 12000.0 / (LF_DIVISOR_125 + 1));
|
LF_DIVISOR_134, LF_DIV2FREQ(LF_DIVISOR_134), LF_DIVISOR_125, LF_DIV2FREQ(LF_DIVISOR_125));
|
||||||
GraphTraceLen = 256;
|
GraphTraceLen = 256;
|
||||||
ShowGraphWindow();
|
ShowGraphWindow();
|
||||||
RepaintGraphWindow();
|
RepaintGraphWindow();
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// High frequency commands
|
// High frequency commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//#include "cmdhf.h"
|
#include "cmdhf.h"
|
||||||
|
|
||||||
#include <ctype.h> // tolower
|
#include <ctype.h> // tolower
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,17 @@
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "cmdtrace.h"
|
#include "cmdtrace.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
|
#include "util.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "mifare.h" // felica_card_select_t struct
|
#include "mifare.h" // felica_card_select_t struct
|
||||||
|
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
static felica_card_select_t last_known_card;
|
||||||
|
|
||||||
|
static void set_last_known_card(felica_card_select_t card) {
|
||||||
|
last_known_card = card;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static int usage_hf_felica_sim(void) {
|
static int usage_hf_felica_sim(void) {
|
||||||
|
@ -43,7 +49,7 @@ static int usage_hf_felica_sim(void) {
|
||||||
static int usage_hf_felica_sniff(void) {
|
static int usage_hf_felica_sniff(void) {
|
||||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
||||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'");
|
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'");
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf felica sniff <s > <t>");
|
PrintAndLogEx(NORMAL, "Usage: hf felica sniff <s> <t>");
|
||||||
PrintAndLogEx(NORMAL, " s samples to skip (decimal)");
|
PrintAndLogEx(NORMAL, " s samples to skip (decimal)");
|
||||||
PrintAndLogEx(NORMAL, " t triggers to skip (decimal)");
|
PrintAndLogEx(NORMAL, " t triggers to skip (decimal)");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
@ -81,15 +87,178 @@ static int usage_hf_felica_raw(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_hf_felica_dump(void) {
|
static int usage_hf_felica_request_service(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] <outputfile>");
|
PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:");
|
||||||
|
PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version.");
|
||||||
|
PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version.");
|
||||||
|
PrintAndLogEx(NORMAL, "For Node Code List of a command packet, Area Code or Service Code of the target "
|
||||||
|
"of acquisition of Key Version shall be enumerated in Little Endian format. "
|
||||||
|
"If Key Version of System is the target of acquisition, FFFFh shall be specified "
|
||||||
|
"in the command packet.");
|
||||||
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A0B Node Code List hex (Little Endian)>");
|
||||||
PrintAndLogEx(NORMAL, " -h this help");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||||
|
PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible nodes 1 < n < 32");
|
||||||
|
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqservice 01 FFFF");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqservice -a FFFF");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqservice -i 01100910c11bc407 01 FFFF \n\n");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usage_hf_felica_request_response(void) {
|
||||||
|
PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of a card and its Mode.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Current Mode of the card is returned.");
|
||||||
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]");
|
||||||
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_status_flag1_interpretation() {
|
||||||
|
PrintAndLogEx(NORMAL, "\nStatus Flag1:");
|
||||||
|
PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command.");
|
||||||
|
PrintAndLogEx(NORMAL, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if "
|
||||||
|
"an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1.");
|
||||||
|
PrintAndLogEx(NORMAL, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List "
|
||||||
|
"in the command packet, the card returns a response by setting a number in the list to Status Flag1, "
|
||||||
|
"indicating the location of the error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_status_flag2_interpration() {
|
||||||
|
PrintAndLogEx(NORMAL, "\nStatus Flag2:");
|
||||||
|
PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command.");
|
||||||
|
PrintAndLogEx(NORMAL, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4"
|
||||||
|
"Bytes when the purse data is incremented.");
|
||||||
|
PrintAndLogEx(NORMAL, " - 02h : The specified data exceeds the value of cashback data at cashback of purse.");
|
||||||
|
PrintAndLogEx(NORMAL, " - 70h : Memory error (fatal error).");
|
||||||
|
PrintAndLogEx(NORMAL, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is "
|
||||||
|
"performed as normal). The maximum number of rewrites can differ, depending on the product being used.");
|
||||||
|
PrintAndLogEx(NORMAL, " In addition, Status Flag1 is either 00h or FFh depending on the product being used.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the "
|
||||||
|
"command (or the Number of Service specified at the times of mutual authentication).");
|
||||||
|
PrintAndLogEx(NORMAL, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. "
|
||||||
|
"The parameter specified by the command does not satisfy the conditions for success.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block "
|
||||||
|
"List Element does not exist. Or, Node specified by Node Code List does not exist.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - A9h : Data write failure: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - AAh : Key-change failure: Key change failed.");
|
||||||
|
PrintAndLogEx(NORMAL, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - ACh : Illegal parameter: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - ADh : Service exists already: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - AEh : Illegal System Code: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service "
|
||||||
|
"exceeds the number of Blocks assigned to Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands.");
|
||||||
|
PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: This is the error that occurs in issuance commands.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usage_hf_felica_read_without_encryption() {
|
||||||
|
PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Mode shall be Mode0.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously. "
|
||||||
|
"The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used. Use as default 01");
|
||||||
|
PrintAndLogEx(NORMAL, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:");
|
||||||
|
PrintAndLogEx(NORMAL, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not be specified to Service Code List.");
|
||||||
|
PrintAndLogEx(NORMAL, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Each Block List Element shall satisfy the following conditions:");
|
||||||
|
PrintAndLogEx(NORMAL, " - The value of Service Code List Order shall not exceed Number of Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Access Mode shall be 000b.");
|
||||||
|
PrintAndLogEx(NORMAL, " - The target specified by Service Code shall not be Area or System.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Service specified in Service Code List shall exist in System.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data");
|
||||||
|
PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2");
|
||||||
|
print_status_flag1_interpretation();
|
||||||
|
print_status_flag2_interpration();
|
||||||
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex>");
|
||||||
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||||
|
PrintAndLogEx(NORMAL, " -b get all Block List Elements starting from 00 to FF - stops when a block return an error status flags");
|
||||||
|
PrintAndLogEx(NORMAL, " -l use 3-byte block list element block number");
|
||||||
|
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -b 01 8B00 01 8000\n\n");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for response from pm3 or timeout.
|
||||||
|
* Checks if receveid bytes have a valid CRC.
|
||||||
|
* @param verbose prints out the response received.
|
||||||
|
*/
|
||||||
|
static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) {
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) {
|
||||||
|
uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff);
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(NORMAL, "Client Received %i octets", len);
|
||||||
|
if (!len || len < 2) {
|
||||||
|
PrintAndLogEx(ERR, "Could not receive data correctly!");
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len));
|
||||||
|
if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) {
|
||||||
|
PrintAndLogEx(WARNING, "Wrong or no CRC bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Counts and sets the number of parameters.
|
||||||
|
*/
|
||||||
|
static void strip_cmds(const char *Cmd) {
|
||||||
|
while (*Cmd == ' ' || *Cmd == '\t') {
|
||||||
|
Cmd++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts integer value to equivalent hex value.
|
||||||
|
* Examples: 1 = 1, 11 = B
|
||||||
|
* @param number number of hex bytes.
|
||||||
|
* @return number as hex value.
|
||||||
|
*/
|
||||||
|
static uint8_t int_to_hex(uint16_t *number) {
|
||||||
|
uint32_t hex;
|
||||||
|
char dataLengthChar[5];
|
||||||
|
sprintf(dataLengthChar, "%x", *number);
|
||||||
|
sscanf(dataLengthChar, "%x", &hex);
|
||||||
|
return (uint8_t)(hex & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the last known IDm (8-Byte) to the data frame.
|
||||||
|
* @param position start of where the IDm is added within the frame.
|
||||||
|
* @param data frame in where the IDM is added.
|
||||||
|
* @return true if IDm was added;
|
||||||
|
*/
|
||||||
|
static bool add_last_IDm(uint8_t position, uint8_t *data) {
|
||||||
|
if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
uint16_t number = (uint16_t)last_known_card.IDm[i];
|
||||||
|
data[position + i] = int_to_hex(&number);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHFFelicaList(const char *Cmd) {
|
static int CmdHFFelicaList(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd;
|
||||||
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead");
|
|
||||||
CmdTraceList("felica");
|
CmdTraceList("felica");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -99,9 +268,371 @@ static int CmdHFFelicaReader(const char *Cmd) {
|
||||||
return readFelicaUid(verbose);
|
return readFelicaUid(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFFelicaDump(const char *Cmd) {
|
/**
|
||||||
if (strlen(Cmd) < 1) return usage_hf_felica_dump();
|
* Clears command buffer and sends the given data to pm3 with mix mode.
|
||||||
return dump(*Cmd);
|
*/
|
||||||
|
static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) {
|
||||||
|
uint16_t numbits = 0;
|
||||||
|
clearCommandBuffer();
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen));
|
||||||
|
}
|
||||||
|
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter to the frame and checks if the parameter has the specific length.
|
||||||
|
* @param Cmd User input with the parameter.
|
||||||
|
* @param paramCount number of the parameter within the user input.
|
||||||
|
* @param data frame in which the data is stored.
|
||||||
|
* @param dataPosition position within frame where the data will be stored.
|
||||||
|
* @param length which the parameter should have and will be tested against.
|
||||||
|
* @return true if parameters was added.
|
||||||
|
*/
|
||||||
|
static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length) {
|
||||||
|
if (param_getlength(Cmd, paramCount) == length) {
|
||||||
|
param_gethex(Cmd, paramCount, data + dataPosition, length);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i", paramCount);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints read-without-encryption response.
|
||||||
|
* @param rd_noCry_resp Response frame.
|
||||||
|
*/
|
||||||
|
static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) {
|
||||||
|
if (rd_noCry_resp->status_flag1[0] == 00 && rd_noCry_resp->status_flag2[0] == 00) {
|
||||||
|
char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data));
|
||||||
|
char bl_data[256];
|
||||||
|
strcpy(bl_data, temp);
|
||||||
|
|
||||||
|
char bl_element_number[4];
|
||||||
|
temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number));
|
||||||
|
strcpy(bl_element_number, temp);
|
||||||
|
PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->IDm, sizeof(rd_noCry_resp->IDm)));
|
||||||
|
PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1)));
|
||||||
|
PrintAndLogEx(NORMAL, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request service frame to the pm3 and prints response.
|
||||||
|
*/
|
||||||
|
int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) {
|
||||||
|
clear_and_send_command(flags, datalen, data, verbose);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (datalen > 0) {
|
||||||
|
if (!waitCmdFelica(0, &resp, 1)) {
|
||||||
|
PrintAndLogEx(ERR, "\nGot no Response from card");
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
felica_request_service_response_t rqs_response;
|
||||||
|
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
|
||||||
|
|
||||||
|
if (rqs_response.IDm[0] != 0) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\nGot Service Response:");
|
||||||
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm)));
|
||||||
|
PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number)));
|
||||||
|
PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions)));
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a read_without_encryption frame to the pm3 and prints response.
|
||||||
|
* @param flags to use for pm3 communication.
|
||||||
|
* @param datalen frame length.
|
||||||
|
* @param data frame to be send.
|
||||||
|
* @param verbose display additional output.
|
||||||
|
* @param rd_noCry_resp frame in which the response will be saved
|
||||||
|
* @return success if response was received.
|
||||||
|
*/
|
||||||
|
int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) {
|
||||||
|
clear_and_send_command(flags, datalen, data, verbose);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (!waitCmdFelica(0, &resp, verbose)) {
|
||||||
|
PrintAndLogEx(ERR, "\nGot no Response from card");
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
} else {
|
||||||
|
memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t));
|
||||||
|
rd_noCry_resp->block_element_number[0] = data[15];
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command parser for rdunencrypted.
|
||||||
|
* @param Cmd input data of the user.
|
||||||
|
* @return client result code.
|
||||||
|
*/
|
||||||
|
static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
|
if (strlen(Cmd) < 4)
|
||||||
|
return usage_hf_felica_read_without_encryption();
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
|
bool custom_IDm = false;
|
||||||
|
strip_cmds(Cmd);
|
||||||
|
uint16_t datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3)
|
||||||
|
uint8_t paramCount = 0;
|
||||||
|
uint8_t flags = 0;
|
||||||
|
uint8_t all_block_list_elements = false;
|
||||||
|
uint8_t long_block_numbers = false;
|
||||||
|
int i = 0;
|
||||||
|
while (Cmd[i] != '\0') {
|
||||||
|
if (Cmd[i] == '-') {
|
||||||
|
switch (Cmd[i + 1]) {
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
return usage_hf_felica_request_response();
|
||||||
|
case 'i':
|
||||||
|
paramCount++;
|
||||||
|
custom_IDm = true;
|
||||||
|
if (!add_param(Cmd, paramCount, data, 3, 8)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
paramCount++;
|
||||||
|
all_block_list_elements = true;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
paramCount++;
|
||||||
|
long_block_numbers = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
data[0] = 0x10; // Static length
|
||||||
|
data[1] = 0x06; // Command ID
|
||||||
|
if (!custom_IDm) {
|
||||||
|
if (!add_last_IDm(2, data)) {
|
||||||
|
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4
|
||||||
|
uint8_t lengths[] = {2, 4, 2, 4};
|
||||||
|
uint8_t dataPositions[] = {10, 11, 13, 14};
|
||||||
|
if (long_block_numbers) {
|
||||||
|
datalen += 1;
|
||||||
|
lengths[3] = 6;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) {
|
||||||
|
paramCount++;
|
||||||
|
} else {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= FELICA_APPEND_CRC;
|
||||||
|
flags |= FELICA_RAW;
|
||||||
|
if (all_block_list_elements) {
|
||||||
|
uint16_t last_block_number = 0xFF;
|
||||||
|
if (long_block_numbers) {
|
||||||
|
last_block_number = 0xFFFF;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "Block Element\t| Data ");
|
||||||
|
for (int i = 0x00; i < last_block_number; i++) {
|
||||||
|
data[15] = i;
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
felica_read_without_encryption_response_t rd_noCry_resp;
|
||||||
|
if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) {
|
||||||
|
if (rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00) {
|
||||||
|
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
datalen -= 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
felica_read_without_encryption_response_t rd_noCry_resp;
|
||||||
|
send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp);
|
||||||
|
PrintAndLogEx(NORMAL, "Block Element\t| Data ");
|
||||||
|
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command parser for rqresponse
|
||||||
|
* @param Cmd input data of the user.
|
||||||
|
* @return client result code.
|
||||||
|
*/
|
||||||
|
static int CmdHFFelicaRequestResponse(const char *Cmd) {
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
|
bool custom_IDm = false;
|
||||||
|
strip_cmds(Cmd);
|
||||||
|
uint16_t datalen = 10; // Length (1), Command ID (1), IDm (8)
|
||||||
|
uint8_t paramCount = 0;
|
||||||
|
uint8_t flags = 0;
|
||||||
|
int i = 0;
|
||||||
|
while (Cmd[i] != '\0') {
|
||||||
|
if (Cmd[i] == '-') {
|
||||||
|
switch (Cmd[i + 1]) {
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
return usage_hf_felica_request_response();
|
||||||
|
case 'i':
|
||||||
|
paramCount++;
|
||||||
|
custom_IDm = true;
|
||||||
|
if (param_getlength(Cmd, paramCount) == 16) {
|
||||||
|
param_gethex(Cmd, paramCount++, data + 2, 16);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte.");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
data[0] = 0x0A; // Static length
|
||||||
|
data[1] = 0x04; // Command ID
|
||||||
|
if (!custom_IDm) {
|
||||||
|
if (!add_last_IDm(2, data)) {
|
||||||
|
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
flags |= FELICA_APPEND_CRC;
|
||||||
|
flags |= FELICA_RAW;
|
||||||
|
clear_and_send_command(flags, datalen, data, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (!waitCmdFelica(0, &resp, 1)) {
|
||||||
|
PrintAndLogEx(ERR, "\nGot no Response from card");
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
} else {
|
||||||
|
felica_request_request_response_t rq_response;
|
||||||
|
memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t));
|
||||||
|
if (rq_response.IDm[0] != 0) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\nGot Request Response:");
|
||||||
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_response.IDm, sizeof(rq_response.IDm)));
|
||||||
|
PrintAndLogEx(NORMAL, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command parser for rqservice.
|
||||||
|
* @param Cmd input data of the user.
|
||||||
|
* @return client result code.
|
||||||
|
*/
|
||||||
|
static int CmdHFFelicaRequestService(const char *Cmd) {
|
||||||
|
if (strlen(Cmd) < 2) return usage_hf_felica_request_service();
|
||||||
|
int i = 0;
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
|
bool custom_IDm = false;
|
||||||
|
bool all_nodes = false;
|
||||||
|
uint16_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2)
|
||||||
|
uint8_t flags = 0;
|
||||||
|
uint8_t paramCount = 0;
|
||||||
|
strip_cmds(Cmd);
|
||||||
|
while (Cmd[i] != '\0') {
|
||||||
|
if (Cmd[i] == '-') {
|
||||||
|
switch (Cmd[i + 1]) {
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
return usage_hf_felica_request_service();
|
||||||
|
case 'i':
|
||||||
|
paramCount++;
|
||||||
|
custom_IDm = true;
|
||||||
|
if (param_getlength(Cmd, paramCount) == 16) {
|
||||||
|
param_gethex(Cmd, paramCount++, data + 2, 16);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte.");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
i += 8;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
paramCount++;
|
||||||
|
all_nodes = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return usage_hf_felica_request_service();
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (!all_nodes) {
|
||||||
|
// Node Number
|
||||||
|
if (param_getlength(Cmd, paramCount) == 2) {
|
||||||
|
param_gethex(Cmd, paramCount++, data + 10, 2);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Incorrect Node number length!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Code List
|
||||||
|
if (param_getlength(Cmd, paramCount) == 4) {
|
||||||
|
param_gethex(Cmd, paramCount++, data + 11, 4);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Incorrect Node Code List length!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= FELICA_APPEND_CRC;
|
||||||
|
if (custom_IDm) {
|
||||||
|
flags |= FELICA_NO_SELECT;
|
||||||
|
}
|
||||||
|
if (datalen > 0) {
|
||||||
|
flags |= FELICA_RAW;
|
||||||
|
}
|
||||||
|
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
||||||
|
if (!custom_IDm) {
|
||||||
|
if (!add_last_IDm(2, data)) {
|
||||||
|
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data[0] = int_to_hex(&datalen);
|
||||||
|
data[1] = 0x02; // Service Request Command ID
|
||||||
|
if (all_nodes) {
|
||||||
|
for (uint16_t y = 1; y < 32; y++) {
|
||||||
|
data[10] = int_to_hex(&y);
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
send_request_service(flags, datalen, data, 1);
|
||||||
|
datalen -= 2; // Remove CRC bytes before adding new ones
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
send_request_service(flags, datalen, data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CmdHFFelicaNotImplementedYet(const char *Cmd) {
|
||||||
|
PrintAndLogEx(NORMAL, "Feature not implemented Yet!");
|
||||||
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulate iso18092 / FeliCa tag
|
// simulate iso18092 / FeliCa tag
|
||||||
|
@ -172,7 +703,6 @@ static int CmdHFFelicaSim(const char *Cmd) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int CmdHFFelicaSniff(const char *Cmd) {
|
static int CmdHFFelicaSniff(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
uint64_t samples2skip = 0;
|
uint64_t samples2skip = 0;
|
||||||
uint64_t triggers2skip = 0;
|
uint64_t triggers2skip = 0;
|
||||||
|
@ -209,7 +739,6 @@ static int CmdHFFelicaSniff(const char *Cmd) {
|
||||||
|
|
||||||
// uid hex
|
// uid hex
|
||||||
static int CmdHFFelicaSimLite(const char *Cmd) {
|
static int CmdHFFelicaSimLite(const char *Cmd) {
|
||||||
|
|
||||||
uint64_t uid = param_get64ex(Cmd, 0, 0, 16);
|
uint64_t uid = param_get64ex(Cmd, 0, 0, 16);
|
||||||
|
|
||||||
if (!uid)
|
if (!uid)
|
||||||
|
@ -421,7 +950,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu64" bytes)", tracelen);
|
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen);
|
||||||
|
|
||||||
print_hex_break(trace, tracelen, 32);
|
print_hex_break(trace, tracelen, 32);
|
||||||
printSep();
|
printSep();
|
||||||
|
@ -436,19 +965,6 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void waitCmdFelica(uint8_t iSelect) {
|
|
||||||
PacketResponseNG resp;
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
|
||||||
uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff);
|
|
||||||
PrintAndLogEx(NORMAL, "Client Received %i octets", len);
|
|
||||||
if (!len)
|
|
||||||
return;
|
|
||||||
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len));
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
bool reply = 1;
|
bool reply = 1;
|
||||||
bool crc = false;
|
bool crc = false;
|
||||||
|
@ -525,12 +1041,9 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
|
if (crc) {
|
||||||
uint8_t b1, b2;
|
AddCrc(data, datalen);
|
||||||
compute_crc(CRC_FELICA, data, datalen, &b1, &b2);
|
datalen += 2;
|
||||||
// TODO FIND OUT IF FeliCa Light has another CRC order - Order changed for FeliCa Standard cards
|
|
||||||
data[datalen++] = b2;
|
|
||||||
data[datalen++] = b1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
|
@ -552,15 +1065,18 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
PrintAndLogEx(NORMAL, "Data: %s", sprint_hex(data, datalen));
|
||||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
if (active_select) {
|
if (active_select) {
|
||||||
PrintAndLogEx(NORMAL, "Active select wait for FeliCa.");
|
PrintAndLogEx(NORMAL, "Active select wait for FeliCa.");
|
||||||
waitCmdFelica(1);
|
PacketResponseNG resp_IDm;
|
||||||
|
waitCmdFelica(1, &resp_IDm, 1);
|
||||||
}
|
}
|
||||||
if (datalen > 0) {
|
if (datalen > 0) {
|
||||||
waitCmdFelica(0);
|
PacketResponseNG resp_frame;
|
||||||
|
waitCmdFelica(0, &resp_frame, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -573,7 +1089,6 @@ int readFelicaUid(bool verbose) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||||
if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed");
|
if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed");
|
||||||
//SendCommandMIX(CMD_HF_FELICA_COMMAND, 0, 0, 0, NULL, 0);
|
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,33 +1125,45 @@ int readFelicaUid(bool verbose) {
|
||||||
PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt)));
|
PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt)));
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode)));
|
PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode)));
|
||||||
|
set_last_known_card(card);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dump(const char *Cmd) {
|
|
||||||
clearCommandBuffer();
|
|
||||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (ctmp == 'h') return usage_hf_felica_dumplite();
|
|
||||||
|
|
||||||
// TODO FINISH THIS METHOD
|
|
||||||
PrintAndLogEx(SUCCESS, "NOT IMPLEMENTED YET!");
|
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""},
|
||||||
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
||||||
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"},
|
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
||||||
{"sniff", CmdHFFelicaSniff, IfPm3Felica, "sniff ISO 18092/Felica traffic"},
|
{"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"},
|
||||||
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
||||||
{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping Felica"},
|
{"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""},
|
||||||
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
//{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"},
|
||||||
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
{"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."},
|
||||||
|
{"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."},
|
||||||
|
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."},
|
||||||
|
{"wrunencrypted", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
||||||
|
//{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."},
|
||||||
|
//{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."},
|
||||||
|
//{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."},
|
||||||
|
//{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."},
|
||||||
|
//{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."},
|
||||||
|
//{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."},
|
||||||
|
//{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."},
|
||||||
|
//{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."},
|
||||||
|
//{"rqspecver", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."},
|
||||||
|
//{"resetmode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."},
|
||||||
|
//{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."},
|
||||||
|
//{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."},
|
||||||
|
//{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."},
|
||||||
|
//{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."},
|
||||||
|
//{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."},
|
||||||
|
{"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""},
|
||||||
|
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
||||||
|
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
||||||
|
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"}
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
#define CMDHFFELICA_H__
|
#define CMDHFFELICA_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "mifare.h"
|
||||||
|
|
||||||
int CmdHFFelica(const char *Cmd);
|
int CmdHFFelica(const char *Cmd);
|
||||||
|
|
||||||
int readFelicaUid(bool verbose);
|
int readFelicaUid(bool verbose);
|
||||||
|
int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose);
|
||||||
int dump();
|
int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -366,7 +366,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
|
||||||
PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Type: %s", asBuff);
|
PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Type: %s", asBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdDbg(const char *Cmd) {
|
static int CmdDbg(const char *Cmd) {
|
||||||
|
|
||||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_dbg();
|
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_dbg();
|
||||||
|
|
|
@ -213,7 +213,7 @@ static int usage_lf_tune(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdLFTune(const char *Cmd) {
|
static int CmdLFTune(const char *Cmd) {
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
uint8_t divisor = LF_DIVISOR_125;//Frequency divisor
|
uint8_t divisor = LF_DIVISOR_125;//Frequency divisor
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
|
@ -231,12 +231,12 @@ int CmdLFTune(const char *Cmd) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'f': {
|
case 'f': {
|
||||||
int freq = param_get32ex(Cmd, cmdp + 1, 125, 10);
|
float freq = param_getfloat(Cmd, cmdp + 1, 125);
|
||||||
divisor = LF_DIVISOR(freq);
|
if ((freq < 47) || (freq > 600)) {
|
||||||
if (divisor < 19) {
|
|
||||||
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
divisor = LF_FREQ2DIV(freq);
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ int CmdLFTune(const char *Cmd) {
|
||||||
//Validations
|
//Validations
|
||||||
if (errors) return usage_lf_tune();
|
if (errors) return usage_lf_tune();
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Measuring LF antenna at %.2f kHz, click button or press Enter to exit", 12000.0 / (divisor + 1));
|
PrintAndLogEx(SUCCESS, "Measuring LF antenna at %.2f kHz, click button or press Enter to exit", LF_DIV2FREQ(divisor));
|
||||||
|
|
||||||
uint8_t params[] = {1, 0};
|
uint8_t params[] = {1, 0};
|
||||||
params[1] = divisor;
|
params[1] = divisor;
|
||||||
|
@ -498,7 +498,7 @@ int CmdLFConfig(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'f': {
|
case 'f': {
|
||||||
int freq = param_get32ex(Cmd, cmdp + 1, 125, 10);
|
int freq = param_get32ex(Cmd, cmdp + 1, 125, 10);
|
||||||
divisor = LF_DIVISOR(freq);
|
divisor = LF_FREQ2DIV(freq);
|
||||||
if (divisor < 19) {
|
if (divisor < 19) {
|
||||||
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
PrintAndLogEx(ERR, "freq must be between 47 and 600");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// Low frequency Hitag support
|
// Low frequency Hitag support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfhitag.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
|
|
|
@ -127,7 +127,7 @@ static int CmdMotorolaRead(const char *Cmd) {
|
||||||
.decimation = 0,
|
.decimation = 0,
|
||||||
.bits_per_sample = 0,
|
.bits_per_sample = 0,
|
||||||
.averaging = false,
|
.averaging = false,
|
||||||
.divisor = LF_DIVISOR(74),
|
.divisor = LF_FREQ2DIV(74),
|
||||||
.trigger_threshold = -1,
|
.trigger_threshold = -1,
|
||||||
.samples_to_skip = 4500,
|
.samples_to_skip = 4500,
|
||||||
.verbose = false
|
.verbose = false
|
||||||
|
|
|
@ -426,7 +426,7 @@ static int CmdLfNedapGen(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdLFNedapClone(const char *Cmd) {
|
static int CmdLFNedapClone(const char *Cmd) {
|
||||||
uint8_t max;
|
uint8_t max;
|
||||||
uint32_t blocks[5] = {0};
|
uint32_t blocks[5] = {0};
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,8 @@ int fileExists(const char *filename) {
|
||||||
* @param filename
|
* @param filename
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool is_regular_file(const char *filename) {
|
/*
|
||||||
|
static bool is_regular_file(const char *filename) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct _stat st;
|
struct _stat st;
|
||||||
if (_stat(filename, &st) == -1)
|
if (_stat(filename, &st) == -1)
|
||||||
|
@ -87,12 +88,14 @@ bool is_regular_file(const char *filename) {
|
||||||
#endif
|
#endif
|
||||||
return S_ISREG(st.st_mode) != 0;
|
return S_ISREG(st.st_mode) != 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief checks if path is directory.
|
* @brief checks if path is directory.
|
||||||
* @param filename
|
* @param filename
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool is_directory(const char *filename) {
|
static bool is_directory(const char *filename) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct _stat st;
|
struct _stat st;
|
||||||
if (_stat(filename, &st) == -1)
|
if (_stat(filename, &st) == -1)
|
||||||
|
|
|
@ -58,6 +58,8 @@ From "Dismantling iclass":
|
||||||
output of hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 .
|
output of hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 .
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
#include "ikeys.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#ifndef IKEYS_H
|
#ifndef IKEYS_H
|
||||||
#define IKEYS_H
|
#define IKEYS_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
|
|
|
@ -56,7 +56,7 @@ static void showBanner(void) {
|
||||||
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_comm(void) {
|
static int check_comm(void) {
|
||||||
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
|
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
|
||||||
if (IsCommunicationThreadDead() && session.pm3_present) {
|
if (IsCommunicationThreadDead() && session.pm3_present) {
|
||||||
rl_set_prompt(PROXPROMPT_OFFLINE);
|
rl_set_prompt(PROXPROMPT_OFFLINE);
|
||||||
|
@ -86,7 +86,7 @@ int push_cmdscriptfile(char *path, bool stayafter) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *current_cmdscriptfile() {
|
static FILE *current_cmdscriptfile() {
|
||||||
return cmdscriptfile[cmdscriptfile_idx];
|
return cmdscriptfile[cmdscriptfile_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,14 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) {
|
||||||
return deflt;
|
return deflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float param_getfloat(const char *line, int paramnum, float deflt) {
|
||||||
|
int bg, en;
|
||||||
|
if (!param_getptr(line, &bg, &en, paramnum))
|
||||||
|
return strtof(&line[bg], NULL);
|
||||||
|
else
|
||||||
|
return deflt;
|
||||||
|
}
|
||||||
|
|
||||||
int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt) {
|
int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt) {
|
||||||
int bg, en, i;
|
int bg, en, i;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
|
|
|
@ -68,6 +68,7 @@ uint8_t param_get8(const char *line, int paramnum);
|
||||||
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
|
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
|
||||||
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
|
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
|
||||||
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
||||||
|
float param_getfloat(const char *line, int paramnum, float deflt);
|
||||||
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
|
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
|
||||||
uint8_t param_isdec(const char *line, int paramnum);
|
uint8_t param_isdec(const char *line, int paramnum);
|
||||||
int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt);
|
int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt);
|
||||||
|
|
|
@ -650,7 +650,7 @@ bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed) {
|
||||||
return FormatTable[format_idx].Pack(card, packed);
|
return FormatTable[format_idx].Pack(card, packed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) {
|
static void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp);
|
PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp);
|
||||||
|
|
|
@ -120,7 +120,7 @@ bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBit
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get_length_from_header(wiegand_message_t *data) {
|
static uint8_t get_length_from_header(wiegand_message_t *data) {
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
uint32_t hfmt = 0; // for calculating card length
|
uint32_t hfmt = 0; // for calculating card length
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,11 @@
|
||||||
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
|
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
|
||||||
|
|
||||||
void crypto1_init(struct Crypto1State *state, uint64_t key) {
|
void crypto1_init(struct Crypto1State *state, uint64_t key) {
|
||||||
|
if (state == NULL)
|
||||||
|
return;
|
||||||
state->odd = 0;
|
state->odd = 0;
|
||||||
state->even = 0;
|
state->even = 0;
|
||||||
|
for (int i = 47; i > 0; i -= 2) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 47; state && i > 0; i -= 2) {
|
|
||||||
state->odd = state->odd << 1 | BIT(key, (i - 1) ^ 7);
|
state->odd = state->odd << 1 | BIT(key, (i - 1) ^ 7);
|
||||||
state->even = state->even << 1 | BIT(key, i ^ 7);
|
state->even = state->even << 1 | BIT(key, i ^ 7);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,35 @@ typedef struct {
|
||||||
uint8_t servicecode[2];
|
uint8_t servicecode[2];
|
||||||
} PACKED felica_card_select_t;
|
} PACKED felica_card_select_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t sync[2];
|
||||||
|
uint8_t length[1];
|
||||||
|
uint8_t cmd_code[1];
|
||||||
|
uint8_t IDm[8];
|
||||||
|
uint8_t node_number[1];
|
||||||
|
uint8_t node_key_versions[2];
|
||||||
|
} PACKED felica_request_service_response_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t sync[2];
|
||||||
|
uint8_t length[1];
|
||||||
|
uint8_t cmd_code[1];
|
||||||
|
uint8_t IDm[8];
|
||||||
|
uint8_t mode[1];
|
||||||
|
} PACKED felica_request_request_response_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t sync[2];
|
||||||
|
uint8_t length[1];
|
||||||
|
uint8_t cmd_code[1];
|
||||||
|
uint8_t IDm[8];
|
||||||
|
uint8_t status_flag1[1];
|
||||||
|
uint8_t status_flag2[1];
|
||||||
|
uint8_t number_of_block[1];
|
||||||
|
uint8_t block_data[16];
|
||||||
|
uint8_t block_element_number[1];
|
||||||
|
} PACKED felica_read_without_encryption_response_t;
|
||||||
|
|
||||||
typedef enum FELICA_COMMAND {
|
typedef enum FELICA_COMMAND {
|
||||||
FELICA_CONNECT = (1 << 0),
|
FELICA_CONNECT = (1 << 0),
|
||||||
FELICA_NO_DISCONNECT = (1 << 1),
|
FELICA_NO_DISCONNECT = (1 << 1),
|
||||||
|
|
|
@ -590,9 +590,10 @@ typedef struct {
|
||||||
#define PM3_EFATAL -99
|
#define PM3_EFATAL -99
|
||||||
|
|
||||||
// LF
|
// LF
|
||||||
#define LF_DIVISOR(f) (((12000 + (f)/2)/(f))-1)
|
#define LF_FREQ2DIV(f) ((int)(((12000.0 + (f)/2.0)/(f))-1))
|
||||||
#define LF_DIVISOR_125 LF_DIVISOR(125)
|
#define LF_DIVISOR_125 LF_FREQ2DIV(125)
|
||||||
#define LF_DIVISOR_134 LF_DIVISOR(134)
|
#define LF_DIVISOR_134 LF_FREQ2DIV(134.2)
|
||||||
|
#define LF_DIV2FREQ(d) (12000.0/((d)+1))
|
||||||
|
|
||||||
// Receiving from USART need more than 30ms as we used on USB
|
// Receiving from USART need more than 30ms as we used on USB
|
||||||
// else we get errors about partial packet reception
|
// else we get errors about partial packet reception
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue