2001-11-22 15:40:51 +00:00
|
|
|
/*
|
2005-06-16 19:35:31 +00:00
|
|
|
* pkcs15-crypt.c: Tool for cryptography operations with smart cards
|
2001-11-22 15:40:51 +00:00
|
|
|
*
|
2006-12-19 21:35:42 +00:00
|
|
|
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
2001-11-22 15:40:51 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2001-12-30 21:17:34 +00:00
|
|
|
#include <stdio.h>
|
2001-11-22 15:40:51 +00:00
|
|
|
#include <stdlib.h>
|
2002-10-19 14:04:52 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-12-30 21:17:34 +00:00
|
|
|
#include <unistd.h>
|
2002-06-14 12:52:56 +00:00
|
|
|
#endif
|
2001-11-22 15:40:51 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2008-03-06 16:06:59 +00:00
|
|
|
#ifdef ENABLE_OPENSSL
|
2002-04-18 11:00:08 +00:00
|
|
|
#include <openssl/evp.h>
|
|
|
|
#include <openssl/rsa.h>
|
|
|
|
#include <openssl/dsa.h>
|
|
|
|
#endif
|
2010-03-04 08:14:36 +00:00
|
|
|
|
|
|
|
#include "common/compat_getpass.h"
|
2017-11-17 09:47:53 +00:00
|
|
|
#include "libopensc/internal.h"
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "libopensc/opensc.h"
|
|
|
|
#include "libopensc/pkcs15.h"
|
2015-02-15 12:57:47 +00:00
|
|
|
#include "libopensc/asn1.h"
|
2002-04-05 13:48:00 +00:00
|
|
|
#include "util.h"
|
2001-11-22 15:40:51 +00:00
|
|
|
|
2007-06-29 13:19:19 +00:00
|
|
|
static const char *app_name = "pkcs15-crypt";
|
2002-03-24 14:12:38 +00:00
|
|
|
|
2010-01-24 15:29:47 +00:00
|
|
|
static int verbose = 0, opt_wait = 0, opt_raw = 0;
|
|
|
|
static char * opt_reader;
|
2007-06-21 12:58:57 +00:00
|
|
|
static char * opt_pincode = NULL, * opt_key_id = NULL;
|
|
|
|
static char * opt_input = NULL, * opt_output = NULL;
|
2011-01-05 15:22:12 +00:00
|
|
|
static char * opt_bind_to_aid = NULL;
|
2015-02-15 12:57:47 +00:00
|
|
|
static char * opt_sig_format = NULL;
|
2007-06-21 12:58:57 +00:00
|
|
|
static int opt_crypt_flags = 0;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
2003-04-11 11:28:09 +00:00
|
|
|
enum {
|
2015-02-15 12:57:47 +00:00
|
|
|
OPT_SHA1 = 0x100,
|
2007-02-02 22:15:14 +00:00
|
|
|
OPT_SHA256,
|
|
|
|
OPT_SHA384,
|
|
|
|
OPT_SHA512,
|
|
|
|
OPT_SHA224,
|
2003-04-11 11:28:09 +00:00
|
|
|
OPT_MD5,
|
|
|
|
OPT_PKCS1,
|
2011-01-05 15:22:12 +00:00
|
|
|
OPT_BIND_TO_AID,
|
2016-03-28 18:41:19 +00:00
|
|
|
OPT_VERSION,
|
2003-04-11 11:28:09 +00:00
|
|
|
};
|
2001-11-22 15:40:51 +00:00
|
|
|
|
2007-06-29 13:19:19 +00:00
|
|
|
static const struct option options[] = {
|
2016-03-28 18:41:19 +00:00
|
|
|
{ "version", 0, NULL, OPT_VERSION },
|
2007-06-21 12:58:57 +00:00
|
|
|
{ "sign", 0, NULL, 's' },
|
|
|
|
{ "decipher", 0, NULL, 'c' },
|
|
|
|
{ "key", 1, NULL, 'k' },
|
|
|
|
{ "reader", 1, NULL, 'r' },
|
|
|
|
{ "input", 1, NULL, 'i' },
|
|
|
|
{ "output", 1, NULL, 'o' },
|
2015-02-15 12:57:47 +00:00
|
|
|
{ "signature-format", 1, NULL, 'f' },
|
2007-06-21 12:58:57 +00:00
|
|
|
{ "raw", 0, NULL, 'R' },
|
|
|
|
{ "sha-1", 0, NULL, OPT_SHA1 },
|
|
|
|
{ "sha-256", 0, NULL, OPT_SHA256 },
|
|
|
|
{ "sha-384", 0, NULL, OPT_SHA384 },
|
|
|
|
{ "sha-512", 0, NULL, OPT_SHA512 },
|
|
|
|
{ "sha-224", 0, NULL, OPT_SHA224 },
|
|
|
|
{ "md5", 0, NULL, OPT_MD5 },
|
|
|
|
{ "pkcs1", 0, NULL, OPT_PKCS1 },
|
|
|
|
{ "pin", 1, NULL, 'p' },
|
2011-01-06 14:39:19 +00:00
|
|
|
{ "aid", 1, NULL, OPT_BIND_TO_AID },
|
2007-06-21 12:58:57 +00:00
|
|
|
{ "wait", 0, NULL, 'w' },
|
|
|
|
{ "verbose", 0, NULL, 'v' },
|
|
|
|
{ NULL, 0, NULL, 0 }
|
2001-11-22 15:40:51 +00:00
|
|
|
};
|
|
|
|
|
2007-06-29 13:19:19 +00:00
|
|
|
static const char *option_help[] = {
|
2016-04-27 18:07:54 +00:00
|
|
|
"Print OpenSC package version",
|
2001-11-22 15:40:51 +00:00
|
|
|
"Performs digital signature operation",
|
|
|
|
"Decipher operation",
|
|
|
|
"Selects the private key ID to use",
|
|
|
|
"Uses reader number <arg>",
|
2016-01-21 16:30:26 +00:00
|
|
|
"Selects the input file to use (defaults to stdin)",
|
|
|
|
"Outputs to file <arg> (defaults to stdout)",
|
2015-02-15 12:57:47 +00:00
|
|
|
"Format for ECDSA signature <arg>: 'rs' (default), 'sequence', 'openssl'",
|
2004-08-21 14:26:16 +00:00
|
|
|
"Outputs raw 8 bit data",
|
2001-11-22 15:40:51 +00:00
|
|
|
"Input file is a SHA-1 hash",
|
2007-02-02 22:15:14 +00:00
|
|
|
"Input file is a SHA-256 hash",
|
|
|
|
"Input file is a SHA-384 hash",
|
|
|
|
"Input file is a SHA-512 hash",
|
|
|
|
"Input file is a SHA-224 hash",
|
2002-03-14 17:02:08 +00:00
|
|
|
"Input file is a MD5 hash",
|
2002-01-20 21:20:09 +00:00
|
|
|
"Use PKCS #1 v1.5 padding",
|
2006-10-02 10:34:57 +00:00
|
|
|
"Uses password (PIN) <arg> (use - for reading PIN from STDIN)",
|
2011-01-06 14:39:19 +00:00
|
|
|
"Specify AID of the on-card PKCS#15 application to be binded to (in hexadecimal form)",
|
2003-01-03 17:07:56 +00:00
|
|
|
"Wait for card insertion",
|
2004-06-13 20:13:12 +00:00
|
|
|
"Verbose operation. Use several times to enable debug output.",
|
2001-11-22 15:40:51 +00:00
|
|
|
};
|
|
|
|
|
2007-06-21 12:58:57 +00:00
|
|
|
static sc_context_t *ctx = NULL;
|
|
|
|
static sc_card_t *card = NULL;
|
|
|
|
static struct sc_pkcs15_card *p15card = NULL;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
2007-06-21 12:58:57 +00:00
|
|
|
static char *readpin_stdin(void)
|
2006-10-02 10:34:57 +00:00
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = fgets(buf, sizeof(buf), stdin);
|
|
|
|
if (p != NULL) {
|
|
|
|
p = strchr(buf, '\n');
|
|
|
|
if (p != NULL)
|
|
|
|
*p = '\0';
|
|
|
|
return strdup(buf);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-02-04 22:52:13 +00:00
|
|
|
static char * get_pin(struct sc_pkcs15_object *obj)
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
2017-11-17 09:47:53 +00:00
|
|
|
char buf[(sizeof obj->label) + 20];
|
2001-11-22 15:40:51 +00:00
|
|
|
char *pincode;
|
2020-01-31 15:27:06 +00:00
|
|
|
struct sc_pkcs15_auth_info *pinfo;
|
2011-06-05 15:46:25 +00:00
|
|
|
|
2020-01-31 15:27:06 +00:00
|
|
|
if (!obj)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pinfo = (struct sc_pkcs15_auth_info *) obj->data;
|
2011-06-05 15:46:25 +00:00
|
|
|
if (pinfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
|
|
|
|
return NULL;
|
|
|
|
|
2006-10-02 10:34:57 +00:00
|
|
|
if (opt_pincode != NULL) {
|
|
|
|
if (strcmp(opt_pincode, "-") == 0)
|
|
|
|
return readpin_stdin();
|
|
|
|
else
|
|
|
|
return strdup(opt_pincode);
|
|
|
|
}
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2017-11-17 09:47:53 +00:00
|
|
|
snprintf(buf, sizeof(buf), "Enter PIN [%.*s]: ",
|
|
|
|
(int) sizeof obj->label, obj->label);
|
2001-11-22 15:40:51 +00:00
|
|
|
while (1) {
|
|
|
|
pincode = getpass(buf);
|
|
|
|
if (strlen(pincode) == 0)
|
|
|
|
return NULL;
|
2011-06-05 15:46:25 +00:00
|
|
|
if (strlen(pincode) < pinfo->attrs.pin.min_length ||
|
2015-02-15 12:57:47 +00:00
|
|
|
strlen(pincode) > pinfo->attrs.pin.max_length)
|
|
|
|
continue;
|
2003-10-10 14:48:40 +00:00
|
|
|
return strdup(pincode);
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-04 22:52:13 +00:00
|
|
|
static int read_input(u8 *buf, int buflen)
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
|
|
|
FILE *inf;
|
|
|
|
int c;
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2016-01-20 20:35:44 +00:00
|
|
|
if (opt_input==NULL) {
|
|
|
|
inf = stdin;
|
|
|
|
} else {
|
|
|
|
inf = fopen(opt_input, "rb");
|
|
|
|
if (inf == NULL) {
|
|
|
|
fprintf(stderr, "Unable to open '%s' for reading.\n", opt_input);
|
|
|
|
return -1;
|
|
|
|
}
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
c = fread(buf, 1, buflen, inf);
|
2016-01-20 20:35:44 +00:00
|
|
|
if (inf!=stdin) {
|
|
|
|
fclose(inf);
|
|
|
|
}
|
2001-11-22 15:40:51 +00:00
|
|
|
if (c < 0) {
|
|
|
|
perror("read");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2005-02-04 22:52:13 +00:00
|
|
|
static int write_output(const u8 *buf, int len)
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
|
|
|
FILE *outf;
|
2004-08-21 14:26:16 +00:00
|
|
|
int output_binary = (opt_output == NULL && opt_raw == 0 ? 0 : 1);
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (opt_output != NULL) {
|
2002-06-14 12:52:56 +00:00
|
|
|
outf = fopen(opt_output, "wb");
|
2001-11-22 15:40:51 +00:00
|
|
|
if (outf == NULL) {
|
|
|
|
fprintf(stderr, "Unable to open '%s' for writing.\n", opt_output);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outf = stdout;
|
|
|
|
}
|
2015-02-15 12:57:47 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (output_binary == 0)
|
2008-03-06 16:06:59 +00:00
|
|
|
util_print_binary(outf, buf, len);
|
2001-11-22 15:40:51 +00:00
|
|
|
else
|
|
|
|
fwrite(buf, len, 1, outf);
|
2015-02-15 12:57:47 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (outf != stdout)
|
|
|
|
fclose(outf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-02-04 22:52:13 +00:00
|
|
|
static int sign(struct sc_pkcs15_object *obj)
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
|
|
|
u8 buf[1024], out[1024];
|
2002-04-19 14:23:31 +00:00
|
|
|
struct sc_pkcs15_prkey_info *key = (struct sc_pkcs15_prkey_info *) obj->data;
|
2001-11-22 15:40:51 +00:00
|
|
|
int r, c, len;
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (opt_input == NULL) {
|
2016-01-20 20:35:44 +00:00
|
|
|
fprintf(stderr, "No input file specified. Reading from stdin\n");
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
2005-02-04 22:52:13 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
c = read_input(buf, sizeof(buf));
|
|
|
|
if (c < 0)
|
|
|
|
return 2;
|
|
|
|
len = sizeof(out);
|
2012-04-02 22:00:56 +00:00
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA
|
2011-06-02 19:43:10 +00:00
|
|
|
&& !(opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
|
|
|
&& (size_t)c != key->modulus_length/8) {
|
2006-04-26 11:41:57 +00:00
|
|
|
fprintf(stderr, "Input has to be exactly %lu bytes, when using no padding.\n",
|
2006-05-01 10:02:50 +00:00
|
|
|
(unsigned long) key->modulus_length/8);
|
2002-03-08 05:59:57 +00:00
|
|
|
return 2;
|
|
|
|
}
|
2002-04-18 11:00:08 +00:00
|
|
|
if (!key->native) {
|
2011-05-24 19:08:43 +00:00
|
|
|
fprintf(stderr, "Deprecated non-native key detected! Upgrade your smart cards.\n");
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
2002-04-18 11:00:08 +00:00
|
|
|
}
|
2011-05-24 19:08:43 +00:00
|
|
|
|
|
|
|
r = sc_pkcs15_compute_signature(p15card, obj, opt_crypt_flags, buf, c, out, len);
|
2001-11-22 15:40:51 +00:00
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Compute signature failed: %s\n", sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
2015-02-15 12:57:47 +00:00
|
|
|
len = r;
|
2011-05-24 19:08:43 +00:00
|
|
|
|
2015-02-15 12:57:47 +00:00
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
|
|
|
|
if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) {
|
|
|
|
unsigned char *seq;
|
|
|
|
size_t seqlen;
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2015-02-15 12:57:47 +00:00
|
|
|
if (sc_asn1_sig_value_rs_to_sequence(ctx, out, len, &seq, &seqlen)) {
|
|
|
|
fprintf(stderr, "Failed to convert signature to ASN1 sequence format.\n");
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(out, seq, seqlen);
|
|
|
|
len = seqlen;
|
|
|
|
|
|
|
|
free(seq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r = write_output(out, len);
|
|
|
|
|
|
|
|
return r;
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
|
2005-02-04 22:52:13 +00:00
|
|
|
static int decipher(struct sc_pkcs15_object *obj)
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
|
|
|
u8 buf[1024], out[1024];
|
|
|
|
int r, c, len;
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (opt_input == NULL) {
|
2016-01-20 20:35:44 +00:00
|
|
|
fprintf(stderr, "No input file specified. Reading from stdin\n");
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
c = read_input(buf, sizeof(buf));
|
|
|
|
if (c < 0)
|
|
|
|
return 2;
|
2002-04-18 11:00:08 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
len = sizeof(out);
|
2002-04-18 11:00:08 +00:00
|
|
|
if (!((struct sc_pkcs15_prkey_info *) obj->data)->native) {
|
2011-05-24 19:08:43 +00:00
|
|
|
fprintf(stderr, "Deprecated non-native key detected! Upgrade your smart cards.\n");
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
2002-04-18 11:00:08 +00:00
|
|
|
}
|
|
|
|
|
2011-05-24 19:08:43 +00:00
|
|
|
r = sc_pkcs15_decipher(p15card, obj, opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1, buf, c, out, len);
|
2001-11-22 15:40:51 +00:00
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Decrypt failed: %s\n", sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
r = write_output(out, r);
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2017-08-03 15:02:03 +00:00
|
|
|
return r;
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
|
2003-04-17 12:38:08 +00:00
|
|
|
static int get_key(unsigned int usage, sc_pkcs15_object_t **result)
|
|
|
|
{
|
2019-05-10 16:18:36 +00:00
|
|
|
sc_pkcs15_object_t *key, *pin = NULL;
|
2003-04-17 12:38:08 +00:00
|
|
|
const char *usage_name;
|
|
|
|
sc_pkcs15_id_t id;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
usage_name = (usage & SC_PKCS15_PRKEY_USAGE_SIGN)? "signature" : "decryption";
|
|
|
|
|
|
|
|
if (opt_key_id != NULL) {
|
|
|
|
sc_pkcs15_hex_string_to_id(opt_key_id, &id);
|
|
|
|
r = sc_pkcs15_find_prkey_by_id_usage(p15card, &id, usage, &key);
|
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Unable to find private %s key '%s': %s\n",
|
|
|
|
usage_name, opt_key_id, sc_strerror(r));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r = sc_pkcs15_find_prkey_by_id_usage(p15card, NULL, usage, &key);
|
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Unable to find any private %s key: %s\n",
|
|
|
|
usage_name, sc_strerror(r));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*result = key;
|
|
|
|
|
|
|
|
if (key->auth_id.len) {
|
|
|
|
static sc_pkcs15_object_t *prev_pin = NULL;
|
|
|
|
char *pincode;
|
|
|
|
|
|
|
|
r = sc_pkcs15_find_pin_by_auth_id(p15card, &key->auth_id, &pin);
|
|
|
|
if (r) {
|
|
|
|
fprintf(stderr, "Unable to find PIN code for private key: %s\n",
|
|
|
|
sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pin already verified previously */
|
2018-11-09 14:22:46 +00:00
|
|
|
if (pin == prev_pin && key->user_consent == 0)
|
2003-04-17 12:38:08 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
pincode = get_pin(pin);
|
2005-02-26 19:47:54 +00:00
|
|
|
if (((pincode == NULL || *pincode == '\0')) &&
|
2015-04-29 21:22:30 +00:00
|
|
|
!(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)) {
|
|
|
|
free(pincode);
|
|
|
|
return 5;
|
|
|
|
}
|
2018-11-09 14:22:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do what PKCS#11 would do for keys requiring CKA_ALWAYS_AUTHENTICATE
|
|
|
|
* and CKU_CONTEXT_SPECIFIC login to let driver know this verify will be followed by
|
|
|
|
* a crypto operation. Card drivers can test for SC_AC_CONTEXT_SPECIFIC
|
|
|
|
* to do any special handling.
|
|
|
|
*/
|
2019-05-10 16:18:36 +00:00
|
|
|
if (key->user_consent && pin) {
|
2018-11-09 14:22:46 +00:00
|
|
|
int auth_meth_saved;
|
|
|
|
struct sc_pkcs15_auth_info *pinfo = (struct sc_pkcs15_auth_info *) pin->data;
|
|
|
|
|
|
|
|
auth_meth_saved = pinfo->auth_method;
|
|
|
|
|
|
|
|
pinfo->auth_method = SC_AC_CONTEXT_SPECIFIC;
|
|
|
|
r = sc_pkcs15_verify_pin(p15card, pin, (const u8 *)pincode, pincode ? strlen(pincode) : 0);
|
|
|
|
pinfo->auth_method = auth_meth_saved;
|
|
|
|
} else
|
|
|
|
r = sc_pkcs15_verify_pin(p15card, pin, (const u8 *)pincode, pincode ? strlen(pincode) : 0);
|
2003-04-17 12:38:08 +00:00
|
|
|
|
2015-04-29 21:22:30 +00:00
|
|
|
free(pincode);
|
2003-04-17 12:38:08 +00:00
|
|
|
if (r) {
|
|
|
|
fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r));
|
|
|
|
return 5;
|
|
|
|
}
|
2004-06-13 20:13:12 +00:00
|
|
|
if (verbose)
|
2003-04-17 12:38:08 +00:00
|
|
|
fprintf(stderr, "PIN code correct.\n");
|
|
|
|
prev_pin = pin;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:12:58 +00:00
|
|
|
int main(int argc, char *argv[])
|
2001-11-22 15:40:51 +00:00
|
|
|
{
|
|
|
|
int err = 0, r, c, long_optind = 0;
|
|
|
|
int do_decipher = 0;
|
|
|
|
int do_sign = 0;
|
2016-03-28 18:41:19 +00:00
|
|
|
int do_print_version = 0;
|
2001-11-22 15:40:51 +00:00
|
|
|
int action_count = 0;
|
2016-03-28 18:41:19 +00:00
|
|
|
struct sc_pkcs15_object *key;
|
2006-02-07 20:14:43 +00:00
|
|
|
sc_context_param_t ctx_param;
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
while (1) {
|
2015-02-15 12:57:47 +00:00
|
|
|
c = getopt_long(argc, argv, "sck:r:i:o:f:Rp:vw", options, &long_optind);
|
2001-11-22 15:40:51 +00:00
|
|
|
if (c == -1)
|
|
|
|
break;
|
|
|
|
if (c == '?')
|
2012-05-26 16:53:09 +00:00
|
|
|
util_print_usage_and_die(app_name, options, option_help, NULL);
|
2001-11-22 15:40:51 +00:00
|
|
|
switch (c) {
|
2016-03-28 18:41:19 +00:00
|
|
|
case OPT_VERSION:
|
|
|
|
do_print_version = 1;
|
|
|
|
action_count++;
|
|
|
|
break;
|
2001-11-22 15:40:51 +00:00
|
|
|
case 's':
|
|
|
|
do_sign++;
|
|
|
|
action_count++;
|
|
|
|
break;
|
2001-12-15 01:27:51 +00:00
|
|
|
case 'c':
|
2001-11-22 15:40:51 +00:00
|
|
|
do_decipher++;
|
|
|
|
action_count++;
|
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
opt_key_id = optarg;
|
|
|
|
action_count++;
|
|
|
|
break;
|
|
|
|
case 'r':
|
2010-01-24 15:29:47 +00:00
|
|
|
opt_reader = optarg;
|
2001-11-22 15:40:51 +00:00
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
opt_input = optarg;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
opt_output = optarg;
|
|
|
|
break;
|
2015-02-15 12:57:47 +00:00
|
|
|
case 'f':
|
|
|
|
opt_sig_format = optarg;
|
|
|
|
break;
|
2004-08-21 14:26:16 +00:00
|
|
|
case 'R':
|
|
|
|
opt_raw = 1;
|
|
|
|
break;
|
2001-11-22 15:40:51 +00:00
|
|
|
case OPT_SHA1:
|
2002-03-08 05:59:57 +00:00
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
|
2002-01-20 21:20:09 +00:00
|
|
|
break;
|
2007-02-02 22:15:14 +00:00
|
|
|
case OPT_SHA256:
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256;
|
|
|
|
break;
|
|
|
|
case OPT_SHA384:
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384;
|
|
|
|
break;
|
|
|
|
case OPT_SHA512:
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512;
|
|
|
|
break;
|
|
|
|
case OPT_SHA224:
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA224;
|
|
|
|
break;
|
2002-03-14 17:02:08 +00:00
|
|
|
case OPT_MD5:
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5;
|
|
|
|
break;
|
2002-01-20 21:20:09 +00:00
|
|
|
case OPT_PKCS1:
|
2002-03-08 05:59:57 +00:00
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
2001-11-22 15:40:51 +00:00
|
|
|
break;
|
2004-06-13 20:13:12 +00:00
|
|
|
case 'v':
|
|
|
|
verbose++;
|
2001-11-22 15:40:51 +00:00
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
opt_pincode = optarg;
|
|
|
|
break;
|
2011-01-05 15:22:12 +00:00
|
|
|
case OPT_BIND_TO_AID:
|
|
|
|
opt_bind_to_aid = optarg;
|
|
|
|
break;
|
2003-01-03 16:58:32 +00:00
|
|
|
case 'w':
|
|
|
|
opt_wait = 1;
|
|
|
|
break;
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (action_count == 0)
|
2012-05-26 16:53:09 +00:00
|
|
|
util_print_usage_and_die(app_name, options, option_help, NULL);
|
2006-02-07 20:14:43 +00:00
|
|
|
|
2016-03-28 18:41:19 +00:00
|
|
|
if (do_print_version) {
|
|
|
|
printf("%s\n", OPENSC_SCM_REVISION);
|
|
|
|
action_count--;
|
|
|
|
}
|
|
|
|
|
2012-11-10 23:42:52 +00:00
|
|
|
if (!(opt_crypt_flags & SC_ALGORITHM_RSA_HASHES))
|
|
|
|
opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_NONE;
|
|
|
|
|
2006-02-07 20:14:43 +00:00
|
|
|
memset(&ctx_param, 0, sizeof(ctx_param));
|
|
|
|
ctx_param.ver = 0;
|
|
|
|
ctx_param.app_name = app_name;
|
|
|
|
|
|
|
|
r = sc_context_create(&ctx, &ctx_param);
|
2001-11-22 15:40:51 +00:00
|
|
|
if (r) {
|
|
|
|
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
2010-03-15 12:17:13 +00:00
|
|
|
|
2018-05-18 21:21:14 +00:00
|
|
|
err = util_connect_card_ex(ctx, &card, opt_reader, opt_wait, 0, verbose);
|
2003-01-03 16:58:32 +00:00
|
|
|
if (err)
|
2001-11-22 15:40:51 +00:00
|
|
|
goto end;
|
|
|
|
|
2004-06-13 20:13:12 +00:00
|
|
|
if (verbose)
|
2002-03-03 00:32:28 +00:00
|
|
|
fprintf(stderr, "Trying to find a PKCS #15 compatible card...\n");
|
2011-01-05 15:22:12 +00:00
|
|
|
if (opt_bind_to_aid) {
|
|
|
|
struct sc_aid aid;
|
|
|
|
|
|
|
|
aid.len = sizeof(aid.value);
|
|
|
|
if (sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len)) {
|
|
|
|
fprintf(stderr, "Invalid AID value: '%s'\n", opt_bind_to_aid);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sc_pkcs15_bind(card, &aid, &p15card);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
r = sc_pkcs15_bind(card, NULL, &p15card);
|
|
|
|
}
|
2001-11-22 15:40:51 +00:00
|
|
|
if (r) {
|
2010-03-15 10:34:18 +00:00
|
|
|
fprintf(stderr, "PKCS #15 binding failed: %s\n", sc_strerror(r));
|
2001-11-22 15:40:51 +00:00
|
|
|
err = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
2004-06-13 20:13:12 +00:00
|
|
|
if (verbose)
|
2010-10-05 15:44:58 +00:00
|
|
|
fprintf(stderr, "Found %s!\n", p15card->tokeninfo->label);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
|
|
if (do_decipher) {
|
2016-03-28 17:59:28 +00:00
|
|
|
if ((err = get_key(SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP, &key))
|
2003-04-17 12:38:08 +00:00
|
|
|
|| (err = decipher(key)))
|
2001-11-22 15:40:51 +00:00
|
|
|
goto end;
|
|
|
|
action_count--;
|
|
|
|
}
|
2012-04-02 22:00:56 +00:00
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
if (do_sign) {
|
2003-08-08 08:44:38 +00:00
|
|
|
if ((err = get_key(SC_PKCS15_PRKEY_USAGE_SIGN|
|
|
|
|
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
|
|
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, &key))
|
2003-04-17 12:38:08 +00:00
|
|
|
|| (err = sign(key)))
|
2001-11-22 15:40:51 +00:00
|
|
|
goto end;
|
|
|
|
action_count--;
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
if (p15card)
|
2001-12-22 20:52:57 +00:00
|
|
|
sc_pkcs15_unbind(p15card);
|
2001-11-22 15:40:51 +00:00
|
|
|
if (card) {
|
2010-01-24 15:29:47 +00:00
|
|
|
sc_disconnect_card(card);
|
2001-11-22 15:40:51 +00:00
|
|
|
}
|
|
|
|
if (ctx)
|
2002-03-24 14:12:38 +00:00
|
|
|
sc_release_context(ctx);
|
2001-11-22 15:40:51 +00:00
|
|
|
return err;
|
|
|
|
}
|