2012-05-19 18:28:25 +00:00
|
|
|
/*
|
|
|
|
* openpgp-tool.c: OpenPGP card utility
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Peter Marschall <peter@adpm.de>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "common/compat_getopt.h"
|
|
|
|
#include "libopensc/opensc.h"
|
|
|
|
#include "libopensc/asn1.h"
|
|
|
|
#include "libopensc/cards.h"
|
2012-06-06 10:04:33 +00:00
|
|
|
#include "libopensc/cardctl.h"
|
2013-02-20 04:54:30 +00:00
|
|
|
#include "libopensc/log.h"
|
2012-05-19 18:28:25 +00:00
|
|
|
#include "util.h"
|
2013-05-25 02:22:28 +00:00
|
|
|
#include "libopensc/log.h"
|
2012-05-19 18:28:25 +00:00
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
#define OPT_RAW 256
|
|
|
|
#define OPT_PRETTY 257
|
2012-06-06 10:04:33 +00:00
|
|
|
#define OPT_VERIFY 258
|
|
|
|
#define OPT_PIN 259
|
2012-05-26 16:52:05 +00:00
|
|
|
|
2012-05-19 18:28:25 +00:00
|
|
|
/* define structures */
|
|
|
|
struct ef_name_map {
|
|
|
|
const char *name;
|
|
|
|
const char *env_name;
|
|
|
|
const char *ef;
|
|
|
|
char *(*prettify_value)(char *);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* declare functions */
|
|
|
|
static void show_version(void);
|
2012-05-26 16:52:05 +00:00
|
|
|
static char *prettify_name(char *str);
|
2012-05-19 18:28:25 +00:00
|
|
|
static char *prettify_language(char *str);
|
|
|
|
static char *prettify_gender(char *str);
|
|
|
|
static void display_data(const struct ef_name_map *mapping, char *value);
|
|
|
|
static int decode_options(int argc, char **argv);
|
2012-05-26 16:52:05 +00:00
|
|
|
static int do_userinfo(sc_card_t *card);
|
2012-05-19 18:28:25 +00:00
|
|
|
|
|
|
|
/* define global variables */
|
2012-05-26 16:52:05 +00:00
|
|
|
static int actions = 0;
|
2012-05-19 18:28:25 +00:00
|
|
|
static char *opt_reader = NULL;
|
|
|
|
static int opt_wait = 0;
|
2012-05-26 16:52:05 +00:00
|
|
|
static int opt_raw = 0;
|
|
|
|
static int verbose = 0;
|
|
|
|
static int opt_userinfo = 0;
|
|
|
|
static int opt_cardinfo = 0;
|
2012-05-19 18:28:25 +00:00
|
|
|
static char *exec_program = NULL;
|
2012-06-06 10:04:33 +00:00
|
|
|
static int opt_genkey = 0;
|
|
|
|
static int opt_keylen = 0;
|
|
|
|
static u8 key_id = 0;
|
|
|
|
static unsigned int key_len = 2048;
|
|
|
|
static int opt_verify = 0;
|
|
|
|
static char *verifytype = NULL;
|
|
|
|
static int opt_pin = 0;
|
|
|
|
static char *pin = NULL;
|
2013-03-04 04:28:08 +00:00
|
|
|
static int opt_erase = 0;
|
2012-05-26 16:52:05 +00:00
|
|
|
|
|
|
|
static const char *app_name = "openpgp-tool";
|
2012-05-19 18:28:25 +00:00
|
|
|
|
|
|
|
static const struct option options[] = {
|
2012-05-26 16:52:05 +00:00
|
|
|
{ "reader", required_argument, NULL, 'r' },
|
|
|
|
{ "wait", no_argument, NULL, 'w' },
|
|
|
|
{ "exec", required_argument, NULL, 'x' },
|
|
|
|
{ "raw", no_argument, NULL, OPT_RAW },
|
|
|
|
{ "pretty", no_argument, NULL, OPT_PRETTY },
|
|
|
|
{ "card-info", no_argument, NULL, 'C' },
|
|
|
|
{ "user-info", no_argument, NULL, 'U' },
|
2012-06-06 10:04:33 +00:00
|
|
|
{ "gen-key", required_argument, NULL, 'G' },
|
|
|
|
{ "key-length",required_argument, NULL, 'L' },
|
2012-05-26 16:52:05 +00:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "verbose", no_argument, NULL, 'v' },
|
|
|
|
{ "version", no_argument, NULL, 'V' },
|
2013-03-04 04:28:08 +00:00
|
|
|
{ "erase", no_argument, NULL, 'E' },
|
2012-06-06 10:04:33 +00:00
|
|
|
{ "verify", required_argument, NULL, OPT_VERIFY },
|
|
|
|
{ "pin", required_argument, NULL, OPT_PIN },
|
2012-05-19 18:28:25 +00:00
|
|
|
{ NULL, 0, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
static const char *option_help[] = {
|
|
|
|
/* r */ "Use reader number <arg> [0]",
|
|
|
|
/* w */ "Wait for card insertion",
|
|
|
|
/* x */ "Execute program <arg> with data in env vars",
|
|
|
|
"Print values in raw format",
|
|
|
|
"Print values in pretty format",
|
|
|
|
/* C */ NULL,
|
|
|
|
/* U */ "Show card holder information",
|
2012-06-06 10:04:33 +00:00
|
|
|
/* G */ "Generate key",
|
|
|
|
/* L */ "Key length (default 2048)",
|
2012-05-26 16:52:05 +00:00
|
|
|
/* h */ "Print this help message",
|
|
|
|
/* v */ "Verbose operation. Use several times to enable debug output.",
|
2012-06-06 10:04:33 +00:00
|
|
|
/* V */ "Show version number",
|
2013-03-04 04:28:08 +00:00
|
|
|
/* E */ "Erase (reset) the card",
|
2012-06-06 10:04:33 +00:00
|
|
|
"Verify PIN (CHV1, CHV2, CHV3...)",
|
|
|
|
"PIN string"
|
2012-05-26 16:52:05 +00:00
|
|
|
};
|
2012-05-19 18:28:25 +00:00
|
|
|
|
|
|
|
static const struct ef_name_map openpgp_data[] = {
|
2012-05-26 16:52:05 +00:00
|
|
|
{ "Account", "OPENGPG_ACCOUNT", "3F00:005E", NULL },
|
|
|
|
{ "URL", "OPENPGP_URL", "3F00:5F50", NULL },
|
|
|
|
{ "Name", "OPENPGP_NAME", "3F00:0065:005B", prettify_name },
|
2012-05-19 18:28:25 +00:00
|
|
|
{ "Language", "OPENPGP_LANG", "3F00:0065:5F2D", prettify_language },
|
|
|
|
{ "Gender", "OPENPGP_GENDER", "3F00:0065:5F35", prettify_gender },
|
2012-05-26 16:52:05 +00:00
|
|
|
{ "DO 0101", "OPENPGP_DO0101", "3F00:0101", NULL },
|
|
|
|
{ "DO 0102", "OPENPGP_DO0102", "3F00:0102", NULL },
|
|
|
|
// { "DO 0103", "OPENPGP_DO0103", "3F00:0103", NULL },
|
|
|
|
// { "DO 0104", "OPENPGP_DO0104", "3F00:0104", NULL },
|
2012-05-19 18:28:25 +00:00
|
|
|
{ NULL, NULL, NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void show_version(void)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"openpgp-tool - OpenPGP card utility version " PACKAGE_VERSION "\n"
|
|
|
|
"\n"
|
|
|
|
"Copyright (c) 2012 Peter Marschall <peter@adpm.de>\n"
|
|
|
|
"Licensed under LGPL v2\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
/* prettify card holder's name */
|
|
|
|
static char *prettify_name(char *str)
|
2012-05-19 18:28:25 +00:00
|
|
|
{
|
2012-05-26 16:52:05 +00:00
|
|
|
if (str != NULL) {
|
|
|
|
char *src = str;
|
|
|
|
char *dst = str;
|
|
|
|
|
|
|
|
while (*src != '\0') {
|
|
|
|
*dst = *src++;
|
|
|
|
if (*dst == '<') {
|
|
|
|
if (*src == '<')
|
|
|
|
src++;
|
|
|
|
*dst = ' ';
|
|
|
|
}
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
*dst = '\0';
|
|
|
|
}
|
|
|
|
return str;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* prettify language */
|
|
|
|
static char *prettify_language(char *str)
|
|
|
|
{
|
|
|
|
if (str != NULL) {
|
|
|
|
switch (strlen(str)) {
|
|
|
|
case 8: memmove(str+7, str+6, 1+strlen(str+6));
|
|
|
|
str[6] = ',';
|
|
|
|
/* fall through */
|
|
|
|
case 6: memmove(str+5, str+4, 1+strlen(str+4));
|
|
|
|
str[4] = ',';
|
|
|
|
/* fall through */
|
2012-05-26 16:52:05 +00:00
|
|
|
case 4: memmove(str+3, str+2, 1+strlen(str+2));
|
2012-05-19 18:28:25 +00:00
|
|
|
str[2] = ',';
|
|
|
|
/* fall through */
|
|
|
|
case 2: return str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* convert the raw ISO-5218 SEX value to an english word */
|
|
|
|
static char *prettify_gender(char *str)
|
|
|
|
{
|
|
|
|
if (str != NULL) {
|
|
|
|
switch (*str) {
|
|
|
|
case '0': return "unknown";
|
|
|
|
case '1': return "male";
|
|
|
|
case '2': return "female";
|
|
|
|
case '9': return "not applicable";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void display_data(const struct ef_name_map *mapping, char *value)
|
|
|
|
{
|
|
|
|
if (mapping != NULL && value != NULL) {
|
2012-05-26 16:52:05 +00:00
|
|
|
if (mapping->prettify_value != NULL && !opt_raw)
|
2012-05-19 18:28:25 +00:00
|
|
|
value = mapping->prettify_value(value);
|
|
|
|
|
|
|
|
if (value != NULL) {
|
|
|
|
if (exec_program) {
|
|
|
|
char *envvar;
|
|
|
|
|
|
|
|
envvar = malloc(strlen(mapping->env_name) +
|
|
|
|
strlen(value) + 2);
|
|
|
|
if (envvar != NULL) {
|
|
|
|
strcpy(envvar, mapping->env_name);
|
|
|
|
strcat(envvar, "=");
|
|
|
|
strcat(envvar, value);
|
|
|
|
putenv(envvar);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *label = mapping->name;
|
|
|
|
|
2014-06-01 17:42:01 +00:00
|
|
|
printf("%s:%*s%s\n", label, (int)(10-strlen(label)), "", value);
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int decode_options(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
2013-03-04 04:28:08 +00:00
|
|
|
while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVE", options, (int *) 0)) != EOF) {
|
2012-05-19 18:28:25 +00:00
|
|
|
switch (c) {
|
|
|
|
case 'r':
|
|
|
|
opt_reader = optarg;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if (exec_program)
|
|
|
|
free(exec_program);
|
|
|
|
exec_program = strdup(optarg);
|
|
|
|
break;
|
2012-05-26 16:52:05 +00:00
|
|
|
case OPT_RAW:
|
|
|
|
opt_raw = 1;
|
|
|
|
break;
|
|
|
|
case OPT_PRETTY:
|
|
|
|
opt_raw = 0;
|
2012-05-19 18:28:25 +00:00
|
|
|
break;
|
2012-06-06 10:04:33 +00:00
|
|
|
case OPT_VERIFY:
|
|
|
|
opt_verify++;
|
|
|
|
if (verifytype)
|
|
|
|
free(verifytype);
|
|
|
|
verifytype = strdup(optarg);
|
|
|
|
actions++;
|
|
|
|
break;
|
|
|
|
case OPT_PIN:
|
|
|
|
opt_pin++;
|
|
|
|
if (pin)
|
|
|
|
free(pin);
|
|
|
|
pin = strdup(optarg);
|
|
|
|
break;
|
2012-05-26 16:52:05 +00:00
|
|
|
case 'C':
|
|
|
|
opt_cardinfo++;
|
|
|
|
actions++;;
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
opt_userinfo++;
|
|
|
|
actions++;;
|
|
|
|
break;
|
2012-06-06 10:04:33 +00:00
|
|
|
case 'G':
|
|
|
|
opt_genkey++;
|
|
|
|
key_id = optarg[0] - '0';
|
|
|
|
actions++;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
opt_keylen++;
|
|
|
|
key_len = atoi(optarg);
|
|
|
|
actions++;
|
|
|
|
break;
|
2012-05-26 16:52:05 +00:00
|
|
|
case 'h':
|
2012-05-26 16:53:09 +00:00
|
|
|
util_print_usage_and_die(app_name, options, option_help, NULL);
|
2012-05-19 18:28:25 +00:00
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
opt_wait = 1;
|
|
|
|
break;
|
2012-05-26 16:52:05 +00:00
|
|
|
case 'v':
|
|
|
|
verbose++;
|
|
|
|
break;
|
2012-05-19 18:28:25 +00:00
|
|
|
case 'V':
|
|
|
|
show_version();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
break;
|
2013-03-04 04:28:08 +00:00
|
|
|
case 'E':
|
|
|
|
opt_erase++;
|
|
|
|
break;
|
2012-05-19 18:28:25 +00:00
|
|
|
default:
|
2012-05-26 16:53:09 +00:00
|
|
|
util_print_usage_and_die(app_name, options, option_help, NULL);
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
return optind;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
static int do_userinfo(sc_card_t *card)
|
2012-05-19 18:28:25 +00:00
|
|
|
{
|
|
|
|
int i;
|
2014-02-25 08:07:09 +00:00
|
|
|
/* FIXME there are no length checks on buf. */
|
2012-05-19 18:28:25 +00:00
|
|
|
unsigned char buf[2048];
|
|
|
|
|
|
|
|
for (i = 0; openpgp_data[i].ef != NULL; i++) {
|
|
|
|
sc_path_t path;
|
|
|
|
sc_file_t *file;
|
2014-06-01 17:42:01 +00:00
|
|
|
int count;
|
2012-05-19 18:28:25 +00:00
|
|
|
int r;
|
|
|
|
|
|
|
|
sc_format_path(openpgp_data[i].ef, &path);
|
|
|
|
r = sc_select_file(card, &path, &file);
|
|
|
|
if (r) {
|
2014-06-01 17:42:01 +00:00
|
|
|
fprintf(stderr, "Failed to select EF %s: %s\n", openpgp_data[i].ef, sc_strerror(r));
|
2012-05-26 16:52:05 +00:00
|
|
|
return EXIT_FAILURE;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
count = file->size;
|
2014-06-01 17:42:01 +00:00
|
|
|
if (!count)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (count > (int)sizeof(buf) - 1) {
|
|
|
|
fprintf(stderr, "Too small buffer to read the OpenPGP data\n");
|
|
|
|
return EXIT_FAILURE;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
2014-06-01 17:42:01 +00:00
|
|
|
|
|
|
|
r = sc_read_binary(card, 0, buf, count, 0);
|
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "%s: read failed - %s\n", openpgp_data[i].ef, sc_strerror(r));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
if (r != count) {
|
|
|
|
fprintf(stderr, "%s: expecting %d, got only %d bytes\n", openpgp_data[i].ef, count, r);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[count] = '\0';
|
|
|
|
|
|
|
|
display_data(openpgp_data + i, (char *) buf);
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
return EXIT_SUCCESS;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-06 10:04:33 +00:00
|
|
|
int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_cardctl_openpgp_keygen_info_t key_info;
|
|
|
|
u8 fingerprints[60];
|
|
|
|
sc_path_t path;
|
|
|
|
sc_file_t *file;
|
|
|
|
|
2013-02-20 04:54:30 +00:00
|
|
|
LOG_FUNC_CALLED(card->ctx);
|
|
|
|
|
2012-06-06 10:04:33 +00:00
|
|
|
if (key_id < 1 || key_id > 3) {
|
|
|
|
printf("Unknown key ID %d.\n", key_id);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t));
|
|
|
|
key_info.keytype = key_id;
|
|
|
|
key_info.modulus_len = key_len;
|
|
|
|
key_info.modulus = malloc(key_len/8);
|
|
|
|
r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info);
|
|
|
|
free(key_info.modulus);
|
|
|
|
if (r < 0) {
|
|
|
|
printf("Failed to generate key. Error %s.\n", sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
sc_format_path("006E007300C5", &path);
|
|
|
|
r = sc_select_file(card, &path, &file);
|
|
|
|
r = sc_read_binary(card, 0, fingerprints, 60, 0);
|
|
|
|
if (r < 0) {
|
|
|
|
printf("Failed to retrieve fingerprints. Error %s.\n", sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(key_id - 1), 20));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-27 14:44:32 +00:00
|
|
|
int do_verify(sc_card_t *card, char *type, char *pin)
|
2012-06-06 10:04:33 +00:00
|
|
|
{
|
|
|
|
struct sc_pin_cmd_data data;
|
|
|
|
int tries_left;
|
|
|
|
int r;
|
|
|
|
if (!type || !pin)
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
if (strncasecmp("CHV", type, 3) != 0) {
|
|
|
|
printf("Invalid PIN type. Please use CHV1, CHV2 or CHV3.\n");
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type[3] < '1' || type[3] > '3' || type[4] != '\0') {
|
|
|
|
printf("Invalid PIN reference. Please use CHV1, CHV2 or CHV3.\n");
|
|
|
|
return SC_ERROR_INVALID_PIN_REFERENCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&data, 0, sizeof(struct sc_pin_cmd_data));
|
|
|
|
data.cmd = SC_PIN_CMD_VERIFY;
|
|
|
|
data.pin_type = SC_AC_CHV;
|
|
|
|
data.pin_reference = type[3] - '0';
|
2014-02-25 08:07:09 +00:00
|
|
|
data.pin1.data = (unsigned char *) pin;
|
2012-06-06 10:04:33 +00:00
|
|
|
data.pin1.len = strlen(pin);
|
|
|
|
r = sc_pin_cmd(card, &data, &tries_left);
|
|
|
|
return r;
|
|
|
|
}
|
2012-05-19 18:28:25 +00:00
|
|
|
|
2013-03-04 04:28:08 +00:00
|
|
|
int do_erase(sc_card_t *card)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
/* Check card version */
|
|
|
|
if (card->type != SC_CARD_TYPE_OPENPGP_V2) {
|
|
|
|
printf("Do not erase card which is not OpenPGP v2\n");
|
|
|
|
}
|
|
|
|
printf("Erase card\n");
|
|
|
|
r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2012-05-19 18:28:25 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
sc_context_t *ctx = NULL;
|
|
|
|
sc_context_param_t ctx_param;
|
|
|
|
sc_card_t *card = NULL;
|
|
|
|
int r;
|
2012-05-26 16:52:05 +00:00
|
|
|
int argind = 0;
|
|
|
|
int exit_status = EXIT_FAILURE;
|
2012-05-19 18:28:25 +00:00
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
/* decode options */
|
2012-05-19 18:28:25 +00:00
|
|
|
argind = decode_options(argc, argv);
|
|
|
|
|
|
|
|
/* connect to the card */
|
|
|
|
memset(&ctx_param, 0, sizeof(ctx_param));
|
|
|
|
ctx_param.ver = 0;
|
|
|
|
ctx_param.app_name = app_name;
|
|
|
|
|
|
|
|
r = sc_context_create(&ctx, &ctx_param);
|
|
|
|
if (r) {
|
2012-05-26 16:52:05 +00:00
|
|
|
util_fatal("failed to establish context: %s\n",
|
2012-05-19 18:28:25 +00:00
|
|
|
sc_strerror(r));
|
2012-05-26 16:52:05 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (verbose > 1) {
|
|
|
|
ctx->debug = verbose;
|
|
|
|
sc_ctx_log_to_file(ctx, "stderr");
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
2012-05-26 16:52:05 +00:00
|
|
|
|
|
|
|
r = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose);
|
2012-05-19 18:28:25 +00:00
|
|
|
if (r) {
|
2012-05-26 16:52:05 +00:00
|
|
|
util_fatal("failed to connect to card: %s\n",
|
2012-05-19 18:28:25 +00:00
|
|
|
sc_strerror(r));
|
2012-05-26 16:52:05 +00:00
|
|
|
return EXIT_FAILURE;
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
/* check card type */
|
2012-05-19 18:28:25 +00:00
|
|
|
if ((card->type != SC_CARD_TYPE_OPENPGP_V1) &&
|
2013-02-20 04:54:30 +00:00
|
|
|
(card->type != SC_CARD_TYPE_OPENPGP_V2) &&
|
|
|
|
(card->type != SC_CARD_TYPE_OPENPGP_GNUK)) {
|
2012-05-26 16:52:05 +00:00
|
|
|
util_error("not an OpenPGP card");
|
2013-02-20 04:54:30 +00:00
|
|
|
sc_log(card->ctx, "Card type %X", card->type);
|
2012-05-26 16:52:05 +00:00
|
|
|
exit_status = EXIT_FAILURE;
|
2012-05-19 18:28:25 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
/* fail on too many arguments */
|
2012-05-19 18:28:25 +00:00
|
|
|
if (argind > argc)
|
2012-05-26 16:53:09 +00:00
|
|
|
util_print_usage_and_die(app_name, options, option_help, NULL);
|
2012-05-19 18:28:25 +00:00
|
|
|
|
2012-05-26 16:52:05 +00:00
|
|
|
/* set default action */
|
|
|
|
if (!actions)
|
|
|
|
opt_userinfo = 1;
|
|
|
|
|
|
|
|
if (opt_userinfo)
|
|
|
|
exit_status |= do_userinfo(card);
|
2012-05-19 18:28:25 +00:00
|
|
|
|
2012-06-06 10:04:33 +00:00
|
|
|
if (opt_verify && opt_pin) {
|
|
|
|
exit_status |= do_verify(card, verifytype, pin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt_genkey)
|
|
|
|
exit_status |= do_genkey(card, key_id, key_len);
|
|
|
|
|
2012-05-19 18:28:25 +00:00
|
|
|
if (exec_program) {
|
|
|
|
char *const largv[] = {exec_program, NULL};
|
|
|
|
sc_unlock(card);
|
|
|
|
sc_disconnect_card(card);
|
|
|
|
sc_release_context(ctx);
|
|
|
|
execv(exec_program, largv);
|
|
|
|
/* we should not get here */
|
|
|
|
perror("execv()");
|
2012-05-26 16:52:05 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2012-05-19 18:28:25 +00:00
|
|
|
}
|
|
|
|
|
2013-03-04 04:28:08 +00:00
|
|
|
if (opt_erase)
|
|
|
|
exit_status != do_erase(card);
|
|
|
|
|
2012-05-19 18:28:25 +00:00
|
|
|
out:
|
|
|
|
sc_unlock(card);
|
|
|
|
sc_disconnect_card(card);
|
|
|
|
sc_release_context(ctx);
|
2012-05-26 16:52:05 +00:00
|
|
|
|
2012-05-19 18:28:25 +00:00
|
|
|
exit(exit_status);
|
|
|
|
}
|