Merge pull request #23 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2019-10-26 12:59:08 +11:00 committed by GitHub
commit 5a3a1fcc0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 699 additions and 222 deletions

View file

@ -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)

View file

@ -1590,8 +1590,13 @@ static void PacketReceived(PacketCommandNG *packet) {
} }
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;
} }

View file

@ -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(
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,
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);
@ -533,7 +525,7 @@ void felica_sendraw(PacketCommandNG *c) {
} }
} }
} 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};

View file

@ -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

View file

@ -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);

View file

@ -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();

View file

@ -8,7 +8,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// High frequency commands // High frequency commands
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//#include "cmdhf.h" #include "cmdhf.h"
#include <ctype.h> // tolower #include <ctype.h> // tolower

View file

@ -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) {
@ -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[] = {
{"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""},
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, {"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"},
{"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, ""},
//{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"},
{"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"}, {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, {"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}
}; };

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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};

View file

@ -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)

View file

@ -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>

View file

@ -38,6 +38,7 @@
#ifndef IKEYS_H #ifndef IKEYS_H
#define IKEYS_H #define IKEYS_H
#include <inttypes.h>
/** /**
* @brief * @brief

View file

@ -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];
} }

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);
} }

View file

@ -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),

View file

@ -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