pkcs15-tool: add compact output format

Closes https://github.com/OpenSC/OpenSC/pull/900
This commit is contained in:
Nuno Goncalves 2016-11-10 17:14:40 +01:00 committed by Frank Morgner
parent a16aaed41e
commit a25a2484f1
2 changed files with 176 additions and 85 deletions

View File

@ -72,7 +72,7 @@
<option>--dump</option>, <option>--dump</option>,
<option>-D</option> <option>-D</option>
</term> </term>
<listitem><para>Dump card objects.</para></listitem> <listitem><para>List all card objects.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -87,7 +87,7 @@
<option>--list-certificates</option>, <option>--list-certificates</option>,
<option>-c</option> <option>-c</option>
</term> </term>
<listitem><para>Lists all certificates stored on the token.</para></listitem> <listitem><para>List all certificates stored on the token.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -95,7 +95,7 @@
<option>--list-data-objects</option>, <option>--list-data-objects</option>,
<option>-C</option> <option>-C</option>
</term> </term>
<listitem><para>Lists all data objects stored on the token. <listitem><para>List all data objects stored on the token.
For some cards the PKCS#15 attributes of the private data objects are For some cards the PKCS#15 attributes of the private data objects are
protected for reading and need the authentication with the User PIN. protected for reading and need the authentication with the User PIN.
In such a case the <option>--verify-pin</option> option has to be used. In such a case the <option>--verify-pin</option> option has to be used.
@ -107,7 +107,7 @@
<option>--list-keys</option>, <option>--list-keys</option>,
<option>-k</option> <option>-k</option>
</term> </term>
<listitem><para>Lists all private keys stored on the token. General <listitem><para>List all private keys stored on the token. General
information about each private key is listed (eg. key name, id and information about each private key is listed (eg. key name, id and
algorithm). Actual private key values are not displayed. algorithm). Actual private key values are not displayed.
For some cards the PKCS#15 attributes of the private keys are protected for reading For some cards the PKCS#15 attributes of the private keys are protected for reading
@ -119,7 +119,7 @@
<term> <term>
<option>--list-pins</option> <option>--list-pins</option>
</term> </term>
<listitem><para>Lists all PINs stored on the token. General information <listitem><para>List all PINs stored on the token. General information
about each PIN is listed (eg. PIN name). Actual PIN values are not shown.</para></listitem> about each PIN is listed (eg. PIN name). Actual PIN values are not shown.</para></listitem>
</varlistentry> </varlistentry>
@ -127,10 +127,18 @@
<term> <term>
<option>--list-public-keys</option> <option>--list-public-keys</option>
</term> </term>
<listitem><para>Lists all public keys stored on the token, including <listitem><para>List all public keys stored on the token, including
key name, id, algorithm and length information.</para></listitem> key name, id, algorithm and length information.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>--short</option>
<option>-s</option>
</term>
<listitem><para>Output lists in compact format.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>--no-cache</option> <option>--no-cache</option>

View File

