Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/wip_protocol_refresh' into wip_p…
Browse files Browse the repository at this point in the history
…rotocol_refresh
  • Loading branch information
xianglin1998 committed Sep 20, 2023
2 parents ad3241a + 14bffaf commit d31d1af
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 215 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ 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]
- Removed MF1_DETECT_DARKSIDE (@doegox)
- Added MF1_STATIC_NESTED_ACQUIRE and its support in `hf mf nested` (@xianglin1998)
- Changed `hf 14a scan`: Automatically send RATS to 14443-4a tags (@augustozanellato)
- Changed Darkside: use LEDs for visual feedback of attack progression (@doegox)
- Changed Darkside: longer RF field off for reset and longer CLI timeout (@doegox)
Expand Down
14 changes: 7 additions & 7 deletions docs/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,19 @@ Notes:
* Command: no data
* Response: 1 byte, according to `mf1_nested_type_t` enum
* CLI: cf `hf 14a info`
### 2003: MF1_DETECT_DARKSIDE
* Command: no data
* Response: 1 byte, according to `mf1_darkside_status_t` enum
* CLI: unused
### 2003: MF1_STATIC_NESTED_ACQUIRE
* Command: 10 bytes: `type_known|block_known|key_known[6]|type_target|block_target`. Key as 6 bytes.
* Response: 4+N*8 bytes: `uid[4]` followed by N tuples of `nt[4]|nt_enc[4]`. All values as U32.
* CLI: cf `hf mf nested` on static nonce tag
### 2004: MF1_DARKSIDE_ACQUIRE
* Command: 4 bytes: `type_target|block_target|first_recover|sync_max`
* Response: 1 byte if Darkside failed, according to `mf1_darkside_status_t` enum,
else 25 bytes `darkside_status|uid[4]|nt1[4]|par[4]|ks1[4]|nr[4]|ar[4]`
else 33 bytes `darkside_status|uid[4]|nt1[4]|par[8]|ks1[8]|nr[4]|ar[4]`
* `darkside_status`
* `uid[4]` U32 (format expected by `darkside` tool)
* `nt1[4]` U32
* `par[4]` U32
* `ks1[4]` U32
* `par[8]` U64
* `ks1[8]` U64
* `nr[4]` U32
* `ar[4]` U32
* CLI: cf `hf mf darkside`
Expand Down
13 changes: 1 addition & 12 deletions firmware/application/src/app_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,6 @@ static data_frame_tx_t *cmd_processor_mf1_detect_prng(uint16_t cmd, uint16_t sta
return data_frame_make(cmd, HF_TAG_OK, sizeof(type), &type);
}

static data_frame_tx_t *cmd_processor_mf1_detect_darkside(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t darkside_status;
status = check_darkside_support((mf1_darkside_status_t *)&darkside_status);
if (status != HF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}
return data_frame_make(cmd, HF_TAG_OK, sizeof(darkside_status), &darkside_status);
}

static data_frame_tx_t *cmd_processor_mf1_darkside_acquire(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length != 4) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
Expand Down Expand Up @@ -938,16 +929,14 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_HF14A_SCAN, before_hf_reader_run, cmd_processor_hf14a_scan, after_hf_reader_run },
{ DATA_CMD_MF1_DETECT_SUPPORT, before_hf_reader_run, cmd_processor_mf1_detect_support, after_hf_reader_run },
{ DATA_CMD_MF1_DETECT_PRNG, before_hf_reader_run, cmd_processor_mf1_detect_prng, after_hf_reader_run },
{ DATA_CMD_MF1_DETECT_DARKSIDE, before_hf_reader_run, cmd_processor_mf1_detect_darkside, after_hf_reader_run },

{ DATA_CMD_MF1_STATIC_NESTED_ACQUIRE, before_hf_reader_run, cmd_processor_mf1_static_nested_acquire, after_hf_reader_run },
{ DATA_CMD_MF1_DARKSIDE_ACQUIRE, before_hf_reader_run, cmd_processor_mf1_darkside_acquire, after_hf_reader_run },
{ DATA_CMD_MF1_DETECT_NT_DIST, before_hf_reader_run, cmd_processor_mf1_detect_nt_dist, after_hf_reader_run },
{ DATA_CMD_MF1_NESTED_ACQUIRE, before_hf_reader_run, cmd_processor_mf1_nested_acquire, after_hf_reader_run },

