2001-11-22 15:40:51 +00:00
|
|
|
|
/*
|
2002-01-16 23:59:18 +00:00
|
|
|
|
* pkcs15-crypt.c: Tool for cryptography operations with SmartCards
|
2001-11-22 15:40:51 +00:00
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2001 Juha Yrj<EFBFBD>l<EFBFBD> <juha.yrjola@iki.fi>
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2002-02-25 16:30:38 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
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>
|
2002-04-05 13:48:00 +00:00
|
|
|
|
#include <opensc/opensc.h>
|
|
|
|
|
#include <opensc/pkcs15.h>
|
2002-04-18 11:00:08 +00:00
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
|
#include <openssl/evp.h>
|
|
|
|
|
#include <openssl/rsa.h>
|
|
|
|
|
#include <openssl/dsa.h>
|
|
|
|
|
#endif
|
2002-04-05 13:48:00 +00:00
|
|
|
|
#include "util.h"
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
2002-03-24 14:12:38 +00:00
|
|
|
|
const char *app_name = "pkcs15-crypt";
|
|
|
|
|
|
2003-01-03 16:58:32 +00:00
|
|
|
|
int opt_reader = -1, quiet = 0, opt_wait = 0;
|
2001-12-20 12:16:05 +00:00
|
|
|
|
int opt_debug = 0;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
char * opt_pincode = NULL, * opt_key_id = NULL;
|
|
|
|
|
char * opt_input = NULL, * opt_output = NULL;
|
2002-01-20 21:20:09 +00:00
|
|
|
|
int opt_crypt_flags = 0;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
2002-01-17 23:47:03 +00:00
|
|
|
|
#define OPT_SHA1 0x101
|
2002-03-14 17:02:08 +00:00
|
|
|
|
#define OPT_MD5 0x102
|
|
|
|
|
#define OPT_PKCS1 0x103
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
|
|
|
|
const struct option options[] = {
|
|
|
|
|
{ "sign", 0, 0, 's' },
|
2001-12-15 01:27:51 +00:00
|
|
|
|
{ "decipher", 0, 0, 'c' },
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{ "key", 1, 0, 'k' },
|
|
|
|
|
{ "reader", 1, 0, 'r' },
|
|
|
|
|
{ "input", 1, 0, 'i' },
|
|
|
|
|
{ "output", 1, 0, 'o' },
|
|
|
|
|
{ "sha-1", 0, 0, OPT_SHA1 },
|
2002-03-14 17:02:08 +00:00
|
|
|
|
{ "md5", 0, 0, OPT_MD5 },
|
2002-01-20 21:20:09 +00:00
|
|
|
|
{ "pkcs1", 0, 0, OPT_PKCS1 },
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{ "quiet", 0, 0, 'q' },
|
2001-12-15 01:27:51 +00:00
|
|
|
|
{ "debug", 0, 0, 'd' },
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{ "pin", 1, 0, 'p' },
|
2003-01-03 16:58:32 +00:00
|
|
|
|
{ "wait", 0, 0, 'w' },
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{ 0, 0, 0, 0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const char *option_help[] = {
|
|
|
|
|
"Performs digital signature operation",
|
|
|
|
|
"Decipher operation",
|
|
|
|
|
"Selects the private key ID to use",
|
|
|
|
|
"Uses reader number <arg>",
|
|
|
|
|
"Selects the input file to use",
|
|
|
|
|
"Outputs to file <arg>",
|
|
|
|
|
"Input file is a SHA-1 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",
|
2001-11-22 15:40:51 +00:00
|
|
|
|
"Quiet operation",
|
|
|
|
|
"Debug output -- may be supplied several times",
|
|
|
|
|
"Uses password (PIN) <arg>",
|
2003-01-03 17:07:56 +00:00
|
|
|
|
"Wait for card insertion",
|
2001-11-22 15:40:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct sc_context *ctx = NULL;
|
|
|
|
|
struct sc_card *card = NULL;
|
|
|
|
|
struct sc_pkcs15_card *p15card = NULL;
|
|
|
|
|
|
2002-03-03 00:32:28 +00:00
|
|
|
|
char * get_pin(struct sc_pkcs15_object *obj)
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{
|
|
|
|
|
char buf[80];
|
|
|
|
|
char *pincode;
|
2002-04-19 14:23:31 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pinfo = (struct sc_pkcs15_pin_info *) obj->data;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
|
|
|
|
if (opt_pincode != NULL)
|
2001-12-22 20:52:57 +00:00
|
|
|
|
return strdup(opt_pincode);
|
2002-03-03 00:32:28 +00:00
|
|
|
|
sprintf(buf, "Enter PIN [%s]: ", obj->label);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
while (1) {
|
|
|
|
|
pincode = getpass(buf);
|
|
|
|
|
if (strlen(pincode) == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
if (strlen(pincode) < pinfo->min_length ||
|
2003-02-20 23:19:01 +00:00
|
|
|
|
strlen(pincode) > pinfo->max_length)
|
2001-11-22 15:40:51 +00:00
|
|
|
|
continue;
|
|
|
|
|
return pincode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-30 21:17:34 +00:00
|
|
|
|
int read_input(u8 *buf, int buflen)
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{
|
|
|
|
|
FILE *inf;
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
inf = fopen(opt_input, "r");
|
|
|
|
|
if (inf == NULL) {
|
|
|
|
|
fprintf(stderr, "Unable to open '%s' for reading.\n", opt_input);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
c = fread(buf, 1, buflen, inf);
|
|
|
|
|
fclose(inf);
|
|
|
|
|
if (c < 0) {
|
|
|
|
|
perror("read");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int write_output(const u8 *buf, int len)
|
|
|
|
|
{
|
|
|
|
|
FILE *outf;
|
|
|
|
|
int output_binary = 1;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
output_binary = 0;
|
|
|
|
|
}
|
|
|
|
|
if (output_binary == 0)
|
2001-12-29 02:07:32 +00:00
|
|
|
|
print_binary(outf, buf, len);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
else
|
|
|
|
|
fwrite(buf, len, 1, outf);
|
|
|
|
|
if (outf != stdout)
|
|
|
|
|
fclose(outf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-18 11:00:08 +00:00
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
|
#define GETBN(bn) ((bn)->len? BN_bin2bn((bn)->data, (bn)->len, NULL) : NULL)
|
|
|
|
|
int extract_key(struct sc_pkcs15_object *obj, EVP_PKEY **pk)
|
|
|
|
|
{
|
|
|
|
|
struct sc_pkcs15_prkey *key;
|
|
|
|
|
const char *pass = NULL;
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
r = sc_pkcs15_read_prkey(p15card, obj, pass, &key);
|
|
|
|
|
if (r != SC_ERROR_PASSPHRASE_REQUIRED)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (pass)
|
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
|
pass = "lalla"; continue;
|
|
|
|
|
pass = getpass("Please enter pass phrase "
|
|
|
|
|
"to unlock secret key: ");
|
|
|
|
|
if (!pass || !*pass)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
*pk = EVP_PKEY_new();
|
|
|
|
|
switch (key->algorithm) {
|
|
|
|
|
case SC_ALGORITHM_RSA:
|
|
|
|
|
{
|
|
|
|
|
RSA *rsa = RSA_new();
|
|
|
|
|
|
|
|
|
|
EVP_PKEY_set1_RSA(*pk, rsa);
|
|
|
|
|
rsa->n = GETBN(&key->u.rsa.modulus);
|
|
|
|
|
rsa->e = GETBN(&key->u.rsa.exponent);
|
|
|
|
|
rsa->d = GETBN(&key->u.rsa.d);
|
|
|
|
|
rsa->p = GETBN(&key->u.rsa.p);
|
|
|
|
|
rsa->q = GETBN(&key->u.rsa.q);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SC_ALGORITHM_DSA:
|
|
|
|
|
{
|
|
|
|
|
DSA *dsa = DSA_new();
|
|
|
|
|
|
|
|
|
|
EVP_PKEY_set1_DSA(*pk, dsa);
|
|
|
|
|
dsa->priv_key = GETBN(&key->u.dsa.priv);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
r = SC_ERROR_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* DSA keys need additional parameters from public key file */
|
|
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_DSA) {
|
|
|
|
|
struct sc_pkcs15_id *id;
|
|
|
|
|
struct sc_pkcs15_object *pub_obj;
|
|
|
|
|
struct sc_pkcs15_pubkey *pub;
|
|
|
|
|
DSA *dsa;
|
|
|
|
|
|
|
|
|
|
id = &((struct sc_pkcs15_prkey_info *) obj->data)->id;
|
|
|
|
|
r = sc_pkcs15_find_pubkey_by_id(p15card, id, &pub_obj);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
goto done;
|
|
|
|
|
r = sc_pkcs15_read_pubkey(p15card, pub_obj, &pub);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
dsa = (*pk)->pkey.dsa;
|
|
|
|
|
dsa->pub_key = GETBN(&pub->u.dsa.pub);
|
|
|
|
|
dsa->p = GETBN(&pub->u.dsa.p);
|
|
|
|
|
dsa->q = GETBN(&pub->u.dsa.q);
|
|
|
|
|
dsa->g = GETBN(&pub->u.dsa.g);
|
|
|
|
|
sc_pkcs15_free_pubkey(pub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done: if (r < 0)
|
|
|
|
|
EVP_PKEY_free(*pk);
|
|
|
|
|
sc_pkcs15_free_prkey(key);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sign_ext(struct sc_pkcs15_object *obj,
|
|
|
|
|
u8 *data, size_t len, u8 *out, size_t out_len)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
int r, nid = -1;
|
|
|
|
|
|
|
|
|
|
r = extract_key(obj, &pkey);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
switch (obj->type) {
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
|
if (opt_crypt_flags & SC_ALGORITHM_RSA_HASH_MD5) {
|
|
|
|
|
nid = NID_md5;
|
|
|
|
|
} else if (opt_crypt_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
|
|
|
|
|
nid = NID_sha1;
|
|
|
|
|
} else {
|
|
|
|
|
if (len == 16)
|
|
|
|
|
nid = NID_md5;
|
|
|
|
|
else if (len == 20)
|
|
|
|
|
nid = NID_sha1;
|
|
|
|
|
else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Invalid input size (%u bytes)\n",
|
|
|
|
|
len);
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-18 11:59:32 +00:00
|
|
|
|
r = RSA_sign(nid, data, len, out, (unsigned int *) &out_len,
|
2002-04-18 11:00:08 +00:00
|
|
|
|
pkey->pkey.rsa);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
r = SC_ERROR_INTERNAL;
|
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_DSA:
|
2002-04-18 11:59:32 +00:00
|
|
|
|
r = DSA_sign(NID_sha1, data, len, out, (unsigned int *) &out_len,
|
2002-04-18 11:00:08 +00:00
|
|
|
|
pkey->pkey.dsa);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
r = SC_ERROR_INTERNAL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (r >= 0)
|
|
|
|
|
r = out_len;
|
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-08 05:59:57 +00:00
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (opt_input == NULL) {
|
|
|
|
|
fprintf(stderr, "No input file specified.\n");
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
2002-06-17 11:17:46 +00:00
|
|
|
|
#if 0
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (opt_output == NULL) {
|
|
|
|
|
fprintf(stderr, "No output file specified.\n");
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
2002-06-17 11:17:46 +00:00
|
|
|
|
#endif
|
2001-11-22 15:40:51 +00:00
|
|
|
|
c = read_input(buf, sizeof(buf));
|
|
|
|
|
if (c < 0)
|
|
|
|
|
return 2;
|
|
|
|
|
len = sizeof(out);
|
2002-04-18 11:00:08 +00:00
|
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA
|
|
|
|
|
&& !(opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
2002-05-26 12:31:23 +00:00
|
|
|
|
&& c != key->modulus_length/8) {
|
2002-03-08 05:59:57 +00:00
|
|
|
|
fprintf(stderr, "Input has to be exactly %d bytes, when using no padding.\n",
|
|
|
|
|
key->modulus_length/8);
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
2002-04-18 11:00:08 +00:00
|
|
|
|
if (!key->native) {
|
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
|
r = sign_ext(obj, buf, c, out, len);
|
|
|
|
|
#else
|
|
|
|
|
fprintf(stderr, "Cannot use extractable key because this "
|
|
|
|
|
"program was compiled without crypto "
|
|
|
|
|
"support.\n");
|
|
|
|
|
r = SC_ERROR_NOT_SUPPORTED;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
r = sc_pkcs15_compute_signature(p15card, obj, opt_crypt_flags,
|
2001-11-22 15:40:51 +00:00
|
|
|
|
buf, c, out, len);
|
2002-04-18 11:00:08 +00:00
|
|
|
|
}
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (r < 0) {
|
|
|
|
|
fprintf(stderr, "Compute signature failed: %s\n", sc_strerror(r));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
r = write_output(out, r);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-18 11:00:08 +00:00
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
|
static int decipher_ext(struct sc_pkcs15_object *obj,
|
|
|
|
|
u8 *data, size_t len, u8 *out, size_t out_len)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
r = extract_key(obj, &pkey);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
switch (obj->type) {
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
|
r = EVP_PKEY_decrypt(out, data, len, pkey);
|
|
|
|
|
if (r <= 0) {
|
|
|
|
|
fprintf(stderr, "Decryption failed.\n");
|
|
|
|
|
r = SC_ERROR_INTERNAL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stderr, "Key type not supported.\n");
|
|
|
|
|
r = SC_ERROR_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-08 05:59:57 +00:00
|
|
|
|
int decipher(struct sc_pkcs15_object *obj)
|
2001-11-22 15:40:51 +00:00
|
|
|
|
{
|
|
|
|
|
u8 buf[1024], out[1024];
|
|
|
|
|
int r, c, len;
|
|
|
|
|
|
|
|
|
|
if (opt_input == NULL) {
|
|
|
|
|
fprintf(stderr, "No input file specified.\n");
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
|
r = decipher_ext(obj, buf, c, out, len);
|
|
|
|
|
#else
|
|
|
|
|
fprintf(stderr, "Cannot use extractable key because this "
|
|
|
|
|
"program was compiled without crypto "
|
|
|
|
|
"support.\n");
|
|
|
|
|
r = SC_ERROR_NOT_SUPPORTED;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
2002-04-23 08:17:06 +00:00
|
|
|
|
r = sc_pkcs15_decipher(p15card, obj,
|
|
|
|
|
opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1,
|
|
|
|
|
buf, c, out, len);
|
2002-04-18 11:00:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char * const argv[])
|
|
|
|
|
{
|
|
|
|
|
int err = 0, r, c, long_optind = 0;
|
|
|
|
|
int do_decipher = 0;
|
|
|
|
|
int do_sign = 0;
|
|
|
|
|
int action_count = 0;
|
2002-03-03 00:32:28 +00:00
|
|
|
|
struct sc_pkcs15_object *key, *pin, *objs[32];
|
2001-11-22 15:40:51 +00:00
|
|
|
|
struct sc_pkcs15_id id;
|
2001-12-22 20:52:57 +00:00
|
|
|
|
char *pincode;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
|
|
|
|
|
while (1) {
|
2003-01-03 16:58:32 +00:00
|
|
|
|
c = getopt_long(argc, argv, "sck:r:i:o:qp:dw", options, &long_optind);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (c == -1)
|
|
|
|
|
break;
|
|
|
|
|
if (c == '?')
|
2002-04-19 14:23:31 +00:00
|
|
|
|
print_usage_and_die();
|
2001-11-22 15:40:51 +00:00
|
|
|
|
switch (c) {
|
|
|
|
|
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':
|
|
|
|
|
opt_reader = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'i':
|
|
|
|
|
opt_input = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
opt_output = optarg;
|
|
|
|
|
break;
|
|
|
|
|
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;
|
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;
|
|
|
|
|
case 'q':
|
|
|
|
|
quiet++;
|
|
|
|
|
break;
|
2001-12-15 01:27:51 +00:00
|
|
|
|
case 'd':
|
2001-12-20 12:16:05 +00:00
|
|
|
|
opt_debug++;
|
2001-11-22 15:40:51 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
opt_pincode = 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)
|
2002-04-19 14:23:31 +00:00
|
|
|
|
print_usage_and_die();
|
2002-03-24 14:12:38 +00:00
|
|
|
|
r = sc_establish_context(&ctx, app_name);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2002-03-24 21:56:13 +00:00
|
|
|
|
if (opt_debug)
|
|
|
|
|
ctx->debug = opt_debug;
|
2003-01-03 16:58:32 +00:00
|
|
|
|
|
|
|
|
|
err = connect_card(ctx, &card, opt_reader, 0, opt_wait, quiet);
|
|
|
|
|
if (err)
|
2001-11-22 15:40:51 +00:00
|
|
|
|
goto end;
|
|
|
|
|
|
2002-01-21 09:05:22 +00:00
|
|
|
|
#if 1
|
2001-12-25 20:45:48 +00:00
|
|
|
|
r = sc_lock(card);
|
|
|
|
|
if (r) {
|
|
|
|
|
fprintf(stderr, "Unable to lock card: %s\n", sc_strerror(r));
|
|
|
|
|
err = 1;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (!quiet)
|
2002-03-03 00:32:28 +00:00
|
|
|
|
fprintf(stderr, "Trying to find a PKCS #15 compatible card...\n");
|
2001-12-22 20:52:57 +00:00
|
|
|
|
r = sc_pkcs15_bind(card, &p15card);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (r) {
|
2002-03-03 00:32:28 +00:00
|
|
|
|
fprintf(stderr, "PKCS #15 initialization failed: %s\n", sc_strerror(r));
|
2001-11-22 15:40:51 +00:00
|
|
|
|
err = 1;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
if (!quiet)
|
|
|
|
|
fprintf(stderr, "Found %s!\n", p15card->label);
|
|
|
|
|
|
2002-04-18 11:00:08 +00:00
|
|
|
|
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, objs, 32);
|
2001-11-22 15:40:51 +00:00
|
|
|
|
if (r <= 0) {
|
|
|
|
|
if (r == 0)
|
|
|
|
|
r = SC_ERROR_OBJECT_NOT_FOUND;
|
|
|
|
|
fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r));
|
|
|
|
|
err = 1;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
if (opt_key_id != NULL) {
|
|
|
|
|
sc_pkcs15_hex_string_to_id(opt_key_id, &id);
|
|
|
|
|
r = sc_pkcs15_find_prkey_by_id(p15card, &id, &key);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
fprintf(stderr, "Unable to find private key '%s': %s\n",
|
|
|
|
|
opt_key_id, sc_strerror(r));
|
|
|
|
|
err = 2;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
} else
|
2002-03-03 00:32:28 +00:00
|
|
|
|
key = objs[0];
|
2002-06-07 20:21:11 +00:00
|
|
|
|
if (key->auth_id.len) {
|
|
|
|
|
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));
|
|
|
|
|
err = 1;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
pincode = get_pin(pin);
|
|
|
|
|
if (pincode == NULL) {
|
|
|
|
|
err = 5;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
r = sc_pkcs15_verify_pin(p15card, (struct sc_pkcs15_pin_info *) pin->data, (const u8 *) pincode, strlen(pincode));
|
|
|
|
|
if (r) {
|
|
|
|
|
fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r));
|
|
|
|
|
err = 5;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
free(pincode);
|
|
|
|
|
if (!quiet)
|
|
|
|
|
fprintf(stderr, "PIN code correct.\n");
|
2001-11-22 15:40:51 +00:00
|
|
|
|
}
|
|
|
|
|
if (do_decipher) {
|
2002-03-08 05:59:57 +00:00
|
|
|
|
if ((err = decipher(key)))
|
2001-11-22 15:40:51 +00:00
|
|
|
|
goto end;
|
|
|
|
|
action_count--;
|
|
|
|
|
}
|
|
|
|
|
if (do_sign) {
|
2002-03-08 05:59:57 +00:00
|
|
|
|
if ((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) {
|
2002-01-21 09:05:22 +00:00
|
|
|
|
#if 1
|
2001-11-22 15:40:51 +00:00
|
|
|
|
sc_unlock(card);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
#endif
|
2002-02-24 19:32:14 +00:00
|
|
|
|
sc_disconnect_card(card, 0);
|
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;
|
|
|
|
|
}
|