- eToken patches from Markus Friedl
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@546 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
f87bbcee4c
commit
5d8b1000ca
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
static const struct sc_card_operations *iso_ops = NULL;
|
||||
|
||||
struct sc_card_operations etoken_ops;
|
||||
const struct sc_card_driver etoken_drv = {
|
||||
"Aladdin eToken PRO",
|
||||
|
@ -221,6 +223,9 @@ int etoken_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
|||
fids=0;
|
||||
offset=0;
|
||||
|
||||
/* 0x16: DIRECTORY */
|
||||
/* 0x02: list both DF and EF */
|
||||
|
||||
get_next_part:
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x16, 0x02, offset);
|
||||
apdu.cla = 0x80;
|
||||
|
@ -272,17 +277,149 @@ end:
|
|||
return fids;
|
||||
}
|
||||
|
||||
static void add_acl_entry(struct sc_file *file, int op, u8 byte)
|
||||
{
|
||||
/* XXX todo: */
|
||||
}
|
||||
|
||||
static const int df_acl[9] = {
|
||||
-1, /* LCYCLE (life cycle change) */
|
||||
-1, /* UPDATE Objects */
|
||||
-1, /* APPEND Objects */
|
||||
|
||||
SC_AC_OP_INVALIDATE, /* DF */
|
||||
SC_AC_OP_REHABILITATE, /* DF */
|
||||
SC_AC_OP_DELETE, /* DF */
|
||||
|
||||
-1, /* ADMIN DF */
|
||||
SC_AC_OP_CREATE, /* Files */
|
||||
-1 /* Reserved */
|
||||
};
|
||||
static const int ef_acl[9] = {
|
||||
SC_AC_OP_READ, /* Data */
|
||||
SC_AC_OP_UPDATE, /* Data (write file content) */
|
||||
SC_AC_OP_WRITE, /* */
|
||||
|
||||
SC_AC_OP_INVALIDATE, /* EF */
|
||||
SC_AC_OP_REHABILITATE, /* EF */
|
||||
SC_AC_OP_ERASE, /* (delete) EF */
|
||||
|
||||
-1, /* ADMIN EF (modify meta information?) */
|
||||
-1, /* INC (-> cylic fixed files) */
|
||||
-1 /* DEC */
|
||||
};
|
||||
|
||||
static void parse_sec_attr(struct sc_file *file, const u8 *buf, size_t len)
|
||||
{
|
||||
int i;
|
||||
const int *idx;
|
||||
|
||||
if (len < 9)
|
||||
return;
|
||||
|
||||
idx = (file->type == SC_FILE_TYPE_DF) ? df_acl : ef_acl;
|
||||
for (i = 0; i < 9; i++)
|
||||
if (idx[i] != -1)
|
||||
add_acl_entry(file, idx[i], buf[i]);
|
||||
}
|
||||
|
||||
static int etoken_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 etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||
{
|
||||
int r;
|
||||
const u8 acl[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
u8 type[3], status[3];
|
||||
|
||||
if (file->type_attr_len == 0) {
|
||||
type[0] = 0x00;
|
||||
switch (file->type) {
|
||||
case SC_FILE_TYPE_WORKING_EF:
|
||||
break;
|
||||
case SC_FILE_TYPE_INTERNAL_EF:
|
||||
type[0] = 0x08;
|
||||
break;
|
||||
case SC_FILE_TYPE_DF:
|
||||
type[0] = 0x38;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
switch (file->ef_structure) {
|
||||
case SC_FILE_EF_LINEAR_FIXED_TLV:
|
||||
case SC_FILE_EF_LINEAR_VARIABLE:
|
||||
case SC_FILE_EF_CYCLIC_TLV:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
default:
|
||||
type[0] |= file->ef_structure & 7;
|
||||
break;
|
||||
}
|
||||
type[1] = type[2] = 0x00; /* not used, but required */
|
||||
r = sc_file_set_type_attr(file, type, sizeof(type));
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (file->prop_attr_len == 0) {
|
||||
status[0] = 0x01;
|
||||
if (file->type == SC_FILE_TYPE_DF) {
|
||||
status[1] = 0; /* bodys size of DF in bigendian */
|
||||
status[2] = 0;
|
||||
} else {
|
||||
status[1] = status[2] = 0x00; /* not used */
|
||||
}
|
||||
r = sc_file_set_prop_attr(file, status, sizeof(status));
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (file->sec_attr_len == 0) {
|
||||
r = sc_file_set_sec_attr(file, acl, sizeof(acl));
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
return iso_ops->create_file(card, file);
|
||||
}
|
||||
|
||||
static int etoken_update_binary(struct sc_card *card,
|
||||
unsigned int idx, const u8 *buf,
|
||||
size_t count, unsigned long flags)
|
||||
{
|
||||
/* hm, my card only works for small payloads */
|
||||
if (count > 120)
|
||||
count = 120;
|
||||
return iso_ops->update_binary(card, idx, buf, count, flags);
|
||||
}
|
||||
|
||||
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
|
||||
|
||||
const struct sc_card_driver * sc_get_driver(void)
|
||||
{
|
||||
etoken_ops = *sc_get_iso7816_driver()->ops;
|
||||
if (iso_ops == NULL)
|
||||
iso_ops = sc_get_iso7816_driver()->ops;
|
||||
etoken_ops = *iso_ops;
|
||||
etoken_ops.match_card = etoken_match_card;
|
||||
etoken_ops.init = etoken_init;
|
||||
etoken_ops.finish = etoken_finish;
|
||||
etoken_ops.finish = etoken_finish;
|
||||
etoken_ops.select_file = etoken_select_file;
|
||||
etoken_ops.create_file = etoken_create_file;
|
||||
etoken_ops.update_binary = etoken_update_binary;
|
||||
|
||||
etoken_ops.list_files = etoken_list_files;
|
||||
etoken_ops.list_files = etoken_list_files;
|
||||
etoken_ops.check_sw = etoken_check_sw;
|
||||
|
||||
return &etoken_drv;
|
||||
return &etoken_drv;
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
|
|
@ -491,21 +491,27 @@ static int construct_fci(const struct sc_file *file, u8 *out, size_t *outlen)
|
|||
buf[0] = (file->size >> 8) & 0xFF;
|
||||
buf[1] = file->size & 0xFF;
|
||||
sc_asn1_put_tag(0x81, buf, 2, p, 16, &p);
|
||||
buf[0] = file->shareable ? 0x40 : 0;
|
||||
switch (file->type) {
|
||||
case SC_FILE_TYPE_WORKING_EF:
|
||||
break;
|
||||
case SC_FILE_TYPE_INTERNAL_EF:
|
||||
buf[0] |= 0x08;
|
||||
break;
|
||||
case SC_FILE_TYPE_DF:
|
||||
buf[0] |= 0x38;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
|
||||
if (file->type_attr_len) {
|
||||
memcpy(buf, file->type_attr, file->type_attr_len);
|
||||
sc_asn1_put_tag(0x82, buf, file->type_attr_len, p, 16, &p);
|
||||
} else {
|
||||
buf[0] = file->shareable ? 0x40 : 0;
|
||||
switch (file->type) {
|
||||
case SC_FILE_TYPE_WORKING_EF:
|
||||
break;
|
||||
case SC_FILE_TYPE_INTERNAL_EF:
|
||||
buf[0] |= 0x08;
|
||||
break;
|
||||
case SC_FILE_TYPE_DF:
|
||||
buf[0] |= 0x38;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
buf[0] |= file->ef_structure & 7;
|
||||
sc_asn1_put_tag(0x82, buf, 1, p, 16, &p);
|
||||
}
|
||||
buf[0] |= file->ef_structure & 7;
|
||||
sc_asn1_put_tag(0x82, buf, 1, p, 16, &p);
|
||||
buf[0] = (file->id >> 8) & 0xFF;
|
||||
buf[1] = file->id & 0xFF;
|
||||
sc_asn1_put_tag(0x83, buf, 2, p, 16, &p);
|
||||
|
|
|
@ -668,6 +668,8 @@ int sc_file_set_sec_attr(struct sc_file *file, const u8 *sec_attr,
|
|||
size_t sec_attr_len);
|
||||
int sc_file_set_prop_attr(struct sc_file *file, const u8 *prop_attr,
|
||||
size_t prop_attr_len);
|
||||
int sc_file_set_type_attr(struct sc_file *file, const u8 *type_attr,
|
||||
size_t type_attr_len);
|
||||
|
||||
void sc_format_path(const char *path_in, struct sc_path *path_out);
|
||||
int sc_append_path(struct sc_path *dest, const struct sc_path *src);
|
||||
|
|
|
@ -294,6 +294,8 @@ void sc_file_free(struct sc_file *file)
|
|||
free(file->sec_attr);
|
||||
if (file->prop_attr)
|
||||
free(file->prop_attr);
|
||||
if (file->type_attr)
|
||||
free(file->type_attr);
|
||||
free(file);
|
||||
}
|
||||
|
||||
|
@ -365,6 +367,29 @@ int sc_file_set_prop_attr(struct sc_file *file, const u8 *prop_attr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sc_file_set_type_attr(struct sc_file *file, const u8 *type_attr,
|
||||
size_t type_attr_len)
|
||||
{
|
||||
assert(sc_file_valid(file));
|
||||
|
||||
if (type_attr == NULL) {
|
||||
if (file->type_attr != NULL)
|
||||
free(file->type_attr);
|
||||
file->type_attr = NULL;
|
||||
file->type_attr_len = 0;
|
||||
return 0;
|
||||
}
|
||||
file->type_attr = realloc(file->type_attr, type_attr_len);
|
||||
if (file->type_attr == NULL) {
|
||||
file->type_attr_len = 0;
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(file->type_attr, type_attr, type_attr_len);
|
||||
file->type_attr_len = type_attr_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int sc_file_valid(const struct sc_file *file) {
|
||||
#ifndef NDEBUG
|
||||
assert(file != NULL);
|
||||
|
|
|
@ -72,6 +72,9 @@ typedef struct sc_file {
|
|||
size_t sec_attr_len;
|
||||
u8 *prop_attr;
|
||||
size_t prop_attr_len;
|
||||
u8 *type_attr;
|
||||
size_t type_attr_len;
|
||||
|
||||
unsigned int magic;
|
||||
} sc_file_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue