- added default driver for unidentified cards
- added select_file operation in Multiflex driver - added 'list-drivers' command to opensc-tool - moved stuff from opensc.h to sc-internal.h - improved locking behaviour git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@106 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
1d220ccdca
commit
2b99f2df14
|
@ -6,10 +6,12 @@ libopensc_la_SOURCES = sc-asn1.c sc-base64.c sc-defaults.c \
|
|||
sc-pkcs15.c sc-pkcs15-cert.c \
|
||||
sc-pkcs15-pin.c sc-pkcs15-prkey.c \
|
||||
sc-pkcs15-defaults.c sc-pkcs15-sec.c \
|
||||
sc-card-setec.c sc-card-multiflex.c
|
||||
sc-card-setec.c sc-card-multiflex.c \
|
||||
sc-card-default.c
|
||||
libopensc_la_LDFLAGS = -version-info 0:4:0
|
||||
libopensc_la_LIBADD = @LIBPCSCLITE@
|
||||
libopensc_la_CFLAGS = $(AM_CFLAGS) -Werror
|
||||
|
||||
include_HEADERS = opensc.h opensc-pkcs15.h
|
||||
noinst_HEADERS = sc-asn1.h sc-log.h
|
||||
noinst_HEADERS = sc-asn1.h sc-log.h sc-internal.h
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-asn1.h"
|
||||
#include "sc-log.h"
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* sc-card-unknown.c: Support for cards with no driver
|
||||
*
|
||||
* 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 "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
|
||||
static struct sc_card_operations default_ops;
|
||||
static const struct sc_card_driver default_drv = {
|
||||
NULL,
|
||||
"Default driver for unknown cards",
|
||||
&default_ops
|
||||
};
|
||||
|
||||
static int default_finish(struct sc_card *card)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int default_match_card(struct sc_card *card)
|
||||
{
|
||||
return 1; /* always match */
|
||||
}
|
||||
|
||||
static int autodetect_class(struct sc_card *card)
|
||||
{
|
||||
int classes[] = { 0x00, 0xC0, 0xB0, 0xA0 };
|
||||
int class_count = sizeof(classes)/sizeof(int);
|
||||
u8 buf[2];
|
||||
struct sc_apdu apdu;
|
||||
int i, r;
|
||||
|
||||
if (card->ctx->debug >= 2)
|
||||
debug(card->ctx, "autodetecting CLA byte\n");
|
||||
for (i = 0; i < class_count; i++) {
|
||||
if (card->ctx->debug >= 2)
|
||||
debug(card->ctx, "trying with 0x%02X\n", classes[i]);
|
||||
apdu.cla = classes[i];
|
||||
apdu.cse = SC_APDU_CASE_3_SHORT;
|
||||
apdu.no_response = 1;
|
||||
memcpy(buf, "\x3F\x00", 2);
|
||||
apdu.data = buf;
|
||||
apdu.datalen = 2;
|
||||
apdu.lc = 2;
|
||||
apdu.resplen = 0;
|
||||
apdu.ins = 0xA4;
|
||||
apdu.p1 = apdu.p2 = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
|
||||
break;
|
||||
if (apdu.sw1 == 0x61)
|
||||
break;
|
||||
if (apdu.sw1 == 0x6E)
|
||||
continue;
|
||||
if (card->ctx->debug >= 2)
|
||||
debug(card->ctx, "got strange SWs: 0x%02X 0x%02X\n",
|
||||
apdu.sw1, apdu.sw2);
|
||||
}
|
||||
if (i == class_count)
|
||||
return -1;
|
||||
card->cla = classes[i];
|
||||
if (card->ctx->debug >= 2)
|
||||
debug(card->ctx, "detected CLA byte as 0x%02X\n", card->cla);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int default_init(struct sc_card *card)
|
||||
{
|
||||
int r;
|
||||
|
||||
card->ops_data = NULL;
|
||||
r = autodetect_class(card);
|
||||
if (r) {
|
||||
error(card->ctx, "unable to determine the right class byte\n");
|
||||
return SC_ERROR_INVALID_CARD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sc_card_driver * sc_get_driver(void)
|
||||
{
|
||||
const struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
|
||||
default_ops = *iso_drv->ops;
|
||||
default_ops.match_card = default_match_card;
|
||||
default_ops.init = default_init;
|
||||
default_ops.finish = default_finish;
|
||||
|
||||
return &default_drv;
|
||||
}
|
||||
|
||||
#if 1
|
||||
const struct sc_card_driver * sc_get_default_driver(void)
|
||||
{
|
||||
return sc_get_driver();
|
||||
}
|
||||
#endif
|
|
@ -18,7 +18,8 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
|
||||
static const char *mflex_atrs[] = {
|
||||
"3B:19:14:55:90:01:02:02:00:05:04:B0",
|
||||
|
@ -28,7 +29,7 @@ static const char *mflex_atrs[] = {
|
|||
static struct sc_card_operations mflex_ops;
|
||||
static const struct sc_card_driver mflex_drv = {
|
||||
NULL,
|
||||
"Schlumberger/Multiflex",
|
||||
"Multiflex/Schlumberger",
|
||||
&mflex_ops
|
||||
};
|
||||
|
||||
|
@ -69,10 +70,120 @@ static int mflex_init(struct sc_card *card)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_flex_sf_reply(struct sc_context *ctx, const u8 *buf, int buflen,
|
||||
struct sc_file *file)
|
||||
{
|
||||
const u8 *p = buf + 2;
|
||||
int left;
|
||||
|
||||
file->size = (*p++ << 8) + *p++;
|
||||
file->id = (*p++ << 8) + *p++;
|
||||
switch (*p) {
|
||||
case 0x01:
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||
break;
|
||||
case 0x02:
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
|
||||
break;
|
||||
case 0x04:
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
|
||||
break;
|
||||
case 0x06:
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_CYCLIC;
|
||||
break;
|
||||
case 0x38:
|
||||
file->type = SC_FILE_TYPE_DF;
|
||||
break;
|
||||
default:
|
||||
error(ctx, "invalid file type: 0x%02X\n", *p);
|
||||
return SC_ERROR_UNKNOWN_REPLY;
|
||||
}
|
||||
p++;
|
||||
p += 3; /* skip ACs */
|
||||
if (*p++)
|
||||
file->status = SC_FILE_STATUS_ACTIVATED;
|
||||
else
|
||||
file->status = SC_FILE_STATUS_INVALIDATED;
|
||||
left = *p++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
struct sc_file *file)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
int r;
|
||||
struct sc_apdu apdu;
|
||||
u8 rbuf[MAX_BUFFER_SIZE];
|
||||
u8 *pathptr = path->value;
|
||||
size_t pathlen = path->len;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 3);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0);
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.p1 = apdu.p2 = 0;
|
||||
|
||||
switch (path->type) {
|
||||
case SC_PATH_TYPE_PATH:
|
||||
if ((pathlen & 1) != 0) /* not divisible by 2 */
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
if (pathlen != 2 || memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
struct sc_path tmppath;
|
||||
|
||||
if (memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
sc_format_path("I3F00", &tmppath);
|
||||
r = mflex_select_file(card, &tmppath, NULL);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select Master File (MF)");
|
||||
pathptr += 2;
|
||||
pathlen -= 2;
|
||||
}
|
||||
while (pathlen > 2) {
|
||||
memcpy(tmppath.value, pathptr, 2);
|
||||
tmppath.len = 2;
|
||||
r = mflex_select_file(card, &tmppath, NULL);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select DF");
|
||||
pathptr += 2;
|
||||
pathlen -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SC_PATH_TYPE_DF_NAME:
|
||||
apdu.p1 = 0x04;
|
||||
break;
|
||||
case SC_PATH_TYPE_FILE_ID:
|
||||
if ((pathlen & 1) != 0)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
break;
|
||||
}
|
||||
apdu.datalen = pathlen;
|
||||
apdu.data = pathptr;
|
||||
apdu.lc = pathlen;
|
||||
|
||||
/* No need to get file information, if file is NULL or already
|
||||
* valid. */
|
||||
if (file == NULL || sc_file_valid(file))
|
||||
apdu.no_response = 1;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, r, "Card returned error");
|
||||
if (apdu.no_response)
|
||||
return 0;
|
||||
|
||||
if (apdu.resplen < 14)
|
||||
return SC_ERROR_UNKNOWN_REPLY;
|
||||
|
||||
if (apdu.resp[0] == 0x6F) {
|
||||
error(card->ctx, "unsupported: Multiflex returned FCI\n");
|
||||
return SC_ERROR_UNKNOWN_REPLY; /* FIXME */
|
||||
}
|
||||
|
||||
return parse_flex_sf_reply(card->ctx, apdu.resp, apdu.resplen, file);
|
||||
}
|
||||
|
||||
static const struct sc_card_driver * sc_get_driver(void)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
|
||||
static const char *setec_atrs[] = {
|
||||
/* the current FINEID card has this ATR: */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
#include "sc-asn1.h"
|
||||
#include <assert.h>
|
||||
|
@ -61,6 +61,21 @@ int sc_sw_to_errorcode(struct sc_card *card, int sw1, int sw2)
|
|||
return SC_ERROR_UNKNOWN_REPLY;
|
||||
}
|
||||
|
||||
static int _sc_pcscret_to_error(long rv)
|
||||
{
|
||||
switch (rv) {
|
||||
case SCARD_W_REMOVED_CARD:
|
||||
return SC_ERROR_CARD_REMOVED;
|
||||
case SCARD_W_RESET_CARD:
|
||||
return SC_ERROR_CARD_RESET;
|
||||
case SCARD_E_NOT_TRANSACTED:
|
||||
return SC_ERROR_TRANSMIT_FAILED;
|
||||
default:
|
||||
return SC_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int sc_check_apdu(struct sc_context *ctx, const struct sc_apdu *apdu)
|
||||
{
|
||||
switch (apdu->cse) {
|
||||
|
@ -190,8 +205,13 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
|
|||
SC_FUNC_CALLED(card->ctx, 4);
|
||||
r = sc_check_apdu(card->ctx, apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU sanity check failed");
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
r = sc_transceive_t0(card, apdu);
|
||||
SC_TEST_RET(card->ctx, r, "transceive_t0() failed");
|
||||
if (r != 0) {
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "transceive_t0() failed");
|
||||
}
|
||||
if (card->ctx->debug >= 5) {
|
||||
char buf[2048];
|
||||
|
||||
|
@ -207,9 +227,13 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
|
|||
struct sc_apdu rspapdu;
|
||||
BYTE rsp[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
if (apdu->no_response != 0)
|
||||
if (apdu->no_response != 0) {
|
||||
apdu->sw1 = 0x90;
|
||||
apdu->sw2 = 0;
|
||||
sc_unlock(card);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &rspapdu, SC_APDU_CASE_2_SHORT,
|
||||
0xC0, 0, 0);
|
||||
rspapdu.le = (size_t) apdu->sw2;
|
||||
|
@ -219,6 +243,7 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
|
|||
if (r != 0) {
|
||||
error(card->ctx, "error while getting response: %s\n",
|
||||
sc_strerror(r));
|
||||
sc_unlock(card);
|
||||
return r;
|
||||
}
|
||||
if (card->ctx->debug >= 5) {
|
||||
|
@ -238,6 +263,7 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
|
|||
apdu->sw1 = rspapdu.sw1;
|
||||
apdu->sw2 = rspapdu.sw2;
|
||||
}
|
||||
sc_unlock(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -296,6 +322,7 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
card->reader = reader;
|
||||
card->ctx = ctx;
|
||||
card->pcsc_card = card_handle;
|
||||
card->lock_count = 0;
|
||||
i = rgReaderStates[0].cbAtr;
|
||||
if (i >= SC_MAX_ATR_SIZE)
|
||||
i = SC_MAX_ATR_SIZE;
|
||||
|
@ -305,15 +332,27 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
|
||||
const struct sc_card_driver *drv = ctx->card_drivers[i];
|
||||
const struct sc_card_operations *ops = drv->ops;
|
||||
int r;
|
||||
|
||||
if (ctx->debug >= 3)
|
||||
debug(ctx, "trying driver: %s\n", drv->name);
|
||||
if (ops == NULL || ops->match_card == NULL)
|
||||
continue;
|
||||
if (ops->match_card(card) == 1) {
|
||||
if (ctx->debug >= 3)
|
||||
debug(ctx, "matched\n");
|
||||
card->ops = ops;
|
||||
if (ops->match_card(card) != 1)
|
||||
continue;
|
||||
if (ctx->debug >= 3)
|
||||
debug(ctx, "matched: %s\n", drv->name);
|
||||
card->ops = ops;
|
||||
r = card->ops->init(card);
|
||||
if (r) {
|
||||
error(ctx, "driver '%s' init() failed: %s\n", drv->name,
|
||||
sc_strerror(r));
|
||||
if (r == SC_ERROR_INVALID_CARD)
|
||||
continue;
|
||||
free(card);
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (card->ops == NULL) {
|
||||
error(ctx, "unable to find driver for inserted card\n");
|
||||
|
@ -321,6 +360,7 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
return SC_ERROR_INVALID_CARD;
|
||||
}
|
||||
pthread_mutex_init(&card->mutex, NULL);
|
||||
card->magic = SC_CARD_MAGIC;
|
||||
*card_out = card;
|
||||
|
||||
SC_FUNC_RETURN(ctx, 1, 0);
|
||||
|
@ -328,15 +368,25 @@ int sc_connect_card(struct sc_context *ctx,
|
|||
|
||||
int sc_disconnect_card(struct sc_card *card)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
assert(card != NULL);
|
||||
struct sc_context *ctx;
|
||||
assert(sc_card_valid(card));
|
||||
ctx = card->ctx;
|
||||
SC_FUNC_CALLED(ctx, 1);
|
||||
assert(card->lock_count == 0);
|
||||
if (card->ops->finish) {
|
||||
int r = card->ops->finish(card);
|
||||
if (r)
|
||||
error(card->ctx, "driver finish() failed: %s\n",
|
||||
sc_strerror(r));
|
||||
}
|
||||
SCardDisconnect(card->pcsc_card, SCARD_LEAVE_CARD);
|
||||
pthread_mutex_destroy(&card->mutex);
|
||||
free(card);
|
||||
SC_FUNC_RETURN(ctx, 1, 0);
|
||||
}
|
||||
|
||||
/* internal lock function -- should make sure that the card is exclusively
|
||||
* in our use */
|
||||
static int _sc_lock_int(struct sc_card *card)
|
||||
{
|
||||
long rv;
|
||||
|
@ -345,18 +395,27 @@ static int _sc_lock_int(struct sc_card *card)
|
|||
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
error(card->ctx, "SCardBeginTransaction failed: %s\n", pcsc_stringify_error(rv));
|
||||
return -1;
|
||||
return _sc_pcscret_to_error(rv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc_lock(struct sc_card *card)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
assert(card != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, 2);
|
||||
pthread_mutex_lock(&card->mutex);
|
||||
SC_FUNC_RETURN(card->ctx, 2, _sc_lock_int(card));
|
||||
if (card->lock_count == 0)
|
||||
r = _sc_lock_int(card);
|
||||
if (r == 0)
|
||||
card->lock_count++;
|
||||
pthread_mutex_unlock(&card->mutex);
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
|
||||
/* internal unlock function */
|
||||
static int _sc_unlock_int(struct sc_card *card)
|
||||
{
|
||||
long rv;
|
||||
|
@ -371,9 +430,17 @@ static int _sc_unlock_int(struct sc_card *card)
|
|||
|
||||
int sc_unlock(struct sc_card *card)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
assert(card != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, 2);
|
||||
pthread_mutex_lock(&card->mutex);
|
||||
card->lock_count--;
|
||||
assert(card->lock_count >= 0);
|
||||
if (card->lock_count == 0)
|
||||
r = _sc_unlock_int(card);
|
||||
pthread_mutex_unlock(&card->mutex);
|
||||
SC_FUNC_RETURN(card->ctx, 2, _sc_unlock_int(card));
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
|
||||
int sc_list_files(struct sc_card *card, u8 *buf, int buflen)
|
||||
|
@ -475,13 +542,6 @@ int sc_delete_file(struct sc_card *card, int file_id)
|
|||
SC_FUNC_RETURN(card->ctx, 1, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
|
||||
int sc_file_valid(const struct sc_file *file)
|
||||
{
|
||||
assert(file != NULL);
|
||||
|
||||
return file->magic == SC_FILE_MAGIC;
|
||||
}
|
||||
|
||||
int sc_read_binary(struct sc_card *card, unsigned int idx,
|
||||
unsigned char *buf, size_t count)
|
||||
{
|
||||
|
@ -500,17 +560,25 @@ int sc_read_binary(struct sc_card *card, unsigned int idx,
|
|||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
/* no read_binary_large support... */
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
int n = count > RB_BUF_SIZE ? RB_BUF_SIZE : count;
|
||||
r = sc_read_binary(card, idx, p, n);
|
||||
SC_TEST_RET(card->ctx, r, "sc_read_binary() failed");
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_read_binary() failed");
|
||||
}
|
||||
p += r;
|
||||
idx += r;
|
||||
bytes_read += r;
|
||||
count -= r;
|
||||
if (r == 0)
|
||||
if (r == 0) {
|
||||
sc_unlock(card);
|
||||
SC_FUNC_RETURN(card->ctx, 2, bytes_read);
|
||||
}
|
||||
}
|
||||
sc_unlock(card);
|
||||
SC_FUNC_RETURN(card->ctx, 2, bytes_read);
|
||||
}
|
||||
if (card->ops->read_binary == NULL)
|
||||
|
@ -528,7 +596,7 @@ int sc_select_file(struct sc_card *card,
|
|||
assert(card != NULL && in_path != NULL);
|
||||
if (card->ctx->debug >= 2) {
|
||||
char line[128], *linep = line;
|
||||
|
||||
|
||||
linep += sprintf(linep, "called with type %d, path ", in_path->type);
|
||||
for (r = 0; r < in_path->len; r++) {
|
||||
sprintf(linep, "%02X", in_path->value[r]);
|
||||
|
@ -556,3 +624,10 @@ int sc_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
|
|||
r = card->ops->get_challenge(card, rnd, len);
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
|
||||
inline int sc_card_valid(const struct sc_card *card) {
|
||||
#ifndef NDEBUG
|
||||
assert(card != NULL);
|
||||
#endif
|
||||
return card->magic == SC_CARD_MAGIC;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-asn1.h"
|
||||
#include "sc-log.h"
|
||||
|
||||
|
@ -178,7 +178,7 @@ static int iso7816_select_file(struct sc_card *card,
|
|||
default:
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
apdu.p2 = 0; /* record */
|
||||
apdu.p2 = 0; /* first record */
|
||||
apdu.lc = pathlen;
|
||||
apdu.data = path;
|
||||
apdu.datalen = pathlen;
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <pthread.h>
|
||||
#include <winscard.h>
|
||||
#ifndef NDEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -70,31 +73,18 @@ extern "C" {
|
|||
#define SC_APDU_CASE_3_EXT 6
|
||||
#define SC_APDU_CASE_4_EXT 7
|
||||
|
||||
#define SC_ISO7816_4_SELECT_FILE 0xA4
|
||||
#define SC_ISO7816_4_GET_RESPONSE 0xC0
|
||||
#define SC_ISO7616_4_READ_BINARY 0xB0
|
||||
#define SC_ISO7616_4_VERIFY 0x20
|
||||
#define SC_ISO7616_4_UPDATE_BINARY 0xD6
|
||||
#define SC_ISO7616_4_ERASE_BINARY 0x0E
|
||||
|
||||
#define SC_SELECT_FILE_RECORD_FIRST 0x00
|
||||
#define SC_SELECT_FILE_RECORD_LAST 0x01
|
||||
#define SC_SELECT_FILE_RECORD_NEXT 0x02
|
||||
#define SC_SELECT_FILE_RECORD_PREVIOUS 0x03
|
||||
|
||||
#define SC_SELECT_FILE_BY_FILE_ID 0x00
|
||||
#define SC_SELECT_FILE_BY_DF_NAME 0x01
|
||||
#define SC_SELECT_FILE_BY_PATH 0x02
|
||||
|
||||
#define SC_FILE_MAGIC 0x10203040
|
||||
|
||||
#define SC_FILE_TYPE_DF 0x03
|
||||
#define SC_FILE_TYPE_DF 0x02
|
||||
#define SC_FILE_TYPE_INTERNAL_EF 0x01
|
||||
#define SC_FILE_TYPE_WORKING_EF 0x00
|
||||
|
||||
#define SC_FILE_EF_TRANSPARENT 0x01
|
||||
#define SC_FILE_EF_LINEAR_FIXED 0x02
|
||||
#define SC_FILE_EF_LINEAR_FIXED_TLV 0x03
|
||||
#define SC_FILE_EF_LINEAR_VARIABLE 0x04
|
||||
#define SC_FILE_EF_CYCLIC 0x06
|
||||
|
||||
#define SC_FILE_STATUS_ACTIVATED 0x00
|
||||
#define SC_FILE_STATUS_INVALIDATED 0x01
|
||||
|
||||
#define SC_MAX_CARD_DRIVERS 16
|
||||
#define SC_MAX_READERS 4
|
||||
|
@ -132,10 +122,10 @@ struct sc_file {
|
|||
|
||||
int type, shareable, ef_structure;
|
||||
size_t size;
|
||||
int id;
|
||||
int id, status;
|
||||
u8 sec_attr[SC_MAX_SEC_ATTR_SIZE];
|
||||
size_t sec_attr_len;
|
||||
u8 prop_attr[SC_MAX_SEC_ATTR_SIZE];
|
||||
u8 prop_attr[SC_MAX_PROP_ATTR_SIZE];
|
||||
size_t prop_attr_len;
|
||||
unsigned int magic;
|
||||
};
|
||||
|
@ -146,7 +136,6 @@ struct sc_file {
|
|||
struct sc_security_env {
|
||||
int algorithm_ref;
|
||||
struct sc_path key_file_id;
|
||||
/* operation=1 ==> digital signing, signature=0 ==> decipher */
|
||||
int operation;
|
||||
int key_ref;
|
||||
};
|
||||
|
@ -161,8 +150,11 @@ struct sc_card {
|
|||
size_t atr_len;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
int lock_count;
|
||||
const struct sc_card_operations *ops;
|
||||
void *ops_data;
|
||||
|
||||
unsigned int magic;
|
||||
};
|
||||
|
||||
struct sc_card_operations {
|
||||
|
@ -250,7 +242,7 @@ struct sc_context {
|
|||
int debug;
|
||||
|
||||
int use_std_output, use_cache;
|
||||
const struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS];
|
||||
const struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS+1];
|
||||
};
|
||||
|
||||
struct sc_apdu {
|
||||
|
@ -295,7 +287,6 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout);
|
|||
int sc_lock(struct sc_card *card);
|
||||
int sc_unlock(struct sc_card *card);
|
||||
|
||||
|
||||
/* ISO 7816-4 related functions */
|
||||
int sc_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
struct sc_file *file);
|
||||
|
@ -327,17 +318,12 @@ int sc_list_files(struct sc_card *card, u8 * buf, int buflen);
|
|||
|
||||
const char *sc_strerror(int error);
|
||||
|
||||
/* Internal use only */
|
||||
int sc_file_valid(const struct sc_file *file);
|
||||
void sc_print_binary(FILE *f, const u8 *buf, int len);
|
||||
int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen);
|
||||
int sc_sw_to_errorcode(struct sc_card *card, int sw1, int sw2);
|
||||
void sc_format_path(const char *path_in, struct sc_path *path_out);
|
||||
|
||||
extern const char *sc_version;
|
||||
|
||||
extern const struct sc_card_driver *sc_get_iso7816_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_setec_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_mflex_driver(void);
|
||||
extern const struct sc_card_driver *sc_get_default_driver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include "sc-log.h"
|
||||
#include "sc-asn1.h"
|
||||
|
@ -229,14 +229,21 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
|
|||
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
||||
r = find_cached_cert(p15card, info, &data, &len);
|
||||
if (r) {
|
||||
r = sc_lock(p15card->card);
|
||||
SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
|
||||
r = sc_select_file(p15card->card, &info->path, &file);
|
||||
if (r)
|
||||
if (r) {
|
||||
sc_unlock(p15card->card);
|
||||
return r;
|
||||
}
|
||||
data = malloc(file.size);
|
||||
if (data == NULL)
|
||||
if (data == NULL) {
|
||||
sc_unlock(p15card->card);
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
r = sc_read_binary(p15card->card, 0, data, file.size);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
free(data);
|
||||
return r;
|
||||
}
|
||||
|
@ -244,6 +251,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
|
|||
#ifdef CACHE_CERTS
|
||||
store_cert_to_cache(p15card, info, data, len);
|
||||
#endif
|
||||
sc_unlock(p15card->card);
|
||||
}
|
||||
cert = malloc(sizeof(struct sc_pkcs15_cert));
|
||||
if (cert == NULL) {
|
||||
|
@ -351,16 +359,21 @@ static int get_certs_from_file(struct sc_pkcs15_card *card,
|
|||
|
||||
int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card)
|
||||
{
|
||||
int r, i;
|
||||
int r = 0, i;
|
||||
assert(card != NULL);
|
||||
|
||||
if (card->cert_count)
|
||||
return card->cert_count; /* already enumerated */
|
||||
r = sc_lock(card->card);
|
||||
SC_TEST_RET(card->card->ctx, r, "sc_lock() failed");
|
||||
for (i = 0; i < card->cdf_count; i++) {
|
||||
r = get_certs_from_file(card, &card->file_cdf[i]);
|
||||
if (r != 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
sc_unlock(card->card);
|
||||
if (r != 0)
|
||||
return r;
|
||||
return card->cert_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include "sc-asn1.h"
|
||||
#include "sc-log.h"
|
||||
|
@ -147,10 +147,16 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card)
|
|||
return i; /* Already enumerated */
|
||||
}
|
||||
p15card->pin_count = 0;
|
||||
r = sc_lock(p15card->card);
|
||||
SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
|
||||
for (i = 0; i < p15card->aodf_count; i++) {
|
||||
r = get_pins_from_file(p15card, &p15card->file_aodf[i]);
|
||||
SC_TEST_RET(ctx, r, "Failed to read PINs from AODF");
|
||||
if (r != 0)
|
||||
break;
|
||||
}
|
||||
sc_unlock(p15card->card);
|
||||
if (r != 0)
|
||||
return r;
|
||||
return p15card->pin_count;
|
||||
}
|
||||
|
||||
|
@ -169,15 +175,19 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
|
|||
if (pinlen > pin->stored_length || pinlen < pin->min_length)
|
||||
return SC_ERROR_INVALID_PIN_LENGTH;
|
||||
card = p15card->card;
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
r = sc_select_file(card, &pin->path, &file);
|
||||
if (r)
|
||||
if (r) {
|
||||
sc_unlock(card);
|
||||
return r;
|
||||
|
||||
}
|
||||
memset(pinbuf, pin->pad_char, pin->stored_length);
|
||||
memcpy(pinbuf, pincode, pinlen);
|
||||
r = sc_verify(card, pin->auth_id.value[0],
|
||||
pinbuf, pin->stored_length, &pin->tries_left);
|
||||
memset(pinbuf, 0, pinlen);
|
||||
sc_unlock(card);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -203,10 +213,13 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
|
|||
if ((oldpinlen < pin->min_length) || (newpinlen < pin->min_length))
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
card = p15card->card;
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
r = sc_select_file(card, &pin->path, &file);
|
||||
if (r)
|
||||
if (r) {
|
||||
sc_unlock(card);
|
||||
return r;
|
||||
|
||||
}
|
||||
memset(pinbuf, pin->pad_char, pin->stored_length * 2);
|
||||
memcpy(pinbuf, oldpin, oldpinlen);
|
||||
memcpy(pinbuf + pin->stored_length, newpin, newpinlen);
|
||||
|
@ -214,6 +227,7 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
|
|||
pin->stored_length, pinbuf+pin->stored_length,
|
||||
pin->stored_length, &pin->tries_left);
|
||||
memset(pinbuf, 0, pin->stored_length * 2);
|
||||
sc_unlock(card);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include "sc-asn1.h"
|
||||
#include "sc-log.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -133,11 +134,16 @@ int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card)
|
|||
|
||||
if (card->prkey_count)
|
||||
return card->prkey_count; /* already enumerated */
|
||||
r = sc_lock(card->card);
|
||||
SC_TEST_RET(card->card->ctx, r, "sc_lock() failed");
|
||||
for (i = 0; i < 1; i++) {
|
||||
r = get_prkeys_from_file(card, &card->file_prkdf);
|
||||
if (r != 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
sc_unlock(card->card);
|
||||
if (r != 0)
|
||||
return r;
|
||||
return card->prkey_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include "sc-log.h"
|
||||
#include <assert.h>
|
||||
|
@ -37,12 +37,12 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
|||
|
||||
senv.algorithm_ref = 0x02;
|
||||
senv.key_file_id = prkey->file_id;
|
||||
senv.operation = 0;
|
||||
senv.operation = SC_SEC_OPERATION_DECIPHER;
|
||||
senv.key_ref = prkey->key_reference;
|
||||
|
||||
SC_FUNC_CALLED(ctx, 1);
|
||||
r = sc_select_file(p15card->card, &p15card->file_app.path,
|
||||
&p15card->file_app);
|
||||
NULL);
|
||||
SC_TEST_RET(ctx, r, "sc_select_file() failed");
|
||||
#if 0
|
||||
/* FIXME! */
|
||||
|
@ -75,12 +75,12 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
break;
|
||||
}
|
||||
senv.key_file_id = prkey->file_id;
|
||||
senv.operation = 1;
|
||||
senv.operation = SC_SEC_OPERATION_SIGN;
|
||||
senv.key_ref = prkey->key_reference;
|
||||
|
||||
SC_FUNC_CALLED(ctx, 1);
|
||||
r = sc_select_file(p15card->card, &p15card->file_app.path,
|
||||
&p15card->file_app);
|
||||
NULL);
|
||||
SC_TEST_RET(ctx, r, "sc_select_file() failed");
|
||||
#if 0
|
||||
/* FIXME! */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "opensc-pkcs15.h"
|
||||
#include "sc-asn1.h"
|
||||
#include "sc-log.h"
|
||||
|
@ -252,9 +252,11 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
struct sc_pkcs15_card *p15card = NULL;
|
||||
struct sc_path tmppath;
|
||||
const struct sc_pkcs15_defaults *defaults = NULL;
|
||||
struct sc_context *ctx;
|
||||
|
||||
assert(card != NULL && p15card_out != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
assert(sc_card_valid(card) && p15card_out != NULL);
|
||||
ctx = card->ctx;
|
||||
SC_FUNC_CALLED(ctx, 1);
|
||||
p15card = malloc(sizeof(struct sc_pkcs15_card));
|
||||
if (p15card == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -262,19 +264,30 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
p15card->card = card;
|
||||
|
||||
sc_format_path("2F00", &tmppath);
|
||||
err = sc_lock(card);
|
||||
if (err) {
|
||||
error(ctx, "sc_lock() failed: %s\n", sc_strerror(err));
|
||||
goto error;
|
||||
}
|
||||
err = sc_select_file(card, &tmppath, &p15card->file_dir);
|
||||
if (err)
|
||||
if (err) {
|
||||
error(ctx, "Error selecting EF(DIR): %s\n", sc_strerror(err));
|
||||
goto error;
|
||||
}
|
||||
err = sc_read_binary(card, 0, buf, p15card->file_dir.size);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
error(ctx, "Error reading EF(DIR): %s\n", sc_strerror(err));
|
||||
goto error;
|
||||
}
|
||||
if (err <= 2) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
error(ctx, "Error reading EF(DIR): too few bytes read\n");
|
||||
goto error;
|
||||
}
|
||||
len = err;
|
||||
if (parse_dir(buf, len, p15card)) {
|
||||
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
||||
error(ctx, "Error parsing EF(DIR)\n");
|
||||
goto error;
|
||||
}
|
||||
if (p15card->use_cache)
|
||||
|
@ -288,7 +301,7 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
tmppath = p15card->file_odf.path;
|
||||
|
||||
err = sc_select_file(card, &tmppath, &p15card->file_odf);
|
||||
if (err)
|
||||
if (err) /* FIXME: finish writing error stuff */
|
||||
goto error;
|
||||
err = sc_read_binary(card, 0, buf, p15card->file_odf.size);
|
||||
if (err < 0)
|
||||
|
@ -327,10 +340,12 @@ int sc_pkcs15_bind(struct sc_card *card,
|
|||
p15card->use_cache = card->ctx->use_cache;
|
||||
|
||||
*p15card_out = p15card;
|
||||
sc_unlock(card);
|
||||
return 0;
|
||||
error:
|
||||
free(p15card);
|
||||
return err;
|
||||
sc_unlock(card);
|
||||
SC_FUNC_RETURN(ctx, 1, err);
|
||||
}
|
||||
|
||||
int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
#include "sc-asn1.h"
|
||||
#include <stdio.h>
|
||||
|
@ -187,14 +187,21 @@ int sc_establish_context(struct sc_context **ctx_out)
|
|||
break;
|
||||
} while (p < (reader_buf + reader_buf_size - 1));
|
||||
free(reader_buf);
|
||||
for (i = 0; i < SC_MAX_CARD_DRIVERS; i++)
|
||||
for (i = 0; i < SC_MAX_CARD_DRIVERS+1; i++)
|
||||
ctx->card_drivers[i] = NULL;
|
||||
i = 0;
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_setec_driver();
|
||||
#endif
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_mflex_driver();
|
||||
#endif
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_iso7816_driver();
|
||||
#endif
|
||||
#if 1
|
||||
ctx->card_drivers[i++] = sc_get_setec_driver();
|
||||
/* this should be last in line */
|
||||
ctx->card_drivers[i++] = sc_get_default_driver();
|
||||
#endif
|
||||
|
||||
*ctx_out = ctx;
|
||||
|
@ -216,8 +223,13 @@ int sc_destroy_context(struct sc_context *ctx)
|
|||
void sc_format_path(const char *str, struct sc_path *path)
|
||||
{
|
||||
int len = 0;
|
||||
int type = SC_PATH_TYPE_PATH;
|
||||
u8 *p = path->value;
|
||||
|
||||
if (*p == 'i' || *p == 'I') {
|
||||
type = SC_PATH_TYPE_FILE_ID;
|
||||
p++;
|
||||
}
|
||||
while (str) {
|
||||
int byte;
|
||||
|
||||
|
@ -228,7 +240,7 @@ void sc_format_path(const char *str, struct sc_path *path)
|
|||
str += 2;
|
||||
}
|
||||
path->len = len;
|
||||
path->type = SC_PATH_TYPE_PATH;
|
||||
path->type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -275,3 +287,10 @@ const char *sc_strerror(int error)
|
|||
return errors[0];
|
||||
return errors[error];
|
||||
}
|
||||
|
||||
inline int sc_file_valid(const struct sc_file *file) {
|
||||
#ifndef NDEBUG
|
||||
assert(file != NULL);
|
||||
#endif
|
||||
return file->magic == SC_FILE_MAGIC;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "opensc.h"
|
||||
#include "sc-internal.h"
|
||||
#include "sc-log.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
@ -35,12 +35,17 @@ int sc_set_security_env(struct sc_card *card,
|
|||
assert(card != NULL && env != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, 2);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
|
||||
if (env->operation == 1) {
|
||||
apdu.p1 = 0x81;
|
||||
apdu.p2 = 0xB6;
|
||||
} else {
|
||||
switch (env->operation) {
|
||||
case SC_SEC_OPERATION_DECIPHER:
|
||||
apdu.p1 = 0x41;
|
||||
apdu.p2 = 0xB8;
|
||||
break;
|
||||
case SC_SEC_OPERATION_SIGN:
|
||||
apdu.p1 = 0x81;
|
||||
apdu.p2 = 0xB6;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
apdu.le = 0;
|
||||
p = sbuf;
|
||||
|
|
|
@ -10,15 +10,15 @@ SRC = pam_pkcs15.c
|
|||
INC =
|
||||
|
||||
if HAVE_PAM_AND_SSL
|
||||
lib_LTLIBRARIES = libpam_pkcs15.la
|
||||
lib_LTLIBRARIES = pam_pkcs15.la
|
||||
noinst_PROGRAMS = pam_pkcs15-test
|
||||
else
|
||||
lib_LTLIBRARIES =
|
||||
noinst_PROGRAMS =
|
||||
endif
|
||||
|
||||
libpam_pkcs15_la_SOURCES = $(SRC) $(INC)
|
||||
libpam_pkcs15_la_LDFLAGS = -module -avoid-version
|
||||
pam_pkcs15_la_SOURCES = $(SRC) $(INC)
|
||||
pam_pkcs15_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pam_pkcs15_test_SOURCES = $(SRC) $(INC)
|
||||
pam_pkcs15_test_CFLAGS = -DTEST
|
||||
|
@ -27,7 +27,5 @@ if HAVE_PAM_AND_SSL
|
|||
|
||||
install-exec-local: install-libLTLIBRARIES
|
||||
@$(NORMAL_INSTALL)
|
||||
-rm -f $(DESTDIR)$(libdir)/pam_pkcs15.so
|
||||
-cd $(DESTDIR)$(libdir) && ln -s libpam_pkcs15.so pam_pkcs15.so
|
||||
|
||||
endif
|
||||
|
|
|
@ -16,4 +16,4 @@ INC = sc-pkcs11.h
|
|||
lib_LTLIBRARIES = libopensc-pkcs11.la
|
||||
|
||||
libopensc_pkcs11_la_SOURCES = $(SRC) $(INC)
|
||||
libopensc_pkcs11_la_LDFLAGS = -module
|
||||
libopensc_pkcs11_la_LDFLAGS = -module -version-info 1:0:0
|
||||
|
|
|
@ -292,7 +292,15 @@ int main(int argc, char * const argv[])
|
|||
goto end;
|
||||
}
|
||||
|
||||
sc_lock(card);
|
||||
#if 0
|
||||
r = sc_lock(card);
|
||||
if (r) {
|
||||
fprintf(stderr, "Unable to lock card: %s\n", sc_strerror(r));
|
||||
err = 1;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!quiet)
|
||||
fprintf(stderr, "Trying to find a PKCS#15 compatible card...\n");
|
||||
r = sc_pkcs15_bind(card, &p15card);
|
||||
|
@ -358,7 +366,9 @@ end:
|
|||
if (p15card)
|
||||
sc_pkcs15_unbind(p15card);
|
||||
if (card) {
|
||||
#if 0
|
||||
sc_unlock(card);
|
||||
#endif
|
||||
sc_disconnect_card(card);
|
||||
}
|
||||
if (ctx)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <opensc.h>
|
||||
#include <opensc-pkcs15.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define OPT_CHANGE_PIN 0x100
|
||||
#define OPT_LIST_PINS 0x101
|
||||
|
@ -44,6 +45,7 @@ int quiet = 0;
|
|||
|
||||
const struct option options[] = {
|
||||
{ "list-readers", 0, 0, 'l' },
|
||||
{ "list-drivers", 0, 0, 'D' },
|
||||
{ "list-files", 0, 0, 'f' },
|
||||
{ "learn-card", 0, 0, 'L' },
|
||||
{ "send-apdu", 1, 0, 's' },
|
||||
|
@ -63,6 +65,7 @@ const struct option options[] = {
|
|||
|
||||
const char *option_help[] = {
|
||||
"Lists all configured readers",
|
||||
"Lists all installed card drivers",
|
||||
"Recursively lists files stored on card",
|
||||
"Stores card info to cache [P15]",
|
||||
"Sends an APDU in format AA:BB:CC:DD:EE:FF...",
|
||||
|
@ -126,6 +129,10 @@ int list_readers()
|
|||
{
|
||||
int i;
|
||||
|
||||
if (ctx->reader_count == 0) {
|
||||
printf("No readers configured!\n");
|
||||
return 0;
|
||||
}
|
||||
printf("Configured readers:\n");
|
||||
for (i = 0; i < ctx->reader_count; i++) {
|
||||
printf("\t%d - %s\n", i, ctx->readers[i]);
|
||||
|
@ -133,6 +140,21 @@ int list_readers()
|
|||
return 0;
|
||||
}
|
||||
|
||||
int list_drivers()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ctx->card_drivers[0] == NULL) {
|
||||
printf("No card drivers installed!\n");
|
||||
return 0;
|
||||
}
|
||||
printf("Configured card drivers:\n");
|
||||
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
|
||||
printf("\t%s\n", ctx->card_drivers[i]->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_certificates()
|
||||
{
|
||||
int r, i;
|
||||
|
@ -359,7 +381,7 @@ int enum_dir(struct sc_path path, int depth)
|
|||
u8 buf[2048];
|
||||
const char *tmps;
|
||||
|
||||
r = sc_select_file(card, &file, &path);
|
||||
r = sc_select_file(card, &path, &file);
|
||||
if (r) {
|
||||
fprintf(stderr, "SELECT FILE failed: %s\n", sc_strerror(r));
|
||||
return 1;
|
||||
|
@ -528,18 +550,44 @@ int learn_card()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void hex_dump_asc(const u8 *in, size_t count)
|
||||
{
|
||||
int lines = 0;
|
||||
|
||||
while (count) {
|
||||
char ascbuf[17];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count && i < 16; i++) {
|
||||
printf("%02X ", *in);
|
||||
if (isprint(*in))
|
||||
ascbuf[i] = *in;
|
||||
else
|
||||
ascbuf[i] = '.';
|
||||
in++;
|
||||
}
|
||||
count -= i;
|
||||
ascbuf[i] = 0;
|
||||
for (; i < 16 && lines; i++)
|
||||
printf(" ");
|
||||
printf("%s\n", ascbuf);
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
int send_apdu()
|
||||
{
|
||||
struct sc_apdu apdu;
|
||||
u8 buf[MAX_BUFFER_SIZE], sbuf[MAX_BUFFER_SIZE],
|
||||
rbuf[MAX_BUFFER_SIZE], *p = buf;
|
||||
int len = sizeof(buf), r;
|
||||
int len = sizeof(buf), len0, r;
|
||||
|
||||
sc_hex_to_bin(opt_apdu, buf, &len);
|
||||
sc_hex_to_bin(opt_apdu, buf, &len0);
|
||||
if (len < 4) {
|
||||
fprintf(stderr, "APDU too short (must be at least 4 bytes).\n");
|
||||
return 2;
|
||||
}
|
||||
len = len0;
|
||||
apdu.cla = *p++;
|
||||
apdu.ins = *p++;
|
||||
apdu.p1 = *p++;
|
||||
|
@ -548,6 +596,7 @@ int send_apdu()
|
|||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.data = NULL;
|
||||
apdu.datalen = 0;
|
||||
apdu.no_response = 0;
|
||||
len -= 4;
|
||||
if (len > 1) {
|
||||
apdu.lc = *p++;
|
||||
|
@ -577,15 +626,21 @@ int send_apdu()
|
|||
apdu.cse = SC_APDU_CASE_2_SHORT;
|
||||
} else
|
||||
apdu.cse = SC_APDU_CASE_1;
|
||||
|
||||
ctx->debug = 5;
|
||||
printf("Sending: ");
|
||||
for (r = 0; r < len0; r++)
|
||||
printf("%02X ", buf[r]);
|
||||
printf("\n");
|
||||
// ctx->debug = 5;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
ctx->debug = opt_debug;
|
||||
// ctx->debug = opt_debug;
|
||||
if (r) {
|
||||
fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2,
|
||||
apdu.resplen ? ":" : "");
|
||||
if (apdu.resplen)
|
||||
hex_dump_asc(apdu.resp, apdu.resplen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -593,6 +648,7 @@ int main(int argc, char * const argv[])
|
|||
{
|
||||
int err = 0, r, c, long_optind = 0;
|
||||
int do_list_readers = 0;
|
||||
int do_list_drivers = 0;
|
||||
int do_read_cert = 0;
|
||||
int do_list_certs = 0;
|
||||
int do_list_pins = 0;
|
||||
|
@ -604,7 +660,7 @@ int main(int argc, char * const argv[])
|
|||
int action_count = 0;
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "lfr:kco:qdp:s:L", options, &long_optind);
|
||||
c = getopt_long(argc, argv, "lfr:kco:qdp:s:LD", options, &long_optind);
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '?')
|
||||
|
@ -619,6 +675,10 @@ int main(int argc, char * const argv[])
|
|||
do_list_readers = 1;
|
||||
action_count++;
|
||||
break;
|
||||
case 'D':
|
||||
do_list_drivers = 1;
|
||||
action_count++;
|
||||
break;
|
||||
case 'f':
|
||||
do_list_files = 1;
|
||||
action_count++;
|
||||
|
@ -684,6 +744,11 @@ int main(int argc, char * const argv[])
|
|||
goto end;
|
||||
action_count--;
|
||||
}
|
||||
if (do_list_drivers) {
|
||||
if ((err = list_drivers()))
|
||||
goto end;
|
||||
action_count--;
|
||||
}
|
||||
if (action_count <= 0)
|
||||
goto end;
|
||||
if (opt_reader >= ctx->reader_count || opt_reader < 0) {
|
||||
|
@ -704,7 +769,12 @@ int main(int argc, char * const argv[])
|
|||
goto end;
|
||||
}
|
||||
|
||||
sc_lock(card);
|
||||
r = sc_lock(card);
|
||||
if (r) {
|
||||
fprintf(stderr, "Unable to lock card: %s\n", sc_strerror(r));
|
||||
err = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (do_send_apdu) {
|
||||
if ((err = send_apdu()))
|
||||
|
|
Loading…
Reference in New Issue