- fixed some minor glitches (potential buffer overflow in read_dir;
missing SW check) - added card_ctl for put_data_fci - added some debug output git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@620 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
5fba18d152
commit
f973a3d942
|
@ -19,8 +19,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 "internal.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "opensc.h"
|
#include "opensc.h"
|
||||||
|
#include "cardctl.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -219,13 +221,14 @@ int etoken_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct sc_apdu apdu;
|
struct sc_apdu apdu;
|
||||||
u8 rbuf[256];
|
u8 rbuf[256];
|
||||||
u8 fidbuf[256];
|
|
||||||
int r,i;
|
int r,i;
|
||||||
int fids;
|
int fids;
|
||||||
int len;
|
int len;
|
||||||
u8 offset;
|
u8 offset;
|
||||||
u8 *fid;
|
u8 *fid;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
fids=0;
|
fids=0;
|
||||||
offset=0;
|
offset=0;
|
||||||
|
|
||||||
|
@ -238,9 +241,12 @@ get_next_part:
|
||||||
apdu.le = 256;
|
apdu.le = 256;
|
||||||
apdu.resplen = 256;
|
apdu.resplen = 256;
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r)
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
return r;
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
SC_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
|
||||||
|
|
||||||
if (apdu.resplen > 256) {
|
if (apdu.resplen > 256) {
|
||||||
error(card->ctx, "directory listing > 256 bytes, cutting");
|
error(card->ctx, "directory listing > 256 bytes, cutting");
|
||||||
r = 256;
|
r = 256;
|
||||||
|
@ -263,13 +269,10 @@ get_next_part:
|
||||||
fid = etoken_extract_fid(&rbuf[i+2], len);
|
fid = etoken_extract_fid(&rbuf[i+2], len);
|
||||||
|
|
||||||
if (fid) {
|
if (fid) {
|
||||||
fidbuf[fids++] = fid[0];
|
if (fids + 2 >= buflen)
|
||||||
fidbuf[fids++] = fid[1];
|
break;
|
||||||
if (fids >= 128) {
|
buf[fids++] = fid[0];
|
||||||
error(card->ctx,"only memory for 128 fids etoken_list_files");
|
buf[fids++] = fid[1];
|
||||||
fids=128;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = etoken_extract_offset(&rbuf[i+2], len);
|
offset = etoken_extract_offset(&rbuf[i+2], len);
|
||||||
|
@ -278,9 +281,9 @@ get_next_part:
|
||||||
i += len+2;
|
i += len+2;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
r = fids;
|
||||||
memcpy(buf,fidbuf,2*fids);
|
|
||||||
return fids;
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_acl_entry(struct sc_file *file, int op, u8 byte)
|
static void add_acl_entry(struct sc_file *file, int op, u8 byte)
|
||||||
|
@ -349,6 +352,8 @@ static const int ef_acl[9] = {
|
||||||
SC_AC_OP_REHABILITATE, /* EF */
|
SC_AC_OP_REHABILITATE, /* EF */
|
||||||
SC_AC_OP_ERASE, /* (delete) EF */
|
SC_AC_OP_ERASE, /* (delete) EF */
|
||||||
|
|
||||||
|
/* XXX: ADMIN should be an ACL type of its own, or mapped
|
||||||
|
* to erase */
|
||||||
-1, /* ADMIN EF (modify meta information?) */
|
-1, /* ADMIN EF (modify meta information?) */
|
||||||
-1, /* INC (-> cylic fixed files) */
|
-1, /* INC (-> cylic fixed files) */
|
||||||
-1 /* DEC */
|
-1 /* DEC */
|
||||||
|
@ -373,12 +378,12 @@ static int etoken_select_file(struct sc_card *card,
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
r = iso_ops->select_file(card, in_path, file);
|
r = iso_ops->select_file(card, in_path, file);
|
||||||
if (r)
|
if (r >= 0 && file)
|
||||||
return r;
|
|
||||||
if (file != NULL)
|
|
||||||
parse_sec_attr((*file), (*file)->sec_attr, (*file)->sec_attr_len);
|
parse_sec_attr((*file), (*file)->sec_attr, (*file)->sec_attr_len);
|
||||||
return 0;
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
|
@ -387,6 +392,18 @@ static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
const int *idx;
|
const int *idx;
|
||||||
u8 acl[9], type[3], status[3];
|
u8 acl[9], type[3], status[3];
|
||||||
|
|
||||||
|
if (card->ctx->debug >= 1) {
|
||||||
|
char pbuf[128+1];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < file->path.len; n++) {
|
||||||
|
snprintf(pbuf + 2 * n, sizeof(pbuf) - 2 * n,
|
||||||
|
"%02X", file->path.value[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(card->ctx, "etoken_create_file(%s)\n", pbuf);
|
||||||
|
}
|
||||||
|
|
||||||
if (file->type_attr_len == 0) {
|
if (file->type_attr_len == 0) {
|
||||||
type[0] = 0x00;
|
type[0] = 0x00;
|
||||||
switch (file->type) {
|
switch (file->type) {
|
||||||
|
@ -399,14 +416,16 @@ static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
type[0] = 0x38;
|
type[0] = 0x38;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (file->type != SC_FILE_TYPE_DF) {
|
if (file->type != SC_FILE_TYPE_DF) {
|
||||||
switch (file->ef_structure) {
|
switch (file->ef_structure) {
|
||||||
case SC_FILE_EF_LINEAR_FIXED_TLV:
|
case SC_FILE_EF_LINEAR_FIXED_TLV:
|
||||||
case SC_FILE_EF_LINEAR_VARIABLE:
|
case SC_FILE_EF_LINEAR_VARIABLE:
|
||||||
case SC_FILE_EF_CYCLIC_TLV:
|
case SC_FILE_EF_CYCLIC_TLV:
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
|
goto out;
|
||||||
default:
|
default:
|
||||||
type[0] |= file->ef_structure & 7;
|
type[0] |= file->ef_structure & 7;
|
||||||
break;
|
break;
|
||||||
|
@ -415,19 +434,19 @@ static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
type[1] = type[2] = 0x00; /* not used, but required */
|
type[1] = type[2] = 0x00; /* not used, but required */
|
||||||
r = sc_file_set_type_attr(file, type, sizeof(type));
|
r = sc_file_set_type_attr(file, type, sizeof(type));
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
goto out;
|
||||||
}
|
}
|
||||||
if (file->prop_attr_len == 0) {
|
if (file->prop_attr_len == 0) {
|
||||||
status[0] = 0x01;
|
status[0] = 0x01;
|
||||||
if (file->type == SC_FILE_TYPE_DF) {
|
if (file->type == SC_FILE_TYPE_DF) {
|
||||||
status[1] = 0; /* bodys size of DF in bigendian */
|
status[1] = file->size >> 8;
|
||||||
status[2] = 0;
|
status[2] = file->size;
|
||||||
} else {
|
} else {
|
||||||
status[1] = status[2] = 0x00; /* not used */
|
status[1] = status[2] = 0x00; /* not used */
|
||||||
}
|
}
|
||||||
r = sc_file_set_prop_attr(file, status, sizeof(status));
|
r = sc_file_set_prop_attr(file, status, sizeof(status));
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
goto out;
|
||||||
}
|
}
|
||||||
if (file->sec_attr_len == 0) {
|
if (file->sec_attr_len == 0) {
|
||||||
idx = (file->type == SC_FILE_TYPE_DF) ? df_acl : ef_acl;
|
idx = (file->type == SC_FILE_TYPE_DF) ? df_acl : ef_acl;
|
||||||
|
@ -439,15 +458,18 @@ static int etoken_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
sc_file_get_acl_entry(file, idx[i]));
|
sc_file_get_acl_entry(file, idx[i]));
|
||||||
if (byte < 0) {
|
if (byte < 0) {
|
||||||
error(card->ctx, "Invalid ACL\n");
|
error(card->ctx, "Invalid ACL\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
acl[i] = byte;
|
acl[i] = byte;
|
||||||
}
|
}
|
||||||
r = sc_file_set_sec_attr(file, acl, sizeof(acl));
|
r = sc_file_set_sec_attr(file, acl, sizeof(acl));
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
goto out;
|
||||||
}
|
}
|
||||||
return iso_ops->create_file(card, file);
|
r = iso_ops->create_file(card, file);
|
||||||
|
|
||||||
|
out: SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etoken_update_binary(struct sc_card *card,
|
static int etoken_update_binary(struct sc_card *card,
|
||||||
|
@ -488,6 +510,46 @@ static int etoken_read_binary(struct sc_card *card,
|
||||||
return total? total : n;
|
return total? total : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
etoken_put_data_fci(struct sc_card *card,
|
||||||
|
struct sc_cardctl_etoken_pin_info *args)
|
||||||
|
{
|
||||||
|
struct sc_apdu apdu;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
memset(&apdu, 0, sizeof(apdu));
|
||||||
|
apdu.cse = SC_APDU_CASE_3_SHORT;
|
||||||
|
apdu.cla = 0x00;
|
||||||
|
apdu.ins = 0xda;
|
||||||
|
apdu.p1 = 0x01;
|
||||||
|
apdu.p2 = 0x6e;
|
||||||
|
apdu.lc = args->len;
|
||||||
|
apdu.data = args->data;
|
||||||
|
apdu.datalen = args->len;
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
SC_TEST_RET(card->ctx, r, "Card returned error");
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
etoken_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case SC_CARDCTL_ETOKEN_PUT_DATA_FCI:
|
||||||
|
break;
|
||||||
|
case SC_CARDCTL_ETOKEN_PUT_DATA_OCI:
|
||||||
|
return etoken_put_data_fci(card,
|
||||||
|
(struct sc_cardctl_etoken_pin_info *) ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
|
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
|
||||||
|
|
||||||
const struct sc_card_driver * sc_get_driver(void)
|
const struct sc_card_driver * sc_get_driver(void)
|
||||||
|
@ -505,6 +567,7 @@ const struct sc_card_driver * sc_get_driver(void)
|
||||||
|
|
||||||
etoken_ops.list_files = etoken_list_files;
|
etoken_ops.list_files = etoken_list_files;
|
||||||
etoken_ops.check_sw = etoken_check_sw;
|
etoken_ops.check_sw = etoken_check_sw;
|
||||||
|
etoken_ops.card_ctl = etoken_card_ctl;
|
||||||
|
|
||||||
return &etoken_drv;
|
return &etoken_drv;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue