Skip to content

Commit

Permalink
Added support for mifare classic value block operations
Browse files Browse the repository at this point in the history
  • Loading branch information
taichunmin committed Oct 25, 2023
1 parent ecf3c06 commit 549d378
Show file tree
Hide file tree
Showing 9 changed files with 505 additions and 43 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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...

## [unreleased][unreleased]
- Added support for mifare classic value block operations (@taichunmin)
- Added regression tests (@doegox)
- Changed git version to version tag instead of dev tag (@taichunmin)
- Fixed 14A emulate bug and MF1 emulate bug (@spp2000 and @xianglin1998)
Expand Down
4 changes: 4 additions & 0 deletions docs/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ Notes:
* `reserved`:2
* Response: data sent by the card
* CLI: cf `hf 14a raw`
### 2011: MF1_MANIPULATE_VALUE_BLOCK
* Command: 21 bytes: `src_type|src_block|src_key[6]|operator|operand[4]|dst_type|dst_block|dst_key[6]`. Key as 6 bytes. Type=`0x60` for key A, `0x61` for key B. Operator=`0xC0` for decrement, `0xC1` for increment, `0xC2` for restore. Operand as I32 in Network byte order.
* Response: no data
* CLI: cf `hf mf value`
### 3000: EM410X_SCAN
* Command: no data
* Response: 5 bytes. `id[5]`. ID as 5 bytes.
Expand Down
53 changes: 53 additions & 0 deletions firmware/application/src/app_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,58 @@ static data_frame_tx_t *cmd_processor_hf14a_raw(uint16_t cmd, uint16_t status, u
return data_frame_make(cmd, status, resp_length, resp);
}

static data_frame_tx_t *cmd_processor_mf1_manipulate_value_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
typedef struct {
uint8_t src_type;
uint8_t src_block;
uint8_t src_key[6];
uint8_t operator;
uint32_t operand;
uint8_t dst_type;
uint8_t dst_block;
uint8_t dst_key[6];
} PACKED payload_t;
if (length != sizeof(payload_t)) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}

payload_t *payload = (payload_t *)data;

// scan tag
picc_14a_tag_t taginfo;
if (pcd_14a_reader_scan_auto(&taginfo) != STATUS_HF_TAG_OK) {
return data_frame_make(cmd, STATUS_HF_TAG_NO, 0, NULL);
}

// auth src
status = pcd_14a_reader_mf1_auth(&taginfo, payload->src_type, payload->src_block, payload->src_key);
if (status != STATUS_HF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}

// value block operation
status = pcd_14a_reader_mf1_manipulate_value_block(payload->operator, payload->src_block, (int32_t) U32NTOHL(payload->operand));
if (status != STATUS_HF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}

// auth dst if needed
if (payload->src_block != payload->dst_block || payload->src_type != payload->dst_type) {
status = pcd_14a_reader_mf1_auth(&taginfo, payload->dst_type, payload->dst_block, payload->dst_key);
if (status != STATUS_HF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}
}

// transfer value block
status = pcd_14a_reader_mf1_transfer_value_block(payload->dst_block);
if (status != STATUS_HF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}

return data_frame_make(cmd, status, 0, NULL);
}

static data_frame_tx_t *cmd_processor_em410x_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t id_buffer[5] = { 0x00 };
status = PcdScanEM410X(id_buffer);
Expand Down Expand Up @@ -1015,6 +1067,7 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_MF1_READ_ONE_BLOCK, before_hf_reader_run, cmd_processor_mf1_read_one_block, after_hf_reader_run },
{ DATA_CMD_MF1_WRITE_ONE_BLOCK, before_hf_reader_run, cmd_processor_mf1_write_one_block, after_hf_reader_run },
{ DATA_CMD_HF14A_RAW, before_reader_run, cmd_processor_hf14a_raw, NULL },
{ DATA_CMD_MF1_MANIPULATE_VALUE_BLOCK, before_hf_reader_run, cmd_processor_mf1_manipulate_value_block, after_hf_reader_run },

{ DATA_CMD_EM410X_SCAN, before_reader_run, cmd_processor_em410x_scan, NULL },
{ DATA_CMD_EM410X_WRITE_TO_T55XX, before_reader_run, cmd_processor_em410x_write_to_t55XX, NULL },
Expand Down
1 change: 1 addition & 0 deletions firmware/application/src/data_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#define DATA_CMD_MF1_READ_ONE_BLOCK (2008)
#define DATA_CMD_MF1_WRITE_ONE_BLOCK (2009)
#define DATA_CMD_HF14A_RAW (2010)
#define DATA_CMD_MF1_MANIPULATE_VALUE_BLOCK (2011)

//
// ******************************************************************
Expand Down
Loading

0 comments on commit 549d378

Please sign in to comment.