mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
Merge branch 'main' into hw-slot-info
This commit is contained in:
@@ -76,7 +76,8 @@ jobs:
|
||||
name: ${{ matrix.device_type }}-dfu-full
|
||||
path: firmware/objects/dfu-full/*
|
||||
create_release:
|
||||
permissions: write-all
|
||||
permissions:
|
||||
contents: write
|
||||
name: Create Pre-Release with dfu app images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
@@ -85,52 +86,34 @@ jobs:
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.run_number }}
|
||||
release_name: Compiled commit ${{ github.sha }}
|
||||
body: |
|
||||
Auto-Generated DFU images
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Download Ultra DFU
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ultra-dfu-app
|
||||
path: dfu-app-artifacts
|
||||
- name: Compress
|
||||
path: ultra-dfu-app
|
||||
- name: Compress Ultra DFU package
|
||||
run: |
|
||||
zip --junk-paths -0 -r ./dfu-app-artifacts/dfu-app.zip ./dfu-app-artifacts/*
|
||||
- name: Upload Ultra DFU
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./dfu-app-artifacts/dfu-app.zip
|
||||
asset_name: ultra-dfu-app.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Clear
|
||||
run: |
|
||||
rm -rf ./dfu-app-artifacts/
|
||||
zip --junk-paths -0 -r ./ultra-dfu-app.zip ./ultra-dfu-app/*
|
||||
- name: Download Lite DFU
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: lite-dfu-app
|
||||
path: dfu-app-artifacts
|
||||
- name: Compress
|
||||
path: lite-dfu-app
|
||||
- name: Compress Lite DFU package
|
||||
run: |
|
||||
zip --junk-paths -0 -r ./dfu-app-artifacts/dfu-app.zip ./dfu-app-artifacts/*
|
||||
- name: Upload Lite DFU
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
zip --junk-paths -0 -r ./lite-dfu-app.zip ./lite-dfu-app/*
|
||||
- name: Upload to dev release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./dfu-app-artifacts/dfu-app.zip
|
||||
asset_name: lite-dfu-app.zip
|
||||
asset_content_type: application/zip
|
||||
body: |
|
||||
Auto-Generated DFU packages from latest `main` commit.
|
||||
For development purposes only.
|
||||
These are not tested, here be dragons.
|
||||
Built from commit ${{ github.sha }}
|
||||
tag_name: dev
|
||||
name: Development release
|
||||
draft: false
|
||||
prerelease: true
|
||||
target_commitish: main
|
||||
generate_release_notes: true
|
||||
files: ./*-dfu-app.zip
|
||||
|
||||
@@ -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)
|
||||
@@ -737,12 +772,14 @@ static cmd_data_map_t m_data_cmd_map[] = {
|
||||
|
||||
|
||||
{ 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 },
|
||||
|
||||
@@ -68,9 +68,15 @@
|
||||
// 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)
|
||||
@@ -80,7 +86,6 @@
|
||||
#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)
|
||||
|
||||
//
|
||||
// ******************************************************************
|
||||
|
||||
@@ -94,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -116,6 +116,7 @@ class ChameleonCLI:
|
||||
'settings': new_uint(chameleon_cli_unit.HFMFSettings, "Settings of Mifare Classic emulator"),
|
||||
'sim': new_uint(chameleon_cli_unit.HFMFSim, "Simulate a Mifare Classic card"),
|
||||
'eload': new_uint(chameleon_cli_unit.HFMFELoad, "Load data to emulator memory"),
|
||||
'eread': new_uint(chameleon_cli_unit.HFMFERead, "Read data from emulator memory"),
|
||||
'help': "Mifare Classic mini/1/2/4, attack/read/write"
|
||||
},
|
||||
'help': "high frequency tag/reader",
|
||||
@@ -124,7 +125,11 @@ class ChameleonCLI:
|
||||
'em': {
|
||||
'read': new_uint(chameleon_cli_unit.LFEMRead, "Scan em410x tag and print id"),
|
||||
'write': new_uint(chameleon_cli_unit.LFEMWriteT55xx, "Write em410x id to t55xx"),
|
||||
'sim': new_uint(chameleon_cli_unit.LFEMSim, "Simulation a em410x id card"),
|
||||
'sim': {
|
||||
'set': new_uint(chameleon_cli_unit.LFEMSimSet, "Set simulated em410x card id"),
|
||||
'get': new_uint(chameleon_cli_unit.LFEMSimGet, "Get simulated em410x card id"),
|
||||
'help': "Manage EM410x emulation data for selected slot"
|
||||
},
|
||||
'help': "EM410x read/write/emulator",
|
||||
},
|
||||
'help': "low frequency tag/reader",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import binascii
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
@@ -681,6 +682,55 @@ class HFMFELoad(DeviceRequiredUnit):
|
||||
block += 1
|
||||
print("\n - Load success")
|
||||
|
||||
class HFMFERead(DeviceRequiredUnit):
|
||||
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
parser = ArgumentParserNoExit()
|
||||
parser.add_argument('-f', '--file', type=str, required=True, help="file path")
|
||||
parser.add_argument('-t', '--type', type=str, required=False, help="content type", choices=['bin', 'hex'])
|
||||
return parser
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
file = args.file
|
||||
if args.type is None:
|
||||
if file.endswith('.bin'):
|
||||
content_type = 'bin'
|
||||
elif file.endswith('.eml'):
|
||||
content_type = 'hex'
|
||||
else:
|
||||
raise Exception("Unknown file format, Specify content type with -t option")
|
||||
else:
|
||||
content_type = args.type
|
||||
|
||||
selected_slot = self.cmd_positive.get_active_slot().data[0]
|
||||
slot_info = self.cmd_positive.get_slot_info().data
|
||||
tag_type = chameleon_cmd.TagSpecificType(slot_info[selected_slot * 2])
|
||||
if tag_type == chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_Mini:
|
||||
block_count = 20
|
||||
elif tag_type == chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_1024:
|
||||
block_count = 64
|
||||
elif tag_type == chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_2048:
|
||||
block_count = 128
|
||||
elif tag_type == chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_4096:
|
||||
block_count = 256
|
||||
else:
|
||||
raise Exception("Card in current slot is not Mifare Classic/Plus in SL1 mode")
|
||||
|
||||
with open(file, 'wb') as fd:
|
||||
block = 0
|
||||
while block < block_count:
|
||||
response = self.cmd_positive.get_mf1_block_data(block, 1)
|
||||
print('.', end='')
|
||||
block += 1
|
||||
if content_type == 'hex':
|
||||
hex_char_repr = binascii.hexlify(response.data)
|
||||
fd.write(hex_char_repr)
|
||||
fd.write(bytes([0x0a]))
|
||||
else:
|
||||
fd.write(response.data)
|
||||
|
||||
print("\n - Read success")
|
||||
|
||||
|
||||
class HFMFSettings(DeviceRequiredUnit):
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
@@ -965,18 +1015,29 @@ class HWSlotEnableSet(SlotIndexRequireUint):
|
||||
print(f' - Set slot {slot_num} {"enable" if enable else "disable"} success.')
|
||||
|
||||
|
||||
class LFEMSim(LFEMCardRequiredUint):
|
||||
class LFEMSimSet(LFEMCardRequiredUint):
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
parser = ArgumentParserNoExit()
|
||||
return self.add_card_arg(parser)
|
||||
|
||||
# lf em sim --id 4545454545
|
||||
# lf em sim set --id 4545454545
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
id_hex = args.id
|
||||
id_bytes = bytearray.fromhex(id_hex)
|
||||
self.cmd_positive.set_em140x_sim_id(id_bytes)
|
||||
self.cmd_positive.set_em410x_sim_id(id_bytes)
|
||||
print(f' - Set em410x tag id success.')
|
||||
|
||||
class LFEMSimGet(DeviceRequiredUnit):
|
||||
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
return None
|
||||
|
||||
# lf em sim get
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
response = self.cmd_positive.get_em410x_sim_id()
|
||||
print(f' - Get em410x tag id success.')
|
||||
print(f'ID: {response.data.hex()}')
|
||||
|
||||
|
||||
class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint):
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import enum
|
||||
import struct
|
||||
|
||||
import chameleon_com
|
||||
import chameleon_status
|
||||
@@ -48,9 +49,15 @@ 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
|
||||
@@ -62,9 +69,7 @@ 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
|
||||
@@ -439,7 +444,7 @@ class BaseChameleonCMD:
|
||||
data.append(0x01 if enable else 0x00)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data)
|
||||
|
||||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||||
def set_em410x_sim_id(self, id_bytes: bytearray):
|
||||
"""
|
||||
设置EM410x模拟的卡号
|
||||
:param id_bytes: 卡号的字节
|
||||
@@ -448,6 +453,12 @@ class BaseChameleonCMD:
|
||||
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)
|
||||
|
||||
def set_mf1_detection_enable(self, enable: bool):
|
||||
"""
|
||||
@@ -486,7 +497,14 @@ class BaseChameleonCMD:
|
||||
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)
|
||||
|
||||
def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray):
|
||||
"""
|
||||
@@ -710,8 +728,8 @@ class PositiveChameleonCMD(BaseChameleonCMD):
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).set_em140x_sim_id(id_bytes)
|
||||
def set_em410x_sim_id(self, id_bytes: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).set_em410x_sim_id(id_bytes)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
|
||||
Reference in New Issue
Block a user