From ebd9f24af4a9bd2fefb397a2cfcc578ac656b3fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 17:38:17 +0200 Subject: [PATCH] fix hf iclass config - now uses a default config card data if no config card present on device. --- client/src/cmdhficlass.c | 79 ++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 08c4e9360..37120f29b 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -37,6 +37,9 @@ #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" +static void print_picopass_info(const picopass_hdr_t *hdr); +void print_picopass_header(const picopass_hdr_t *hdr); + static picopass_hdr_t iclass_last_known_card; static void iclass_set_last_known_card(picopass_hdr_t *card) { memcpy(&iclass_last_known_card, card, sizeof(picopass_hdr_t)); @@ -129,7 +132,7 @@ static void iclass_upload_emul(uint8_t *d, uint16_t n, uint16_t *bytes_sent) { uint16_t bytes_remaining = n; while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); + uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE - 4, bytes_remaining); if (bytes_in_packet == bytes_remaining) { // Disable fast mode on last packet conn.block_after_ACK = false; @@ -244,8 +247,8 @@ static void print_config_cards(void) { static void print_config_card(const iclass_config_card_item_t *o) { if (check_config_card(o)) { - PrintAndLogEx(INFO, "description... %s", o->desc); - PrintAndLogEx(INFO, "data....... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); + PrintAndLogEx(INFO, "description... " _YELLOW_("%s") , o->desc); + PrintAndLogEx(INFO, "data.......... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); } } @@ -253,20 +256,37 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke if (check_config_card(o) == false) { return PM3_EINVARG; } + + // generated config card header + picopass_hdr_t configcard; + memset(&configcard, 0xFF, sizeof(picopass_hdr_t)); + memcpy(configcard.csn, "\x41\x87\x66\x00\xFB\xFF\x12\xE0", 8); + memcpy(&configcard.conf, "\xFF\xFF\xFF\xFF\xF9\xFF\xFF\xBC", 8); + memcpy(&configcard.epurse, "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8); + // defaulting to known AA1 key + HFiClassCalcDivKey(configcard.csn, iClass_Key_Table[0], configcard.key_d, false); + + // reference + picopass_hdr_t *cc = &configcard; + // get header from card - //bool have = memcmp(iclass_last_known_card.csn, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); PrintAndLogEx(INFO, "trying to read a card.."); int res = read_iclass_csn(false, false); - if (res != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "Put a card on antenna and try again..."); - return res; + if (res == PM3_SUCCESS) { + cc = &iclass_last_known_card; + // calc diversified key for selected card + HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false); + } else { + PrintAndLogEx(INFO, "failed to read a card, will use default config card data"); } // generate dump file - uint8_t app1_limit = iclass_last_known_card.conf.app_limit; + uint8_t app1_limit = cc->conf.app_limit; uint8_t old_limit = app1_limit; - uint8_t tot_bytes = (app1_limit + 1) * 8; + uint16_t tot_bytes = (app1_limit + 1) * 8; + PrintAndLogEx(INFO, " APP1 limit: %u", app1_limit); + PrintAndLogEx(INFO, "total bytes: %u", tot_bytes); // normal size uint8_t *data = calloc(1, tot_bytes); if (data == NULL) { @@ -274,12 +294,9 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke return PM3_EMALLOC; } + memcpy(data, cc, sizeof(picopass_hdr_t)); - // calc diversified key for selected card - HFiClassCalcDivKey(iclass_last_known_card.csn, iClass_Key_Table[0], iclass_last_known_card.key_d, false); - - memset(data, 0x00, tot_bytes); - memcpy(data, (uint8_t *)&iclass_last_known_card, sizeof(picopass_hdr_t)); + print_picopass_header(cc); // Keyrolling configuration cards are special. if (strstr(o->desc, "Keyroll") != NULL) { @@ -295,7 +312,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke PrintAndLogEx(WARNING, "Adapting applimit1 for KEY rolling.."); app1_limit = 0x16; - iclass_last_known_card.conf.app_limit = 0x16; + cc->conf.app_limit = 0x16; tot_bytes = (app1_limit + 1) * 8; uint8_t *p = realloc(data, tot_bytes); @@ -308,25 +325,22 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memset(data, 0xFF, tot_bytes); } - // need to encrypt - PrintAndLogEx(INFO, "Detecting cardhelper..."); - if (IsCardHelperPresent(false) == false) { - PrintAndLogEx(FAILED, "failed to detect cardhelper"); - free(data); - return PM3_ENODATA; - } - + // KEYROLL need to encrypt uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (Encrypt(ffs, ffs) == false) { PrintAndLogEx(WARNING, "failed to encrypt FF"); } + // local key copy + uint8_t lkey[8]; + memcpy(lkey, key, sizeof(lkey)); + uint8_t enckey1[8]; - if (Encrypt(key, enckey1) == false) { + if (Encrypt(lkey, enckey1) == false) { PrintAndLogEx(WARNING, "failed to encrypt key1"); } - memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); // encrypted keyroll key 0D @@ -338,7 +352,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // encrypted partial keyroll key 14 uint8_t foo[8] = {0x15}; - memcpy(foo + 1, key, 7); + memcpy(foo + 1, lkey, 7); uint8_t enckey2[8]; if (Encrypt(foo, enckey2) == false) { PrintAndLogEx(WARNING, "failed to encrypt partial 1"); @@ -347,7 +361,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // encrypted partial keyroll key 15 memset(foo, 0xFF, sizeof(foo)); - foo[0] = key[7]; + foo[0] = lkey[7]; if (Encrypt(foo, enckey2) == false) { PrintAndLogEx(WARNING, "failed to encrypt partial 2"); } @@ -358,12 +372,11 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memcpy(data + (i * 8), ffs, sizeof(ffs)); } - // revert potential modified app1_limit - iclass_last_known_card.conf.app_limit = old_limit; + cc->conf.app_limit = old_limit; } else { - memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); } @@ -532,13 +545,13 @@ static void mem_app_config(const picopass_hdr_t *hdr) { } } -static void print_picopass_info(const picopass_hdr_t *hdr) { +void print_picopass_info(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "-------------------- " _CYAN_("card configuration") " --------------------"); fuse_config(hdr); mem_app_config(hdr); } -static void print_picopass_header(const picopass_hdr_t *hdr) { +void print_picopass_header(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "--------------------------- " _CYAN_("card") " ---------------------------"); PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); @@ -3859,6 +3872,8 @@ int CmdHFiClass(const char *Cmd) { // SR | 6,7,8,9, | AA1, Access control payload | 2 // | 10,11,12,13,14,15,16 | AA1, Secure identity object (SIO) | // SEOS | | | +// MFC SIO| | | +// DESFIRE| | | //} int info_iclass(void) {