Merge pull request #32 from frankmorgner/4d9ea43ab24a2e36fc36d1be81b3414cc003786f
new commands for opensc-explorer and bugfix for iso7816 driver - opensc-explorer: new find command: tested; nice, useful feature. - opensc-explorer: pace: no means to test -- accepted. - iso driver: really bug, thanks.
This commit is contained in:
commit
fb1aa8ed11
|
@ -460,17 +460,19 @@ static int iso7816_select_file(sc_card_t *card,
|
|||
default:
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
apdu.p2 = 0; /* first record, return FCI */
|
||||
apdu.lc = pathlen;
|
||||
apdu.data = path;
|
||||
apdu.datalen = pathlen;
|
||||
|
||||
if (file_out != NULL) {
|
||||
apdu.p2 = 0; /* first record, return FCI */
|
||||
apdu.resp = buf;
|
||||
apdu.resplen = sizeof(buf);
|
||||
apdu.le = card->max_recv_size > 0 ? card->max_recv_size : 256;
|
||||
} else
|
||||
} else {
|
||||
apdu.p2 = 0x0C; /* first record, return nothing */
|
||||
apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
|
||||
}
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
#include <arpa/inet.h> /* for htons() */
|
||||
#endif
|
||||
|
||||
#include "libopensc/opensc.h"
|
||||
#include "libopensc/asn1.h"
|
||||
|
@ -74,6 +77,7 @@ static const char *option_help[] = {
|
|||
|
||||
/* declare functions called by user commands */
|
||||
static int do_ls(int argc, char **argv);
|
||||
static int do_find(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);
|
||||
|
@ -81,6 +85,7 @@ static int do_create(int argc, char **argv);
|
|||
static int do_mkdir(int argc, char **argv);
|
||||
static int do_delete(int argc, char **argv);
|
||||
static int do_verify(int argc, char **argv);
|
||||
static int do_pace(int argc, char **argv);
|
||||
static int do_change(int argc, char **argv);
|
||||
static int do_unblock(int argc, char **argv);
|
||||
static int do_get(int argc, char **argv);
|
||||
|
@ -109,6 +114,9 @@ static struct command cmds[] = {
|
|||
{ do_ls,
|
||||
"ls", "",
|
||||
"list all files in the current DF" },
|
||||
{ do_find,
|
||||
"find", "[<start id> [<end id>]]",
|
||||
"find all files in the current DF" },
|
||||
{ do_cd,
|
||||
"cd", "{.. | <file id> | aid:<DF name>}",
|
||||
"change to another DF" },
|
||||
|
@ -133,6 +141,9 @@ static struct command cmds[] = {
|
|||
{ do_verify,
|
||||
"verify", "<key type><key ref> [<pin>]",
|
||||
"present a PIN or key to the card" },
|
||||
{ do_pace,
|
||||
"pace", "{pin|can|puk|mrz} [<secret>]",
|
||||
"Establish a PACE channel" },
|
||||
{ do_change,
|
||||
"change", "CHV<pin ref> [[<old pin>] <new pin>]",
|
||||
"change a PIN" },
|
||||
|
@ -283,6 +294,19 @@ static void check_ret(int r, int op, const char *err, const sc_file_t *file)
|
|||
fprintf(stderr, "ACL for operation: %s\n", util_acl_to_str(sc_file_get_acl_entry(file, op)));
|
||||
}
|
||||
|
||||
static int arg_to_fid(const char *arg, u8 *fid)
|
||||
{
|
||||
if (strlen(arg) != 4) {
|
||||
printf("Wrong ID length.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sscanf(arg, "%02X%02X", &fid[0], &fid[1]) != 2) {
|
||||
printf("Invalid ID.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int arg_to_path(const char *arg, sc_path_t *path, int is_id)
|
||||
{
|
||||
memset(path, 0, sizeof(sc_path_t));
|
||||
|
@ -300,19 +324,10 @@ static int arg_to_path(const char *arg, sc_path_t *path, int is_id)
|
|||
}
|
||||
} else {
|
||||
/* file id */
|
||||
unsigned int buf[2];
|
||||
u8 cbuf[2];
|
||||
if (arg_to_fid(arg, cbuf) < 0)
|
||||
return -1;
|
||||
|
||||
if (strlen(arg) != 4) {
|
||||
printf("Wrong ID length.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sscanf(arg, "%02X%02X", &buf[0], &buf[1]) != 2) {
|
||||
printf("Invalid ID.\n");
|
||||
return -1;
|
||||
}
|
||||
cbuf[0] = buf[0];
|
||||
cbuf[1] = buf[1];
|
||||
if ((cbuf[0] == 0x3F && cbuf[1] == 0x00) || is_id) {
|
||||
path->len = 2;
|
||||
memcpy(path->value, cbuf, 2);
|
||||
|
@ -410,6 +425,71 @@ static int do_ls(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int do_find(int argc, char **argv)
|
||||
{
|
||||
u8 fid[2], end[2];
|
||||
sc_path_t path;
|
||||
int r, count;
|
||||
|
||||
fid[0] = 0;
|
||||
fid[1] = 0;
|
||||
end[0] = 0xFF;
|
||||
end[1] = 0xFF;
|
||||
switch (argc) {
|
||||
case 2:
|
||||
if (arg_to_fid(argv[1], end) != 0)
|
||||
return usage(do_find);
|
||||
/* fall through */
|
||||
case 1:
|
||||
if (arg_to_fid(argv[0], fid) != 0)
|
||||
return usage(do_find);
|
||||
/* fall through */
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return usage(do_find);
|
||||
}
|
||||
|
||||
printf("FileID\tType Size\n");
|
||||
while (1) {
|
||||
sc_file_t *file = NULL;
|
||||
|
||||
printf("(%02X%02X)\r", fid[0], fid[1]);
|
||||
fflush(stdout);
|
||||
|
||||
if (current_path.type != SC_PATH_TYPE_DF_NAME) {
|
||||
path = current_path;
|
||||
sc_append_path_id(&path, fid, sizeof fid);
|
||||
} else {
|
||||
if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0) != SC_SUCCESS) {
|
||||
printf("unable to set path.\n");
|
||||
die(1);
|
||||
}
|
||||
}
|
||||
|
||||
r = sc_select_file(card, &path, &file);
|
||||
switch (r) {
|
||||
case SC_SUCCESS:
|
||||
file->id = (fid[0] << 8) | fid[1];
|
||||
print_file(file);
|
||||
sc_file_free(file);
|
||||
select_current_path_or_die();
|
||||
break;
|
||||
case SC_ERROR_NOT_ALLOWED:
|
||||
case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED:
|
||||
printf("(%02X%02X)\t%s\n", fid[0], fid[1], sc_strerror(r));
|
||||
break;
|
||||
}
|
||||
|
||||
if (fid[0] == end[0] && fid[1] == end[1])
|
||||
break;
|
||||
fid[1] = fid[1] + 1;
|
||||
if (fid[1] == 0)
|
||||
fid[0] = fid[0] + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_cd(int argc, char **argv)
|
||||
{
|
||||
sc_path_t path;
|
||||
|
@ -868,6 +948,45 @@ usage:
|
|||
}
|
||||
|
||||
|
||||
static int do_pace(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
struct establish_pace_channel_input pace_input;
|
||||
struct establish_pace_channel_output pace_output;
|
||||
memset(&pace_input, 0, sizeof(pace_input));
|
||||
memset(&pace_output, 0, sizeof(pace_output));
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
pace_input.pin = (unsigned char *) argv[1];
|
||||
/* fall through */
|
||||
case 1:
|
||||
if (strcmp(argv[0], "pin") == 0)
|
||||
pace_input.pin_id = PACE_PIN_ID_PIN;
|
||||
else if (strcmp(argv[0], "puk") == 0)
|
||||
pace_input.pin_id = PACE_PIN_ID_PUK;
|
||||
else if (strcmp(argv[0], "can") == 0)
|
||||
pace_input.pin_id = PACE_PIN_ID_CAN;
|
||||
else if (strcmp(argv[0], "mrz") == 0)
|
||||
pace_input.pin_id = PACE_PIN_ID_MRZ;
|
||||
else
|
||||
return usage(do_pace);
|
||||
break;
|
||||
default:
|
||||
return usage(do_pace);
|
||||
}
|
||||
|
||||
r = sc_perform_pace(card, &pace_input, &pace_output);
|
||||
if (r) {
|
||||
printf("PACE failed: %s\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
printf("Established PACE channel.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int do_change(int argc, char **argv)
|
||||
{
|
||||
int ref, r, tries_left = -1;
|
||||
|
|
Loading…
Reference in New Issue