- 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.c sc-pkcs15-cert.c \
sc-pkcs15-pin.c sc-pkcs15-prkey.c \ sc-pkcs15-pin.c sc-pkcs15-prkey.c \
sc-pkcs15-defaults.c sc-pkcs15-sec.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_LDFLAGS = -version-info 0:4:0
libopensc_la_LIBADD = @LIBPCSCLITE@ libopensc_la_LIBADD = @LIBPCSCLITE@
libopensc_la_CFLAGS = $(AM_CFLAGS) -Werror libopensc_la_CFLAGS = $(AM_CFLAGS) -Werror
include_HEADERS = opensc.h opensc-pkcs15.h 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 * 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-asn1.h"
#include "sc-log.h" #include "sc-log.h"
#include <stdio.h> #include <stdio.h>

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.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 * 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[] = { static const char *mflex_atrs[] = {
"3B:19:14:55:90:01:02:02:00:05:04:B0", "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 struct sc_card_operations mflex_ops;
static const struct sc_card_driver mflex_drv = { static const struct sc_card_driver mflex_drv = {
NULL, NULL,
"Schlumberger/Multiflex", "Multiflex/Schlumberger",
&mflex_ops &mflex_ops
}; };
@ -69,10 +70,120 @@ static int mflex_init(struct sc_card *card)
return 0; 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, static int mflex_select_file(struct sc_card *card, const struct sc_path *path,
struct sc_file *file) 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) 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
static const char *setec_atrs[] = { static const char *setec_atrs[] = {
/* the current FINEID card has this ATR: */ /* 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 * 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-log.h"
#include "sc-asn1.h" #include "sc-asn1.h"
#include <assert.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; 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) static int sc_check_apdu(struct sc_context *ctx, const struct sc_apdu *apdu)
{ {
switch (apdu->cse) { 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); SC_FUNC_CALLED(card->ctx, 4);
r = sc_check_apdu(card->ctx, apdu); r = sc_check_apdu(card->ctx, apdu);
SC_TEST_RET(card->ctx, r, "APDU sanity check failed"); 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); 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) { if (card->ctx->debug >= 5) {
char buf[2048]; char buf[2048];
@ -207,9 +227,13 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu)
struct sc_apdu rspapdu; struct sc_apdu rspapdu;
BYTE rsp[SC_MAX_APDU_BUFFER_SIZE]; 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; return 0;
}
sc_format_apdu(card, &rspapdu, SC_APDU_CASE_2_SHORT, sc_format_apdu(card, &rspapdu, SC_APDU_CASE_2_SHORT,
0xC0, 0, 0); 0xC0, 0, 0);
rspapdu.le = (size_t) apdu->sw2; 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) { if (r != 0) {
error(card->ctx, "error while getting response: %s\n", error(card->ctx, "error while getting response: %s\n",
sc_strerror(r)); sc_strerror(r));
sc_unlock(card);
return r; return r;
} }
if (card->ctx->debug >= 5) { 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->sw1 = rspapdu.sw1;
apdu->sw2 = rspapdu.sw2; apdu->sw2 = rspapdu.sw2;
} }
sc_unlock(card);
return 0; return 0;
} }
@ -296,6 +322,7 @@ int sc_connect_card(struct sc_context *ctx,
card->reader = reader; card->reader = reader;
card->ctx = ctx; card->ctx = ctx;
card->pcsc_card = card_handle; card->pcsc_card = card_handle;
card->lock_count = 0;
i = rgReaderStates[0].cbAtr; i = rgReaderStates[0].cbAtr;
if (i >= SC_MAX_ATR_SIZE) if (i >= SC_MAX_ATR_SIZE)
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++) { for (i = 0; ctx->card_drivers[i] != NULL; i++) {
const struct sc_card_driver *drv = ctx->card_drivers[i]; const struct sc_card_driver *drv = ctx->card_drivers[i];
const struct sc_card_operations *ops = drv->ops; const struct sc_card_operations *ops = drv->ops;
int r;
if (ctx->debug >= 3) if (ctx->debug >= 3)
debug(ctx, "trying driver: %s\n", drv->name); debug(ctx, "trying driver: %s\n", drv->name);
if (ops == NULL || ops->match_card == NULL) if (ops == NULL || ops->match_card == NULL)
continue; continue;
if (ops->match_card(card) == 1) { if (ops->match_card(card) != 1)
if (ctx->debug >= 3) continue;
debug(ctx, "matched\n"); if (ctx->debug >= 3)
card->ops = ops; 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) { if (card->ops == NULL) {
error(ctx, "unable to find driver for inserted card\n"); 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; return SC_ERROR_INVALID_CARD;
} }
pthread_mutex_init(&card->mutex, NULL); pthread_mutex_init(&card->mutex, NULL);
card->magic = SC_CARD_MAGIC;
*card_out = card; *card_out = card;
SC_FUNC_RETURN(ctx, 1, 0); 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) int sc_disconnect_card(struct sc_card *card)
{ {
struct sc_context *ctx = card->ctx; struct sc_context *ctx;
assert(card != NULL); assert(sc_card_valid(card));
ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1); 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); SCardDisconnect(card->pcsc_card, SCARD_LEAVE_CARD);
pthread_mutex_destroy(&card->mutex); pthread_mutex_destroy(&card->mutex);
free(card); free(card);
SC_FUNC_RETURN(ctx, 1, 0); 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) static int _sc_lock_int(struct sc_card *card)
{ {
long rv; long rv;
@ -345,18 +395,27 @@ static int _sc_lock_int(struct sc_card *card)
if (rv != SCARD_S_SUCCESS) { if (rv != SCARD_S_SUCCESS) {
error(card->ctx, "SCardBeginTransaction failed: %s\n", pcsc_stringify_error(rv)); error(card->ctx, "SCardBeginTransaction failed: %s\n", pcsc_stringify_error(rv));
return -1; return _sc_pcscret_to_error(rv);
} }
return 0; return 0;
} }
int sc_lock(struct sc_card *card) int sc_lock(struct sc_card *card)
{ {
int r = 0;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2); SC_FUNC_CALLED(card->ctx, 2);
pthread_mutex_lock(&card->mutex); 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) static int _sc_unlock_int(struct sc_card *card)
{ {
long rv; long rv;
@ -371,9 +430,17 @@ static int _sc_unlock_int(struct sc_card *card)
int sc_unlock(struct sc_card *card) int sc_unlock(struct sc_card *card)
{ {
int r = 0;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2); 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); 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) 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)); 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, int sc_read_binary(struct sc_card *card, unsigned int idx,
unsigned char *buf, size_t count) 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); SC_FUNC_RETURN(card->ctx, 2, r);
} }
/* no read_binary_large support... */ /* no read_binary_large support... */
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
while (count > 0) { while (count > 0) {
int n = count > RB_BUF_SIZE ? RB_BUF_SIZE : count; int n = count > RB_BUF_SIZE ? RB_BUF_SIZE : count;
r = sc_read_binary(card, idx, p, n); 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; p += r;
idx += r; idx += r;
bytes_read += r; bytes_read += r;
count -= r; count -= r;
if (r == 0) if (r == 0) {
sc_unlock(card);
SC_FUNC_RETURN(card->ctx, 2, bytes_read); SC_FUNC_RETURN(card->ctx, 2, bytes_read);
}
} }
sc_unlock(card);
SC_FUNC_RETURN(card->ctx, 2, bytes_read); SC_FUNC_RETURN(card->ctx, 2, bytes_read);
} }
if (card->ops->read_binary == NULL) if (card->ops->read_binary == NULL)
@ -528,7 +596,7 @@ int sc_select_file(struct sc_card *card,
assert(card != NULL && in_path != NULL); assert(card != NULL && in_path != NULL);
if (card->ctx->debug >= 2) { if (card->ctx->debug >= 2) {
char line[128], *linep = line; char line[128], *linep = line;
linep += sprintf(linep, "called with type %d, path ", in_path->type); linep += sprintf(linep, "called with type %d, path ", in_path->type);
for (r = 0; r < in_path->len; r++) { for (r = 0; r < in_path->len; r++) {
sprintf(linep, "%02X", in_path->value[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); r = card->ops->get_challenge(card, rnd, len);
SC_FUNC_RETURN(card->ctx, 2, r); 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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-asn1.h"
#include "sc-log.h" #include "sc-log.h"
@ -178,7 +178,7 @@ static int iso7816_select_file(struct sc_card *card,
default: default:
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
} }
apdu.p2 = 0; /* record */ apdu.p2 = 0; /* first record */
apdu.lc = pathlen; apdu.lc = pathlen;
apdu.data = path; apdu.data = path;
apdu.datalen = pathlen; apdu.datalen = pathlen;

View File

@ -23,6 +23,9 @@
#include <pthread.h> #include <pthread.h>
#include <winscard.h> #include <winscard.h>
#ifndef NDEBUG
#include <assert.h>
#endif
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -70,31 +73,18 @@ extern "C" {
#define SC_APDU_CASE_3_EXT 6 #define SC_APDU_CASE_3_EXT 6
#define SC_APDU_CASE_4_EXT 7 #define SC_APDU_CASE_4_EXT 7
#define SC_ISO7816_4_SELECT_FILE 0xA4 #define SC_FILE_TYPE_DF 0x02
#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_INTERNAL_EF 0x01 #define SC_FILE_TYPE_INTERNAL_EF 0x01
#define SC_FILE_TYPE_WORKING_EF 0x00 #define SC_FILE_TYPE_WORKING_EF 0x00
#define SC_FILE_EF_TRANSPARENT 0x01 #define SC_FILE_EF_TRANSPARENT 0x01
#define SC_FILE_EF_LINEAR_FIXED 0x02 #define SC_FILE_EF_LINEAR_FIXED 0x02
#define SC_FILE_EF_LINEAR_FIXED_TLV 0x03 #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_CARD_DRIVERS 16
#define SC_MAX_READERS 4 #define SC_MAX_READERS 4
@ -132,10 +122,10 @@ struct sc_file {
int type, shareable, ef_structure; int type, shareable, ef_structure;
size_t size; size_t size;
int id; int id, status;
u8 sec_attr[SC_MAX_SEC_ATTR_SIZE]; u8 sec_attr[SC_MAX_SEC_ATTR_SIZE];
size_t sec_attr_len; 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; size_t prop_attr_len;
unsigned int magic; unsigned int magic;
}; };
@ -146,7 +136,6 @@ struct sc_file {
struct sc_security_env { struct sc_security_env {
int algorithm_ref; int algorithm_ref;
struct sc_path key_file_id; struct sc_path key_file_id;
/* operation=1 ==> digital signing, signature=0 ==> decipher */
int operation; int operation;
int key_ref; int key_ref;
}; };
@ -161,8 +150,11 @@ struct sc_card {
size_t atr_len; size_t atr_len;
pthread_mutex_t mutex; pthread_mutex_t mutex;
int lock_count;
const struct sc_card_operations *ops; const struct sc_card_operations *ops;
void *ops_data; void *ops_data;
unsigned int magic;
}; };
struct sc_card_operations { struct sc_card_operations {
@ -250,7 +242,7 @@ struct sc_context {
int debug; int debug;
int use_std_output, use_cache; 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 { 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_lock(struct sc_card *card);
int sc_unlock(struct sc_card *card); int sc_unlock(struct sc_card *card);
/* ISO 7816-4 related functions */ /* ISO 7816-4 related functions */
int sc_select_file(struct sc_card *card, const struct sc_path *path, int sc_select_file(struct sc_card *card, const struct sc_path *path,
struct sc_file *file); 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); 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 char *sc_version;
extern const struct sc_card_driver *sc_get_iso7816_driver(void); 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_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 #ifdef __cplusplus
} }

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include "sc-log.h" #include "sc-log.h"
#include "sc-asn1.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); SC_FUNC_CALLED(p15card->card->ctx, 1);
r = find_cached_cert(p15card, info, &data, &len); r = find_cached_cert(p15card, info, &data, &len);
if (r) { 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); r = sc_select_file(p15card->card, &info->path, &file);
if (r) if (r) {
sc_unlock(p15card->card);
return r; return r;
}
data = malloc(file.size); data = malloc(file.size);
if (data == NULL) if (data == NULL) {
sc_unlock(p15card->card);
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
}
r = sc_read_binary(p15card->card, 0, data, file.size); r = sc_read_binary(p15card->card, 0, data, file.size);
if (r < 0) { if (r < 0) {
sc_unlock(p15card->card);
free(data); free(data);
return r; return r;
} }
@ -244,6 +251,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
#ifdef CACHE_CERTS #ifdef CACHE_CERTS
store_cert_to_cache(p15card, info, data, len); store_cert_to_cache(p15card, info, data, len);
#endif #endif
sc_unlock(p15card->card);
} }
cert = malloc(sizeof(struct sc_pkcs15_cert)); cert = malloc(sizeof(struct sc_pkcs15_cert));
if (cert == NULL) { 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 sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card)
{ {
int r, i; int r = 0, i;
assert(card != NULL); assert(card != NULL);
if (card->cert_count) if (card->cert_count)
return card->cert_count; /* already enumerated */ 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++) { for (i = 0; i < card->cdf_count; i++) {
r = get_certs_from_file(card, &card->file_cdf[i]); r = get_certs_from_file(card, &card->file_cdf[i]);
if (r != 0) if (r != 0)
return r; break;
} }
sc_unlock(card->card);
if (r != 0)
return r;
return card->cert_count; return card->cert_count;
} }

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include "sc-asn1.h" #include "sc-asn1.h"
#include "sc-log.h" #include "sc-log.h"
@ -147,10 +147,16 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card)
return i; /* Already enumerated */ return i; /* Already enumerated */
} }
p15card->pin_count = 0; 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++) { for (i = 0; i < p15card->aodf_count; i++) {
r = get_pins_from_file(p15card, &p15card->file_aodf[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; 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) if (pinlen > pin->stored_length || pinlen < pin->min_length)
return SC_ERROR_INVALID_PIN_LENGTH; return SC_ERROR_INVALID_PIN_LENGTH;
card = p15card->card; card = p15card->card;
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
r = sc_select_file(card, &pin->path, &file); r = sc_select_file(card, &pin->path, &file);
if (r) if (r) {
sc_unlock(card);
return r; return r;
}
memset(pinbuf, pin->pad_char, pin->stored_length); memset(pinbuf, pin->pad_char, pin->stored_length);
memcpy(pinbuf, pincode, pinlen); memcpy(pinbuf, pincode, pinlen);
r = sc_verify(card, pin->auth_id.value[0], r = sc_verify(card, pin->auth_id.value[0],
pinbuf, pin->stored_length, &pin->tries_left); pinbuf, pin->stored_length, &pin->tries_left);
memset(pinbuf, 0, pinlen); memset(pinbuf, 0, pinlen);
sc_unlock(card);
if (r) if (r)
return 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)) if ((oldpinlen < pin->min_length) || (newpinlen < pin->min_length))
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
card = p15card->card; card = p15card->card;
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
r = sc_select_file(card, &pin->path, &file); r = sc_select_file(card, &pin->path, &file);
if (r) if (r) {
sc_unlock(card);
return r; return r;
}
memset(pinbuf, pin->pad_char, pin->stored_length * 2); memset(pinbuf, pin->pad_char, pin->stored_length * 2);
memcpy(pinbuf, oldpin, oldpinlen); memcpy(pinbuf, oldpin, oldpinlen);
memcpy(pinbuf + pin->stored_length, newpin, newpinlen); 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, pinbuf+pin->stored_length,
pin->stored_length, &pin->tries_left); pin->stored_length, &pin->tries_left);
memset(pinbuf, 0, pin->stored_length * 2); memset(pinbuf, 0, pin->stored_length * 2);
sc_unlock(card);
return r; return r;
} }