@ -70,6 +70,7 @@ static char * opt_bind_to_aid = NULL;
static const char * opt_newpin = NULL; static const char * opt_newpin = NULL;
static const char * opt_pin = NULL; static const char * opt_pin = NULL;
static const char * opt_puk = NULL; static const char * opt_puk = NULL;
static int compact = 0;
static int verbose = 0; static int verbose = 0;
static int opt_no_prompt = 0; static int opt_no_prompt = 0;
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
@ -117,6 +118,7 @@ static const struct option options[] = {
{ "list-data-objects", no_argument, NULL, 'C' }, { "list-data-objects", no_argument, NULL, 'C' },
{ "list-pins", no_argument, NULL, OPT_LIST_PINS }, { "list-pins", no_argument, NULL, OPT_LIST_PINS },
{ "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS }, { "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS },
{ "short", no_argument, NULL, 's' },
{ "dump", no_argument, NULL, 'D' }, { "dump", no_argument, NULL, 'D' },
{ "unblock-pin", no_argument, NULL, 'u' }, { "unblock-pin", no_argument, NULL, 'u' },
{ "change-pin", no_argument, NULL, OPT_CHANGE_PIN }, { "change-pin", no_argument, NULL, OPT_CHANGE_PIN },
@ -149,18 +151,19 @@ static const char *option_help[] = {
"Print OpenSC package version", "Print OpenSC package version",
"List card information", "List card information",
"List the on-card PKCS#15 applications", "List the on-card PKCS#15 applications",
"Reads certificate with ID <arg>", "Read certificate with ID <arg>",
"Lists certificates", "List certificates",
"Reads data object with OID, applicationName or label <arg>", "Reads data object with OID, applicationName or label <arg>",
"Outputs raw 8 bit data to stdout. File output will not be affected by this, it always uses raw mode.", "Outputs raw 8 bit data to stdout. File output will not be affected by this, it always uses raw mode.",
"Lists data objects", "List data objects",
"Lists PIN codes", "List PIN codes",
"Lists secret keys", "List secret keys",
"Dump card objects", "Output lists in compact format",
"List all card objects",
"Unblock PIN code", "Unblock PIN code",
"Change PIN or PUK code", "Change PIN or PUK code",
"Lists private keys", "List private keys",
"Lists public keys", "List public keys",
"Reads public key with ID <arg>", "Reads public key with ID <arg>",
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
"Reads public key with ID <arg>, outputs ssh format", "Reads public key with ID <arg>, outputs ssh format",
@ -206,6 +209,8 @@ struct _access_rule_text {
{0, NULL}, {0, NULL},
}; };
static const char *key_types[] = { "", "RSA", "DSA", "GOSTR3410", "EC", "", "", "" };
static void static void
print_access_rules(const struct sc_pkcs15_accessrule *rules, int num) print_access_rules(const struct sc_pkcs15_accessrule *rules, int num)
{ {
@ -253,6 +258,14 @@ static void print_cert_info(const struct sc_pkcs15_object *obj)
struct sc_pkcs15_cert *cert_parsed = NULL; struct sc_pkcs15_cert *cert_parsed = NULL;
int rv; int rv;
if (compact) {
printf("\tPath:%s ID:%s", sc_print_path(&cert_info->path),
sc_pkcs15_print_id(&cert_info->id));
if (cert_info->authority)
printf(" Authority");
return;
}
printf("X.509 Certificate [%.*s]\n", (int) sizeof obj->label, obj->label); printf("X.509 Certificate [%.*s]\n", (int) sizeof obj->label, obj->label);
print_common_flags(obj); print_common_flags(obj);
printf("\tAuthority : %s\n", cert_info->authority ? "yes" : "no"); printf("\tAuthority : %s\n", cert_info->authority ? "yes" : "no");
@ -270,7 +283,6 @@ static void print_cert_info(const struct sc_pkcs15_object *obj)
} }
} }
static int list_certificates(void) static int list_certificates(void)
{ {
int r, i; int r, i;
@ -281,7 +293,9 @@ static int list_certificates(void)
fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r));
return 1; return 1;
} }
if (verbose) if (compact)
printf("Card has %d Certificate(s).\n", r);
else if (verbose)
printf("Card has %d Certificate(s).\n\n", r); printf("Card has %d Certificate(s).\n\n", r);
for (i = 0; i < r; i++) { for (i = 0; i < r; i++) {
print_cert_info(objs[i]); print_cert_info(objs[i]);
@ -494,12 +508,40 @@ static int list_data_objects(void)
return 1; return 1;
} }
count = r; count = r;
if (verbose) if (compact)
printf("Card has %d Data object(s).\n", count);
else if (verbose)
printf("Card has %d Data object(s).\n\n", count); printf("Card has %d Data object(s).\n\n", count);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
int idx; int idx;
struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data;
if (compact) {
printf("\tPath:%-12s", sc_print_path(&cinfo->path));
if (sc_valid_oid(&cinfo->app_oid)) {
printf(" %i", cinfo->app_oid.value[0]);
for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && cinfo->app_oid.value[idx] != -1 ; idx++)
printf(".%i", cinfo->app_oid.value[idx]);
}
if (objs[i]->auth_id.len == 0) {
struct sc_pkcs15_data *data_object;
r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object);
if (r) {
fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r));
if (r == SC_ERROR_FILE_NOT_FOUND)
continue; /* DEE emulation may say there is a file */
return 1;
}
sc_pkcs15_free_data_object(data_object);
printf(" Size:%6lu", cinfo->data.len);
}else {
printf(" AuthID:%3s", sc_pkcs15_print_id(&objs[i]->auth_id));
}
printf(" %-20s", cinfo->app_label);
printf("\n");
continue;
}
if (objs[i]->label[0] != '\0') if (objs[i]->label[0] != '\0')
printf("Data object '%.*s'\n",(int) sizeof objs[i]->label, objs[i]->label); printf("Data object '%.*s'\n",(int) sizeof objs[i]->label, objs[i]->label);
else else
@ -531,38 +573,63 @@ static int list_data_objects(void)
return 0; return 0;
} }
static void print_prkey_info(const struct sc_pkcs15_object *obj) static void print_key_usages(int usage)
{ {
unsigned int i; size_t i;
struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data;
const char *types[] = { "", "RSA", "DSA", "GOSTR3410", "EC", "", "", "" };
const char *usages[] = { const char *usages[] = {
"encrypt", "decrypt", "sign", "signRecover", "encrypt", "decrypt", "sign", "signRecover", "wrap", "unwrap",
"wrap", "unwrap", "verify", "verifyRecover", "verify", "verifyRecover", "derive", "nonRepudiation"
"derive", "nonRepudiation"
}; };
const size_t usage_count = NELEMENTS(usages); const size_t usage_count = NELEMENTS(usages);
const char *access_flags[] = { for (i = 0; i < usage_count; i++)
"sensitive", "extract", "alwaysSensitive", if (usage & (1 << i))
"neverExtract", "local" printf(", %s", usages[i]);
}
static void print_key_access_flags(int flags)
{
size_t i;
const char *key_access_flags[] = {
"sensitive", "extract", "alwaysSensitive","neverExtract", "local"
}; };
const unsigned int af_count = NELEMENTS(access_flags); const size_t af_count = NELEMENTS(key_access_flags);
for (i = 0; i < af_count; i++)
if (flags & (1 << i))
printf(", %s", key_access_flags[i]);
}
static void print_prkey_info(const struct sc_pkcs15_object *obj)
{
struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data;
unsigned char guid[40]; unsigned char guid[40];
size_t guid_len; size_t guid_len;
printf("Private %s Key [%.*s]\n", types[7 & obj->type], (int) sizeof obj->label, obj->label); if (compact) {
printf("\t%-3s", key_types[7 & obj->type]);
if (prkey->modulus_length)
printf("[%lu]", (unsigned long)prkey->modulus_length);
else {
if (prkey->field_length)
printf("[%lu]", (unsigned long)prkey->field_length);
}
printf(" ID:%s", sc_pkcs15_print_id(&prkey->id));
printf(" Ref:0x%02X", prkey->key_reference);
if (obj->auth_id.len != 0)
printf(" AuthID:%s", sc_pkcs15_print_id(&obj->auth_id));
printf("\n\t %-16.*s [0x%X", 16, obj->label, prkey->usage);
print_key_usages(prkey->usage);
printf("]");
return;
}
printf("Private %s Key [%.*s]\n", key_types[7 & obj->type], (int) sizeof obj->label, obj->label);
print_common_flags(obj); print_common_flags(obj);
printf("\tUsage : [0x%X]", prkey->usage); printf("\tUsage : [0x%X]", prkey->usage);
for (i = 0; i < usage_count; i++) print_key_usages(prkey->usage);
if (prkey->usage & (1 << i)) {
printf(", %s", usages[i]);
}
printf("\n"); printf("\n");
printf("\tAccess Flags : [0x%X]", prkey->access_flags); printf("\tAccess Flags : [0x%X]", prkey->access_flags);
for (i = 0; i < af_count; i++) print_key_access_flags(prkey->access_flags);
if (prkey->access_flags & (1 << i))
printf(", %s", access_flags[i]);
printf("\n"); printf("\n");
print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES);
@ -604,7 +671,9 @@ static int list_private_keys(void)
fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r));
return 1; return 1;
} }
if (verbose) if (compact)
printf("Card has %d Private key(s).\n", r);
else if (verbose)
printf("Card has %d Private key(s).\n\n", r); printf("Card has %d Private key(s).\n\n", r);
for (i = 0; i < r; i++) { for (i = 0; i < r; i++) {
print_prkey_info(objs[i]); print_prkey_info(objs[i]);
@ -615,35 +684,34 @@ static int list_private_keys(void)
static void print_pubkey_info(const struct sc_pkcs15_object *obj) static void print_pubkey_info(const struct sc_pkcs15_object *obj)
{ {
unsigned int i;
const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data; const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data;
const char *types[] = { "", "RSA", "DSA", "GOSTR3410", "EC", "", "", "" };
const char *usages[] = {
"encrypt", "decrypt", "sign", "signRecover",
"wrap", "unwrap", "verify", "verifyRecover",
"derive", "nonRepudiation"
};
const unsigned int usage_count = NELEMENTS(usages);
const char *access_flags[] = {
"sensitive", "extract", "alwaysSensitive",
"neverExtract", "local"
};
const unsigned int af_count = NELEMENTS(access_flags);
int have_path = (pubkey->path.len != 0) || (pubkey->path.aid.len != 0); int have_path = (pubkey->path.len != 0) || (pubkey->path.aid.len != 0);
printf("Public %s Key [%.*s]\n", types[7 & obj->type], (int) sizeof obj->label, obj->label); if (compact) {
printf("\t%-3s", key_types[7 & obj->type]);
if (pubkey->modulus_length)
printf("[%lu]", (unsigned long)pubkey->modulus_length);
else
printf("[FieldLength:%lu]", (unsigned long)pubkey->field_length);
printf(" %s", sc_pkcs15_print_id(&pubkey->id));
printf(" Ref:0x%02X", pubkey->key_reference);
if (obj->auth_id.len != 0)
printf(" AuthID:%s", sc_pkcs15_print_id(&obj->auth_id));
printf(" %15.*s [0x%X", (int) sizeof obj->label, obj->label, pubkey->usage);
print_key_usages(pubkey->usage);
printf("]");
return;
}
printf("Public %s Key [%.*s]\n", key_types[7 & obj->type], (int) sizeof obj->label, obj->label);
print_common_flags(obj); print_common_flags(obj);
printf("\tUsage : [0x%X]", pubkey->usage); printf("\tUsage : [0x%X]", pubkey->usage);
for (i = 0; i < usage_count; i++) print_key_usages(pubkey->usage);
if (pubkey->usage & (1 << i)) {
printf(", %s", usages[i]);
}
printf("\n"); printf("\n");
printf("\tAccess Flags : [0x%X]", pubkey->access_flags); printf("\tAccess Flags : [0x%X]", pubkey->access_flags);
for (i = 0; i < af_count; i++) print_key_access_flags(pubkey->access_flags);
if (pubkey->access_flags & (1 << i))
printf(", %s", access_flags[i]);
printf("\n"); printf("\n");
print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES);
@ -683,7 +751,9 @@ static int list_public_keys(void)
fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r)); fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
return 1; return 1;
} }
if (verbose) if (compact)
printf("Card has %d Public key(s).\n", r);
else if (verbose)
printf("Card has %d Public key(s).\n\n", r); printf("Card has %d Public key(s).\n\n", r);
for (i = 0; i < r; i++) { for (i = 0; i < r; i++) {
print_pubkey_info(objs[i]); print_pubkey_info(objs[i]);
@ -756,35 +826,19 @@ static int read_public_key(void)
static void print_skey_info(const struct sc_pkcs15_object *obj) static void print_skey_info(const struct sc_pkcs15_object *obj)
{ {
unsigned int i;
struct sc_pkcs15_skey_info *skey = (struct sc_pkcs15_skey_info *) obj->data; struct sc_pkcs15_skey_info *skey = (struct sc_pkcs15_skey_info *) obj->data;
const char *types[] = { "generic", "DES", "2DES", "3DES"}; const char *types[] = { "generic", "DES", "2DES", "3DES"};
const char *usages[] = {
"encrypt", "decrypt", "sign", "signRecover",
"wrap", "unwrap", "verify", "verifyRecover",
"derive"
};
const size_t usage_count = NELEMENTS(usages);
const char *access_flags[] = {
"sensitive", "extract", "alwaysSensitive",
"neverExtract", "local"
};
const unsigned int af_count = NELEMENTS(access_flags);
unsigned char guid[40]; unsigned char guid[40];
size_t guid_len; size_t guid_len;
printf("Secret %s Key [%.*s]\n", types[3 & obj->type], (int) sizeof obj->label, obj->label); printf("Secret %s Key [%.*s]\n", types[3 & obj->type], (int) sizeof obj->label, obj->label);
print_common_flags(obj); print_common_flags(obj);
printf("\tUsage : [0x%X]", skey->usage); printf("\tUsage : [0x%X]", skey->usage);
for (i = 0; i < usage_count; i++) print_key_usages(skey->usage);
if (skey->usage & (1 << i))
printf(", %s", usages[i]);
printf("\n"); printf("\n");
printf("\tAccess Flags : [0x%X]", skey->access_flags); printf("\tAccess Flags : [0x%X]", skey->access_flags);
for (i = 0; i < af_count; i++) print_key_access_flags(skey->access_flags);
if (skey->access_flags & (1 << i))
printf(", %s", access_flags[i]);
printf("\n"); printf("\n");
print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES);
@ -1320,10 +1374,32 @@ static void print_pin_info(const struct sc_pkcs15_object *obj)
const size_t pf_count = NELEMENTS(pin_flags); const size_t pf_count = NELEMENTS(pin_flags);
size_t i; size_t i;
if (obj->type == SC_PKCS15_TYPE_AUTH_PIN) assert(obj->type == SC_PKCS15_TYPE_AUTH_PIN || obj->type == SC_PKCS15_TYPE_AUTH_AUTHKEY);
printf("PIN [%.*s]\n", (int) sizeof obj->label, obj->label);
else if (obj->type == SC_PKCS15_TYPE_AUTH_AUTHKEY) if (compact) {
printf("AuthKey [%.*s]\n", (int) sizeof obj->label, obj->label); printf("\t%-3s ID:%s", obj->type == SC_PKCS15_TYPE_AUTH_PIN ? "PIN" : "Key",
sc_pkcs15_print_id(&auth_info->auth_id));
if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN) {
const struct sc_pkcs15_pin_attributes *pin_attrs = &(auth_info->attrs.pin);
printf(" Ref:0x%02X", pin_attrs->reference);
}
else {
const struct sc_pkcs15_authkey_attributes *attrs = &auth_info->attrs.authkey;
printf(" Derived:%i", attrs->derived);
printf(" SecretKeyID:%s", sc_pkcs15_print_id(&attrs->skey_id));
}
if (obj->auth_id.len)
printf(" AuthID:%s", sc_pkcs15_print_id(&obj->auth_id));
if (auth_info->path.len || auth_info->path.aid.len)
printf(" Path:%s", sc_print_path(&auth_info->path));
if (auth_info->tries_left >= 0)
printf(" Tries:%d", auth_info->tries_left);
printf(" %.*s", (int) sizeof obj->label, obj->label);
return;
}
printf("%s [%.*s]\n", obj->type == SC_PKCS15_TYPE_AUTH_PIN ? "PIN" : "AuthKey",
(int) sizeof obj->label, obj->label);
print_common_flags(obj); print_common_flags(obj);
if (obj->auth_id.len) if (obj->auth_id.len)
@ -1371,8 +1447,11 @@ static int list_pins(void)
fprintf(stderr, "AUTH objects enumeration failed: %s\n", sc_strerror(r)); fprintf(stderr, "AUTH objects enumeration failed: %s\n", sc_strerror(r));
return 1; return 1;
} }
if (verbose) if (compact)
printf("Card has %d Authentication object(s).\n", r);
else if (verbose)
printf("Card has %d Authentication object(s).\n\n", r); printf("Card has %d Authentication object(s).\n\n", r);
for (i = 0; i < r; i++) { for (i = 0; i < r; i++) {
print_pin_info(objs[i]); print_pin_info(objs[i]);
printf("\n"); printf("\n");
@ -1406,7 +1485,8 @@ static int list_apps(FILE *fout)
return 0; return 0;
} }
static void list_info(void){ static void list_info(void)
{
const char *flags[] = { const char *flags[] = {
"Read-only", "Read-only",
"Login required", "Login required",
@ -1887,7 +1967,7 @@ int main(int argc, char * const argv[])
c = OPT_PUK; c = OPT_PUK;
while (1) { while (1) {
c = getopt_long(argc, argv, "r:cuko:va:LR:CwDTU", options, &long_optind); c = getopt_long(argc, argv, "r:cuko:sva:LR:CwDTU", options, &long_optind);
if (c == -1) if (c == -1)
break; break;
if (c == '?') if (c == '?')
@ -1992,6 +2072,9 @@ int main(int argc, char * const argv[])
case 'o': case 'o':
opt_outfile = optarg; opt_outfile = optarg;
break; break;
case 's':
compact++;
break;
case 'v': case 'v':
verbose++; verbose++;
break; break;