- 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:
jey 2001-12-25 20:45:48 +00:00
parent 1d220ccdca
commit 2b99f2df14
21 changed files with 554 additions and 115 deletions

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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)

View File

@ -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: */

View File

@ -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;
}

View File

@ -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>

View File

@ -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;

View File

@ -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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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! */

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()))