View File

@ -18,9 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include "sc-asn1.h" #include "sc-asn1.h"
#include "sc-log.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -133,11 +134,16 @@ int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card)
if (card->prkey_count) if (card->prkey_count)
return card->prkey_count; /* already enumerated */ 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++) { for (i = 0; i < 1; i++) {
r = get_prkeys_from_file(card, &card->file_prkdf); r = get_prkeys_from_file(card, &card->file_prkdf);
if (r != 0) if (r != 0)
return r; break;
} }
sc_unlock(card->card);
if (r != 0)
return r;
return card->prkey_count; return card->prkey_count;
} }

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include "sc-log.h" #include "sc-log.h"
#include <assert.h> #include <assert.h>
@ -37,12 +37,12 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
senv.algorithm_ref = 0x02; senv.algorithm_ref = 0x02;
senv.key_file_id = prkey->file_id; senv.key_file_id = prkey->file_id;
senv.operation = 0; senv.operation = SC_SEC_OPERATION_DECIPHER;
senv.key_ref = prkey->key_reference; senv.key_ref = prkey->key_reference;
SC_FUNC_CALLED(ctx, 1); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path, r = sc_select_file(p15card->card, &p15card->file_app.path,
&p15card->file_app); NULL);
SC_TEST_RET(ctx, r, "sc_select_file() failed"); SC_TEST_RET(ctx, r, "sc_select_file() failed");
#if 0 #if 0
/* FIXME! */ /* FIXME! */
@ -75,12 +75,12 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
break; break;
} }
senv.key_file_id = prkey->file_id; senv.key_file_id = prkey->file_id;
senv.operation = 1; senv.operation = SC_SEC_OPERATION_SIGN;
senv.key_ref = prkey->key_reference; senv.key_ref = prkey->key_reference;
SC_FUNC_CALLED(ctx, 1); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path, r = sc_select_file(p15card->card, &p15card->file_app.path,
&p15card->file_app); NULL);
SC_TEST_RET(ctx, r, "sc_select_file() failed"); SC_TEST_RET(ctx, r, "sc_select_file() failed");
#if 0 #if 0
/* FIXME! */ /* FIXME! */

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "opensc.h" #include "sc-internal.h"
#include "opensc-pkcs15.h" #include "opensc-pkcs15.h"
#include "sc-asn1.h" #include "sc-asn1.h"
#include "sc-log.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_pkcs15_card *p15card = NULL;
struct sc_path tmppath; struct sc_path tmppath;
const struct sc_pkcs15_defaults *defaults = NULL; const struct sc_pkcs15_defaults *defaults = NULL;
struct sc_context *ctx;
assert(card != NULL && p15card_out != NULL); assert(sc_card_valid(card) && p15card_out != NULL);
SC_FUNC_CALLED(card->ctx, 1); ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1);
p15card = malloc(sizeof(struct sc_pkcs15_card)); p15card = malloc(sizeof(struct sc_pkcs15_card));
if (p15card == NULL) if (p15card == NULL)
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
@ -262,19 +264,30 @@ int sc_pkcs15_bind(struct sc_card *card,
p15card->card = card; p15card->card = card;
sc_format_path("2F00", &tmppath); 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); 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; goto error;
}
err = sc_read_binary(card, 0, buf, p15card->file_dir.size); 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; goto error;
}
if (err <= 2) { if (err <= 2) {
err = SC_ERROR_PKCS15_CARD_NOT_FOUND; err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
error(ctx, "Error reading EF(DIR): too few bytes read\n");
goto error; goto error;
} }
len = err; len = err;
if (parse_dir(buf, len, p15card)) { if (parse_dir(buf, len, p15card)) {
err = SC_ERROR_PKCS15_CARD_NOT_FOUND; err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
error(ctx, "Error parsing EF(DIR)\n");
goto error; goto error;
} }
if (p15card->use_cache) if (p15card->use_cache)
@ -288,7 +301,7 @@ int sc_pkcs15_bind(struct sc_card *card,
tmppath = p15card->file_odf.path; tmppath = p15card->file_odf.path;
err = sc_select_file(card, &tmppath, &p15card->file_odf); err = sc_select_file(card, &tmppath, &p15card->file_odf);
if (err) if (err) /* FIXME: finish writing error stuff */
goto error; goto error;
err = sc_read_binary(card, 0, buf, p15card->file_odf.size); err = sc_read_binary(card, 0, buf, p15card->file_odf.size);
if (err < 0) if (err < 0)
@ -327,10 +340,12 @@ int sc_pkcs15_bind(struct sc_card *card,
p15card->use_cache = card->ctx->use_cache; p15card->use_cache = card->ctx->use_cache;
*p15card_out = p15card; *p15card_out = p15card;
sc_unlock(card);
return 0; return 0;
error: error:
free(p15card); free(p15card);
return err; sc_unlock(card);
SC_FUNC_RETURN(ctx, 1, err);
} }
int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)

