- added a driver for MioCOS cards by Miotec

- implemented EF(DIR) updating


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@242 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2002-02-26 11:23:25 +00:00
parent 570af2be56
commit 04dfc47d92
15 changed files with 432 additions and 70 deletions

View File

@ -3,3 +3,4 @@ Authors of OpenSC:
Juha Yrjölä <juha.yrjola@iki.fi>
Antti Tapaninen <aet@cc.hut.fi>
Timo Teräs <timo.teras@iki.fi>
Olaf Kirch <okir@caldera.de>

View File

@ -21,7 +21,7 @@ libopensc_la_SOURCES = asn1.c base64.c sec.c log.c sc.c card.c iso7816.c \
dir.c pkcs15.c pkcs15-cert.c pkcs15-pin.c \
pkcs15-prkey.c pkcs15-sec.c pkcs15-cache.c \
$(PCSC_SRC) \
card-setec.c card-flex.c card-gpk.c \
card-setec.c card-miocos.c card-flex.c card-gpk.c \
card-tcos.c card-emv.c card-default.c
libopensc_la_LDFLAGS = -version-info 0:6:0
libopensc_la_LIBADD = $(PCSC_LIB) $(SSL_LIB)

View File

@ -56,6 +56,7 @@ static int autodetect_class(struct sc_card *card)
apdu.ins = 0xC0;
apdu.p1 = apdu.p2 = 0;
apdu.datalen = 0;
apdu.lc = apdu.le = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x6E)

273
src/libopensc/card-miocos.c Normal file
View File

@ -0,0 +1,273 @@
/*
* card-miocos.c: Support for MioCOS cards by Miotec
*
* Copyright (C) 2002 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 const char *miocos_atrs[] = {
/* MioCOS 1.1 Test Card */
"3B:9D:94:40:23:00:68:10:11:4D:69:6F:43:4F:53:00:90:00",
NULL
};
static struct sc_card_operations miocos_ops;
static const struct sc_card_driver miocos_drv = {
"MioCOS 1.1 cards",
"miocos",
&miocos_ops
};
static int miocos_finish(struct sc_card *card)
{
return 0;
}
static int miocos_match_card(struct sc_card *card)
{
int i, match = -1;
for (i = 0; miocos_atrs[i] != NULL; i++) {
u8 defatr[SC_MAX_ATR_SIZE];
size_t len = sizeof(defatr);
const char *atrp = miocos_atrs[i];
if (sc_hex_to_bin(atrp, defatr, &len))
continue;
if (len != card->atr_len)
continue;
if (memcmp(card->atr, defatr, len) != 0)
continue;
match = i;
break;
}
if (match == -1)
return 0;
return 1;
}
static int miocos_init(struct sc_card *card)
{
card->drv_data = NULL;
card->cla = 0x00;
return 0;
}
static const struct sc_card_operations *iso_ops = NULL;
static u8 acl_to_byte(const struct sc_acl_entry *e)
{
switch (e->method) {
case SC_AC_NONE:
return 0x00;
case SC_AC_CHV:
switch (e->key_ref) {
case 1:
return 0x01;
break;
case 2:
return 0x02;
break;
default:
return 0x00;
}
break;
case SC_AC_TERM:
return 0x04;
case SC_AC_NEVER:
return 0x0F;
}
return 0x00;
}
static int miocos_create_file(struct sc_card *card, struct sc_file *file)
{
if (file->prop_attr_len == 0) {
memcpy(file->prop_attr, "\x03\x00\x00", 3);
file->prop_attr_len = 3;
}
if (file->sec_attr_len == 0) {
int idx[6], i;
u8 buf[6];
if (file->type == SC_FILE_TYPE_DF) {
const int df_idx[6] = {
SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
SC_AC_OP_INVALIDATE
};
for (i = 0; i < 6; i++)
idx[i] = df_idx[i];
} else {
const int ef_idx[6] = {
SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
SC_AC_OP_INVALIDATE
};
for (i = 0; i < 6; i++)
idx[i] = ef_idx[i];
}
for (i = 0; i < 6; i++)
buf[i] = acl_to_byte(file->acl[idx[i]]);
memcpy(file->sec_attr, buf, 6);
file->sec_attr_len = 6;
}
return iso_ops->create_file(card, file);
}
static int miocos_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
if (env->flags & SC_SEC_ENV_ALG_PRESENT) {
struct sc_security_env tmp;
tmp = *env;
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
if (tmp.algorithm != SC_ALGORITHM_RSA) {
error(card->ctx, "Only RSA algorithm supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
tmp.algorithm_ref = 0x00;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_PKCS1_PAD)
tmp.algorithm_ref = 0x02;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
tmp.algorithm_ref |= 0x10;
return iso_ops->set_security_env(card, &tmp, se_num);
}
return iso_ops->set_security_env(card, env, se_num);
}
static void add_acl_entry(struct sc_file *file, int op, u8 byte)
{
unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
switch (byte >> 4) {
case 0:
method = SC_AC_NONE;
break;
case 1:
method = SC_AC_CHV;
key_ref = 1;
break;
case 2:
method = SC_AC_CHV;
key_ref = 2;
break;
case 4:
method = SC_AC_TERM;
break;
case 15:
method = SC_AC_NEVER;
break;
default:
method = SC_AC_UNKNOWN;
break;
}
sc_file_add_acl_entry(file, op, method, key_ref);
}
static void parse_sec_attr(struct sc_file *file, const u8 *buf, size_t len)
{
int i;
int idx[6];
if (len < 6)
return;
if (file->type == SC_FILE_TYPE_DF) {
const int df_idx[6] = {
SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
SC_AC_OP_INVALIDATE
};
for (i = 0; i < 6; i++)
idx[i] = df_idx[i];
} else {
const int ef_idx[6] = {
SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
SC_AC_OP_INVALIDATE
};
for (i = 0; i < 6; i++)
idx[i] = ef_idx[i];
}
for (i = 0; i < 6; i++)
add_acl_entry(file, idx[i], buf[i]);
}
static int miocos_select_file(struct sc_card *card,
const struct sc_path *in_path,
struct sc_file **file)
{
int r;
r = iso_ops->select_file(card, in_path, file);
if (r)
return r;
if (file != NULL)
parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
return 0;
}
static int miocos_list_files(struct sc_card *card, u8 *buf, size_t buflen)
{
struct sc_apdu apdu;
int r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, 0);
apdu.resp = buf;
apdu.resplen = buflen;
apdu.le = buflen > 256 ? 256 : buflen;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
return sc_check_sw(card, apdu.sw1, apdu.sw2);
return apdu.resplen;
}
static const struct sc_card_driver * sc_get_driver(void)
{
const struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
miocos_ops = *iso_drv->ops;
miocos_ops.match_card = miocos_match_card;
miocos_ops.init = miocos_init;
miocos_ops.finish = miocos_finish;
if (iso_ops == NULL)
iso_ops = iso_drv->ops;
miocos_ops.create_file = miocos_create_file;
miocos_ops.set_security_env = miocos_set_security_env;
miocos_ops.select_file = miocos_select_file;
miocos_ops.list_files = miocos_list_files;
return &miocos_drv;
}
#if 1
const struct sc_card_driver * sc_get_miocos_driver(void)
{
return sc_get_driver();
}
#endif

