diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 738425105..edfe30c4a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2356,8 +2356,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_ICLASS_READER: { - iclass_card_select_t *payload = (iclass_card_select_t *) packet->data.asBytes; - ReaderIClass(payload->flags); + ReaderIClass(packet->data.asBytes); break; } case CMD_HF_ICLASS_EML_MEMSET: { diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 0e62d9caa..8c81b14c2 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1373,7 +1373,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t * * @return false = fail * true = Got all. */ -static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status, bool shallow_mod) { +static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status, bool shallow_mod, uint8_t page) { static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; @@ -1421,6 +1421,19 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3 // save CSN memcpy(hdr->csn, resp, sizeof(hdr->csn)); + // card selected, select page + uint8_t pagesel_resp[10]; + start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + uint8_t pagesel[] = {0x80 | ICLASS_CMD_PAGESEL, page, 0x00, 0x00}; + AddCrc(pagesel + 1, 1); + + bool pagesel_res = iclass_send_cmd_with_retries(pagesel, sizeof(pagesel), pagesel_resp, sizeof(resp), + 10, 2, &start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time, shallow_mod); + + if (pagesel_res == false) { + return false; + } + // card selected, now read config (block1) (only 8 bytes no CRC) start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; iclass_send_as_reader(read_conf, sizeof(read_conf), &start_time, eof_time, shallow_mod); @@ -1495,12 +1508,21 @@ static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint3 bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod) { uint8_t result = 0; - return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result, shallow_mod); + return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result, shallow_mod, 0); // page 0 unless specified +} + + +bool select_iclass_tag_and_page(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod, uint8_t page) { + uint8_t result = 0; + return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result, shallow_mod, page); } // Reader iClass Anticollission // turn off afterwards -void ReaderIClass(uint8_t flags) { +void ReaderIClass(uint8_t *msg) { + iclass_card_select_t *cmd = (iclass_card_select_t *)msg; + uint8_t flags = cmd->flags; + uint8_t page = cmd->page; // flag to use credit key bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY); @@ -1519,7 +1541,7 @@ void ReaderIClass(uint8_t flags) { uint32_t eof_time = 0; picopass_hdr_t hdr = {0}; - if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res, shallow_mod) == false) { + if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res, shallow_mod, page) == false) { reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0); goto out; } @@ -1767,6 +1789,7 @@ void iClass_Dump(uint8_t *msg) { iclass_dump_req_t *cmd = (iclass_dump_req_t *)msg; iclass_auth_req_t *req = &cmd->req; bool shallow_mod = req->shallow_mod; + uint8_t page = cmd->page; uint8_t *dataout = BigBuf_calloc(ICLASS_16KS_SIZE); if (dataout == NULL) { @@ -1781,12 +1804,12 @@ void iClass_Dump(uint8_t *msg) { Iso15693InitReader(); - // select tag. + // select tag and page uint32_t eof_time = 0; picopass_hdr_t hdr = {0}; memset(&hdr, 0xff, sizeof(picopass_hdr_t)); - bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time, shallow_mod); + bool res = select_iclass_tag_and_page(&hdr, req->use_credit_key, &eof_time, shallow_mod, page); if (res == false) { if (req->send_reply) { reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0); diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 7933e32cb..c717c49c6 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -47,7 +47,7 @@ #define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1) void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string); -void ReaderIClass(uint8_t flags); +void ReaderIClass(uint8_t *flags); void iClass_WriteBlock(uint8_t *msg); void iclass_credit_epurse(iclass_credit_epurse_t *payload); @@ -67,6 +67,7 @@ void iClass_ReadBlock(uint8_t *msg); bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time, bool shallow_mod); bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod); +bool select_iclass_tag_and_page(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod, uint8_t page); bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out); uint8_t get_pagemap(const picopass_hdr_t *hdr); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 272351499..fd31cb5f7 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1639,7 +1639,8 @@ static int CmdHFiClassInfo(const char *Cmd) { int read_iclass_csn(bool loop, bool verbose, bool shallow_mod) { iclass_card_select_t payload = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support for reader mode yet }; if (shallow_mod) { @@ -2431,7 +2432,8 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose, bool shallow_mod) { iclass_card_select_t payload = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support here yet }; if (shallow_mod) { @@ -2481,7 +2483,8 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose, bool shallow_ static int iclass_dump_non_secure(bool shallow_mod, uint8_t *tag_data, uint16_t *taglen) { iclass_card_select_t payload_rdr = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support here yet }; if (shallow_mod) { @@ -2606,6 +2609,7 @@ static int CmdHFiClassDump(const char *Cmd) { arg_lit0(NULL, "force", "force unsecure card read"), arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"), arg_lit0(NULL, "ns", "no save to file"), + arg_int0(NULL, "page", "", "which page to dump from"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2632,6 +2636,7 @@ static int CmdHFiClassDump(const char *Cmd) { bool force = arg_get_lit(ctx, 10); bool shallow_mod = arg_get_lit(ctx, 11); bool nosave = arg_get_lit(ctx, 12); + int page = arg_get_int_def(ctx, 13, 0); CLIParserFree(ctx); @@ -2702,7 +2707,8 @@ static int CmdHFiClassDump(const char *Cmd) { memset(tag_data, 0xFF, sizeof(tag_data)); iclass_card_select_t payload_rdr = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = page }; if (shallow_mod) { @@ -2791,6 +2797,7 @@ static int CmdHFiClassDump(const char *Cmd) { .req.do_auth = auth, .req.shallow_mod = shallow_mod, .end_block = app_limit1, + .page = page, }; memcpy(payload.req.key, key, 8); @@ -3891,7 +3898,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { //check if the card is in secure mode or not iclass_card_select_t payload_rdr = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support for tearblock yet }; if (shallow_mod) { @@ -4444,7 +4452,8 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { //check if the card is in secure mode or not iclass_card_select_t payload_rdr = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support for blacktears yet }; clearCommandBuffer(); @@ -7891,7 +7900,8 @@ int CmdHFiClass(const char *Cmd) { int info_iclass(bool shallow_mod) { iclass_card_select_t payload = { - .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE), + .page = 0 // no page selection support for info yet }; if (shallow_mod) { diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h index 9c265cd99..0ec809b8a 100644 --- a/include/iclass_cmd.h +++ b/include/iclass_cmd.h @@ -79,6 +79,7 @@ typedef struct { // iCLASS dump data structure typedef struct { iclass_auth_req_t req; + uint8_t page; uint8_t start_block; uint8_t end_block; } PACKED iclass_dump_req_t; @@ -187,6 +188,7 @@ typedef struct { // reader flags typedef struct { uint8_t flags; + uint8_t page; } PACKED iclass_card_select_t; // reader flags