- 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:
parent
570af2be56
commit
04dfc47d92
1
AUTHORS
1
AUTHORS
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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
273
src/libopensc/card-miocos.c
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user