- added sc-crypt program
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@51 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
a96d31344a
commit
674cbb1979
|
@ -193,7 +193,7 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin);
|
|||
int sc_pkcs15_enum_pins(struct sc_pkcs15_card *card);
|
||||
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_pin_info *pin,
|
||||
char *pincode, int pinlen);
|
||||
const u8 *pincode, int pinlen);
|
||||
int sc_pkcs15_change_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_pin_info *pin,
|
||||
char *oldpincode,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <pthread.h>
|
||||
#include <winscard.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SC_ERROR_MIN -1000
|
||||
#define SC_ERROR_UNKNOWN -1000
|
||||
|
@ -228,7 +229,7 @@ const char *sc_strerror(int error);
|
|||
/* Internal use only */
|
||||
int sc_file_valid(const struct sc_file *file);
|
||||
void sc_hex_dump(const u8 *buf, int len);
|
||||
void sc_print_binary(const u8 *buf, int len);
|
||||
void sc_print_binary(FILE *f, const u8 *buf, int len);
|
||||
int sc_hex_to_bin(const char *in, u8 *out, int *outlen);
|
||||
int _sc_sw_to_errorcode(int sw1, int sw2);
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin)
|
|||
printf("\tFlags : %d\n", pin->com_attr.flags);
|
||||
printf("\tLength : %d..%d\n", pin->min_length, pin->stored_length);
|
||||
printf("\tPad char : ");
|
||||
sc_print_binary(&pin->pad_char, 1);
|
||||
sc_print_binary(stdout, &pin->pad_char, 1);
|
||||
printf("\n");
|
||||
printf("\tPath : %s\n", path);
|
||||
printf("\tAuth ID : ");
|
||||
|
@ -165,7 +165,7 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card)
|
|||
|
||||
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
|
||||
struct sc_pkcs15_pin_info *pin,
|
||||
char *pincode, int pinlen)
|
||||
const u8 *pincode, int pinlen)
|
||||
{
|
||||
int r;
|
||||
struct sc_file file;
|
||||
|
|
|
@ -193,7 +193,7 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin);
|
|||
int sc_pkcs15_enum_pins(struct sc_pkcs15_card *card);
|
||||
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_pin_info *pin,
|
||||
char *pincode, int pinlen);
|
||||
const u8 *pincode, int pinlen);
|
||||
int sc_pkcs15_change_pin(struct sc_pkcs15_card *card,
|
||||
struct sc_pkcs15_pin_info *pin,
|
||||
char *oldpincode,
|
||||
|
|
|
@ -77,7 +77,7 @@ void sc_hex_dump(const u8 *buf, int count)
|
|||
fflush(stdout);
|
||||
}
|
||||
|
||||
void sc_print_binary(const u8 *buf, int count)
|
||||
void sc_print_binary(FILE *f, const u8 *buf, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -88,9 +88,9 @@ void sc_print_binary(const u8 *buf, int count)
|
|||
format = "\\x%02X";
|
||||
else
|
||||
format = "%c";
|
||||
printf(format, c);
|
||||
fprintf(f, format, c);
|
||||
}
|
||||
fflush(stdout);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
int sc_hex_to_bin(const char *in, u8 *out, int *outlen)
|
||||
|
@ -229,7 +229,10 @@ static int sc_transceive_t0(struct sc_card *card, struct sc_apdu *apdu)
|
|||
apdu->sw1 = r[dwRecvLength-2];
|
||||
apdu->sw2 = r[dwRecvLength-1];
|
||||
dwRecvLength -= 2;
|
||||
apdu->resplen = dwRecvLength;
|
||||
if (dwRecvLength > apdu->resplen)
|
||||
dwRecvLength = apdu->resplen;
|
||||
else
|
||||
apdu->resplen = dwRecvLength;
|
||||
if (dwRecvLength)
|
||||
memcpy(apdu->resp, r, dwRecvLength);
|
||||
|
||||
|
@ -593,7 +596,7 @@ int sc_establish_context(struct sc_context **ctx_out)
|
|||
}
|
||||
SCardListReaders(ctx->pcsc_ctx, NULL, NULL,
|
||||
(LPDWORD) & reader_buf_size);
|
||||
if (reader_buf_size == 0) {
|
||||
if (reader_buf_size < 2) {
|
||||
if (sc_debug)
|
||||
fprintf(stderr, "No readers found!\n");
|
||||
free(ctx);
|
||||
|
@ -676,7 +679,7 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
|
||||
assert(card_out != NULL);
|
||||
if (reader >= ctx->reader_count || reader < 0)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||
|
||||
rgReaderStates[0].szReader = ctx->readers[reader];
|
||||
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||
|
|
|
@ -170,7 +170,7 @@ int sc_verify(struct sc_card *card, int ref, const u8 *pin, int pinlen,
|
|||
memset(sbuf, 0, pinlen);
|
||||
if (r)
|
||||
return r;
|
||||
if (apdu.sw1 == 0x63 && (apdu.sw2 && 0xF0) == 0xC0) {
|
||||
if (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) {
|
||||
if (tries_left != NULL)
|
||||
*tries_left = apdu.sw2 & 0x0F;
|
||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* sc-crypt.c: Tool for cryptography operations with SmartCards
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <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
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sc.h>
|
||||
#include <sc-pkcs15.h>
|
||||
|
||||
int opt_reader = 0, opt_pin = 0, quiet = 0;
|
||||
char * opt_pincode = NULL, * opt_key_id = NULL;
|
||||
char * opt_input = NULL, * opt_output = NULL;
|
||||
int opt_hash_type = SC_PKCS15_HASH_NONE;
|
||||
|
||||
#define OPT_DEBUG 0x100
|
||||
#define OPT_SHA1 0x101
|
||||
|
||||
const struct option options[] = {
|
||||
{ "sign", 0, 0, 's' },
|
||||
{ "decipher", 0, 0, 'd' },
|
||||
{ "key", 1, 0, 'k' },
|
||||
{ "reader", 1, 0, 'r' },
|
||||
{ "input", 1, 0, 'i' },
|
||||
{ "output", 1, 0, 'o' },
|
||||
{ "sha-1", 0, 0, OPT_SHA1 },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "debug", 0, 0, OPT_DEBUG },
|
||||
{ "pin", 1, 0, 'p' },
|
||||
{ "pin-id", 1, &opt_pin, 0 },
|
||||
{ 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",
|
||||
"Quiet operation",
|
||||
"Debug output -- may be supplied several times",
|
||||
"Uses password (PIN) <arg>",
|
||||
"The auth ID of the PIN to use [P15]",
|
||||
};
|
||||
|
||||
struct sc_context *ctx = NULL;
|
||||
struct sc_card *card = NULL;
|
||||
struct sc_pkcs15_card *p15card = NULL;
|
||||
|
||||
void print_usage_and_die()
|
||||
{
|
||||
int i = 0;
|
||||
printf("Usage: sc-crypt [OPTIONS]\nOptions:\n");
|
||||
|
||||
while (options[i].name) {
|
||||
char buf[40], tmp[5];
|
||||
const char *arg_str;
|
||||
|
||||
if (options[i].val > 0 && options[i].val < 128)
|
||||
sprintf(tmp, ", -%c", options[i].val);
|
||||
else
|
||||
tmp[0] = 0;
|
||||
switch (options[i].has_arg) {
|
||||
case 1:
|
||||
arg_str = " <arg>";
|
||||
break;
|
||||
case 2:
|
||||
arg_str = " [arg]";
|
||||
break;
|
||||
default:
|
||||
arg_str = "";
|
||||
break;
|
||||
}
|
||||
sprintf(buf, "--%s%s%s", options[i].name, tmp, arg_str);
|
||||
printf(" %-30s%s\n", buf, option_help[i]);
|
||||
i++;
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
|
||||
const char * get_pin(struct sc_pkcs15_pin_info *pinfo)
|
||||
{
|
||||
char buf[80];
|
||||
char *pincode;
|
||||
|
||||
if (opt_pincode != NULL)
|
||||
return opt_pincode;
|
||||
sprintf(buf, "Enter PIN [%s]: ", pinfo->com_attr.label);
|
||||
while (1) {
|
||||
pincode = getpass(buf);
|
||||
if (strlen(pincode) == 0)
|
||||
return NULL;
|
||||
if (strlen(pincode) < pinfo->min_length ||
|
||||
strlen(pincode) > pinfo->stored_length)
|
||||
continue;
|
||||
return pincode;
|
||||
}
|
||||
}
|
||||
|
||||
int read_input(char *buf, int buflen)
|
||||
{
|
||||
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) {
|
||||
outf = fopen(opt_output, "w");
|
||||
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)
|
||||
sc_print_binary(outf, buf, len);
|
||||
else
|
||||
fwrite(buf, len, 1, outf);
|
||||
if (outf != stdout)
|
||||
fclose(outf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sign(struct sc_pkcs15_prkey_info *key)
|
||||
{
|
||||
u8 buf[1024], out[1024];
|
||||
int r, c, len;
|
||||
|
||||
if (opt_input == NULL) {
|
||||
fprintf(stderr, "No input file specified.\n");
|
||||
return 2;
|
||||
}
|
||||
if (opt_output == NULL) {
|
||||
fprintf(stderr, "No output file specified.\n");
|
||||
return 2;
|
||||
}
|
||||
c = read_input(buf, sizeof(buf));
|
||||
if (c < 0)
|
||||
return 2;
|
||||
len = sizeof(out);
|
||||
r = sc_pkcs15_compute_signature(p15card, key, opt_hash_type,
|
||||
buf, c, out, len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Compute signature failed: %s\n", sc_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
r = write_output(out, r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decipher(struct sc_pkcs15_prkey_info *key)
|
||||
{
|
||||
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;
|
||||
len = sizeof(out);
|
||||
r = sc_pkcs15_decipher(p15card, key, buf, c, out, len);
|
||||
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;
|
||||
struct sc_pkcs15_prkey_info *key;
|
||||
struct sc_pkcs15_pin_info *pin;
|
||||
struct sc_pkcs15_id id;
|
||||
const char *pincode;
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "sdk:r:i:o:qp:", options, &long_optind);
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '?')
|
||||
print_usage_and_die();
|
||||
switch (c) {
|
||||
case 's':
|
||||
do_sign++;
|
||||
action_count++;
|
||||
break;
|
||||
case 'd':
|
||||
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:
|
||||
opt_hash_type = SC_PKCS15_HASH_SHA1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet++;
|
||||
break;
|
||||
case OPT_DEBUG:
|
||||
sc_debug++;
|
||||
break;
|
||||
case 'p':
|
||||
opt_pincode = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (action_count == 0)
|
||||
print_usage_and_die();
|
||||
r = sc_establish_context(&ctx);
|
||||
if (r) {
|
||||
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
if (opt_reader >= ctx->reader_count || opt_reader < 0) {
|
||||
fprintf(stderr, "Illegal reader number. Only %d reader(s) configured.\n", ctx->reader_count);
|
||||
err = 1;
|
||||
goto end;
|
||||
}
|
||||
if (sc_detect_card(ctx, opt_reader) != 1) {
|
||||
fprintf(stderr, "Card not present.\n");
|
||||
return 3;
|
||||
}
|
||||
if (!quiet)
|
||||
fprintf(stderr, "Connecting to card in reader %s...\n", ctx->readers[opt_reader]);
|
||||
r = sc_connect_card(ctx, opt_reader, &card);
|
||||
if (r) {
|
||||
fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(r));
|
||||
err = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
sc_lock(card);
|
||||
if (!quiet)
|
||||
fprintf(stderr, "Trying to find a PKCS#15 compatible card...\n");
|
||||
r = sc_pkcs15_init(card, &p15card);
|
||||
if (r) {
|
||||
fprintf(stderr, "PKCS#15 initialization failed: %s\n", sc_strerror(r));
|
||||
err = 1;
|
||||
goto end;
|
||||
}
|
||||
if (!quiet)
|
||||
fprintf(stderr, "Found %s!\n", p15card->label);
|
||||
|
||||
r = sc_pkcs15_enum_private_keys(p15card);
|
||||
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
|
||||
key = &p15card->prkey_info[0];
|
||||
r = sc_pkcs15_find_pin_by_auth_id(p15card, &key->com_attr.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, pin, (const u8 *) pincode, strlen(pincode));
|
||||
if (r) {
|
||||
fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r));
|
||||
err = 5;
|
||||
goto end;
|
||||
}
|
||||
if (!quiet)
|
||||
fprintf(stderr, "PIN code correct.\n");
|
||||
if (do_decipher) {
|
||||
if ((err = decipher(key)))
|
||||
goto end;
|
||||
action_count--;
|
||||
}
|
||||
if (do_sign) {
|
||||
if ((err = sign(key)))
|
||||
goto end;
|
||||
action_count--;
|
||||
}
|
||||
end:
|
||||
if (p15card)
|
||||
sc_pkcs15_destroy(p15card);
|
||||
if (card) {
|
||||
sc_unlock(card);
|
||||
sc_disconnect_card(card);
|
||||
}
|
||||
if (ctx)
|
||||
sc_destroy_context(ctx);
|
||||
return err;
|
||||
}
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* sc-tool.c: Tool for accessing SmartCards with libsc
|
||||
*
|
||||
* Copyright (C) 2001 Juha Yrjölä <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
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -294,7 +313,7 @@ int enum_dir(struct sc_path path, int depth)
|
|||
if (sc_file_valid(&file)) {
|
||||
if (file.namelen) {
|
||||
printf("[");
|
||||
sc_print_binary(file.name, file.namelen);
|
||||
sc_print_binary(stdout, file.name, file.namelen);
|
||||
printf("] ");
|
||||
}
|
||||
switch (file.type) {
|
||||
|
@ -438,7 +457,7 @@ int main(int argc, char * const argv[])
|
|||
if (c == -1)
|
||||
break;
|
||||
if (c == '?')
|
||||
continue;
|
||||
print_usage_and_die();
|
||||
switch (c) {
|
||||
case 'r':
|
||||
opt_cert = optarg;
|
||||
|
|
Loading…
Reference in New Issue