View File

@ -235,6 +235,22 @@ static int setec_select_file(struct sc_card *card,
return 0;
}
static int setec_list_files(struct sc_card *card, u8 *buf, size_t buflen)
{
struct sc_apdu apdu;
int r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0);
apdu.resp = buf;
apdu.resplen = buflen;
apdu.le = buflen > 256 ? 256 : buflen;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
return sc_check_sw(card, apdu.sw1, apdu.sw2);
return apdu.resplen;
}
static const struct sc_card_driver * sc_get_driver(void)
{
const struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
@ -248,6 +264,7 @@ static const struct sc_card_driver * sc_get_driver(void)
setec_ops.create_file = setec_create_file;
setec_ops.set_security_env = setec_set_security_env;
setec_ops.select_file = setec_select_file;
setec_ops.list_files = setec_list_files;
return &setec_drv;
}

View File

@ -60,7 +60,8 @@ static const struct sc_asn1_entry c_asn1_dir[] = {
{ NULL }
};
static int parse_dir_record(struct sc_card *card, u8 ** buf, size_t *buflen)
static int parse_dir_record(struct sc_card *card, u8 ** buf, size_t *buflen,
int rec_nr)
{
struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2];
struct sc_app_info *app = NULL;
@ -126,6 +127,7 @@ static int parse_dir_record(struct sc_card *card, u8 ** buf, size_t *buflen)
app->desc = ae->desc;
else
app->desc = NULL;
app->rec_nr = rec_nr;
card->app[card->app_count] = app;
card->app_count++;
@ -134,27 +136,31 @@ static int parse_dir_record(struct sc_card *card, u8 ** buf, size_t *buflen)
int sc_enum_apps(struct sc_card *card)
{
struct sc_file *file;
struct sc_path path;
int ef_structure;
size_t file_size;
int r;
if (card->app_count < 0)
card->app_count = 0;
sc_format_path("3F002F00", &path);
r = sc_select_file(card, &path, &file);
if (card->ef_dir != NULL) {
sc_file_free(card->ef_dir);
card->ef_dir = NULL;
}
r = sc_select_file(card, &path, &card->ef_dir);
if (r)
return r;
if (file->type != SC_FILE_TYPE_WORKING_EF) {
if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
error(card->ctx, "EF(DIR) is not a working EF.\n");
sc_file_free(file);
sc_file_free(card->ef_dir);
card->ef_dir = NULL;
return SC_ERROR_INVALID_CARD;
}
ef_structure = file->ef_structure;
file_size = file->size;
sc_file_free(file);
file = NULL;
ef_structure = card->ef_dir->ef_structure;
file_size = card->ef_dir->size;
if (file_size == 0)
return 0;
if (ef_structure == SC_FILE_EF_TRANSPARENT) {
u8 buf[1024], *p = buf;
size_t bufsize;
@ -169,7 +175,7 @@ int sc_enum_apps(struct sc_card *card)
error(card->ctx, "Too many applications on card");
break;
}
r = parse_dir_record(card, &p, &bufsize);
r = parse_dir_record(card, &p, &bufsize, -1);
if (r)
break;
}
@ -190,7 +196,7 @@ int sc_enum_apps(struct sc_card *card)
}
rec_size = r;
p = buf;
parse_dir_record(card, &p, &rec_size);
parse_dir_record(card, &p, &rec_size, rec_nr);
}
}
return card->app_count;
@ -200,7 +206,7 @@ const struct sc_app_info * sc_find_app_by_aid(struct sc_card *card,
const u8 *aid, size_t aid_len)
{
int i;
assert(card->app_count > 0);
for (i = 0; i < card->app_count; i++) {
if (card->app[i]->aid_len == aid_len &&
@ -240,24 +246,81 @@ static int encode_dir_record(struct sc_context *ctx, const struct sc_app_info *a
return 0;
}
int sc_update_dir(struct sc_card *card)
static int update_transparent(struct sc_card *card, struct sc_file *file)
{
u8 *rec, *buf = NULL;
size_t rec_size, buf_size = 0;
int i, r;
for (i = 0; i < card->app_count; i++) {
r = encode_dir_record(card->ctx, card->app[i], &rec, &rec_size);
if (r) {
free(buf);
return r;
}
buf = realloc(buf, buf_size + rec_size);
if (buf == NULL) {
free(rec);
return SC_ERROR_OUT_OF_MEMORY;
}
memcpy(buf + buf_size, rec, rec_size);
buf_size += rec_size;
}
if (file->size > buf_size) {
buf = realloc(buf, file->size);
memset(buf + buf_size, 0, file->size - buf_size);
buf_size = file->size;
}
r = sc_update_binary(card, 0, buf, buf_size, 0);
SC_TEST_RET(card->ctx, r, "Unable to update EF(DIR)");
return 0;
}
static int update_single_record(struct sc_card *card, struct sc_file *file,
struct sc_app_info *app)
{
u8 *rec;
size_t rec_size;
int r;
r = encode_dir_record(card->ctx, app, &rec, &rec_size);
if (r)
return r;
r = sc_update_record(card, app->rec_nr, rec, rec_size, 0);
free(rec);
SC_TEST_RET(card->ctx, r, "Unable to update EF(DIR) record");
return 0;
}
static int update_records(struct sc_card *card, struct sc_file *file)
{
int i, r;
for (i = 0; i < card->app_count; i++) {
r = update_single_record(card, file, card->app[i]);
if (r)
return r;
}
return 0;
}
int sc_update_dir(struct sc_card *card, struct sc_app_info *app)
{
struct sc_path path;
struct sc_file *file;
u8 *rec;
size_t rec_size;
int i, r;
int r;
sc_format_path("3F002F00", &path);
r = sc_select_file(card, &path, &file);
SC_TEST_RET(card->ctx, r, "unable to select EF(DIR)");
for (i = 0; i < card->app_count; i++) {
r = encode_dir_record(card->ctx, card->app[i], &rec, &rec_size);
if (r)
return r;
free(rec);
}
if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
r = update_transparent(card, file);
else if (app == NULL)
r = update_records(card, file);
else
r = update_single_record(card, file, app);
sc_file_free(file);
return r;
}

View File

@ -289,6 +289,15 @@ static void process_fci(struct sc_context *ctx, struct sc_file *file,
debug(ctx, " bytes in file: %d\n", bytes);
file->size = bytes;
}
if (tag == NULL) {
tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
if (tag != NULL && taglen >= 2) {
int bytes = (tag[0] << 8) + tag[1];
if (ctx->debug >= 3)
debug(ctx, " bytes in file: %d\n", bytes);
file->size = bytes;
}
}
tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
if (tag != NULL) {
if (taglen > 0) {
@ -416,7 +425,6 @@ static int iso7816_select_file(struct sc_card *card,
apdu.resplen = 0;
apdu.le = 0;
apdu.cse = SC_APDU_CASE_3_SHORT;
apdu.p2 = 0x0c;
}
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -562,22 +570,6 @@ static int iso7816_delete_file(struct sc_card *card, const struct sc_path *path)
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_list_files(struct sc_card *card, u8 *buf, size_t buflen)
{
struct sc_apdu apdu;
int r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0);
apdu.resp = buf;
apdu.resplen = buflen;
apdu.le = buflen > 256 ? 256 : buflen;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
return sc_check_sw(card, apdu.sw1, apdu.sw2);
return apdu.resplen;
}
static int iso7816_verify(struct sc_card *card, unsigned int type, int ref,
const u8 *pin, size_t pinlen, int *tries_left)
{
@ -853,7 +845,6 @@ const struct sc_card_driver * sc_get_iso7816_driver(void)
iso_ops.get_challenge = iso7816_get_challenge;
iso_ops.create_file = iso7816_create_file;
iso_ops.delete_file = iso7816_delete_file;
iso_ops.list_files = iso7816_list_files;
iso_ops.verify = iso7816_verify;
iso_ops.set_security_env = iso7816_set_security_env;
iso_ops.restore_security_env = iso7816_restore_security_env;

View File

@ -248,6 +248,7 @@ struct sc_app_info {
size_t ddo_len;
const char *desc; /* App description, if known */
int rec_nr; /* -1, if EF(DIR) is transparent */
};
struct sc_card_cache {
@ -356,6 +357,7 @@ struct sc_card {
struct sc_app_info *app[SC_MAX_CARD_APPS];
int app_count;
struct sc_file *ef_dir;
pthread_mutex_t mutex;
int lock_count;
@ -562,18 +564,18 @@ inline int sc_card_valid(const struct sc_card *card);
*/
int sc_detect_card_presence(struct sc_reader *reader, int slot_id);
#if 0
/**
* Waits for card insertion to a reader
* @param ctx OpenSC context
* @param reader Reader number; -1 implies to listen on all readers
* Waits for an event on a reader
* @param reader Reader structure
* @param slot_id Slot ID
* @param event_mask The types of events to wait for
* @param timeout Amount of millisecs to wait; -1 means forever
* @retval 1 if a card was inserted
* @retval 0 if operation timed out
* @retval < 0 if an error occured
*/
int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout);
#endif
int sc_wait_for_event(struct sc_reader *reader, int slot_id,
unsigned int event_mask, int timeout);
/**
* Locks the card against modification from other threads.
@ -694,6 +696,7 @@ extern const struct sc_reader_driver *sc_get_pcsc_driver(void);
extern const struct sc_card_driver *sc_get_iso7816_driver(void);
extern const struct sc_card_driver *sc_get_emv_driver(void);
extern const struct sc_card_driver *sc_get_setec_driver(void);
extern const struct sc_card_driver *sc_get_miocos_driver(void);
extern const struct sc_card_driver *sc_get_flex_driver(void);
extern const struct sc_card_driver *sc_get_gpk_driver(void);
extern const struct sc_card_driver *sc_get_tcos_driver(void);

View File

@ -92,7 +92,7 @@ static int pkcs1_add_padding(const u8 *in, size_t inlen, u8 *out, size_t outlen)
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey,
unsigned int hash, const u8 *in, size_t inlen,
unsigned int flags, const u8 *in, size_t inlen,
u8 *out, size_t outlen)
{
int r;
@ -115,9 +115,9 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
}
senv.algorithm = SC_ALGORITHM_RSA;
senv.algorithm_flags = SC_ALGORITHM_RSA_PKCS1_PAD;
if (hash & SC_PKCS15_HASH_SHA1)
if (flags & SC_PKCS15_HASH_SHA1)
senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
if (hash & SC_PKCS15_PAD_PKCS1_V1_5) {
if (flags & SC_PKCS15_PAD_PKCS1_V1_5) {
size_t modlen = prkey->modulus_length >> 3;
if (inlen > (modlen - 11)) {

View File

@ -708,20 +708,17 @@ static int create_and_update_file(struct sc_pkcs15_card *p15card,
struct sc_file *inf, const u8 *buf,
size_t bufsize)
{
struct sc_file file;
int i, r;
memset(&file, 0, sizeof(file));
file.type = SC_FILE_TYPE_WORKING_EF;
file.ef_structure = SC_FILE_EF_TRANSPARENT;
file.size = inf->size + bufsize;
file.path = inf->path;
for (i = 0; i < SC_MAX_AC_OPS; i++)
file.acl[i] = inf->acl[i];
file.status = SC_FILE_STATUS_ACTIVATED;
struct sc_file *file;
int r;
sc_file_dup(&file, inf);
file->type = SC_FILE_TYPE_WORKING_EF;
file->ef_structure = SC_FILE_EF_TRANSPARENT;
file->size = inf->size + bufsize;
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
r = create_file(card, &file);
r = create_file(card, file);
sc_file_free(file);
if (r) {
sc_unlock(card);
return r;
@ -745,11 +742,11 @@ int sc_pkcs15_create(struct sc_pkcs15_card *p15card, struct sc_card *card)
int r, i;
u8 *tokinf_buf = NULL, *odf_buf = NULL;
size_t tokinf_size, odf_size;
if (p15card->file_app == NULL || p15card->file_odf == NULL ||
p15card->file_tokeninfo == NULL) {
error(card->ctx, "Not all of the necessary files have been supplied\n");
return SC_ERROR_INVALID_ARGUMENTS;
error(card->ctx, "Not all of the necessary files have been supplied\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
if (card->ctx->debug)
debug(card->ctx, "creating EF(DIR)\n");

View File

@ -175,6 +175,9 @@ int sc_establish_context(struct sc_context **ctx_out)
#if 1
ctx->card_drivers[i++] = sc_get_setec_driver();
#endif
#if 1
ctx->card_drivers[i++] = sc_get_miocos_driver();
#endif
#if 1
ctx->card_drivers[i++] = sc_get_flex_driver();
#endif

View File

@ -21,6 +21,6 @@ pkcs15_crypt_LDADD = @GETOPTSRC@
cryptoflex_tool_SOURCES = cryptoflex-tool.c util.c
cryptoflex_tool_LDADD = @GETOPTSRC@ @LIBCRYPTO@
pkcs15_init_SOURCES = pkcs15-init.c profile.c util.c \
pkcs15-gpk.c
pkcs15-gpk.c pkcs15-miocos.c
pkcs15_init_LDADD = @GETOPTSRC@ @LIBCRYPTO@
noinst_HEADERS = util.h profile.h

View File

@ -25,7 +25,7 @@
#include <string.h>
#include <stdlib.h>
#include <opensc.h>
#ifdef HAVE_READLINE__READLINE_H
#ifdef HAVE_READLINE_READLINE_H
#include <readline/readline.h>
#endif
#include "util.h"
@ -317,6 +317,11 @@ int do_cat(const char *arg, const char *dummy2)
return -1;
}
}
if (file->type != SC_FILE_TYPE_WORKING_EF) {
printf("only working EFs may be read\n");
sc_file_free(file);
return -1;
}
if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
read_and_print_binary_file(file);
else
@ -623,6 +628,11 @@ int do_get(const char *arg, const char *arg2)
check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
return -1;
}
if (file->type != SC_FILE_TYPE_WORKING_EF) {
printf("only working EFs may be read\n");
sc_file_free(file);
return -1;
}
count = file->size;
while (count) {
int c = count > sizeof(buf) ? sizeof(buf) : count;
@ -803,7 +813,7 @@ static int parse_line(char *in, char **argv)
return argc;
}
#if !defined(HAVE_READLINE__READLINE_H)
#if !defined(HAVE_READLINE_READLINE_H)
char * readline(const char *prompt)
{
static char buf[128];

View File

@ -233,6 +233,8 @@ bind_operations(struct pkcs15_init_operations *ops, const char *driver)
if (!strcasecmp(driver, "GPK"))
bind_gpk_operations(ops);
else if (!strcasecmp(driver, "MioCOS"))
bind_miocos_operations(ops);
else
fatal("Don't know how to handle %s cards", driver);
}

View File

@ -27,5 +27,6 @@ extern int do_verify_authinfo(struct sc_profile *, struct sc_file *, int);
/* Card specific stuff */
extern void bind_gpk_operations(struct pkcs15_init_operations *);
extern void bind_miocos_operations(struct pkcs15_init_operations *);
#endif /* PKCS15_INIT_H */