diff --git a/doc/tools/opensc-explorer.1.xml b/doc/tools/opensc-explorer.1.xml
index 40646fb7..85ab0857 100644
--- a/doc/tools/opensc-explorer.1.xml
+++ b/doc/tools/opensc-explorer.1.xml
@@ -292,6 +292,14 @@
Files are found by selecting all file identifiers in the range from start-fid to end-fid (by default from 0000 to FFFF).
+
+
+ find_tags [start-tag [end-tag]]
+
+ Find all tags of data objects in the current context.
+ Tags are found by using GET DATA in the range from start-tag to end-tag (by default from 0000 to FFFF).
+
+
mkdir file-id size
diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c
index b6b208ae..1a716030 100644
--- a/src/libopensc/card-cardos.c
+++ b/src/libopensc/card-cardos.c
@@ -1217,35 +1217,6 @@ cardos_logout(sc_card_t *card)
return SC_ERROR_NOT_SUPPORTED;
}
-static int cardos_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len)
-{
- int r;
- struct sc_apdu apdu;
-
- SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
-
- sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA,
- (tag >> 8) & 0xff, tag & 0xff);
- apdu.lc = 0;
- apdu.datalen = 0;
- apdu.le = len;
- apdu.resp = buf;
- apdu.resplen = len;
- r = sc_transmit_apdu(card, &apdu);
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
-
- r = sc_check_sw(card, apdu.sw1, apdu.sw2);
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error");
-
- if (apdu.resplen > len)
- r = SC_ERROR_WRONG_LENGTH;
- else
- r = apdu.resplen;
-
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
-}
-
-
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
static struct sc_card_driver * sc_get_driver(void)
@@ -1266,7 +1237,6 @@ static struct sc_card_driver * sc_get_driver(void)
cardos_ops.card_ctl = cardos_card_ctl;
cardos_ops.pin_cmd = cardos_pin_cmd;
cardos_ops.logout = cardos_logout;
- cardos_ops.get_data = cardos_get_data;
return &cardos_drv;
}
diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c
index 19f9e7e3..baa15814 100644
--- a/src/libopensc/iso7816.c
+++ b/src/libopensc/iso7816.c
@@ -1128,6 +1128,38 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l
}
+static int iso7816_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len)
+{
+ int r, cse;
+ struct sc_apdu apdu;
+
+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
+
+ if (buf && len)
+ cse = SC_APDU_CASE_2;
+ else
+ cse = SC_APDU_CASE_1;
+
+ sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
+ apdu.le = len;
+ apdu.resp = buf;
+ apdu.resplen = len;
+ r = sc_transmit_apdu(card, &apdu);
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
+
+ r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error");
+
+ if (apdu.resplen > len)
+ r = SC_ERROR_WRONG_LENGTH;
+ else
+ r = apdu.resplen;
+
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
+}
+
+
+
static int
iso7816_init(struct sc_card *card)
{
@@ -1175,7 +1207,7 @@ static struct sc_card_operations iso_ops = {
iso7816_process_fci,
iso7816_construct_fci,
iso7816_pin_cmd,
- NULL, /* get_data */
+ iso7816_get_data,
NULL, /* put_data */
NULL, /* delete_record */
NULL /* read_public_key */
diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c
index 75588df7..22943596 100644
--- a/src/tools/opensc-explorer.c
+++ b/src/tools/opensc-explorer.c
@@ -85,6 +85,7 @@ static const char *option_help[] = {
static int do_echo(int argc, char **argv);
static int do_ls(int argc, char **argv);
static int do_find(int argc, char **argv);
+static int do_find_tags(int argc, char **argv);
static int do_cd(int argc, char **argv);
static int do_cat(int argc, char **argv);
static int do_info(int argc, char **argv);
@@ -127,6 +128,9 @@ static struct command cmds[] = {
{ do_find,
"find", "[ []]",
"find all files in the current DF" },
+ { do_find_tags,
+ "find_tags", "[ []]",
+ "find all tags of data objects in the current context" },
{ do_cd,
"cd", "{.. | | aid:}",
"change to another DF" },
@@ -579,6 +583,73 @@ static int do_find(int argc, char **argv)
return 0;
}
+static int do_find_tags(int argc, char **argv)
+{
+ u8 start[2], end[2], rbuf[256];
+ int r;
+ unsigned int tag, tag_end;
+
+ start[0] = 0x00;
+ start[1] = 0x00;
+ end[0] = 0xFF;
+ end[1] = 0xFF;
+ switch (argc) {
+ case 2:
+ if (arg_to_fid(argv[1], end) != 0)
+ return usage(do_find_tags);
+ /* fall through */
+ case 1:
+ if (arg_to_fid(argv[0], start) != 0)
+ return usage(do_find_tags);
+ /* fall through */
+ case 0:
+ break;
+ default:
+ return usage(do_find_tags);
+ }
+ tag = (start[0] << 8) | start[1];
+ tag_end = (end[0] << 8) | end[1];
+
+ printf("Tag\tType\n");
+ while (1) {
+ printf("(%04X)\r", tag);
+ fflush(stdout);
+
+ r = sc_get_data(card, tag, rbuf, sizeof rbuf);
+ if (r >= 0) {
+ printf(" %04X ", tag);
+ if (tag == 0)
+ printf("\tdump file");
+ if ((0x0001 <= tag && tag <= 0x00FE)
+ || (0x1F1F <= tag && tag <= 0xFFFF))
+ printf("\tBER-TLV");
+ if (tag == 0x00FF || tag == 0x02FF)
+ printf("\tspecial function");
+ if (0x0100 <= tag && tag <= 0x01FF)
+ printf("\tproprietary");
+ if (tag == 0x0200)
+ printf("\tRFU");
+ if (0x0201 <= tag && tag <= 0x02FE)
+ printf("\tSIMPLE-TLV");
+ printf("\n");
+ if (r > 0)
+ util_hex_dump_asc(stdout, rbuf, r, -1);
+ } else {
+ switch (r) {
+ case SC_ERROR_NOT_ALLOWED:
+ case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED:
+ printf("(%04X)\t%s\n", tag, sc_strerror(r));
+ break;
+ }
+ }
+
+ if (tag >= tag_end)
+ break;
+ tag++;
+ }
+ return 0;
+}
+
static int do_cd(int argc, char **argv)
{
sc_path_t path;