From 624e96aee94a31bcf21d041da3def68259740286 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 13:18:02 +0200 Subject: [PATCH 1/7] fix compilation --- software/src/common.h | 6 +++--- software/src/nested.c | 2 +- software/src/staticnested.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/software/src/common.h b/software/src/common.h index 278df6a6..8fac65be 100644 --- a/software/src/common.h +++ b/software/src/common.h @@ -1,7 +1,7 @@ -#ifndef NESTED_H__ -#define NESTED_H__ +#ifndef COMMON_H__ +#define COMMON_H__ uint64_t atoui(const char* str); void num_to_bytes(uint64_t n, uint32_t len, uint8_t* dest); -#endif \ No newline at end of file +#endif diff --git a/software/src/nested.c b/software/src/nested.c index 33b5b2a4..fde471bb 100644 --- a/software/src/nested.c +++ b/software/src/nested.c @@ -2,7 +2,7 @@ #include #include #include - +#include "common.h" #include "nested_util.h" int main(int argc, char *const argv[]) { diff --git a/software/src/staticnested.c b/software/src/staticnested.c index 73ed002d..d1ba0bda 100644 --- a/software/src/staticnested.c +++ b/software/src/staticnested.c @@ -2,7 +2,7 @@ #include #include #include - +#include "common.h" #include "nested_util.h" int main(int argc, char *const argv[]) { From 5a9d49ddb421e400760bfff9c24bca1dacc82a5a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 16:03:17 +0200 Subject: [PATCH 2/7] Remove unused MF1_DETECT_DARKSIDE, reallocate 2003 to MF1_STATIC_NESTED_ACQUIRE MF1_DETECT_DARKSIDE was actually runnign the full attack, as there is no quick way to detect Darkside So if you want to check for Darkside, just run directly MF1_DARKSIDE_ACQUIRE. --- docs/protocol.md | 8 ++++---- firmware/application/src/app_cmd.c | 13 +------------ firmware/application/src/data_cmd.h | 3 +-- .../application/src/rfid/reader/hf/mf1_toolbox.c | 14 -------------- .../application/src/rfid/reader/hf/mf1_toolbox.h | 1 - software/script/chameleon_cmd.py | 15 +-------------- 6 files changed, 7 insertions(+), 47 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index ef476e58..d3199398 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -211,10 +211,10 @@ 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, diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 1fbd36f8..93518efc 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -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); @@ -938,8 +929,7 @@ 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 }, @@ -947,7 +937,6 @@ static cmd_data_map_t m_data_cmd_map[] = { { 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 }, diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index e04e93c7..ce8efc8a 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -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) // // ****************************************************************** diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c index 61f1a61a..358d1b55 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c @@ -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, diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h index 40b35ac9..5f336ae3 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h @@ -90,7 +90,6 @@ uint8_t nested_distance_detect( 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 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); diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 2f8ef128..a4dcd2ce 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -61,15 +61,13 @@ DATA_CMD_HF14A_SCAN = 2000 DATA_CMD_MF1_DETECT_SUPPORT = 2001 DATA_CMD_MF1_DETECT_PRNG = 2002 -# FIXME: implemented but unused in CLI commands -DATA_CMD_MF1_DETECT_DARKSIDE = 2003 +DATA_CMD_MF1_STATIC_NESTED_ACQUIRE = 2003 DATA_CMD_MF1_DARKSIDE_ACQUIRE = 2004 DATA_CMD_MF1_DETECT_NT_DIST = 2005 DATA_CMD_MF1_NESTED_ACQUIRE = 2006 DATA_CMD_MF1_AUTH_ONE_KEY_BLOCK = 2007 DATA_CMD_MF1_READ_ONE_BLOCK = 2008 DATA_CMD_MF1_WRITE_ONE_BLOCK = 2009 -DATA_CMD_MF1_STATIC_NESTED_ACQUIRE = 2010 DATA_CMD_EM410X_SCAN = 3000 DATA_CMD_EM410X_WRITE_TO_T55XX = 3001 @@ -465,17 +463,6 @@ def mf1_detect_prng(self): resp.data = resp.data[0] return resp - @expect_response(chameleon_status.Device.HF_TAG_OK) - def mf1_detect_darkside_support(self): - """ - Check if the card is vulnerable to mifare classic darkside attack - :return: - """ - resp = self.device.send_cmd_sync(DATA_CMD_MF1_DETECT_DARKSIDE, timeout=20) - if resp.status == chameleon_status.Device.HF_TAG_OK: - resp.data = resp.data[0] - return resp - @expect_response(chameleon_status.Device.HF_TAG_OK) def mf1_detect_nt_dist(self, block_known, type_known, key_known): """ From 52953de9274c12a78e3ec5131007ede55bffc78b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 21:37:56 +0200 Subject: [PATCH 3/7] changelog & typos in protocol --- CHANGELOG.md | 2 ++ docs/protocol.md | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1025dd98..422c2096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/docs/protocol.md b/docs/protocol.md index d3199398..9b57a341 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -218,12 +218,12 @@ Notes: ### 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[4]` U64 + * `ks1[4]` U64 * `nr[4]` U32 * `ar[4]` U32 * CLI: cf `hf mf darkside` From 3889033815668186876123e7721bc3112a89a93d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 21:47:37 +0200 Subject: [PATCH 4/7] sigh --- docs/protocol.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index 9b57a341..d508215a 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -222,8 +222,8 @@ Notes: * `darkside_status` * `uid[4]` U32 (format expected by `darkside` tool) * `nt1[4]` U32 - * `par[4]` U64 - * `ks1[4]` U64 + * `par[8]` U64 + * `ks1[8]` U64 * `nr[4]` U32 * `ar[4]` U32 * CLI: cf `hf mf darkside` From ebb77dc93878ddc26bc3177d8abf0d302f74269a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 22:02:49 +0200 Subject: [PATCH 5/7] recode GB18030..UTF-8 staticnested.c --- software/src/staticnested.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/software/src/staticnested.c b/software/src/staticnested.c index d1ba0bda..5fffc254 100644 --- a/software/src/staticnested.c +++ b/software/src/staticnested.c @@ -23,11 +23,11 @@ int main(int argc, char *const argv[]) { // Which generation of ST tags is detected. if (!check_st_level_at_sirst_run) { if (nt1 == 0x01200145) { - // 发现一代无漏洞,此标签全卡可用默认160的参数进行解密! + // 鍙戠幇涓浠f棤婕忔礊锛屾鏍囩鍏ㄥ崱鍙敤榛樿160鐨勫弬鏁拌繘琛岃В瀵嗭紒 dist = 160; // st gen1 } else if (nt1 == 0x009080A2) { // st gen2 - // 发现无漏洞二代,我们如果确认目前需要攻击的时B密钥,那么就需要更换攻击参数 + // 鍙戠幇鏃犳紡娲炰簩浠o紝鎴戜滑濡傛灉纭鐩墠闇瑕佹敾鍑荤殑鏃禕瀵嗛挜锛岄偅涔堝氨闇瑕佹洿鎹㈡敾鍑诲弬鏁 if (type == 0x61) { dist = 161; } From cd73ac89eec06e202d26cf780e819d8bf2c43888 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 19 Sep 2023 22:09:15 +0200 Subject: [PATCH 6/7] staticnested.c: translate comments, fix typo --- software/src/staticnested.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/software/src/staticnested.c b/software/src/staticnested.c index 5fffc254..094249c6 100644 --- a/software/src/staticnested.c +++ b/software/src/staticnested.c @@ -14,20 +14,20 @@ int main(int argc, char *const argv[]) { uint8_t type = (uint8_t)atoui(argv[2]); // target key type // process all args. - bool check_st_level_at_sirst_run = false; + bool check_st_level_at_first_run = false; for (i = 3, j = 0; i < argc; i += 2) { // nt + par nt1 = atoui(argv[i]); nt2 = atoui(argv[i + 1]); - // Which generation of ST tags is detected. - if (!check_st_level_at_sirst_run) { + // Which generation of static tag is detected. + if (!check_st_level_at_first_run) { if (nt1 == 0x01200145) { - // 鍙戠幇涓浠f棤婕忔礊锛屾鏍囩鍏ㄥ崱鍙敤榛樿160鐨勫弬鏁拌繘琛岃В瀵嗭紒 + // There is no loophole in this generation. + // This tag can be decrypted with the default parameter value 160! dist = 160; // st gen1 - } - else if (nt1 == 0x009080A2) { // st gen2 - // 鍙戠幇鏃犳紡娲炰簩浠o紝鎴戜滑濡傛灉纭鐩墠闇瑕佹敾鍑荤殑鏃禕瀵嗛挜锛岄偅涔堝氨闇瑕佹洿鎹㈡敾鍑诲弬鏁 + } else if (nt1 == 0x009080A2) { // st gen2 + // We found that the gen2 tag is vulnerable too but parameter must be adapted depending on the attacked key if (type == 0x61) { dist = 161; } @@ -35,15 +35,14 @@ int main(int argc, char *const argv[]) { dist = 160; } else { - // can't to here!!! + // can't be here!!! goto error; } - } - else { - // can't to here!!! + } else { + // can't be here!!! goto error; } - check_st_level_at_sirst_run = true; + check_st_level_at_first_run = true; } nttest = prng_successor(nt1, dist); From 14bffafb2a07b188addc6cfd9cb391bca183b3a0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 20 Sep 2023 01:26:47 +0200 Subject: [PATCH 7/7] style --- .../src/rfid/reader/hf/mf1_toolbox.c | 132 +++++++++--------- .../src/rfid/reader/hf/mf1_toolbox.h | 4 +- .../application/src/rfid/reader/hf/rc522.c | 4 +- software/script/chameleon_cli_unit.py | 52 ++++--- software/script/chameleon_cmd.py | 23 ++- software/script/chameleon_utils.py | 2 +- software/src/common.c | 4 +- software/src/common.h | 4 +- software/src/nested_util.c | 57 ++++---- software/src/nested_util.h | 6 +- software/src/staticnested.c | 8 +- 11 files changed, 148 insertions(+), 148 deletions(-) diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c index 358d1b55..473262fc 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c @@ -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. @@ -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) { @@ -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? @@ -928,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; } /** diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h index 5f336ae3..0f28a26f 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h @@ -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]; @@ -88,7 +88,7 @@ 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_prng_type(mf1_prng_type_t *type); uint8_t check_std_mifare_nt_support(bool *support); diff --git a/firmware/application/src/rfid/reader/hf/rc522.c b/firmware/application/src/rfid/reader/hf/rc522.c index 0aec993d..be7d2375 100644 --- a/firmware/application/src/rfid/reader/hf/rc522.c +++ b/firmware/application/src/rfid/reader/hf/rc522.c @@ -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!"); @@ -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. */ } diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index ea592e72..9d08c39e 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -382,7 +382,7 @@ def args_parser(self) -> ArgumentParserNoExit or None: help="The type of the target block to recover") # hf mf nested -o --block-known 0 --type-known A --key FFFFFFFFFFFF --block-target 4 --type-target A return parser - + def from_nt_level_code_to_str(self, nt_level): if nt_level == 0: return 'StaticNested' @@ -409,9 +409,10 @@ def recover_a_key(self, block_known, type_known, key_known, block_target, type_t return None # acquire - if nt_level == 0: # It's a staticnested tag? - nt_uid_obj = self.cmd.mf1_static_nested_acquire(block_known, type_known, key_known, block_target, type_target) - cmd_param = f"{nt_uid_obj['uid']} {str(type_target)}" + if nt_level == 0: # It's a staticnested tag? + nt_uid_obj = self.cmd.mf1_static_nested_acquire( + block_known, type_known, key_known, block_target, type_target) + cmd_param = f"{nt_uid_obj['uid']} {str(type_target)}" for nt_item in nt_uid_obj['nts']: cmd_param += f" {nt_item['nt']} {nt_item['nt_enc']}" decryptor_name = "staticnested" @@ -419,11 +420,11 @@ def recover_a_key(self, block_known, type_known, key_known, block_target, type_t dist_obj = self.cmd.mf1_detect_nt_dist(block_known, type_known, key_known) nt_obj = self.cmd.mf1_nested_acquire(block_known, type_known, key_known, block_target, type_target) # create cmd - cmd_param = f"{dist_obj['uid']} {dist_obj['dist']}" + cmd_param = f"{dist_obj['uid']} {dist_obj['dist']}" for nt_item in nt_obj: cmd_param += f" {nt_item['nt']} {nt_item['nt_enc']} {nt_item['par']}" decryptor_name = "nested" - + # Cross-platform compatibility if sys.platform == "win32": cmd_recover = f"{decryptor_name}.exe {cmd_param}" @@ -517,7 +518,7 @@ def recover_key(self, block_target, type_target): print(f"Darkside error: {chameleon_cmd.MifareClassicDarksideStatus(darkside_resp[0])}") break darkside_obj = darkside_resp[1] - + if darkside_obj['par'] != 0: # NXP tag workaround. self.darkside_list.clear() @@ -1054,12 +1055,12 @@ def args_parser(self) -> ArgumentParserNoExit or None: def get_slot_name(self, slot, sense): try: name = self.cmd.get_slot_tag_nick(slot, sense).decode(encoding="utf8") - return len(name),len(CC+C0),f'{CC}{name}{C0}' + return len(name), len(CC+C0), f'{CC}{name}{C0}' except UnexpectedResponseError: - return 0,0,'' + return 0, 0, '' except UnicodeDecodeError: name = "UTF8 Err" - return len(name),len(CR+C0),f'{CR}{name}{C0}' + return len(name), len(CR+C0), f'{CR}{name}{C0}' # hw slot list def on_exec(self, args: argparse.Namespace): @@ -1086,20 +1087,24 @@ def on_exec(self, args: argparse.Namespace): f'{(slotnames[fwslot][0][2] if args.extend else ""):{maxnamelength+slotnames[fwslot][0][1]+1 if args.extend else maxnamelength+1}}' f'{f"{CY if enabled[fwslot] else C0}{hf_tag_type}{C0}" if hf_tag_type != chameleon_cmd.TagSpecificType.TAG_TYPE_UNKNOWN else "undef"}') if args.extend == 1 and \ - enabled[fwslot] and \ - slot == selected and \ - hf_tag_type in [ - chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_Mini, - chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_1024, - chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_2048, - chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_4096, - ]: + enabled[fwslot] and \ + slot == selected and \ + hf_tag_type in [ + chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_Mini, + chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_1024, + chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_2048, + chameleon_cmd.TagSpecificType.TAG_TYPE_MIFARE_4096, + ]: config = self.cmd.mf1_get_emulator_config() print(' - Mifare Classic emulator settings:') - print(f' {"Detection (mfkey32) mode:":40}{f"{CG}enabled{C0}" if config["detection"] else f"{CR}disabled{C0}"}') - print(f' {"Gen1A magic mode:":40}{f"{CG}enabled{C0}" if config["gen1a_mode"] else f"{CR}disabled{C0}"}') - print(f' {"Gen2 magic mode:":40}{f"{CG}enabled{C0}" if config["gen2_mode"] else f"{CR}disabled{C0}"}') - print(f' {"Use anti-collision data from block 0:":40}{f"{CG}enabled{C0}" if config["block_anti_coll_mode"] else f"{CR}disabled{C0}"}') + print( + f' {"Detection (mfkey32) mode:":40}{f"{CG}enabled{C0}" if config["detection"] else f"{CR}disabled{C0}"}') + print( + f' {"Gen1A magic mode:":40}{f"{CG}enabled{C0}" if config["gen1a_mode"] else f"{CR}disabled{C0}"}') + print( + f' {"Gen2 magic mode:":40}{f"{CG}enabled{C0}" if config["gen2_mode"] else f"{CR}disabled{C0}"}') + print( + f' {"Use anti-collision data from block 0:":40}{f"{CG}enabled{C0}" if config["block_anti_coll_mode"] else f"{CR}disabled{C0}"}') print(f' {"Write mode:":40}{CY}{chameleon_cmd.MifareClassicWriteMode(config["write_mode"])}{C0}') print(f' LF: ' f'{(slotnames[fwslot][1][2] if args.extend else ""):{maxnamelength+slotnames[fwslot][1][1]+1 if args.extend else maxnamelength+1}}' @@ -1555,7 +1560,8 @@ def args_parser(self) -> ArgumentParserNoExit or None: return parser def on_exec(self, args: argparse.Namespace): - response = self.cmd.device.send_cmd_sync(args.command, data=bytes.fromhex(args.data), status=0x0, timeout=args.timeout) + response = self.cmd.device.send_cmd_sync( + args.command, data=bytes.fromhex(args.data), status=0x0, timeout=args.timeout) print(" - Received:") print(f" Command: {response.cmd}") status_string = f" Status: {response.status:#02x}" diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index a4dcd2ce..f12695c0 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -489,7 +489,6 @@ def mf1_nested_acquire(self, block_known, type_known, key_known, block_target, t for nt, nt_enc, par in struct.iter_unpack('!IIB', resp.data)] return resp - @expect_response(chameleon_status.Device.HF_TAG_OK) def mf1_darkside_acquire(self, block_target, type_target, first_recover: int or bool, sync_max): """ @@ -550,7 +549,7 @@ def mf1_write_one_block(self, block, type_value, key, block_data): resp = self.device.send_cmd_sync(DATA_CMD_MF1_WRITE_ONE_BLOCK, data) resp.data = resp.status == chameleon_status.Device.HF_TAG_OK return resp - + @expect_response(chameleon_status.Device.HF_TAG_OK) def mf1_static_nested_acquire(self, block_known, type_known, key_known, block_target, type_target): """ @@ -564,7 +563,7 @@ def mf1_static_nested_acquire(self, block_known, type_known, key_known, block_ta 'uid': struct.unpack('!I', resp.data[0:4])[0], 'nts': [ { - 'nt': nt, + 'nt': nt, 'nt_enc': nt_enc } for nt, nt_enc in struct.iter_unpack('!II', resp.data[4:]) ] @@ -1047,20 +1046,20 @@ def get_device_settings(self): if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS: if resp.data[0] > CURRENT_VERSION_SETTINGS: raise ValueError("Settings version in app older than Chameleon. " - "Please upgrade client") + "Please upgrade client") if resp.data[0] < CURRENT_VERSION_SETTINGS: raise ValueError("Settings version in app newer than Chameleon. " - "Please upgrade Chameleon firmware") + "Please upgrade Chameleon firmware") settings_version, animation_mode, btn_press_A, btn_press_B, btn_long_press_A, btn_long_press_B, ble_pairing_enable, ble_pairing_key = struct.unpack( '!BBBBBBB6s', resp.data) resp.data = {'settings_version': settings_version, - 'animation_mode': animation_mode, - 'btn_press_A': btn_press_A, - 'btn_press_B': btn_press_B, - 'btn_long_press_A': btn_long_press_A, - 'btn_long_press_B': btn_long_press_B, - 'ble_pairing_enable': ble_pairing_enable, - 'ble_pairing_key': ble_pairing_key} + 'animation_mode': animation_mode, + 'btn_press_A': btn_press_A, + 'btn_press_B': btn_press_B, + 'btn_long_press_A': btn_long_press_A, + 'btn_long_press_B': btn_long_press_B, + 'ble_pairing_enable': ble_pairing_enable, + 'ble_pairing_key': ble_pairing_key} return resp @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) diff --git a/software/script/chameleon_utils.py b/software/script/chameleon_utils.py index bca09b40..089992fe 100644 --- a/software/script/chameleon_utils.py +++ b/software/script/chameleon_utils.py @@ -61,7 +61,7 @@ def error_throwing_func(*args, **kwargs): else: raise UnexpectedResponseError( f"Unexpected response and unknown status {ret.status}") - + return ret.data return error_throwing_func diff --git a/software/src/common.c b/software/src/common.c index e405d1ca..0b9cc88d 100644 --- a/software/src/common.c +++ b/software/src/common.c @@ -1,7 +1,7 @@ #include -uint64_t atoui(const char* str) { +uint64_t atoui(const char *str) { uint64_t result = 0; for (int i = 0; str[i] != '\0'; ++i) { @@ -12,7 +12,7 @@ uint64_t atoui(const char* str) { return result; } -void num_to_bytes(uint64_t n, uint32_t len, uint8_t* dest) { +void num_to_bytes(uint64_t n, uint32_t len, uint8_t *dest) { while (len--) { dest[len] = (uint8_t)n; n >>= 8; diff --git a/software/src/common.h b/software/src/common.h index 8fac65be..f66f87ed 100644 --- a/software/src/common.h +++ b/software/src/common.h @@ -1,7 +1,7 @@ #ifndef COMMON_H__ #define COMMON_H__ -uint64_t atoui(const char* str); -void num_to_bytes(uint64_t n, uint32_t len, uint8_t* dest); +uint64_t atoui(const char *str); +void num_to_bytes(uint64_t n, uint32_t len, uint8_t *dest); #endif diff --git a/software/src/nested_util.c b/software/src/nested_util.c index 7d214238..801a2799 100644 --- a/software/src/nested_util.c +++ b/software/src/nested_util.c @@ -25,10 +25,10 @@ typedef struct { } countKeys; typedef struct { - NtpKs1* pNK; + NtpKs1 *pNK; uint32_t authuid; - uint64_t* keys; + uint64_t *keys; uint32_t keyCount; uint32_t startPos; @@ -36,20 +36,20 @@ typedef struct { } RecPar; -int compar_int(const void* a, const void* b) { - return (*(uint64_t*)b - *(uint64_t*)a); +int compar_int(const void *a, const void *b) { + return (*(uint64_t *)b - * (uint64_t *)a); } // Compare countKeys structure -int compar_special_int(const void* a, const void* b) { - return (((countKeys*)b)->count - ((countKeys*)a)->count); +int compar_special_int(const void *a, const void *b) { + return (((countKeys *)b)->count - ((countKeys *)a)->count); } // keys qsort and unique. -countKeys* uniqsort(uint64_t* possibleKeys, uint32_t size) { +countKeys *uniqsort(uint64_t *possibleKeys, uint32_t size) { unsigned int i, j = 0; int count = 0; - countKeys* our_counts; + countKeys *our_counts; qsort(possibleKeys, size, sizeof(uint64_t), compar_int); @@ -62,8 +62,7 @@ countKeys* uniqsort(uint64_t* possibleKeys, uint32_t size) { for (i = 0; i < size; i++) { if (possibleKeys[i + 1] == possibleKeys[i]) { count++; - } - else { + } else { our_counts[j].key = possibleKeys[i]; our_counts[j].count = count; j++; @@ -75,8 +74,8 @@ countKeys* uniqsort(uint64_t* possibleKeys, uint32_t size) { } // nested decrypt -static void nested_revover(RecPar* rp) { - struct Crypto1State* revstate, * revstate_start = NULL; +static void nested_revover(RecPar *rp) { + struct Crypto1State *revstate, * revstate_start = NULL; uint64_t lfsr = 0; uint32_t i, kcount = 0; @@ -98,14 +97,14 @@ static void nested_revover(RecPar* rp) { if (((kcount % MEM_CHUNK) == 0) || (kcount >= rp->keyCount)) { rp->keyCount += MEM_CHUNK; // printf("New chunk by %d, sizeof %lu\n", kcount, key_count * sizeof(uint64_t)); - void* tmp = realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); + void *tmp = realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); if (tmp == NULL) { printf("Memory allocation error for pk->possibleKeys"); // exit(EXIT_FAILURE); rp->keyCount = 0; return; } - rp->keys = (uint64_t*)tmp; + rp->keys = (uint64_t *)tmp; } rp->keys[kcount] = lfsr; kcount++; @@ -117,7 +116,7 @@ static void nested_revover(RecPar* rp) { // Truncate if (kcount != 0) { rp->keyCount = --kcount; - void* tmp = (uint64_t*)realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); + void *tmp = (uint64_t *)realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); if (tmp == NULL) { printf("Memory allocation error for pk->possibleKeys"); // exit(EXIT_FAILURE); @@ -131,11 +130,11 @@ static void nested_revover(RecPar* rp) { return; } -uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyCount) { +uint64_t *nested(NtpKs1 *pNK, uint32_t sizePNK, uint32_t authuid, uint32_t *keyCount) { *keyCount = 0; uint32_t i; - RecPar* pRPs = malloc(sizeof(RecPar)); + RecPar *pRPs = malloc(sizeof(RecPar)); if (pRPs == NULL) { return NULL; } @@ -149,7 +148,7 @@ uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyC nested_revover(pRPs); *keyCount = pRPs->keyCount; - uint64_t* keys = NULL; + uint64_t *keys = NULL; if (*keyCount != 0) { keys = malloc(*keyCount * sizeof(uint64_t)); if (keys != NULL) { @@ -159,9 +158,9 @@ uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyC } free(pRPs); - countKeys* ck = uniqsort(keys, *keyCount); + countKeys *ck = uniqsort(keys, *keyCount); free(keys); - keys = (uint64_t*)NULL; + keys = (uint64_t *)NULL; *keyCount = 0; if (ck != NULL) { @@ -170,30 +169,28 @@ uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyC // This key can be found here two or more times if (ck[i].count > 0) { *keyCount += 1; - void* tmp = realloc(keys, sizeof(uint64_t) * (*keyCount)); + void *tmp = realloc(keys, sizeof(uint64_t) * (*keyCount)); if (tmp != NULL) { keys = tmp; keys[*keyCount - 1] = ck[i].key; - } - else { + } else { printf("Cannot allocate memory for keys on merge."); free(keys); break; } } } - } - else { + } else { printf("Cannot allocate memory for ck on uniqsort."); } return keys; } // Return 1 if the nonce is invalid else return 0 -uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t* parity) { +uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { return ( - (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ - (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ - (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) - ) ? 1 : 0; + (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) + ) ? 1 : 0; } diff --git a/software/src/nested_util.h b/software/src/nested_util.h index 12699ac4..2d569ec7 100644 --- a/software/src/nested_util.h +++ b/software/src/nested_util.h @@ -8,7 +8,7 @@ typedef struct { uint32_t ks1; } NtpKs1; -uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t* parity); -uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyCount); +uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity); +uint64_t *nested(NtpKs1 *pNK, uint32_t sizePNK, uint32_t authuid, uint32_t *keyCount); -#endif \ No newline at end of file +#endif diff --git a/software/src/staticnested.c b/software/src/staticnested.c index 094249c6..f857bfd2 100644 --- a/software/src/staticnested.c +++ b/software/src/staticnested.c @@ -30,11 +30,9 @@ int main(int argc, char *const argv[]) { // We found that the gen2 tag is vulnerable too but parameter must be adapted depending on the attacked key if (type == 0x61) { dist = 161; - } - else if (type == 0x60) { + } else if (type == 0x60) { dist = 160; - } - else { + } else { // can't be here!!! goto error; } @@ -50,7 +48,7 @@ int main(int argc, char *const argv[]) { ++j; dist += 160; - void* tmp = realloc(pNK, sizeof(NtpKs1) * j); + void *tmp = realloc(pNK, sizeof(NtpKs1) * j); if (tmp == NULL) { goto error; }