Merge remote-tracking branch 'origin/main' into cli-overhaul

This commit is contained in:
Szymon Borecki
2023-08-20 01:25:24 +02:00
12 changed files with 676 additions and 261 deletions
+168 -2
View File
@@ -377,6 +377,14 @@ data_frame_tx_t* cmd_processor_set_em410x_emu_id(uint16_t cmd, uint16_t status,
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_em410x_emu_id(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
tag_data_buffer_t* buffer = get_buffer_by_tag_type(TAG_TYPE_EM410X);
uint8_t responseData[LF_EM410X_TAG_ID_SIZE];
memcpy(responseData, buffer->buffer, LF_EM410X_TAG_ID_SIZE);
status = STATUS_DEVICE_SUCCESS;
return data_frame_make(cmd, status, LF_EM410X_TAG_ID_SIZE, responseData);
}
data_frame_tx_t* cmd_processor_set_mf1_detection_enable(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1 && (data[0] == 0 || data[0] == 1)) {
nfc_tag_mf1_detection_log_clear();
@@ -456,6 +464,33 @@ data_frame_tx_t* cmd_processor_set_mf1_emulator_block(uint16_t cmd, uint16_t sta
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_mf1_emulator_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 3) {
uint8_t block_index = data[0];
uint16_t block_count = data[1] | (data[2] << 8);
if (block_count == 0 || block_index + block_count > NFC_TAG_MF1_BLOCK_MAX) {
status = STATUS_PAR_ERR;
}
else {
tag_data_buffer_t* buffer = get_buffer_by_tag_type(TAG_TYPE_MIFARE_4096);
nfc_tag_mf1_information_t *info = (nfc_tag_mf1_information_t *)buffer->buffer;
uint16_t result_length = block_count * NFC_TAG_MF1_DATA_SIZE;
uint8_t result_buffer[result_length];
for (int i = 0, j = block_index; i < result_length; i += NFC_TAG_MF1_DATA_SIZE, j++) {
uint8_t *p_block = &result_buffer[i];
memcpy(p_block, info->memory[j], NFC_TAG_MF1_DATA_SIZE);
}
return data_frame_make(cmd, status, result_length, result_buffer);
}
}
else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_set_mf1_anti_collision_res(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length > 13) {
// sak(1) + atqa(2) + uid(10)
@@ -463,7 +498,7 @@ data_frame_tx_t* cmd_processor_set_mf1_anti_collision_res(uint16_t cmd, uint16_t
} else {
uint8_t uid_length = length - 3;
if (is_valid_uid_size(uid_length)) {
nfc_tag_14a_coll_res_referen_t* info = get_miafre_coll_res();
nfc_tag_14a_coll_res_referen_t* info = get_mifare_coll_res();
// copy sak
info->sak[0] = data[0];
// copy atqa
@@ -528,6 +563,124 @@ data_frame_tx_t* cmd_processor_get_slot_tag_nick_name(uint16_t cmd, uint16_t sta
return data_frame_make(cmd, status, length, data);
}
data_frame_tx_t* cmd_processor_get_mf1_info(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t mf1_info[5] = {};
mf1_info[0] = nfc_tag_mf1_is_detection_enable();
mf1_info[1] = nfc_tag_mf1_is_gen1a_magic_mode();
mf1_info[2] = nfc_tag_mf1_is_gen2_magic_mode();
mf1_info[3] = nfc_tag_mf1_is_use_mf1_coll_res();
nfc_tag_mf1_write_mode_t write_mode = nfc_tag_mf1_get_write_mode();
if (write_mode == NFC_TAG_MF1_WRITE_NORMAL) {
mf1_info[4] = 0;
} else if (write_mode == NFC_TAG_MF1_WRITE_DENIED) {
mf1_info[4] = 1;
} else if (write_mode == NFC_TAG_MF1_WRITE_DECEIVE) {
mf1_info[4] = 2;
} else if (write_mode == NFC_TAG_MF1_WRITE_SHADOW) {
mf1_info[4] = 3;
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 5, mf1_info);
}
data_frame_tx_t* cmd_processor_get_mf1_gen1a_magic_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (nfc_tag_mf1_is_gen1a_magic_mode()) {
status = 1;
} else {
status = 0;
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t*)&status);
}
data_frame_tx_t* cmd_processor_set_mf1_gen1a_magic_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1 && (data[0] == 0 || data[0] == 1)) {
nfc_tag_mf1_set_gen1a_magic_mode(data[0]);
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_mf1_gen2_magic_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (nfc_tag_mf1_is_gen2_magic_mode()) {
status = 1;
} else {
status = 0;
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t*)&status);
}
data_frame_tx_t* cmd_processor_set_mf1_gen2_magic_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1 && (data[0] == 0 || data[0] == 1)) {
nfc_tag_mf1_set_gen2_magic_mode(data[0]);
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_mf1_use_coll_res(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (nfc_tag_mf1_is_use_mf1_coll_res()) {
status = 1;
} else {
status = 0;
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t*)&status);
}
data_frame_tx_t* cmd_processor_set_mf1_use_coll_res(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1 && (data[0] == 0 || data[0] == 1)) {
nfc_tag_mf1_set_use_mf1_coll_res(data[0]);
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_mf1_write_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
nfc_tag_mf1_write_mode_t write_mode = nfc_tag_mf1_get_write_mode();
if (write_mode == NFC_TAG_MF1_WRITE_NORMAL) {
status = 0;
} else if (write_mode == NFC_TAG_MF1_WRITE_DENIED) {
status = 1;
} else if (write_mode == NFC_TAG_MF1_WRITE_DECEIVE) {
status = 2;
} else if (write_mode == NFC_TAG_MF1_WRITE_SHADOW) {
status = 3;
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t*)&status);
}
data_frame_tx_t* cmd_processor_set_mf1_write_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1 && (data[0] >= 0 || data[0] <= 3)) {
uint8_t mode = data[0];
if (mode == 0) {
nfc_tag_mf1_set_write_mode(NFC_TAG_MF1_WRITE_NORMAL);
} else if (mode == 1) {
nfc_tag_mf1_set_write_mode(NFC_TAG_MF1_WRITE_DENIED);
} else if (mode == 2) {
nfc_tag_mf1_set_write_mode(NFC_TAG_MF1_WRITE_DECEIVE);
} else if (mode == 3) {
nfc_tag_mf1_set_write_mode(NFC_TAG_MF1_WRITE_SHADOW);
}
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_enabled_slots(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t slot_info[8] = {};
for (uint8_t slot = 0; slot < 8; slot++) {
slot_info[slot] = tag_emulation_slot_is_enable(slot);
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 8, slot_info);
}
#if defined(PROJECT_CHAMELEON_ULTRA)
@@ -614,16 +767,29 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_GET_ACTIVE_SLOT, NULL, cmd_processor_get_activated_slot, NULL },
{ DATA_CMD_GET_SLOT_INFO, NULL, cmd_processor_get_slot_info, NULL },
{ DATA_CMD_WIPE_FDS, NULL, cmd_processor_wipe_fds, NULL },
{ DATA_CMD_GET_ENABLED_SLOTS, NULL, cmd_processor_get_enabled_slots, NULL },
{ DATA_CMD_SET_EM410X_EMU_ID, NULL, cmd_processor_set_em410x_emu_id, NULL },
{ DATA_CMD_GET_EM410X_EMU_ID, NULL, cmd_processor_get_em410x_emu_id, NULL },
{ DATA_CMD_GET_MF1_DETECTION_STATUS, NULL, cmd_processor_get_mf1_detection_status, NULL },
{ DATA_CMD_SET_MF1_DETECTION_ENABLE, NULL, cmd_processor_set_mf1_detection_enable, NULL },
{ DATA_CMD_GET_MF1_DETECTION_COUNT, NULL, cmd_processor_get_mf1_detection_count, NULL },
{ DATA_CMD_GET_MF1_DETECTION_RESULT, NULL, cmd_processor_get_mf1_detection_log, NULL },
{ DATA_CMD_LOAD_MF1_BLOCK_DATA, NULL, cmd_processor_set_mf1_emulator_block, NULL },
{ DATA_CMD_LOAD_MF1_EMU_BLOCK_DATA, NULL, cmd_processor_set_mf1_emulator_block, NULL },
{ DATA_CMD_READ_MF1_EMU_BLOCK_DATA, NULL, cmd_processor_get_mf1_emulator_block, NULL },
{ DATA_CMD_SET_MF1_ANTI_COLLISION_RES, NULL, cmd_processor_set_mf1_anti_collision_res, NULL },
{ DATA_CMD_GET_MF1_EMULATOR_CONFIG, NULL, cmd_processor_get_mf1_info, NULL },
{ DATA_CMD_GET_MF1_GEN1A_MODE, NULL, cmd_processor_get_mf1_gen1a_magic_mode, NULL },
{ DATA_CMD_SET_MF1_GEN1A_MODE, NULL, cmd_processor_set_mf1_gen1a_magic_mode, NULL },
{ DATA_CMD_GET_MF1_GEN2_MODE, NULL, cmd_processor_get_mf1_gen2_magic_mode, NULL },
{ DATA_CMD_SET_MF1_GEN2_MODE, NULL, cmd_processor_set_mf1_gen2_magic_mode, NULL },
{ DATA_CMD_GET_MF1_USE_FIRST_BLOCK_COLL, NULL, cmd_processor_get_mf1_use_coll_res, NULL },
{ DATA_CMD_SET_MF1_USE_FIRST_BLOCK_COLL, NULL, cmd_processor_set_mf1_use_coll_res, NULL },
{ DATA_CMD_GET_MF1_WRITE_MODE, NULL, cmd_processor_get_mf1_write_mode, NULL },
{ DATA_CMD_SET_MF1_WRITE_MODE, NULL, cmd_processor_set_mf1_write_mode, NULL },
{ DATA_CMD_SET_SLOT_TAG_NICK, NULL, cmd_processor_set_slot_tag_nick_name, NULL },
{ DATA_CMD_GET_SLOT_TAG_NICK, NULL, cmd_processor_get_slot_tag_nick_name, NULL },
+19 -7
View File
@@ -28,6 +28,7 @@
#define DATA_CMD_GET_ACTIVE_SLOT (1018)
#define DATA_CMD_GET_SLOT_INFO (1019)
#define DATA_CMD_WIPE_FDS (1020)
#define DATA_CMD_GET_ENABLED_SLOTS (1023)
//
// ******************************************************************
@@ -67,8 +68,24 @@
// Range from 4000 -> 4999
// ******************************************************************
//
#define DATA_CMD_LOAD_MF1_BLOCK_DATA (4000)
#define DATA_CMD_LOAD_MF1_EMU_BLOCK_DATA (4000)
#define DATA_CMD_SET_MF1_ANTI_COLLISION_RES (4001)
#define DATA_CMD_SET_MF1_ANTICOLLISION_INFO (4002)
#define DATA_CMD_SET_MF1_ATS_RESOURCE (4003)
#define DATA_CMD_SET_MF1_DETECTION_ENABLE (4004)
#define DATA_CMD_GET_MF1_DETECTION_COUNT (4005)
#define DATA_CMD_GET_MF1_DETECTION_RESULT (4006)
#define DATA_CMD_GET_MF1_DETECTION_STATUS (4007)
#define DATA_CMD_READ_MF1_EMU_BLOCK_DATA (4008)
#define DATA_CMD_GET_MF1_EMULATOR_CONFIG (4009)
#define DATA_CMD_GET_MF1_GEN1A_MODE (4010)
#define DATA_CMD_SET_MF1_GEN1A_MODE (4011)
#define DATA_CMD_GET_MF1_GEN2_MODE (4012)
#define DATA_CMD_SET_MF1_GEN2_MODE (4013)
#define DATA_CMD_GET_MF1_USE_FIRST_BLOCK_COLL (4014)
#define DATA_CMD_SET_MF1_USE_FIRST_BLOCK_COLL (4015)
#define DATA_CMD_GET_MF1_WRITE_MODE (4016)
#define DATA_CMD_SET_MF1_WRITE_MODE (4017)
//
// ******************************************************************
@@ -82,11 +99,6 @@
//
// ******************************************************************
#define DATA_CMD_SET_EM410X_EMU_ID (5000)
#define DATA_CMD_SET_MF1_ANTICOLLISION_INFO (5001)
#define DATA_CMD_SET_MF1_ATS_RESOURCE (5002)
#define DATA_CMD_SET_MF1_DETECTION_ENABLE (5003)
#define DATA_CMD_GET_MF1_DETECTION_COUNT (5004)
#define DATA_CMD_GET_MF1_DETECTION_RESULT (5005)
#define DATA_CMD_GET_MF1_DETECTION_STATUS (5006)
#define DATA_CMD_GET_EM410X_EMU_ID (5001)
#endif
@@ -38,14 +38,14 @@ NRF_LOG_MODULE_REGISTER();
#define CMD_AUTH_A 0x60
#define CMD_AUTH_B 0x61
#define CMD_AUTH_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_AUTH_RB_FRAME_SIZE 4 /* Bytes */
#define CMD_AUTH_AB_FRAME_SIZE 8 /* Bytes */
#define CMD_AUTH_BA_FRAME_SIZE 4 /* Bytes */
#define CMD_AUTH_RB_FRAME_SIZE 4 /* Bytes */
#define CMD_AUTH_AB_FRAME_SIZE 8 /* Bytes */
#define CMD_AUTH_BA_FRAME_SIZE 4 /* Bytes */
#define CMD_HALT 0x50
#define CMD_HALT_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_HALT_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_READ 0x30
#define CMD_READ_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_READ_RESPONSE_FRAME_SIZE 16 /* Bytes without CRCA */
#define CMD_READ_RESPONSE_FRAME_SIZE 16 /* Bytes without CRCA */
#define CMD_WRITE 0xA0
#define CMD_WRITE_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_DECREMENT 0xC0
@@ -54,8 +54,6 @@ NRF_LOG_MODULE_REGISTER();
#define CMD_INCREMENT_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_RESTORE 0xC2
#define CMD_RESTORE_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_SIG_READ 0xC2
#define CMD_SIG_READ_FRAME_SIZE 1 /* Bytes without CRCA */
#define CMD_TRANSFER 0xB0
#define CMD_TRANSFER_FRAME_SIZE 2 /* Bytes without CRCA */
@@ -311,9 +309,18 @@ void ValueToBlock(uint8_t *Block, uint32_t Value) {
/** @brief mf1获取一个随机数
* @param nonce 随机数的Buffer
*/
void nfc_tag_mf1_random_nonce(uint8_t nonce[4]) {
void nfc_tag_mf1_random_nonce(uint8_t nonce[4], bool isNested) {
// 使用rand进行快速产生随机数,性能损耗较小
num_to_bytes(rand(), 4, nonce);
// isNested provides more randomness for hardnested attack
if (isNested) {
nonce[0] = rand() & 0xff;
nonce[1] = rand() & 0xff;
nonce[2] = rand() & 0xff;
nonce[3] = rand() & 0xff;
} else {
// fast for most readers
num_to_bytes(rand(), 4, nonce);
}
}
/**
@@ -494,7 +501,7 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) {
m_tag_trailer_info = (nfc_tag_mf1_trailer_info_t*)m_tag_information->memory[BlockEnd];
// 生成随机数
nfc_tag_mf1_random_nonce(CardNonce);
nfc_tag_mf1_random_nonce(CardNonce, false);
// 根据卡随机数预先计算读卡器应答
for (uint8_t i = 0; i < sizeof(ReaderResponse); i++) {
@@ -674,10 +681,10 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) {
case CMD_READ: {
// 保存当前操作的块地址
CurrentAddress = p_data[1];
// 生成访问控制,用于下面的数据访问控制
uint8_t Acc = abTrailorAccessConditions[ GetAccessCondition(CurrentAddress) ][ KeyInUse ];
// 读取命令。从内存中读取数据并附加CRCA。注意:读取操作受到控制位的限制,但是目前我们只限制控制位的读取
if ((p_data[1] < 128 && (p_data[1] & 3) == 3) || ((p_data[1] & 15) == 15)) {
// 生成访问控制,用于下面的数据访问控制
uint8_t Acc = abTrailorAccessConditions[ GetAccessCondition(CurrentAddress) ][ KeyInUse ];
if ((CurrentAddress < 128 && (CurrentAddress & 3) == 3) || ((CurrentAddress & 15) == 15)) {
// 清空一下buffer,避免缓存的数据影响到后续操作
memset(m_tag_tx_buffer.tx_raw_buffer, 0x00, sizeof(m_tag_tx_buffer.tx_raw_buffer));
// 让这块数据区域变成我们需要的尾部块类型
@@ -717,7 +724,7 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) {
}
case CMD_WRITE: {
// 正常的卡不允许写block0,不然会被CUID防火墙识别到
if (p_data[1] == 0x00) {
if (p_data[1] == 0x00 && !m_tag_information->config.mode_gen2_magic) {
// 直接重置14a的状态机,让标签休眠
nfc_tag_14a_set_state(NFC_TAG_STATE_14A_HALTED);
// 告知一下读头此操作不被允许
@@ -823,7 +830,7 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) {
m_tag_trailer_info = (nfc_tag_mf1_trailer_info_t*)m_tag_information->memory[BlockEnd];
// 生成随机数
nfc_tag_mf1_random_nonce(CardNonce);
nfc_tag_mf1_random_nonce(CardNonce, true);
// 根据卡随机数预先计算读卡器响应
for (uint8_t i = 0; i < sizeof(ReaderResponse); i++) {
@@ -1041,7 +1048,7 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) {
/**
* @brief 提供mifare标签必要的防冲突资源(仅提供指针)
*/
nfc_tag_14a_coll_res_referen_t* get_miafre_coll_res() {
nfc_tag_14a_coll_res_referen_t* get_mifare_coll_res() {
// 根据当前的互通配置,选择性的返回其中配置的数据,假设开启了数据互通,那么我们还需要确保当前模拟的卡是4BYTE的
if (m_tag_information->config.use_mf1_coll_res && m_tag_information->res_coll.size == NFC_TAG_14A_UID_SINGLE_SIZE) {
// 获得数据区域的厂商信息
@@ -1119,7 +1126,7 @@ int nfc_tag_mf1_data_loadcb(tag_specific_type_t type, tag_data_buffer_t* buffer)
m_tag_type = type;
// 注册14a通信管理接口
nfc_tag_14a_handler_t handler_for_14a = {
.get_coll_res = get_miafre_coll_res,
.get_coll_res = get_mifare_coll_res,
.cb_state = nfc_tag_mf1_state_handler,
.cb_reset = nfc_tag_mf1_reset_handler,
};
@@ -1166,6 +1173,7 @@ bool nfc_tag_mf1_data_factory(uint8_t slot, tag_specific_type_t tag_type) {
// default mf1 config
p_mf1_information->config.mode_gen1a_magic = false;
p_mf1_information->config.mode_gen2_magic = false;
p_mf1_information->config.use_mf1_coll_res = false;
p_mf1_information->config.mode_block_write = NFC_TAG_MF1_WRITE_NORMAL;
p_mf1_information->config.detection_enable = false;
@@ -1204,3 +1212,44 @@ void nfc_tag_mf1_detection_log_clear(void) {
uint32_t nfc_tag_mf1_detection_log_count(void) {
return m_auth_log.count;
}
// Set gen1a magic mode
void nfc_tag_mf1_set_gen1a_magic_mode(bool enable) {
m_tag_information->config.mode_gen1a_magic = enable;
}
// Is in gen1a magic mode?
bool nfc_tag_mf1_is_gen1a_magic_mode(void) {
return m_tag_information->config.mode_gen1a_magic;
}
// Set gen2 magic mode
void nfc_tag_mf1_set_gen2_magic_mode(bool enable) {
m_tag_information->config.mode_gen2_magic = enable;
}
// Is in gen2 magic mode?
bool nfc_tag_mf1_is_gen2_magic_mode(void) {
return m_tag_information->config.mode_gen2_magic;
}
// Set anti collision data from block 0
void nfc_tag_mf1_set_use_mf1_coll_res(bool enable) {
m_tag_information->config.use_mf1_coll_res = enable;
}
// Get is anti collision data from block 0
bool nfc_tag_mf1_is_use_mf1_coll_res(void) {
return m_tag_information->config.use_mf1_coll_res;
}
// Set write mode
void nfc_tag_mf1_set_write_mode(nfc_tag_mf1_write_mode_t write_mode) {
m_tag_information->config.mode_block_write = write_mode;
}
// Get write mode
nfc_tag_mf1_write_mode_t nfc_tag_mf1_get_write_mode(void) {
return m_tag_information->config.mode_block_write;
}
@@ -44,10 +44,10 @@ typedef enum {
// mf1配置
typedef struct {
/**
* 正常写入模式(根据当前的状态去正常写入,受控制位和后门卡影响)
* 拒绝写入模式(类似控制位锁死,直接拒绝任何写入,返回nack
* 欺诈写入模式(表面上返回ack表示写入成功,其实连RAM都不写入)
* 影子写入模式(写入到RAM里面,并且返回ack表示成功,但是不保存到flash里面)
* Normal write mode (write normally according to the current state, affected by the control bit and the back door card)
* Deny write mode (similar to control bit lock, directly reject any write, return nack)
* Fraudulent writing mode (on the surface, returning ack indicates that the writing is successful, but in fact, even RAM is not written)
* Shadow write mode (write to RAM, and return ack to indicate success, but not save to flash)
* @see nfc_tag_mf1_write_mode_t
*/
nfc_tag_mf1_write_mode_t mode_block_write;
@@ -66,8 +66,10 @@ typedef struct {
* 使能侦测,将自动记录mf1的验证日志
*/
uint8_t detection_enable: 1;
// Allow to write block 0 (CUID/gen2 mode)
uint8_t mode_gen2_magic: 1;
// 保留
uint8_t reserved1: 5;
uint8_t reserved1: 4;
uint8_t reserved2;
uint8_t reserved3;
} nfc_tag_mf1_configure_t;
@@ -140,6 +142,15 @@ void nfc_tag_mf1_set_detection_enable(bool enable);
bool nfc_tag_mf1_is_detection_enable(void);
void nfc_tag_mf1_detection_log_clear(void);
uint32_t nfc_tag_mf1_detection_log_count(void);
nfc_tag_14a_coll_res_referen_t* get_miafre_coll_res(void);
nfc_tag_14a_coll_res_referen_t* get_mifare_coll_res(void);
void nfc_tag_mf1_set_gen1a_magic_mode(bool enable);
bool nfc_tag_mf1_is_gen1a_magic_mode(void);
void nfc_tag_mf1_set_gen2_magic_mode(bool enable);
bool nfc_tag_mf1_is_gen2_magic_mode(void);
void nfc_tag_mf1_set_use_mf1_coll_res(bool enable);
bool nfc_tag_mf1_is_use_mf1_coll_res(void);
void nfc_tag_mf1_set_write_mode(nfc_tag_mf1_write_mode_t write_mode);
nfc_tag_mf1_write_mode_t nfc_tag_mf1_get_write_mode(void);
#endif
@@ -1,3 +1,3 @@
GNU_INSTALL_ROOT ?= /usr/local/gcc-arm-none-eabi-10.3-2021.10/bin/
GNU_INSTALL_ROOT ?= /usr/bin/
GNU_VERSION ?= 9.3.1
GNU_PREFIX ?= arm-none-eabi
@@ -41,6 +41,8 @@
#include <nrfx.h>
#if NRFX_CHECK(NRFX_NFCT_ENABLED)
// ChameleonUltra: workaround because NFC IRQ gets repetitively called when in HF field once a comm has started
#include "bsp_wdt.h"
#include <nrfx_nfct.h>
@@ -907,6 +909,8 @@ void nrfx_nfct_irq_handler(void)
m_nfct_cb.config.cb(&nfct_evt);
}
}
// ChameleonUltra: workaround because NFC IRQ gets repetitively called when in HF field once a comm has started
bsp_wdt_feed();
}
#endif // NRFX_CHECK(NRFX_NFCT_ENABLED)
-1
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import argparse
import os
import platform
import sys
import traceback
File diff suppressed because it is too large Load Diff
+148 -52
View File
@@ -1,4 +1,5 @@
import enum
import struct
import chameleon_com
import chameleon_status
@@ -33,6 +34,8 @@ DATA_CMD_GET_SLOT_INFO = 1019
DATA_CMD_WIPE_FDS = 1020
DATA_CMD_GET_ENABLED_SLOTS = 1023
DATA_CMD_SCAN_14A_TAG = 2000
DATA_CMD_MF1_SUPPORT_DETECT = 2001
DATA_CMD_MF1_NT_LEVEL_DETECT = 2002
@@ -47,13 +50,28 @@ DATA_CMD_MF1_WRITE_ONE_BLOCK = 2009
DATA_CMD_SCAN_EM410X_TAG = 3000
DATA_CMD_WRITE_EM410X_TO_T5577 = 3001
DATA_CMD_LOAD_MF1_BLOCK_DATA = 4000
DATA_CMD_LOAD_MF1_EMU_BLOCK_DATA = 4000
DATA_CMD_SET_MF1_ANTI_COLLISION_RES = 4001
DATA_CMD_SET_MF1_DETECTION_ENABLE = 4004
DATA_CMD_GET_MF1_DETECTION_COUNT = 4005
DATA_CMD_GET_MF1_DETECTION_RESULT = 4006
DATA_CMD_READ_MF1_EMU_BLOCK_DATA = 4008
DATA_CMD_GET_MF1_EMULATOR_CONFIG = 4009
DATA_CMD_GET_MF1_GEN1A_MODE = 4010
DATA_CMD_SET_MF1_GEN1A_MODE = 4011
DATA_CMD_GET_MF1_GEN2_MODE = 4012
DATA_CMD_SET_MF1_GEN2_MODE = 4013
DATA_CMD_GET_MF1_USE_FIRST_BLOCK_COLL = 4014
DATA_CMD_SET_MF1_USE_FIRST_BLOCK_COLL = 4015
DATA_CMD_GET_MF1_WRITE_MODE = 4016
DATA_CMD_SET_MF1_WRITE_MODE = 4017
DATA_CMD_SET_EM410X_EMU_ID = 5000
DATA_CMD_SET_MF1_DETECTION_ENABLE = 5003
DATA_CMD_GET_MF1_DETECTION_COUNT = 5004
DATA_CMD_GET_MF1_DETECTION_RESULT = 5005
DATA_CMD_GET_EM410X_EMU_ID = 5001
@enum.unique
class SlotNumber(enum.IntEnum):
@@ -67,7 +85,7 @@ class SlotNumber(enum.IntEnum):
SLOT_8 = 8,
@staticmethod
def to_fw(index: int): # can be int or SlotNumber
def to_fw(index: int): # can be int or SlotNumber
# SlotNumber() will raise error for us if index not in slot range
return SlotNumber(index).value - 1
@@ -79,13 +97,12 @@ class SlotNumber(enum.IntEnum):
@enum.unique
class TagSenseType(enum.IntEnum):
# 无场感应
TAG_SENSE_NO = 0,
# 低频125khz场感应
TAG_SENSE_LF = 1,
# 高频13.56mhz场感应
TAG_SENSE_HF = 2,
# Unknown
TAG_SENSE_NO = 0
# 125 kHz
TAG_SENSE_LF = 1
# 13.56 MHz
TAG_SENSE_HF = 2
@staticmethod
def list(exclude_unknown=True):
@@ -101,18 +118,19 @@ class TagSenseType(enum.IntEnum):
return "HF"
return "None"
@enum.unique
class TagSpecificType(enum.IntEnum):
# 特定的且必须存在的标志不存在的类型
# Empty slot
TAG_TYPE_UNKNOWN = 0
# 125khzID卡)系列
# 125 kHzIDcards
TAG_TYPE_EM410X = 1
# Mifare系列
# Mifare Classic
TAG_TYPE_MIFARE_Mini = 2
TAG_TYPE_MIFARE_1024 = 3
TAG_TYPE_MIFARE_2048 = 4
TAG_TYPE_MIFARE_4096 = 5
# NTAG系列
# NTAG
TAG_TYPE_NTAG_213 = 6
TAG_TYPE_NTAG_215 = 7
TAG_TYPE_NTAG_216 = 8
@@ -144,6 +162,33 @@ class TagSpecificType(enum.IntEnum):
return "Unknown"
@enum.unique
class MifareClassicWriteMode(enum.IntEnum):
# Normal write
NORMAL = 0
# Send NACK to write attempts
DEINED = 1
# Acknowledge writes, but don't remember contents
DECEIVE = 2
# Store data to RAM, but not to ROM
SHADOW = 3
@staticmethod
def list():
return list(map(int, MifareClassicWriteMode))
def __str__(self):
if self == MifareClassicWriteMode.NORMAL:
return "Normal"
elif self == MifareClassicWriteMode.DEINED:
return "Deined"
elif self == MifareClassicWriteMode.DECEIVE:
return "Deceive"
elif self == MifareClassicWriteMode.SHADOW:
return "Shadow"
return "None"
class ChameleonCMD:
"""
Chameleon cmd function
@@ -159,25 +204,25 @@ class ChameleonCMD:
"""
Get firmware version number(application)
"""
resp = self.device.send_cmd_sync(DATA_CMD_GET_APP_VERSION, 0x00, None)
resp = self.device.send_cmd_sync(DATA_CMD_GET_APP_VERSION, 0x00)
return int.from_bytes(resp.data, 'little')
def get_device_chip_id(self) -> str:
"""
Get device chip id
"""
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_CHIP_ID, 0x00, None)
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_CHIP_ID, 0x00)
return resp.data.hex()
def get_device_address(self) -> str:
"""
Get device address
"""
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_ADDRESS, 0x00, None)
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_ADDRESS, 0x00)
return resp.data[::-1].hex()
def get_git_version(self) -> str:
resp = self.device.send_cmd_sync(DATA_CMD_GET_GIT_VERSION, 0x00, None)
resp = self.device.send_cmd_sync(DATA_CMD_GET_GIT_VERSION, 0x00)
return resp.data.decode('utf-8')
def is_reader_device_mode(self) -> bool:
@@ -185,7 +230,7 @@ class ChameleonCMD:
Get device mode, reader or tag
:return: True is reader mode, else tag mode
"""
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_MODE, 0x00, None)
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_MODE, 0x00)
return True if resp.data[0] == 1 else False
def set_reader_device_mode(self, reader_mode: bool = True):
@@ -202,21 +247,21 @@ class ChameleonCMD:
扫描场内的14a标签
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_SCAN_14A_TAG, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_SCAN_14A_TAG, 0x00)
def detect_mf1_support(self):
"""
检测是否是mifare classic标签
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_MF1_SUPPORT_DETECT, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_MF1_SUPPORT_DETECT, 0x00)
def detect_mf1_nt_level(self):
"""
检测mifare classic的nt漏洞的等级
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_MF1_NT_LEVEL_DETECT, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_MF1_NT_LEVEL_DETECT, 0x00)
def detect_darkside_support(self):
"""
@@ -326,7 +371,7 @@ class ChameleonCMD:
读取EM410X的卡号
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00)
@expect_response(chameleon_status.Device.LF_TAG_OK)
def write_em_410x_to_t55xx(self, id_bytes: bytearray):
@@ -336,10 +381,7 @@ class ChameleonCMD:
:return:
"""
new_key = [0x20, 0x20, 0x66, 0x66]
old_keys = [
[0x51, 0x24, 0x36, 0x48],
[0x19, 0x92, 0x04, 0x27],
]
old_keys = [[0x51, 0x24, 0x36, 0x48], [0x19, 0x92, 0x04, 0x27]]
if len(id_bytes) != 5:
raise ValueError("The id bytes length must equal 5")
data = bytearray()
@@ -354,20 +396,20 @@ class ChameleonCMD:
Get slots info
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_INFO, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_INFO, 0x00)
def get_active_slot(self):
"""
Get selected slot
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_ACTIVE_SLOT, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_GET_ACTIVE_SLOT, 0x00)
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def set_slot_activated(self, slot_index: SlotNumber):
"""
设置当前激活使用的卡槽
:param slot_index: 卡槽索引 1 - 8不是从0下标开始
Set the card slot currently active for use
:param slot_index: Card slot index
:return:
"""
# SlotNumber() will raise error for us if slot_index not in slot range
@@ -420,7 +462,7 @@ class ChameleonCMD:
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data)
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def set_em140x_sim_id(self, id_bytes: bytearray):
def set_em410x_sim_id(self, id_bytes: bytearray):
"""
设置EM410x模拟的卡号
:param id_bytes: 卡号的字节
@@ -429,6 +471,12 @@ class ChameleonCMD:
if len(id_bytes) != 5:
raise ValueError("The id bytes length must equal 5")
return self.device.send_cmd_sync(DATA_CMD_SET_EM410X_EMU_ID, 0x00, id_bytes)
def get_em410x_sim_id(self):
"""
Get the simulated EM410x card id
"""
return self.device.send_cmd_sync(DATA_CMD_GET_EM410X_EMU_ID, 0x00)
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def set_mf1_detection_enable(self, enable: bool):
@@ -446,7 +494,7 @@ class ChameleonCMD:
获取当前侦测记录的统计个数
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00)
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def get_mf1_detection_log(self, index: int):
@@ -470,7 +518,14 @@ class ChameleonCMD:
data = bytearray()
data.append(block_start & 0xFF)
data.extend(block_data)
return self.device.send_cmd_sync(DATA_CMD_LOAD_MF1_BLOCK_DATA, 0x00, data)
return self.device.send_cmd_sync(DATA_CMD_LOAD_MF1_EMU_BLOCK_DATA, 0x00, data)
def get_mf1_block_data(self, block_start: int, block_count: int):
"""
Gets data for selected block range
"""
data = struct.pack('<BH', block_start, block_count)
return self.device.send_cmd_sync(DATA_CMD_READ_MF1_EMU_BLOCK_DATA, 0x00, data)
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray):
@@ -508,20 +563,55 @@ class ChameleonCMD:
设置MF1的模拟卡的防冲撞资源信息
:param slot: 卡槽号码
:param sense_type: 场类型
:param name: 卡槽昵称
:return:
"""
# SlotNumber() will raise error for us if slot not in slot range
data = bytearray()
data.extend([SlotNumber.to_fw(slot), sense_type])
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data)
def get_mf1_emulator_settings(self):
"""
Get array of Mifare Classic emulators settings:
[0] - mf1_is_detection_enable (mfkey32)
[1] - mf1_is_gen1a_magic_mode
[2] - mf1_is_gen2_magic_mode
[3] - mf1_is_use_mf1_coll_res (use UID/BCC/SAK/ATQA from 0 block)
[4] - mf1_get_write_mode
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_EMULATOR_CONFIG, 0x00)
def set_mf1_gen1a_mode(self, enabled: bool):
"""
Set gen1a magic mode
"""
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_GEN1A_MODE, 0x00, bytearray([1 if enabled else 0]))
def set_mf1_gen2_mode(self, enabled: bool):
"""
Set gen2 magic mode
"""
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_GEN2_MODE, 0x00, bytearray([1 if enabled else 0]))
def set_mf1_block_anti_coll_mode(self, enabled: bool):
"""
Set 0 block anti-collision data
"""
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0x00, bytearray([1 if enabled else 0]))
def set_mf1_write_mode(self, mode: int):
"""
Set write mode
"""
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_WRITE_MODE, 0x00, bytearray([mode]))
def update_slot_data_config(self):
"""
更新卡槽的配置和数据到flash中
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_SLOT_DATA_CONFIG_SAVE, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_SLOT_DATA_CONFIG_SAVE, 0x00)
def enter_dfu_mode(self):
"""
@@ -529,19 +619,25 @@ class ChameleonCMD:
:return:
"""
return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True)
def get_settings_animation(self):
"""
Get animation mode value
"""
return self.device.send_cmd_sync(DATA_CMD_GET_ANIMATION_MODE, 0x00, None)
return self.device.send_cmd_sync(DATA_CMD_GET_ANIMATION_MODE, 0x00)
def get_enabled_slots(self):
"""
Get animation mode value
"""
return self.device.send_cmd_sync(DATA_CMD_GET_ENABLED_SLOTS, 0x00)
def set_settings_animation(self, value: int):
"""
Set animation mode value
"""
return self.device.send_cmd_sync(DATA_CMD_SET_ANIMATION_MODE, 0x00, bytearray([value]))
def reset_settings(self):
"""
Reset settings stored in flash memory
@@ -553,7 +649,7 @@ class ChameleonCMD:
Store settings to flash memory
"""
return self.device.send_cmd_sync(DATA_CMD_SAVE_SETTINGS, 0x00)
def factory_reset(self):
"""
Reset to factory settings
@@ -568,12 +664,12 @@ if __name__ == '__main__':
cml = ChameleonCMD(dev)
ver = cml.get_firmware_version()
print(f"Firmware number of application: {ver}")
id = cml.get_device_chip_id()
print(f"Device chip id: {id}")
chip = cml.get_device_chip_id()
print(f"Device chip id: {chip}")
# disconnect
dev.close()
# nerver exit
while True: pass
# never exit
while True:
pass
+14 -27
View File
@@ -40,8 +40,6 @@ class ChameleonCom:
Chameleon device base class
Communication and Data frame implemented
"""
baudrate = 115200
data_frame_sof = 0x11
data_max_length = 512
@@ -49,7 +47,7 @@ class ChameleonCom:
"""
Create a chameleon device instance
"""
self.serial_instance: serial.Serial = None
self.serial_instance: serial.Serial | None = None
self.send_data_queue = queue.Queue()
self.wait_response_map = {}
self.event_closing = threading.Event()
@@ -72,7 +70,7 @@ class ChameleonCom:
error = None
try:
# open serial port
self.serial_instance = serial.Serial(port=port, baudrate=self.baudrate)
self.serial_instance = serial.Serial(port=port, baudrate=115200)
except Exception as e:
error = e
finally:
@@ -80,7 +78,7 @@ class ChameleonCom:
raise OpenFailException(error)
try:
self.serial_instance.dtr = 1 # must make dtr enable
except Exception as e:
except:
# not all serial support dtr, e.g. virtual serial over BLE
pass
self.serial_instance.timeout = 0 # noblock
@@ -89,9 +87,9 @@ class ChameleonCom:
self.wait_response_map.clear()
# Start a sub thread to process data
self.event_closing.clear()
threading.Thread(target=self.thread_data_receive, ).start()
threading.Thread(target=self.thread_data_transfer, ).start()
threading.Thread(target=self.thread_check_timeout, ).start()
threading.Thread(target=self.thread_data_receive).start()
threading.Thread(target=self.thread_data_transfer).start()
threading.Thread(target=self.thread_check_timeout).start()
return self
def check_open(self):
@@ -200,11 +198,8 @@ class ChameleonCom:
del self.wait_response_map[data_cmd]
fn_call(data_cmd, data_status, data_response)
else:
self.wait_response_map[data_cmd]['response'] = Response(
data_cmd,
data_status,
data_response
)
self.wait_response_map[data_cmd]['response'] = Response(data_cmd, data_status,
data_response)
else:
print(f"No task wait process: ${data_cmd}")
else:
@@ -232,13 +227,9 @@ class ChameleonCom:
task_close = task['close']
# register to wait map
if 'callback' in task and callable(task['callback']):
self.wait_response_map[task_cmd] = {
'callback': task['callback'] # The callback for this task
}
self.wait_response_map[task_cmd] = {'callback': task['callback']} # The callback for this task
else:
self.wait_response_map[task_cmd] = {
'response': None,
}
self.wait_response_map[task_cmd] = {'response': None}
# set start time
start_time = time.time()
self.wait_response_map[task_cmd]['start_time'] = start_time
@@ -279,7 +270,6 @@ class ChameleonCom:
:return: frame
"""
frame = bytearray()
lrc = 0x00
# sof and sof lrc byte
frame.append(self.data_frame_sof)
frame.append(self.lrc_calc(frame[0:1]))
@@ -295,7 +285,8 @@ class ChameleonCom:
frame.append(self.lrc_calc(frame))
return frame
def send_cmd_auto(self, cmd: int, status: int, data: bytearray = None, callback=None, timeout: int = 3, close: bool = False):
def send_cmd_auto(self, cmd: int, status: int, data: bytearray = None, callback=None, timeout: int = 3,
close: bool = False):
"""
Send cmd to device
:param timeout: wait response timeout
@@ -303,6 +294,7 @@ class ChameleonCom:
:param status: status(optional)
:param callback: call on response
:param data: bytes data
:param close: close connection after executing
:return:
"""
self.check_open()
@@ -311,12 +303,7 @@ class ChameleonCom:
del self.wait_response_map[cmd]
# make data frame
data_frame = self.make_data_frame_bytes(cmd, status, data)
task = {
'cmd': cmd,
'frame': data_frame,
'timeout': timeout,
'close': close,
}
task = {'cmd': cmd, 'frame': data_frame, 'timeout': timeout, 'close': close}
if callable(callback):
task['callback'] = callback
self.send_data_queue.put(task)
+7 -26
View File
@@ -22,7 +22,7 @@ def parse_14a_scan_tag_result(data: bytearray):
'uid_size': data[10],
'uid_hex': data[0:data[10]].hex(),
'sak_hex': hex(data[12]).lstrip('0x').rjust(2, '0'),
'atqa_hex': data[13:15].hex().upper(),
'atqa_hex': data[13:15].hex().upper()
}
@@ -49,7 +49,7 @@ def parse_nested_nt_acquire_group(data: bytearray):
group.append({
'nt': bytes_to_u32(data[i: i + 4]),
'nt_enc': bytes_to_u32(data[i + 4: i + 8]),
'par': data[i + 8],
'par': data[i + 8]
})
i += 9
return group
@@ -62,32 +62,15 @@ def parse_darkside_acquire_result(data: bytearray):
:return:
"""
return {
'uid': bytes_to_u32(data[0 : 4]),
'nt1': bytes_to_u32(data[4 : 8]),
'par': bytes_to_u32(data[8 : 16]),
'uid': bytes_to_u32(data[0: 4]),
'nt1': bytes_to_u32(data[4: 8]),
'par': bytes_to_u32(data[8: 16]),
'ks1': bytes_to_u32(data[16: 24]),
'nr': bytes_to_u32(data[24: 28]),
'ar': bytes_to_u32(data[28: 32]),
'ar': bytes_to_u32(data[28: 32])
}
"""
// 验证的基础信息
struct {
uint8_t block;
uint8_t is_keyb: 1;
uint8_t is_nested: 1;
// 空域占位置用的
uint8_t : 6;
} cmd;
// mfkey32必要参数
uint8_t uid[4];
uint8_t nt[4];
uint8_t nr[4];
uint8_t ar[4];
"""
def parse_mf1_detection_result(data: bytearray):
"""
From bytes parse detection param
@@ -105,7 +88,7 @@ def parse_mf1_detection_result(data: bytearray):
'uid': data[2 + pos: 6 + pos].hex(),
'nt': data[6 + pos: 10 + pos].hex(),
'nr': data[10 + pos: 14 + pos].hex(),
'ar': data[14 + pos: 18 + pos].hex(),
'ar': data[14 + pos: 18 + pos].hex()
})
pos += 18
@@ -127,5 +110,3 @@ def parse_mf1_detection_result(data: bytearray):
result_map[uid][block][type_chr].append(item)
return result_map
+48 -51
View File
@@ -1,6 +1,4 @@
class MetaDevice(type):
def __iter__(self):
for attr in dir(self):
if not attr.startswith("__"):
@@ -16,60 +14,59 @@ class MetaDevice(type):
class Device(metaclass=MetaDevice):
HF_TAG_OK = 0x00 # IC卡操作成功
HF_TAG_NO = 0x01 # 没有发现IC卡
HF_ERRSTAT = 0x02 # IC卡通信异常
HF_ERRCRC = 0x03 # IC卡通信校验异常
HF_COLLISION = 0x04 # IC卡冲突
HF_ERRBCC = 0x05 # IC卡BCC错误
MF_ERRAUTH = 0x06 # MF卡验证失败
HF_ERRPARITY = 0x07 # IC卡奇偶校验错误
HF_TAG_OK = 0x00 # IC卡操作成功
HF_TAG_NO = 0x01 # 没有发现IC卡
HF_ERRSTAT = 0x02 # IC卡通信异常
HF_ERRCRC = 0x03 # IC卡通信校验异常
HF_COLLISION = 0x04 # IC卡冲突
HF_ERRBCC = 0x05 # IC卡BCC错误
MF_ERRAUTH = 0x06 # MF卡验证失败
HF_ERRPARITY = 0x07 # IC卡奇偶校验错误
#
DARKSIDE_CANT_FIXED_NT = 0x20 # Darkside,无法固定随机数,这个情况可能出现在UID卡上
DARKSIDE_LUCK_AUTH_OK = 0x21 # Darkside,直接验证成功了,可能刚好密钥是空的
DARKSIDE_NACK_NO_SNED = 0x22 # Darkside,卡片不响应nack,可能是一张修复了nack逻辑漏洞的卡片
DARKSIDE_TAG_CHANGED = 0x23 # Darkside,在运行darkside的过程中出现了卡片切换,可能信号问题,或者真的是两张卡迅速切换了
NESTED_TAG_IS_STATIC = 0x24 # Nested,检测到卡片应答的随机数是固定的
NESTED_TAG_IS_HARD = 0x25 # Nested,检测到卡片应答的随机数是不可预测的
#
LF_TAG_OK = 0x40 # 低频卡的一些操作成功!
EM410X_TAG_NO_FOUND = 0x41 # 无法搜索到有效的EM410X标签
#
STATUS_PAR_ERR = 0x60 # BLE指令传递的参数错误,或者是调用某些函数传递的参数错误
STATUS_DEVIEC_MODE_ERROR = 0x66 # 当前设备所处的模式错误,无法调用对应的API
STATUS_INVALID_CMD = 0x67 # 无效的指令
STATUS_DEVICE_SUCCESS = 0x68 # 设备相关操作成功执行
STATUS_NOT_IMPLEMENTED = 0x69 # 调用了某些未实现的操作,属于开发者遗漏的错误
STATUS_FLASH_WRITE_FAIL = 0x70 # flash写入失败
STATUS_FLASH_READ_FAIL = 0x71 # flash读取失败
DARKSIDE_CANT_FIXED_NT = 0x20 # Darkside,无法固定随机数,这个情况可能出现在UID卡上
DARKSIDE_LUCK_AUTH_OK = 0x21 # Darkside,直接验证成功了,可能刚好密钥是空的
DARKSIDE_NACK_NO_SEND = 0x22 # Darkside,卡片不响应nack,可能是一张修复了nack逻辑漏洞的卡片
DARKSIDE_TAG_CHANGED = 0x23 # Darkside,在运行darkside的过程中出现了卡片切换,可能信号问题,或者真的是两张卡迅速切换了
NESTED_TAG_IS_STATIC = 0x24 # Nested,检测到卡片应答的随机数是固定的
NESTED_TAG_IS_HARD = 0x25 # Nested,检测到卡片应答的随机数是不可预测的
LF_TAG_OK = 0x40 # 低频卡的一些操作成功!
EM410X_TAG_NO_FOUND = 0x41 # 无法搜索到有效的EM410X标签
STATUS_PAR_ERR = 0x60 # BLE指令传递的参数错误,或者是调用某些函数传递的参数错误
STATUS_DEVICE_MODE_ERROR = 0x66 # 当前设备所处的模式错误,无法调用对应的API
STATUS_INVALID_CMD = 0x67 # 无效的指令
STATUS_DEVICE_SUCCESS = 0x68 # 设备相关操作成功执行
STATUS_NOT_IMPLEMENTED = 0x69 # 调用了某些未实现的操作,属于开发者遗漏的错误
STATUS_FLASH_WRITE_FAIL = 0x70 # flash写入失败
STATUS_FLASH_READ_FAIL = 0x71 # flash读取失败
message = {
Device.HF_TAG_OK : "HF tag operation succeeded",
Device.HF_TAG_NO : "HF tag no found or lost",
Device.HF_ERRSTAT : "HF tag status error",
Device.HF_ERRCRC : "HF tag data crc error",
Device.HF_COLLISION : "HF tag collision",
Device.HF_ERRBCC : "HF tag uid bcc error",
Device.MF_ERRAUTH : "HF tag auth fail",
Device.HF_ERRPARITY : "HF tag data parity error",
Device.HF_TAG_OK: "HF tag operation succeeded",
Device.HF_TAG_NO: "HF tag no found or lost",
Device.HF_ERRSTAT: "HF tag status error",
Device.HF_ERRCRC: "HF tag data crc error",
Device.HF_COLLISION: "HF tag collision",
Device.HF_ERRBCC: "HF tag uid bcc error",
Device.MF_ERRAUTH: "HF tag auth fail",
Device.HF_ERRPARITY: "HF tag data parity error",
Device.DARKSIDE_CANT_FIXED_NT : "Darkside Can't select a nt(PRNG is unpredictable)",
Device.DARKSIDE_LUCK_AUTH_OK : "Darkside try to recover a default key",
Device.DARKSIDE_NACK_NO_SNED : "Darkside can't make tag response nack(enc)",
Device.DARKSIDE_TAG_CHANGED : "Darkside running, can't change tag",
Device.NESTED_TAG_IS_STATIC : "StaticNested tag, not weak nested",
Device.NESTED_TAG_IS_HARD : "HardNested tag, not weak nested",
Device.DARKSIDE_CANT_FIXED_NT: "Darkside Can't select a nt(PRNG is unpredictable)",
Device.DARKSIDE_LUCK_AUTH_OK: "Darkside try to recover a default key",
Device.DARKSIDE_NACK_NO_SEND: "Darkside can't make tag response nack(enc)",
Device.DARKSIDE_TAG_CHANGED: "Darkside running, can't change tag",
Device.NESTED_TAG_IS_STATIC: "StaticNested tag, not weak nested",
Device.NESTED_TAG_IS_HARD: "HardNested tag, not weak nested",
Device.LF_TAG_OK : "LF tag operation succeeded",
Device.EM410X_TAG_NO_FOUND : "EM410x tag no found",
Device.LF_TAG_OK: "LF tag operation succeeded",
Device.EM410X_TAG_NO_FOUND: "EM410x tag no found",
Device.STATUS_PAR_ERR : "API request fail, param error",
Device.STATUS_DEVIEC_MODE_ERROR : "API request fail, device mode error",
Device.STATUS_INVALID_CMD : "API request fail, cmd invalid",
Device.STATUS_DEVICE_SUCCESS : "Device operation succeeded",
Device.STATUS_NOT_IMPLEMENTED : "Some api not implemented",
Device.STATUS_FLASH_WRITE_FAIL : "Flash write failed",
Device.STATUS_FLASH_READ_FAIL : "Flash read failed"
Device.STATUS_PAR_ERR: "API request fail, param error",
Device.STATUS_DEVICE_MODE_ERROR: "API request fail, device mode error",
Device.STATUS_INVALID_CMD: "API request fail, cmd invalid",
Device.STATUS_DEVICE_SUCCESS: "Device operation succeeded",
Device.STATUS_NOT_IMPLEMENTED: "Some api not implemented",
Device.STATUS_FLASH_WRITE_FAIL: "Flash write failed",
Device.STATUS_FLASH_READ_FAIL: "Flash read failed"
}