{ DATA_CMD_MF1_AUTH_ONE_KEY_BLOCK, before_hf_reader_run, cmd_processor_mf1_auth_one_key_block, after_hf_reader_run },
{ 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_MF1_STATIC_NESTED_ACQUIRE, before_hf_reader_run, cmd_processor_mf1_static_nested_acquire, 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
3 changes: 1 addition & 2 deletions firmware/application/src/data_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,13 @@
#define DATA_CMD_HF14A_SCAN (2000)
#define DATA_CMD_MF1_DETECT_SUPPORT (2001)
#define DATA_CMD_MF1_DETECT_PRNG (2002)
#define DATA_CMD_MF1_DETECT_DARKSIDE (2003)
#define DATA_CMD_MF1_STATIC_NESTED_ACQUIRE (2003)
#define DATA_CMD_MF1_DARKSIDE_ACQUIRE (2004)
#define DATA_CMD_MF1_DETECT_NT_DIST (2005)
#define DATA_CMD_MF1_NESTED_ACQUIRE (2006)
#define DATA_CMD_MF1_AUTH_ONE_KEY_BLOCK (2007)
#define DATA_CMD_MF1_READ_ONE_BLOCK (2008)
#define DATA_CMD_MF1_WRITE_ONE_BLOCK (2009)
#define DATA_CMD_MF1_STATIC_NESTED_ACQUIRE (2010)
//
// ******************************************************************

Expand Down
146 changes: 66 additions & 80 deletions firmware/application/src/rfid/reader/hf/mf1_toolbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ static uint8_t darkside_select_nonces(picc_14a_tag_t *tag, uint8_t block, uint8_
//Random number collection
for (i = 0; i < NT_COUNT; i++) {
bsp_wdt_feed();
while(NRF_LOG_PROCESS());
while (NRF_LOG_PROCESS());
//When the antenna is reset, we must make sure
// 1. The antenna is powered off for a long time to ensure that the card is completely powered off, otherwise the pseudo -random number generator of the card cannot be reset
// 2. Moderate power -off time, don't be too long, it will affect efficiency, and don't be too short.
Expand Down Expand Up @@ -419,7 +419,7 @@ uint8_t darkside_recover_key(uint8_t targetBlk, uint8_t targetTyp,
// Always collect different NACK under a large cycle
do {
bsp_wdt_feed();
while(NRF_LOG_PROCESS());
while (NRF_LOG_PROCESS());
// update LEDs
led_toggle ^= 1;
if (led_toggle) {
Expand Down Expand Up @@ -492,7 +492,7 @@ uint8_t darkside_recover_key(uint8_t targetBlk, uint8_t targetTyp,
resync_count = 0;

if (len == 4) {
NRF_LOG_INFO("NACK acquired (%i/8)", nt_diff+1);
NRF_LOG_INFO("NACK acquired (%i/8)", nt_diff + 1);
received_nack = 1;
} else if (len == 32) {
// did we get lucky and got our dummy key to be valid?
Expand Down Expand Up @@ -569,20 +569,6 @@ void antenna_switch_delay(uint32_t delay_ms) {
g_ant_reset_delay = delay_ms;
}

/**
* @brief :Determine whether this card supports DARKSIDE attack
* @retval : If support, return hf_tag_ok and darkside_status = OK. If it is not supported,
* Return to the results of abnormal results during the detection process in darkside_status
* Or other card -related communication errors, the most common is loss card HF_TAG_NO
*
*/
uint8_t check_darkside_support(mf1_darkside_status_t *darkside_status) {
// Instantiated parameter
DarksideCore_t dc;
//Determine and return the result directly
return darkside_recover_key(0x03, PICC_AUTHENT1A, true, 0x15, &dc, darkside_status);
}

/**
* @brief : Determine whether this card supports M1 verification steps
* @retval : If support, it will return hf_tag_ok,
Expand Down Expand Up @@ -942,80 +928,80 @@ uint8_t nested_distance_detect(uint8_t block, uint8_t type, uint8_t *key, uint8_
}

/**
* @brief : StaticNested core, used to collect NT.
* @brief : StaticNested core, used to collect NT.
* This function is only responsible for collection and is not responsible for converting and parsing to KS.
* @param :p_nt1 : NT1, non encrypted.
* @param :p_nt2 : NT2, encrypted.
* @param :keyKnown : U64 value of the known key of the card
* @param :blkKnown : The sector to which the card's known secret key belongs
* @param :typKnown : The known key type of the card, 0x60 (A key) or 0x61 (B key)
* @param :targetBlock : Target sectors that require nested attacks
* @param :targetType : Target key types that require nested attacks
* @param :nestedAgain : StaticNested enhanced vulnerability, which can obtain two sets of encrypted random numbers based on nested verification of known keys
* @retval : Successfully collected and returned to HF_TAG_OK, otherwise an error code will be returned.
* @param :p_nt1 : NT1, non encrypted.
* @param :p_nt2 : NT2, encrypted.
* @param :keyKnown : U64 value of the known key of the card
* @param :blkKnown : The sector to which the card's known secret key belongs
* @param :typKnown : The known key type of the card, 0x60 (A key) or 0x61 (B key)
* @param :targetBlock : Target sectors that require nested attacks
* @param :targetType : Target key types that require nested attacks
* @param :nestedAgain : StaticNested enhanced vulnerability, which can obtain two sets of encrypted random numbers based on nested verification of known keys
* @retval : Successfully collected and returned to HF_TAG_OK, otherwise an error code will be returned.
*
*/
uint8_t static_nested_recover_core(uint8_t *p_nt1, uint8_t *p_nt2, uint64_t keyKnown, uint8_t blkKnown, uint8_t typKnown, uint8_t targetBlock, uint8_t targetType, uint8_t nestedAgain) {
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs = &mpcs;
uint8_t status, len;
uint8_t parity[4] = {0x00};
uint8_t answer[4] = {0x00};
uint32_t uid, nt1, nt2;
uid = get_u32_tag_uid(p_tag_info);
pcd_14a_reader_halt_tag();
if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) {
return HF_TAG_NO;
}
status = authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_FIRST, &nt1);
if (status != HF_TAG_OK) {
return MF_ERR_AUTH;
}
if (nestedAgain) {
status = authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_NESTED, NULL);
if (status != HF_TAG_OK) {
return MF_ERR_AUTH;
}
}
len = send_cmd(pcs, AUTH_NESTED, targetType, targetBlock, &status, answer, parity, U8ARR_BIT_LEN(answer));
if (len != 32) {
NRF_LOG_INFO("No 32 data recv on sendcmd: %d\r\n", len);
return HF_ERR_STAT;
}
nt2 = bytes_to_num(answer, 4);
num_to_bytes(nt1, 4, p_nt1);
num_to_bytes(nt2, 4, p_nt2);
return HF_TAG_OK;
struct Crypto1State *pcs = &mpcs;
uint8_t status, len;
uint8_t parity[4] = {0x00};
uint8_t answer[4] = {0x00};
uint32_t uid, nt1, nt2;
uid = get_u32_tag_uid(p_tag_info);
pcd_14a_reader_halt_tag();
if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) {
return HF_TAG_NO;
}
status = authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_FIRST, &nt1);
if (status != HF_TAG_OK) {
return MF_ERR_AUTH;
}
if (nestedAgain) {
status = authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_NESTED, NULL);
if (status != HF_TAG_OK) {
return MF_ERR_AUTH;
}
}
len = send_cmd(pcs, AUTH_NESTED, targetType, targetBlock, &status, answer, parity, U8ARR_BIT_LEN(answer));
if (len != 32) {
NRF_LOG_INFO("No 32 data recv on sendcmd: %d\r\n", len);
return HF_ERR_STAT;
}
nt2 = bytes_to_num(answer, 4);
num_to_bytes(nt1, 4, p_nt1);
num_to_bytes(nt2, 4, p_nt2);
return HF_TAG_OK;
}

/**
* @brief : StaticNested encapsulates and calls the functions implemented by the core to collect 2 sets of random numbers.
* @brief : StaticNested encapsulates and calls the functions implemented by the core to collect 2 sets of random numbers.
* This function is only responsible for collection and is not responsible for converting and parsing to KS.
* @param :keyKnown : U64 value of the known key of the card
* @param :blkKnown : The sector to which the card's known secret key belongs
* @param :typKnown : The known key type of the card, 0x60 (A key) or 0x61 (B key)
* @param :targetBlock : Target sectors that require nested attacks
* @param :targetType : Target key type that require nested attacks
* @param :sncs : StaticNested Decrypting Core Structure Array
* @retval : Successfully collected and returned to HF_TAG_OK, otherwise an error code will be returned.
* @param :keyKnown : U64 value of the known key of the card
* @param :blkKnown : The sector to which the card's known secret key belongs
* @param :typKnown : The known key type of the card, 0x60 (A key) or 0x61 (B key)
* @param :targetBlock : Target sectors that require nested attacks
* @param :targetType : Target key type that require nested attacks
* @param :sncs : StaticNested Decrypting Core Structure Array
* @retval : Successfully collected and returned to HF_TAG_OK, otherwise an error code will be returned.
*
*/
uint8_t static_nested_recover_key(uint64_t keyKnown, uint8_t blkKnown, uint8_t typKnown, uint8_t targetBlock, uint8_t targetType, mf1_static_nested_core_t* sncs) {
uint8_t res;
res = pcd_14a_reader_scan_auto(p_tag_info);
if (res!= HF_TAG_OK) {
return res;
}
get_4byte_tag_uid(p_tag_info, sncs->uid);
res = static_nested_recover_core(sncs->core[0].nt1, sncs->core[0].nt2, keyKnown, blkKnown, typKnown, targetBlock, targetType, false);
if (res != HF_TAG_OK) {
return res;
}
res = static_nested_recover_core(sncs->core[1].nt1, sncs->core[1].nt2, keyKnown, blkKnown, typKnown, targetBlock, targetType, true);
if (res != HF_TAG_OK) {
return res;
}
return HF_TAG_OK;
uint8_t static_nested_recover_key(uint64_t keyKnown, uint8_t blkKnown, uint8_t typKnown, uint8_t targetBlock, uint8_t targetType, mf1_static_nested_core_t *sncs) {
uint8_t res;
res = pcd_14a_reader_scan_auto(p_tag_info);
if (res != HF_TAG_OK) {
return res;
}
get_4byte_tag_uid(p_tag_info, sncs->uid);
res = static_nested_recover_core(sncs->core[0].nt1, sncs->core[0].nt2, keyKnown, blkKnown, typKnown, targetBlock, targetType, false);
if (res != HF_TAG_OK) {
return res;
}
res = static_nested_recover_core(sncs->core[1].nt1, sncs->core[1].nt2, keyKnown, blkKnown, typKnown, targetBlock, targetType, true);
if (res != HF_TAG_OK) {
return res;
}
return HF_TAG_OK;
}

/**
Expand Down
5 changes: 2 additions & 3 deletions firmware/application/src/rfid/reader/hf/mf1_toolbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct { //Answer the random number parameters required for N
} mf1_nested_core_t;

typedef struct {
uint8_t uid[4];
uint8_t uid[4];
struct {
uint8_t nt1[4];
uint8_t nt2[4];
Expand Down Expand Up @@ -88,9 +88,8 @@ uint8_t nested_distance_detect(
uint8_t targetType \

uint8_t nested_recover_key(NESTED_CORE_PARAM_DEF, mf1_nested_core_t ncs[SETS_NR]);
uint8_t static_nested_recover_key(NESTED_CORE_PARAM_DEF, mf1_static_nested_core_t* sncs);
uint8_t static_nested_recover_key(NESTED_CORE_PARAM_DEF, mf1_static_nested_core_t *sncs);

uint8_t check_darkside_support(mf1_darkside_status_t *darkside_status);
uint8_t check_prng_type(mf1_prng_type_t *type);
uint8_t check_std_mifare_nt_support(bool *support);
void antenna_switch_delay(uint32_t delay_ms);
Expand Down
4 changes: 2 additions & 2 deletions firmware/application/src/rfid/reader/hf/rc522.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) {
if (tag->sak & 0x20) {
// Tag supports 14443-4, sending RATS
uint16_t ats_size;
status = pcd_14a_reader_ats_request(tag->ats, &ats_size, 0xFF*8);
status = pcd_14a_reader_ats_request(tag->ats, &ats_size, 0xFF * 8);
ats_size -= 2; // size returned by pcd_14a_reader_ats_request includes CRC
if (ats_size > 254) {
NRF_LOG_INFO("Invalid ATS > 254!");
Expand All @@ -600,7 +600,7 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) {
// return HF_ERR_ATS;
}
/*
* FIXME: If there is an issue here, it will cause the label to lose its selected state.
* FIXME: If there is an issue here, it will cause the label to lose its selected state.
* It is necessary to reselect the card after the issue occurs here.
*/
}
Expand Down
Loading

0 comments on commit d31d1af

Please sign in to comment.