bpreader: add card reading
This commit is contained in:
parent
f7cd4f9d28
commit
b5b797377f
268
board/bpreader.c
268
board/bpreader.c
@ -12,12 +12,15 @@
|
|||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
#include "util/hexstr.h"
|
#include "util/hexstr.h"
|
||||||
|
|
||||||
|
#include "iccard/aime.h"
|
||||||
|
#include "iccard/mifare.h"
|
||||||
|
|
||||||
#include "board/bpreader.h"
|
#include "board/bpreader.h"
|
||||||
|
|
||||||
const uint8_t BPREADER_CMD_GO_NEXT[6] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 };
|
const uint8_t BPREADER_CMD_GO_NEXT[6] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 };
|
||||||
|
|
||||||
static bool flg = true;
|
static bool flg = true;
|
||||||
static bool flg_second_pass = false;
|
static struct mifare card;
|
||||||
static HRESULT bp_handle_irp(struct irp *irp);
|
static HRESULT bp_handle_irp(struct irp *irp);
|
||||||
static HRESULT bp_handle_irp_locked(struct irp *irp);
|
static HRESULT bp_handle_irp_locked(struct irp *irp);
|
||||||
static HRESULT crack_bpreader_request();
|
static HRESULT crack_bpreader_request();
|
||||||
@ -35,7 +38,11 @@ static HRESULT bpreader_set_output_cmd();
|
|||||||
static HRESULT bpreader_unk_08_cmd();
|
static HRESULT bpreader_unk_08_cmd();
|
||||||
static HRESULT bpreader_unk_06_cmd();
|
static HRESULT bpreader_unk_06_cmd();
|
||||||
static HRESULT bpreader_unk_0c_cmd();
|
static HRESULT bpreader_unk_0c_cmd();
|
||||||
|
static HRESULT bpreader_unk_44_cmd();
|
||||||
|
static HRESULT bpreader_unk_52_cmd();
|
||||||
static HRESULT bpreader_unk_54_cmd();
|
static HRESULT bpreader_unk_54_cmd();
|
||||||
|
static HRESULT bpreader_send_mifare_cmd();
|
||||||
|
static HRESULT bpreader_empty_resp();
|
||||||
|
|
||||||
static struct bpreader_config *config;
|
static struct bpreader_config *config;
|
||||||
static struct uart bp_uart;
|
static struct uart bp_uart;
|
||||||
@ -54,6 +61,7 @@ HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port)
|
|||||||
if (cfg->port > 0) {
|
if (cfg->port > 0) {
|
||||||
port = cfg->port;
|
port = cfg->port;
|
||||||
}
|
}
|
||||||
|
uint8_t sec1[16] = { 0x00, 0x02, 0x4E, 0x42, 0x47, 0x49, 0x43, 0x36, 0x3A, 0xE7, 0xB5, 0x59, 0x45, 0x64, 0x0F, 0x3D };
|
||||||
|
|
||||||
uart_init(&bp_uart, port);
|
uart_init(&bp_uart, port);
|
||||||
bp_uart.written.bytes = bp_written_bytes;
|
bp_uart.written.bytes = bp_written_bytes;
|
||||||
@ -62,6 +70,13 @@ HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port)
|
|||||||
bp_uart.readable.nbytes = sizeof(bp_readable_bytes);
|
bp_uart.readable.nbytes = sizeof(bp_readable_bytes);
|
||||||
InitializeCriticalSection(&bp_lock);
|
InitializeCriticalSection(&bp_lock);
|
||||||
|
|
||||||
|
HRESULT hr = aime_card_populate(&card, cfg->access_code_bytes, sizeof(cfg->access_code_bytes));
|
||||||
|
//memcpy_s(card.sectors[0].blocks[1].bytes, sizeof(card.sectors[0].blocks[1].bytes), sec1, sizeof(sec1));
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
dprintf("Reader: Init\n");
|
dprintf("Reader: Init\n");
|
||||||
return iohook_push_handler(bp_handle_irp);
|
return iohook_push_handler(bp_handle_irp);
|
||||||
}
|
}
|
||||||
@ -116,120 +131,12 @@ static HRESULT bp_handle_irp_locked(struct irp *irp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (irp->op == IRP_OP_READ) {
|
else if (irp->op == IRP_OP_READ) {
|
||||||
if (flg) {
|
if (!read_ct) {
|
||||||
if (!read_ct || flg_second_pass) {
|
hr = crack_bpreader_request();
|
||||||
hr = crack_bpreader_request();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
switch (bp_uart.written.bytes[3]) {
|
// We need a delay here in order to properly
|
||||||
case 0x02:
|
// "timeout" the DLL's read request.
|
||||||
if (!read_ct) {
|
Sleep(1);
|
||||||
dprintf("Reader: Unknown 0x02\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x05,
|
|
||||||
0xFB, 0xD5, 0x0D, 0x00, 0x06, 0x00, 0x18, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x03:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x03\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02,
|
|
||||||
0xFE, 0xD5, 0x19, 0x12, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x04:
|
|
||||||
if (!read_ct && bp_uart.written.bytes[6] == 0x0E && last_cmd == 0x04) {
|
|
||||||
dprintf("Reader: Unknown second 0x04\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02,
|
|
||||||
0xFE, 0xD5, 0x0F, 0x1C, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
else if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x04\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02,
|
|
||||||
0xFE, 0xD5, 0x33, 0xF8, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x06:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x06\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02,
|
|
||||||
0xFE, 0xD5, 0x33, 0xF8, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x05:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x05\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x03,
|
|
||||||
0xFD, 0xD5, 0x09, 0x00, 0x22, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x0E:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x0E\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xff, 0x02,
|
|
||||||
0xfe, 0xd5, 0x33, 0xf8, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x12:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x12\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x0a,
|
|
||||||
0xf6, 0xd5, 0x07, 0xff, 0x3f, 0x0e, 0xf1, 0xff, 0x3f, 0x0e, 0xf1, 0xaa, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x14:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x14\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x20, 0xE0, 0xD5, 0xA1,
|
|
||||||
0x00, 0x1D, 0x07, // Unknown
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IDm
|
|
||||||
0x00, 0x00, 0x01, // Unknown
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IDm
|
|
||||||
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown
|
|
||||||
0x00, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x18:
|
|
||||||
if (!read_ct) {
|
|
||||||
dprintf("Reader: Unknown 0x18\n");
|
|
||||||
uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x0D,
|
|
||||||
0xF3, 0xD5, 0x07, 0xDC, 0xF4, 0x3F, 0x11, 0x4D, 0x85, 0x61, 0xF1, 0x26,
|
|
||||||
0x6A, 0x87, 0xC9, 0x00 };
|
|
||||||
hr = iobuf_write(&bp_uart.readable, buff, sizeof(buff));
|
|
||||||
}
|
|
||||||
bp_uart.written.pos = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
dprintf("Reader: Unknown Command %02X\n", last_cmd);
|
|
||||||
dump_iobuf(&bp_uart.written);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
read_ct++;
|
read_ct++;
|
||||||
}
|
}
|
||||||
@ -245,9 +152,7 @@ static HRESULT bp_handle_irp_locked(struct irp *irp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!flg_second_pass) {
|
bp_uart.written.pos = 0; // consume the written buffer
|
||||||
bp_uart.written.pos = 0; // consume the written buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -265,19 +170,19 @@ static HRESULT crack_bpreader_request() {
|
|||||||
|
|
||||||
switch(header.cmd) {
|
switch(header.cmd) {
|
||||||
case 0x06:
|
case 0x06:
|
||||||
dprintf("Reader: Cmd 0x06\n");
|
// dprintf("Reader: Cmd 0x06\n");
|
||||||
return bpreader_unk_06_cmd();
|
return bpreader_unk_06_cmd();
|
||||||
|
|
||||||
case 0x08:
|
case 0x08:
|
||||||
dprintf("Reader: Cmd 0x08\n");
|
// dprintf("Reader: Cmd 0x08\n");
|
||||||
return bpreader_unk_08_cmd();
|
return bpreader_unk_08_cmd();
|
||||||
|
|
||||||
case 0x12:
|
case 0x12:
|
||||||
dprintf("Reader: Cmd 0x12\n");
|
// dprintf("Reader: Cmd 0x12\n");
|
||||||
return bpreader_generic_cmd(0x13);
|
return bpreader_generic_cmd(0x13);
|
||||||
|
|
||||||
case 0x18:
|
case 0x18:
|
||||||
dprintf("Reader: Initialize\n");
|
// dprintf("Reader: Initialize\n");
|
||||||
return bpreader_init_cmd();
|
return bpreader_init_cmd();
|
||||||
|
|
||||||
case 0x0C:
|
case 0x0C:
|
||||||
@ -289,15 +194,19 @@ static HRESULT crack_bpreader_request() {
|
|||||||
return bpreader_generic_cmd(0x0F);
|
return bpreader_generic_cmd(0x0F);
|
||||||
|
|
||||||
case 0x32:
|
case 0x32:
|
||||||
dprintf("Reader: Cmd 0x32\n");
|
// dprintf("Reader: Cmd 0x32\n");
|
||||||
return bpreader_generic_cmd(0x33);
|
return bpreader_generic_cmd(0x33);
|
||||||
|
|
||||||
case 0x40:
|
case 0x40:
|
||||||
dprintf("Reader: Read Banapass\n"); // 01 30 00 -> Chip ID; 01 30 01 -> Thing after chip ID; 01 30 02 -> Access Code; 01 60 30 -> send key a
|
// dprintf("Reader: Read Mifare\n");
|
||||||
break;
|
return bpreader_send_mifare_cmd();
|
||||||
|
|
||||||
|
case 0x44:
|
||||||
|
dprintf("Reader: Cmd 0x44\n");
|
||||||
|
return bpreader_unk_44_cmd();
|
||||||
|
|
||||||
case 0x4A:
|
case 0x4A:
|
||||||
dprintf("Reader: Poll Card\n");
|
// dprintf("Reader: Poll Card\n");
|
||||||
return bpreader_poll_card_cmd();
|
return bpreader_poll_card_cmd();
|
||||||
|
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
@ -305,8 +214,8 @@ static HRESULT crack_bpreader_request() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x52:
|
case 0x52:
|
||||||
dprintf("Reader: Cmd 0x52\n");
|
//dprintf("Reader: Cmd 0x52\n");
|
||||||
break;
|
return bpreader_unk_52_cmd();
|
||||||
|
|
||||||
case 0x54:
|
case 0x54:
|
||||||
dprintf("Reader: Cmd 0x54\n");
|
dprintf("Reader: Cmd 0x54\n");
|
||||||
@ -420,7 +329,7 @@ static HRESULT bpreader_poll_card_cmd()
|
|||||||
int data_len = 1;
|
int data_len = 1;
|
||||||
size_t resp_len = 0;
|
size_t resp_len = 0;
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
|
if (GetAsyncKeyState(config->insert_card) & 0x8000) {
|
||||||
dprintf("Reader: Touch card %ls\n", config->access_code);
|
dprintf("Reader: Touch card %ls\n", config->access_code);
|
||||||
|
|
||||||
data.card_present = 0x01;
|
data.card_present = 0x01;
|
||||||
@ -429,11 +338,17 @@ static HRESULT bpreader_poll_card_cmd()
|
|||||||
data.atqa[1] = 0x04;
|
data.atqa[1] = 0x04;
|
||||||
data.sak = 0x08;
|
data.sak = 0x08;
|
||||||
data.unknown5 = 0x04;
|
data.unknown5 = 0x04;
|
||||||
memcpy_s(data.serial_number, sizeof(data.serial_number), config->chip_id_bytes, 4);
|
memcpy_s(data.serial_number, sizeof(data.serial_number), config->access_code_bytes, 4);
|
||||||
data_len = sizeof(data);
|
data_len = sizeof(data);
|
||||||
}
|
|
||||||
|
|
||||||
resp_len = build_bpreader_response((uint8_t *)&data, data_len, &header, buff, sizeof(buff));
|
|
||||||
|
resp_len = build_bpreader_response((uint8_t *)&data, data_len, &header, buff, sizeof(buff));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_len = 3;
|
||||||
|
uint8_t empty_buff[1] = {0};
|
||||||
|
resp_len = build_bpreader_response((uint8_t *)&empty_buff, data_len, &header, buff, sizeof(buff));
|
||||||
|
}
|
||||||
|
|
||||||
if (resp_len > 0) {
|
if (resp_len > 0) {
|
||||||
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
||||||
@ -471,14 +386,14 @@ static HRESULT bpreader_unk_54_cmd()
|
|||||||
uint8_t bfr_data[1] = { 0x00 };
|
uint8_t bfr_data[1] = { 0x00 };
|
||||||
size_t resp_len = 0;
|
size_t resp_len = 0;
|
||||||
|
|
||||||
resp_len = build_bpreader_response(bfr_data, sizeof(bfr_data), &header, buff, sizeof(buff));
|
resp_len = build_bpreader_response(bfr_data, 1, &header, buff, sizeof(buff));
|
||||||
|
|
||||||
if (resp_len > 0) {
|
if (resp_len > 0) {
|
||||||
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dprintf("Reader: No data to return in bpreader_set_output_cmd!\n");
|
dprintf("Reader: No data to return in bpreader_unk_54_cmd!\n");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,3 +447,90 @@ static HRESULT bpreader_unk_0c_cmd()
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT bpreader_send_mifare_cmd()
|
||||||
|
{
|
||||||
|
struct bpreader_read_mifare_req req = { bp_uart.written.bytes[7], bp_uart.written.bytes[8], bp_uart.written.bytes[9] };
|
||||||
|
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x03, 0xFD, 0xD5, 0x41 };
|
||||||
|
uint8_t data[17] = { 0x00 };
|
||||||
|
uint8_t buff[26] = { 0x00 };
|
||||||
|
size_t resp_len = 0;
|
||||||
|
|
||||||
|
switch (req.subcmd) {
|
||||||
|
case MIFARE_CMD_READ:
|
||||||
|
struct bpreader_read_mifare_resp_data resp;
|
||||||
|
|
||||||
|
if (req.block > 3) {
|
||||||
|
dprintf("Reader: MIFARE block number %d is out of range!\n", req.block);
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Reader: Mifare Read Block 0x%02X\n", req.block);
|
||||||
|
resp.padding = 0;
|
||||||
|
memcpy_s(resp.block, sizeof(resp.block), card.sectors[0].blocks[req.block].bytes, sizeof(card.sectors[0].blocks[req.block].bytes));
|
||||||
|
header.data_len = 0x13;
|
||||||
|
resp_len = build_bpreader_response((uint8_t *)&resp, 0x11, &header, buff, sizeof(buff));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIFARE_CMD_AUTH_KEY_A:
|
||||||
|
dprintf("Reader: Mifare Authentication with Key A\n");
|
||||||
|
return iobuf_write(&bp_uart.readable, BPREADER_CMD_GO_NEXT, sizeof(BPREADER_CMD_GO_NEXT));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIFARE_CMD_AUTH_KEY_B:
|
||||||
|
dprintf("Reader: Mifare Authentication with Key B\n");
|
||||||
|
resp_len = build_bpreader_response(data, 1, &header, buff, sizeof(buff));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dprintf("Reader: Unknown Mifare Command 0x%02x\n", req.subcmd);
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp_len > 0) {
|
||||||
|
return iobuf_write(&bp_uart.readable, buff, resp_len);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dprintf("Reader: No data to return in bpreader_send_mifare_cmd!\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT bpreader_unk_52_cmd()
|
||||||
|
{
|
||||||
|
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD5, 0x53 };
|
||||||
|
uint8_t buff[10] = { 0x00 };
|
||||||
|
uint8_t bfr_data[2] = { 0x01, 0x00 };
|
||||||
|
size_t resp_len = 0;
|
||||||
|
|
||||||
|
resp_len = build_bpreader_response(bfr_data, 2, &header, buff, sizeof(buff));
|
||||||
|
|
||||||
|
if (resp_len > 0) {
|
||||||
|
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dprintf("Reader: No data to return in bpreader_unk_52_cmd!\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT bpreader_unk_44_cmd()
|
||||||
|
{
|
||||||
|
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD5, 0x45 };
|
||||||
|
uint8_t buff[10] = { 0x00 };
|
||||||
|
uint8_t bfr_data[2] = { 0x01, 0x00 };
|
||||||
|
size_t resp_len = 0;
|
||||||
|
|
||||||
|
resp_len = build_bpreader_response(bfr_data, 2, &header, buff, sizeof(buff));
|
||||||
|
|
||||||
|
if (resp_len > 0) {
|
||||||
|
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dprintf("Reader: No data to return in bpreader_unk_44_cmd!\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,46 +6,31 @@
|
|||||||
struct bpreader_config {
|
struct bpreader_config {
|
||||||
bool enable;
|
bool enable;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
|
uint8_t insert_card;
|
||||||
wchar_t access_code[21];
|
wchar_t access_code[21];
|
||||||
wchar_t chip_id[33];
|
|
||||||
uint8_t access_code_bytes[10];
|
uint8_t access_code_bytes[10];
|
||||||
uint8_t chip_id_bytes[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port);
|
HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bpreader packet format WIP
|
bpreader packet format WIP
|
||||||
n = final offset
|
maybe rcs956?
|
||||||
|
Response packet
|
||||||
| Offset | Meaning |
|
| Offset | Meaning |
|
||||||
|--------|--------------------------------------------------------------------|
|
|--------|--------------------------------------------------------------------|
|
||||||
| 0 | Always 00 |
|
| 0 | Preamble, Always 00 |
|
||||||
| 1 | Always 00 |
|
| 1 | Packet start, Always 00 |
|
||||||
| 2 | Always FF | Header
|
| 2 | Always FF | Header
|
||||||
| 3 | len(Data), 0 means no data |
|
| 3 | len(Data), 0 means no data |
|
||||||
| 4 | FF - ((sum of header bytes) & FF) if data is present |
|
| 4 | (0x100 - data_len) & FF if data is present |
|
||||||
|--------|--------------------------------------------------------------------|
|
|--------|--------------------------------------------------------------------|
|
||||||
| 5 | Always D5 (resp) or D4 (req) if data is present, identifier? |
|
| 5 | Always 0xD5 (success) or 0x7F (failure) |
|
||||||
| 6 | Command if data is present | Data
|
| 6 | Command if data is present | Data
|
||||||
| 7..n-2 | Data if data is present |
|
| 7..n-2 | Data if data is present |
|
||||||
|--------|--------------------------------------------------------------------|
|
|--------|--------------------------------------------------------------------|
|
||||||
| n-1 | FF - ((sum of head + data bytes) & FF) if data is present, else FF | Footer
|
| n-1 | (FF - sum of data bytes) & FF if data is present, else FF | Footer
|
||||||
| n | Always 00 |
|
| n | Postamble, Always 00 |
|
||||||
|
|
||||||
Commands
|
|
||||||
| Command | Response | Meaning | Response Data (not including leading 0xD5) |
|
|
||||||
|---------|----------|----------------------------------------------------|------------------------------------------------------------------------|
|
|
||||||
| 0x00 | 0x00 | Wait Next Command | None |
|
|
||||||
| 0x02 | 0x05 | Unknown | 0x0D, 0x00, 0x06, 0x00 |
|
|
||||||
| 0x03 | 0x02 | Unknown, first command and then sent randomly | 0x19 |
|
|
||||||
| 0x04 | 0x02 | Unknown, only command seen to change it's req data | 0x0F/0x33 |
|
|
||||||
| 0x05 | 0x03 | Unknown | 0x09, 0x00 |
|
|
||||||
| 0x06 | 0x02 | Unknown | 0x0F |
|
|
||||||
| 0x09 | 0x18 | Poll for card | 0x4B, 0x01, 0x01, 0x14, 0x01, [IDm], [PMm], [Sys Code] |
|
|
||||||
| 0x0E | 0x02 | Unknown | 0x33 |
|
|
||||||
| 0x12 | 0x0A | Unknown | 0x07, 0xFF, 0x3F, 0x0E, 0xF1, 0xFF, 0x3F, 0x0E, 0xF1 |
|
|
||||||
| 0x14 | 0x20 | Unknown | a lot, see bpreader.c |
|
|
||||||
| 0x18 | 0x0D | Unknown | 0x07, 0xDC, 0xF4, 0x3F, 0x11, 0x4D, 0x85, 0x61, 0xF1, 0x26, 0x6A, 0x87 |
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@ -64,6 +49,17 @@ struct bpreader_cmd_footer {
|
|||||||
uint8_t padding;
|
uint8_t padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpreader_read_mifare_req {
|
||||||
|
uint8_t unk0;
|
||||||
|
uint8_t subcmd; // 0x30 for read, 0x60/61 for write?
|
||||||
|
uint8_t block;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bpreader_read_mifare_resp_data {
|
||||||
|
uint8_t padding;
|
||||||
|
uint8_t block[16];
|
||||||
|
};
|
||||||
|
|
||||||
struct bpreader_poll_banapass_data {
|
struct bpreader_poll_banapass_data {
|
||||||
uint8_t card_present;
|
uint8_t card_present;
|
||||||
uint8_t unknown1; // 0x01
|
uint8_t unknown1; // 0x01
|
||||||
|
@ -17,6 +17,7 @@ void bpreader_config_load(struct bpreader_config *cfg, const wchar_t *filename)
|
|||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"reader", L"enable", 1, filename);
|
cfg->enable = GetPrivateProfileIntW(L"reader", L"enable", 1, filename);
|
||||||
cfg->port = GetPrivateProfileIntW(L"reader", L"port", 0, filename);
|
cfg->port = GetPrivateProfileIntW(L"reader", L"port", 0, filename);
|
||||||
|
cfg->insert_card = GetPrivateProfileIntW(L"reader", L"insert_card", VK_RETURN, filename);
|
||||||
GetPrivateProfileStringW(
|
GetPrivateProfileStringW(
|
||||||
L"reader",
|
L"reader",
|
||||||
L"access_code",
|
L"access_code",
|
||||||
@ -24,23 +25,11 @@ void bpreader_config_load(struct bpreader_config *cfg, const wchar_t *filename)
|
|||||||
cfg->access_code,
|
cfg->access_code,
|
||||||
_countof(cfg->access_code),
|
_countof(cfg->access_code),
|
||||||
filename);
|
filename);
|
||||||
GetPrivateProfileStringW(
|
|
||||||
L"reader",
|
|
||||||
L"chip_id",
|
|
||||||
L"00000000000000000000000000000000",
|
|
||||||
cfg->chip_id,
|
|
||||||
_countof(cfg->chip_id),
|
|
||||||
filename);
|
|
||||||
|
|
||||||
HRESULT hr = wstr_to_bytes(cfg->access_code, 20, cfg->access_code_bytes, sizeof(cfg->access_code_bytes));
|
HRESULT hr = wstr_to_bytes(cfg->access_code, 20, cfg->access_code_bytes, sizeof(cfg->access_code_bytes));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Reader: wstr_to_bytes 1 failed! 0x%lX", hr);
|
dprintf("Reader: wstr_to_bytes 1 failed! 0x%lX", hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = wstr_to_bytes(cfg->chip_id, 32, cfg->chip_id_bytes, sizeof(cfg->chip_id_bytes));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("Reader: wstr_to_bytes 2 failed! 0x%lX", hr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void usio_config_load(struct usio_config *cfg, const wchar_t *filename)
|
void usio_config_load(struct usio_config *cfg, const wchar_t *filename)
|
||||||
|
@ -41,6 +41,11 @@ HRESULT aime_card_populate(
|
|||||||
mifare->sectors[0].blocks[2].bytes[6 + i] = b;
|
mifare->sectors[0].blocks[2].bytes[6 + i] = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the card ID, nothing else matters in the first block
|
||||||
|
mifare->sectors[0].blocks[0].bytes[0] = luid[0];
|
||||||
|
mifare->sectors[0].blocks[0].bytes[1] = luid[1];
|
||||||
|
mifare->sectors[0].blocks[0].bytes[2] = luid[2];
|
||||||
|
mifare->sectors[0].blocks[0].bytes[3] = luid[3];
|
||||||
|
|
||||||
sprintf_s(accessCode, sizeof accessCode, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
sprintf_s(accessCode, sizeof accessCode, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
luid[0], luid[1], luid[2], luid[3], luid[4], luid[5], luid[6], luid[7], luid[8], luid[9]);
|
luid[0], luid[1], luid[2], luid[3], luid[4], luid[5], luid[6], luid[7], luid[8], luid[9]);
|
||||||
|
@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum mifare_cmd {
|
||||||
|
MIFARE_CMD_AUTH_KEY_A = 0x60,
|
||||||
|
MIFARE_CMD_AUTH_KEY_B = 0x61,
|
||||||
|
MIFARE_CMD_PERSONALIZE_UID = 0x40,
|
||||||
|
MIFARE_CMD_SET_MOD_TYPE = 0x43,
|
||||||
|
MIFARE_CMD_READ = 0x30,
|
||||||
|
MIFARE_CMD_WRITE = 0xA0,
|
||||||
|
MIFARE_CMD_DECREMENT = 0xC0,
|
||||||
|
MIFARE_CMD_INCREMENT = 0xC1,
|
||||||
|
MIFARE_CMD_RESTORE = 0xC2,
|
||||||
|
MIFARE_CMD_TRANSFER = 0xB0,
|
||||||
|
};
|
||||||
|
|
||||||
struct mifare_block {
|
struct mifare_block {
|
||||||
uint8_t bytes[16];
|
uint8_t bytes[16];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user