View File

@ -21,7 +21,7 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "opensc.h" #include "sc-internal.h"
#include "sc-log.h" #include "sc-log.h"
#include "sc-asn1.h" #include "sc-asn1.h"
#include <stdio.h> #include <stdio.h>
@ -187,14 +187,21 @@ int sc_establish_context(struct sc_context **ctx_out)
break; break;
} while (p < (reader_buf + reader_buf_size - 1)); } while (p < (reader_buf + reader_buf_size - 1));
free(reader_buf); 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; ctx->card_drivers[i] = NULL;
i = 0; 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 #if 1
ctx->card_drivers[i++] = sc_get_iso7816_driver(); ctx->card_drivers[i++] = sc_get_iso7816_driver();
#endif #endif
#if 1 #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 #endif
*ctx_out = ctx; *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) void sc_format_path(const char *str, struct sc_path *path)
{ {
int len = 0; int len = 0;
int type = SC_PATH_TYPE_PATH;
u8 *p = path->value; u8 *p = path->value;
if (*p == 'i' || *p == 'I') {
type = SC_PATH_TYPE_FILE_ID;
p++;
}
while (str) { while (str) {
int byte; int byte;
@ -228,7 +240,7 @@ void sc_format_path(const char *str, struct sc_path *path)
str += 2; str += 2;
} }
path->len = len; path->len = len;
path->type = SC_PATH_TYPE_PATH; path->type = type;
return; return;
} }
@ -275,3 +287,10 @@ const char *sc_strerror(int error)
return errors[0]; return errors[0];
return errors[error]; 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 * 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-log.h"
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -35,12 +35,17 @@ int sc_set_security_env(struct sc_card *card,
assert(card != NULL && env != NULL); assert(card != NULL && env != NULL);
SC_FUNC_CALLED(card->ctx, 2); SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
if (env->operation == 1) { switch (env->operation) {
apdu.p1 = 0x81; case SC_SEC_OPERATION_DECIPHER:
apdu.p2 = 0xB6;
} else {
apdu.p1 = 0x41; apdu.p1 = 0x41;
apdu.p2 = 0xB8; 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; apdu.le = 0;
p = sbuf; p = sbuf;

View File

@ -10,15 +10,15 @@ SRC = pam_pkcs15.c
INC = INC =
if HAVE_PAM_AND_SSL if HAVE_PAM_AND_SSL
lib_LTLIBRARIES = libpam_pkcs15.la lib_LTLIBRARIES = pam_pkcs15.la
noinst_PROGRAMS = pam_pkcs15-test noinst_PROGRAMS = pam_pkcs15-test
else else
lib_LTLIBRARIES = lib_LTLIBRARIES =
noinst_PROGRAMS = noinst_PROGRAMS =
endif endif
libpam_pkcs15_la_SOURCES = $(SRC) $(INC) pam_pkcs15_la_SOURCES = $(SRC) $(INC)
libpam_pkcs15_la_LDFLAGS = -module -avoid-version pam_pkcs15_la_LDFLAGS = -module -avoid-version
pam_pkcs15_test_SOURCES = $(SRC) $(INC) pam_pkcs15_test_SOURCES = $(SRC) $(INC)
pam_pkcs15_test_CFLAGS = -DTEST pam_pkcs15_test_CFLAGS = -DTEST
@ -27,7 +27,5 @@ if HAVE_PAM_AND_SSL
install-exec-local: install-libLTLIBRARIES install-exec-local: install-libLTLIBRARIES
@$(NORMAL_INSTALL) @$(NORMAL_INSTALL)
-rm -f $(DESTDIR)$(libdir)/pam_pkcs15.so
-cd $(DESTDIR)$(libdir) && ln -s libpam_pkcs15.so pam_pkcs15.so
endif endif

View File

@ -16,4 +16,4 @@ INC = sc-pkcs11.h
lib_LTLIBRARIES = libopensc-pkcs11.la lib_LTLIBRARIES = libopensc-pkcs11.la
libopensc_pkcs11_la_SOURCES = $(SRC) $(INC) 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; 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) if (!quiet)
fprintf(stderr, "Trying to find a PKCS#15 compatible card...\n"); fprintf(stderr, "Trying to find a PKCS#15 compatible card...\n");
r = sc_pkcs15_bind(card, &p15card); r = sc_pkcs15_bind(card, &p15card);
@ -358,7 +366,9 @@ end:
if (p15card) if (p15card)
sc_pkcs15_unbind(p15card); sc_pkcs15_unbind(p15card);
if (card) { if (card) {
#if 0
sc_unlock(card); sc_unlock(card);
#endif
sc_disconnect_card(card); sc_disconnect_card(card);
} }
if (ctx) if (ctx)

View File

@ -27,6 +27,7 @@
#include <opensc.h> #include <opensc.h>
#include <opensc-pkcs15.h> #include <opensc-pkcs15.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <ctype.h>
#define OPT_CHANGE_PIN 0x100 #define OPT_CHANGE_PIN 0x100
#define OPT_LIST_PINS 0x101 #define OPT_LIST_PINS 0x101
@ -44,6 +45,7 @@ int quiet = 0;
const struct option options[] = { const struct option options[] = {
{ "list-readers", 0, 0, 'l' }, { "list-readers", 0, 0, 'l' },
{ "list-drivers", 0, 0, 'D' },
{ "list-files", 0, 0, 'f' }, { "list-files", 0, 0, 'f' },
{ "learn-card", 0, 0, 'L' }, { "learn-card", 0, 0, 'L' },
{ "send-apdu", 1, 0, 's' }, { "send-apdu", 1, 0, 's' },
@ -63,6 +65,7 @@ const struct option options[] = {
const char *option_help[] = { const char *option_help[] = {
"Lists all configured readers", "Lists all configured readers",
"Lists all installed card drivers",
"Recursively lists files stored on card", "Recursively lists files stored on card",
"Stores card info to cache [P15]", "Stores card info to cache [P15]",
"Sends an APDU in format AA:BB:CC:DD:EE:FF...", "Sends an APDU in format AA:BB:CC:DD:EE:FF...",
@ -126,6 +129,10 @@ int list_readers()
{ {
int i; int i;
if (ctx->reader_count == 0) {
printf("No readers configured!\n");
return 0;
}
printf("Configured readers:\n"); printf("Configured readers:\n");
for (i = 0; i < ctx->reader_count; i++) { for (i = 0; i < ctx->reader_count; i++) {
printf("\t%d - %s\n", i, ctx->readers[i]); printf("\t%d - %s\n", i, ctx->readers[i]);
@ -133,6 +140,21 @@ int list_readers()
return 0; 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 list_certificates()
{ {
int r, i; int r, i;
@ -359,7 +381,7 @@ int enum_dir(struct sc_path path, int depth)
u8 buf[2048]; u8 buf[2048];
const char *tmps; const char *tmps;
r = sc_select_file(card, &file, &path); r = sc_select_file(card, &path, &file);
if (r) { if (r) {
fprintf(stderr, "SELECT FILE failed: %s\n", sc_strerror(r)); fprintf(stderr, "SELECT FILE failed: %s\n", sc_strerror(r));
return 1; return 1;
@ -528,18 +550,44 @@ int learn_card()
return 0; 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() int send_apdu()
{ {
struct sc_apdu apdu; struct sc_apdu apdu;
u8 buf[MAX_BUFFER_SIZE], sbuf[MAX_BUFFER_SIZE], u8 buf[MAX_BUFFER_SIZE], sbuf[MAX_BUFFER_SIZE],
rbuf[MAX_BUFFER_SIZE], *p = buf; 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) { if (len < 4) {
fprintf(stderr, "APDU too short (must be at least 4 bytes).\n"); fprintf(stderr, "APDU too short (must be at least 4 bytes).\n");
return 2; return 2;
} }
len = len0;
apdu.cla = *p++; apdu.cla = *p++;
apdu.ins = *p++; apdu.ins = *p++;
apdu.p1 = *p++; apdu.p1 = *p++;
@ -548,6 +596,7 @@ int send_apdu()
apdu.resplen = sizeof(rbuf); apdu.resplen = sizeof(rbuf);
apdu.data = NULL; apdu.data = NULL;
apdu.datalen = 0; apdu.datalen = 0;
apdu.no_response = 0;
len -= 4; len -= 4;
if (len > 1) { if (len > 1) {
apdu.lc = *p++; apdu.lc = *p++;
@ -577,15 +626,21 @@ int send_apdu()
apdu.cse = SC_APDU_CASE_2_SHORT; apdu.cse = SC_APDU_CASE_2_SHORT;
} else } else
apdu.cse = SC_APDU_CASE_1; apdu.cse = SC_APDU_CASE_1;
printf("Sending: ");
ctx->debug = 5; for (r = 0; r < len0; r++)
printf("%02X ", buf[r]);
printf("\n");
// ctx->debug = 5;
r = sc_transmit_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu);
ctx->debug = opt_debug; // ctx->debug = opt_debug;
if (r) { if (r) {
fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r));
return 1; 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; return 0;
} }
@ -593,6 +648,7 @@ int main(int argc, char * const argv[])
{ {
int err = 0, r, c, long_optind = 0; int err = 0, r, c, long_optind = 0;
int do_list_readers = 0; int do_list_readers = 0;
int do_list_drivers = 0;
int do_read_cert = 0; int do_read_cert = 0;
int do_list_certs = 0; int do_list_certs = 0;
int do_list_pins = 0; int do_list_pins = 0;
@ -604,7 +660,7 @@ int main(int argc, char * const argv[])
int action_count = 0; int action_count = 0;
while (1) { 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) if (c == -1)
break; break;
if (c == '?') if (c == '?')
@ -619,6 +675,10 @@ int main(int argc, char * const argv[])
do_list_readers = 1; do_list_readers = 1;
action_count++; action_count++;
break; break;
case 'D':
do_list_drivers = 1;
action_count++;
break;
case 'f': case 'f':
do_list_files = 1; do_list_files = 1;
action_count++; action_count++;
@ -684,6 +744,11 @@ int main(int argc, char * const argv[])
goto end; goto end;
action_count--; action_count--;
} }
if (do_list_drivers) {
if ((err = list_drivers()))
goto end;
action_count--;
}
if (action_count <= 0) if (action_count <= 0)
goto end; goto end;
if (opt_reader >= ctx->reader_count || opt_reader < 0) { if (opt_reader >= ctx->reader_count || opt_reader < 0) {
@ -704,7 +769,12 @@ int main(int argc, char * const argv[])
goto end; 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 (do_send_apdu) {
if ((err = send_apdu())) if ((err = send_apdu()))