- 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:
okir 2002-06-04 08:50:17 +00:00
parent 5fba18d152
commit f973a3d942
1 changed files with 90 additions and 27 deletions

View File

@ -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,24 +269,21 @@ 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);
if (offset) if (offset)
goto get_next_part; goto 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;
} }