mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Fix FeliCa select_card. Selection works now for FeliCa standard cards.
Fix SendRaw data. Add some new unfinished cmds.
This commit is contained in:
parent
8ea04a42a6
commit
9d3331511b
4 changed files with 257 additions and 80 deletions
219
armsrc/felica.c
219
armsrc/felica.c
|
@ -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) // 27 + 128 + 64 - 128 = 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) // 64 + 128 + 17 = 209
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// CRC skips two first sync bits in data buffer
|
// CRC skips two first sync bits in data buffer
|
||||||
|
@ -111,7 +111,7 @@ static void shiftInByte(uint8_t bt) {
|
||||||
static void Process18092Byte(uint8_t bt) {
|
static void Process18092Byte(uint8_t bt) {
|
||||||
switch (FelicaFrame.state) {
|
switch (FelicaFrame.state) {
|
||||||
case STATE_UNSYNCD: {
|
case STATE_UNSYNCD: {
|
||||||
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case
|
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
|
||||||
if (bt > 0) {
|
if (bt > 0) {
|
||||||
FelicaFrame.shiftReg = reflect8(bt);
|
FelicaFrame.shiftReg = reflect8(bt);
|
||||||
FelicaFrame.state = STATE_TRYING_SYNC;
|
FelicaFrame.state = STATE_TRYING_SYNC;
|
||||||
|
@ -175,13 +175,11 @@ static void Process18092Byte(uint8_t bt) {
|
||||||
}
|
}
|
||||||
case STATE_GET_CRC: {
|
case STATE_GET_CRC: {
|
||||||
shiftInByte(bt);
|
shiftInByte(bt);
|
||||||
|
|
||||||
if (FelicaFrame.rem_len <= 0) {
|
if (FelicaFrame.rem_len <= 0) {
|
||||||
|
FelicaFrame.rem_len = 0;
|
||||||
// skip sync 2bytes. IF ok, residue should be 0x0000
|
// skip sync 2bytes. IF ok, residue should be 0x0000
|
||||||
FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
||||||
FelicaFrame.state = STATE_FULL;
|
FelicaFrame.state = STATE_FULL;
|
||||||
FelicaFrame.rem_len = 0;
|
|
||||||
if (DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -194,6 +192,7 @@ static void Process18092Byte(uint8_t bt) {
|
||||||
/* Perform FeliCa polling card
|
/* Perform FeliCa polling card
|
||||||
* Currently does NOT do any collision handling.
|
* Currently does NOT do any collision handling.
|
||||||
* It expects 0-1 cards in the device's range.
|
* It expects 0-1 cards in the device's range.
|
||||||
|
* return 0 if selection was successful
|
||||||
*/
|
*/
|
||||||
static uint8_t felica_select_card(felica_card_select_t *card) {
|
static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
|
|
||||||
|
@ -201,17 +200,16 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
// 0xB2 0x4B = sync code
|
// 0xB2 0x4B = sync code
|
||||||
// 0x06 = len
|
// 0x06 = len
|
||||||
// 0x00 = rfu
|
// 0x00 = rfu
|
||||||
// 0xff = system service
|
// 0xff = system code service
|
||||||
// 0xff = system service
|
// 0xff = system code service
|
||||||
// 0x00 =
|
// 0x00 = request code
|
||||||
// b7 = automatic switching of data rate
|
// b7 = automatic switching of data rate
|
||||||
// b6-b2 = reserved
|
// b6-b2 = reserved
|
||||||
// b1 = fc/32 (414kbps)
|
// b1 = fc/32 (414kbps)
|
||||||
// b0 = fc/64 (212kbps)
|
// b0 = fc/64 (212kbps)
|
||||||
// 0x00 = timeslot
|
// 0x00 = timeslot
|
||||||
// 0x09 0x21 = crc
|
// 0x09 0x21 = crc
|
||||||
static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
|
static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
|
||||||
|
|
||||||
int len = 20;
|
int len = 20;
|
||||||
|
|
||||||
// We try 20 times, or if answer was received.
|
// We try 20 times, or if answer was received.
|
||||||
|
@ -222,7 +220,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0);
|
TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0);
|
||||||
|
|
||||||
// polling card, break if success
|
// polling card, break if success
|
||||||
if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
|
if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
@ -230,17 +228,31 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||||
} while (--len);
|
} while (--len);
|
||||||
|
|
||||||
// timed-out
|
// timed-out
|
||||||
if (len == 0)
|
if (len == 0){
|
||||||
|
if (DBGLEVEL > 3)
|
||||||
|
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)
|
||||||
|
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){
|
||||||
|
Dbprintf("Error: CRC check failed!");
|
||||||
|
Dbprintf("CRC check was done on Frame: ");
|
||||||
|
Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0);
|
||||||
|
}
|
||||||
return 3;
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBGLEVEL > 3)
|
||||||
|
Dbprintf("Card selection successful!");
|
||||||
// copy UID
|
// copy UID
|
||||||
// idm 8
|
// idm 8
|
||||||
if (card) {
|
if (card) {
|
||||||
|
@ -251,7 +263,10 @@ 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){
|
||||||
|
Dbprintf("Received Frame: ");
|
||||||
|
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// more status bytes?
|
// more status bytes?
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -349,10 +364,13 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sending sync code
|
// sending data with sync bytes
|
||||||
|
|
||||||
// sending data
|
|
||||||
c = 0;
|
c = 0;
|
||||||
|
if (DBGLEVEL > 3){
|
||||||
|
Dbprintf("Sending frame:");
|
||||||
|
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
|
||||||
|
@ -386,22 +404,21 @@ 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)
|
||||||
|
Dbprintf("WaitForFelicaReply Start");
|
||||||
uint32_t c = 0;
|
uint32_t c = 0;
|
||||||
|
|
||||||
// power, no modulation
|
// power, no modulation
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||||
|
|
||||||
FelicaFrameReset();
|
FelicaFrameReset();
|
||||||
|
|
||||||
// clear RXRDY:
|
// clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
|
||||||
|
|
||||||
uint32_t timeout = iso18092_get_timeout();
|
uint32_t timeout = iso18092_get_timeout();
|
||||||
|
if (DBGLEVEL > 3)
|
||||||
|
Dbprintf("timeout set: %i", timeout);
|
||||||
|
//TODO FIX THIS METHOD - Race Condition or something: TIMING/MEMORY ISSUES
|
||||||
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);
|
||||||
|
@ -410,8 +427,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
MAX(
|
MAX(
|
||||||
felica_nexttransfertime,
|
felica_nexttransfertime,
|
||||||
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
||||||
)
|
);
|
||||||
;
|
|
||||||
|
|
||||||
LogTrace(
|
LogTrace(
|
||||||
FelicaFrame.framebytes,
|
FelicaFrame.framebytes,
|
||||||
|
@ -421,22 +437,20 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
NULL,
|
NULL,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
if (DBGLEVEL > 3) 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");
|
||||||
return false;
|
return false;
|
||||||
} else if (FelicaFrame.state == STATE_GET_CRC) {
|
} // If you add content here, timing problems appear?!
|
||||||
Dbprintf(" Frame: ");
|
|
||||||
Dbhexdump(16, FelicaFrame.framebytes, 0);
|
|
||||||
//return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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");
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
@ -481,7 +495,6 @@ static void iso18092_setup(uint8_t fpga_minor_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 > 3) Dbprintf("FeliCa_sendraw Enter");
|
||||||
|
|
||||||
felica_command_t param = c->oldarg[0];
|
felica_command_t param = c->oldarg[0];
|
||||||
|
@ -492,21 +505,25 @@ 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");
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||||
|
|
||||||
if ((param & FELICA_CONNECT)) {
|
if ((param & FELICA_CONNECT)) {
|
||||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
|
||||||
|
|
||||||
// notify client selecting status.
|
// notify client selecting status.
|
||||||
// if failed selecting, turn off antenna and quite.
|
// if failed selecting, turn off antenna and quite.
|
||||||
if (!(param & FELICA_NO_SELECT)) {
|
if (!(param & FELICA_NO_SELECT)) {
|
||||||
arg0 = felica_select_card(&card);
|
arg0 = felica_select_card(&card);
|
||||||
reply_old(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
reply_old(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||||
if (arg0 > 0)
|
if (arg0 > 0){
|
||||||
goto OUT;
|
Dbprintf("Error: Failed selecting card! ");
|
||||||
|
}
|
||||||
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
if (DBGLEVEL > 3) Dbprintf("No card selection");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & FELICA_RAW)) {
|
if ((param & FELICA_RAW)) {
|
||||||
|
@ -527,22 +544,32 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
AddCrc(buf, len);
|
AddCrc(buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DBGLEVEL > 3) {
|
||||||
|
Dbprintf("Transmit Frame (no CRC shown):");
|
||||||
|
Dbhexdump(len, buf, 0);
|
||||||
|
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) {
|
||||||
|
Dbprintf("Received Frame: %d", arg0);
|
||||||
|
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||||
|
};
|
||||||
reply_old(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
reply_old(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
||||||
|
FelicaFrameReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & FELICA_NO_DISCONNECT))
|
if ((param & FELICA_NO_DISCONNECT))
|
||||||
|
Dbprintf("Disconnect");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
switch_off();
|
switch_off();
|
||||||
|
|
||||||
//Resetting Frame mode (First set in fpgaloader.c)
|
//Resetting Frame mode (First set in fpgaloader.c)
|
||||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
|
|
||||||
if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit");
|
if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit");
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||||
|
@ -722,8 +749,98 @@ void felica_sim_lite(uint64_t uid) {
|
||||||
DbpString("Felica Lite-S sim end");
|
DbpString("Felica Lite-S sim end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_dump_lite_s() {
|
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);
|
||||||
|
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){
|
||||||
|
uint8_t len = sizeof(request_service) / sizeof((request_service)[0]);
|
||||||
|
Dbprintf("Send Service Request - len: d%", len);
|
||||||
|
TransmitFor18092_AsReader(request_service, 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)*11);
|
||||||
|
//{ 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[9] = idm[6];
|
||||||
|
request_service[9] = idm[7];
|
||||||
|
request_service[10] = nodeNumber; // Node we like to ask for services
|
||||||
|
request_service[11] = 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() {
|
||||||
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};
|
||||||
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
|
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
|
||||||
|
|
|
@ -18,5 +18,11 @@ 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_authentication1_frame();
|
||||||
|
void felica_create_authentication2_frame();
|
||||||
|
void felica_send_request_service(uint8_t *request_service);
|
||||||
|
uint8_t * felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@ static int usage_hf_felica_sim(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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'");
|
||||||
|
@ -80,6 +81,12 @@ static int usage_hf_felica_raw(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usage_hf_felica_dump(void) {
|
||||||
|
PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] <outputfile>");
|
||||||
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHFFelicaList(const char *Cmd) {
|
static int CmdHFFelicaList(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead");
|
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead");
|
||||||
|
@ -93,6 +100,12 @@ static int CmdHFFelicaReader(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHFFelicaDump(const char *Cmd) {
|
||||||
|
if (strlen(Cmd) < 1) return usage_hf_felica_dump();
|
||||||
|
dump(*Cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// simulate iso18092 / FeliCa tag
|
// simulate iso18092 / FeliCa tag
|
||||||
// Commented, there is no counterpart in ARM at the moment
|
// Commented, there is no counterpart in ARM at the moment
|
||||||
/*
|
/*
|
||||||
|
@ -351,7 +364,7 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac
|
||||||
PrintAndLogEx(NORMAL, "Authenticated: %s", trace[3] ? "yes" : "no");
|
PrintAndLogEx(NORMAL, "Authenticated: %s", trace[3] ? "yes" : "no");
|
||||||
break;
|
break;
|
||||||
case 0xa0:
|
case 0xa0:
|
||||||
PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3 + 2] == 0xff) ? "no" : "yes");
|
PrintAndLogEx(NORMAL, "CRC of all blocks match : %s", (trace[3 + 2] == 0xff) ? "no" : "yes");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line);
|
PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line);
|
||||||
|
@ -393,8 +406,10 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tracelen = resp.oldarg[1];
|
uint32_t tracelen = resp.oldarg[1];
|
||||||
if (tracelen == 0)
|
if (tracelen == 0){
|
||||||
|
PrintAndLogEx(WARNING, "\nNo trace data! Maybe not a FeliCa Lite card?");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *trace = calloc(tracelen, sizeof(uint8_t));
|
uint8_t *trace = calloc(tracelen, sizeof(uint8_t));
|
||||||
if (trace == NULL) {
|
if (trace == NULL) {
|
||||||
|
@ -408,7 +423,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen);
|
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu64" bytes)", tracelen);
|
||||||
|
|
||||||
print_hex_break(trace, tracelen, 32);
|
print_hex_break(trace, tracelen, 32);
|
||||||
printSep();
|
printSep();
|
||||||
|
@ -427,7 +442,7 @@ static void waitCmdFelica(uint8_t iSelect) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff);
|
uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff);
|
||||||
PrintAndLogEx(NORMAL, "received %i octets", len);
|
PrintAndLogEx(NORMAL, "received %i octets", len);
|
||||||
if (!len)
|
if (!len)
|
||||||
return;
|
return;
|
||||||
|
@ -435,6 +450,7 @@ static void waitCmdFelica(uint8_t iSelect) {
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
|
@ -516,8 +532,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
|
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
|
||||||
uint8_t b1, b2;
|
uint8_t b1, b2;
|
||||||
compute_crc(CRC_FELICA, data, datalen, &b1, &b2);
|
compute_crc(CRC_FELICA, data, datalen, &b1, &b2);
|
||||||
data[datalen++] = b1;
|
|
||||||
data[datalen++] = b2;
|
data[datalen++] = b2;
|
||||||
|
data[datalen++] = b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
|
@ -543,6 +559,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
if (active_select)
|
if (active_select)
|
||||||
|
PrintAndLogEx(NORMAL, "Active select wait for FeliCa.");
|
||||||
waitCmdFelica(1);
|
waitCmdFelica(1);
|
||||||
if (datalen > 0)
|
if (datalen > 0)
|
||||||
waitCmdFelica(0);
|
waitCmdFelica(0);
|
||||||
|
@ -550,30 +567,6 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
|
||||||
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
|
||||||
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
|
||||||
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"},
|
|
||||||
{"sniff", CmdHFFelicaSniff, IfPm3Felica, "sniff ISO 18092/Felica traffic"},
|
|
||||||
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
|
||||||
|
|
||||||
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
|
||||||
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
|
||||||
{NULL, NULL, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd) {
|
|
||||||
(void)Cmd; // Cmd is not used so far
|
|
||||||
CmdsHelp(CommandTable);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CmdHFFelica(const char *Cmd) {
|
|
||||||
clearCommandBuffer();
|
|
||||||
return CmdsParse(CommandTable, Cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int readFelicaUid(bool verbose) {
|
int readFelicaUid(bool verbose) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -587,6 +580,7 @@ int readFelicaUid(bool verbose) {
|
||||||
|
|
||||||
felica_card_select_t card;
|
felica_card_select_t card;
|
||||||
memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t));
|
memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t));
|
||||||
|
PrintAndLogEx(NORMAL, "Received bytes: \n%s", sprint_hex(resp.data.asBytes, sizeof(resp.data.asBytes)));
|
||||||
uint64_t status = resp.oldarg[0];
|
uint64_t status = resp.oldarg[0];
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -622,3 +616,61 @@ int readFelicaUid(bool verbose) {
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO FINISH THIS METHOD
|
||||||
|
int dump(const char *Cmd){
|
||||||
|
clearCommandBuffer();
|
||||||
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
|
if (ctmp == 'h') return usage_hf_felica_dumplite();
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "FeliCa - dump started");
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_FELICALITE_DUMP, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
uint8_t timeout = 0;
|
||||||
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
|
timeout++;
|
||||||
|
printf(".");
|
||||||
|
fflush(stdout);
|
||||||
|
if (kbd_enter_pressed()) {
|
||||||
|
PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n");
|
||||||
|
DropField();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (timeout > 100) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
DropField();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resp.oldarg[0] == 0) {
|
||||||
|
PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static command_t CommandTable[] = {
|
||||||
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
|
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
||||||
|
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
||||||
|
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"},
|
||||||
|
{"sniff", CmdHFFelicaSniff, IfPm3Felica, "sniff ISO 18092/Felica traffic"},
|
||||||
|
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
||||||
|
{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping Felica"},
|
||||||
|
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
||||||
|
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
||||||
|
{NULL, NULL, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int CmdHelp(const char *Cmd) {
|
||||||
|
(void)Cmd; // Cmd is not used so far
|
||||||
|
CmdsHelp(CommandTable);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdHFFelica(const char *Cmd) {
|
||||||
|
clearCommandBuffer();
|
||||||
|
return CmdsParse(CommandTable, Cmd);
|
||||||
|
}
|
||||||
|
|
|
@ -16,4 +16,6 @@
|
||||||
int CmdHFFelica(const char *Cmd);
|
int CmdHFFelica(const char *Cmd);
|
||||||
|
|
||||||
int readFelicaUid(bool verbose);
|
int readFelicaUid(bool verbose);
|
||||||
|
|
||||||
|
int dump();
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue