update the MuscleCard driver for OpenSC to use an msc_id struct rather than
int/bytes and messing around with byte-swapping for that. (by Thomas Harning) git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3067 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
b9daff9b28
commit
b3822c349b
|
@ -28,18 +28,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ATR Values pulled from the Muscle Card library's 'bundle' */
|
||||
#if 0
|
||||
/* UNUSED */
|
||||
static struct sc_atr_table muscle_atrs[] = {
|
||||
{ "3B:75:13:00:00:9C:02:02:01:02", NULL, "Muscle card", SC_CARD_TYPE_MUSCLE_GENERIC, 0, NULL },
|
||||
{ "3B:65:00:00:9C:02:02:01:02", NULL, "Muscle card", SC_CARD_TYPE_MUSCLE_GENERIC, 0, NULL },
|
||||
{ "3B:3B:94:00:90:65:AF:03:0D:01:74:83:0F:90:00", NULL, "Muscle card", SC_CARD_TYPE_MUSCLE_GENERIC, 0, NULL },
|
||||
{ "3F:6D:00:00:80:31:80:65:B0:05:01:02:5E:83:00:90:00", NULL, "Muscle card", SC_CARD_TYPE_MUSCLE_GENERIC, 0, NULL },
|
||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct sc_card_operations muscle_ops;
|
||||
static struct sc_card_driver muscle_drv = {
|
||||
"Muscle Card Driver",
|
||||
|
@ -72,7 +60,15 @@ static u8 muscleAppletId[] = { 0xA0, 0x00,0x00,0x00, 0x01, 0x01 };
|
|||
static int muscle_match_card(sc_card_t *card)
|
||||
{
|
||||
/* Use SELECT APPLET, since its a more deterministic way of detection */
|
||||
return msc_select_applet(card, muscleAppletId, 5);
|
||||
int i;
|
||||
/* Since we send an APDU, the card's logout function may be called...
|
||||
* however it's not always properly nulled out... */
|
||||
card->ops->logout = NULL;
|
||||
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
i = msc_select_applet(card, muscleAppletId, 5);
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Since Musclecard has a different ACL system then PKCS15
|
||||
|
@ -119,7 +115,8 @@ static void muscle_parse_acls(const sc_file_t* file, unsigned short* read, unsig
|
|||
static int muscle_create_directory(sc_card_t *card, sc_file_t *file)
|
||||
{
|
||||
mscfs_t *fs = MUSCLE_FS(card);
|
||||
u8 objectId[4];
|
||||
msc_id objectId;
|
||||
u8* oid = objectId.id;
|
||||
unsigned id = file->id;
|
||||
unsigned short read = 0, write = 0, delete = 0;
|
||||
int objectSize;
|
||||
|
@ -130,14 +127,14 @@ static int muscle_create_directory(sc_card_t *card, sc_file_t *file)
|
|||
/* No nesting directories */
|
||||
if(fs->currentPath[0] != 0x3F || fs->currentPath[1] != 0x00)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
objectId[0] = ((id & 0xFF00) >> 8) & 0xFF;
|
||||
objectId[1] = id & 0xFF;
|
||||
objectId[2] = objectId[3] = 0;
|
||||
oid[0] = ((id & 0xFF00) >> 8) & 0xFF;
|
||||
oid[1] = id & 0xFF;
|
||||
oid[2] = oid[3] = 0;
|
||||
|
||||
objectSize = file->size;
|
||||
|
||||
muscle_parse_acls(file, &read, &write, &delete);
|
||||
r = msc_create_object(card, bebytes2ulong(objectId), objectSize, read, write, delete);
|
||||
r = msc_create_object(card, objectId, objectSize, read, write, delete);
|
||||
mscfs_clear_cache(fs);
|
||||
if(r >= 0) return 0;
|
||||
return r;
|
||||
|
@ -149,7 +146,7 @@ static int muscle_create_file(sc_card_t *card, sc_file_t *file)
|
|||
mscfs_t *fs = MUSCLE_FS(card);
|
||||
int objectSize = file->size;
|
||||
unsigned short read = 0, write = 0, delete = 0;
|
||||
unsigned int objectId;
|
||||
msc_id objectId;
|
||||
int r;
|
||||
if(file->type == SC_FILE_TYPE_DF)
|
||||
return muscle_create_directory(card, file);
|
||||
|
@ -160,7 +157,7 @@ static int muscle_create_file(sc_card_t *card, sc_file_t *file)
|
|||
|
||||
muscle_parse_acls(file, &read, &write, &delete);
|
||||
|
||||
mscfs_lookup_local(fs, file->id, (u8*)&objectId);
|
||||
mscfs_lookup_local(fs, file->id, &objectId);
|
||||
r = msc_create_object(card, objectId, objectSize, read, write, delete);
|
||||
mscfs_clear_cache(fs);
|
||||
if(r >= 0) return 0;
|
||||
|
@ -171,19 +168,21 @@ static int muscle_read_binary(sc_card_t *card, unsigned int index, u8* buf, size
|
|||
{
|
||||
mscfs_t *fs = MUSCLE_FS(card);
|
||||
int r;
|
||||
u8 objectId[4];
|
||||
msc_id objectId;
|
||||
u8* oid = objectId.id;
|
||||
mscfs_file_t *file;
|
||||
|
||||
r = mscfs_check_selection(fs, -1);
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
file = &fs->cache.array[fs->currentFileIndex];
|
||||
memcpy(objectId, file->objectId, 4);
|
||||
objectId = file->objectId;
|
||||
// memcpy(objectId.id, file->objectId.id, 4);
|
||||
if(!file->ef) {
|
||||
objectId[0] = objectId[2];
|
||||
objectId[1] = objectId[3];
|
||||
objectId[2] = objectId[3] = 0;
|
||||
oid[0] = oid[2];
|
||||
oid[1] = oid[3];
|
||||
oid[2] = oid[3] = 0;
|
||||
}
|
||||
r = msc_read_object(card, bebytes2ulong(objectId), index, buf, count);
|
||||
r = msc_read_object(card, objectId, index, buf, count);
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
}
|
||||
|
||||
|
@ -192,49 +191,52 @@ static int muscle_update_binary(sc_card_t *card, unsigned int index, const u8* b
|
|||
mscfs_t *fs = MUSCLE_FS(card);
|
||||
int r;
|
||||
mscfs_file_t *file;
|
||||
u8 objectId[4];
|
||||
msc_id objectId;
|
||||
u8* oid = objectId.id;
|
||||
|
||||
r = mscfs_check_selection(fs, -1);
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
file = &fs->cache.array[fs->currentFileIndex];
|
||||
|
||||
memcpy(objectId, file->objectId, 4);
|
||||
objectId = file->objectId;
|
||||
//memcpy(objectId.id, file->objectId.id, 4);
|
||||
if(!file->ef) {
|
||||
objectId[0] = objectId[2];
|
||||
objectId[1] = objectId[3];
|
||||
objectId[2] = objectId[3] = 0;
|
||||
oid[0] = oid[2];
|
||||
oid[1] = oid[3];
|
||||
oid[2] = oid[3] = 0;
|
||||
}
|
||||
if(file->size < index + count) {
|
||||
int newFileSize = index + count;
|
||||
u8* buffer = malloc(newFileSize);
|
||||
if(buffer == NULL) SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
r = msc_read_object(card, bebytes2ulong(objectId), 0, buffer, file->size);
|
||||
r = msc_read_object(card, objectId, 0, buffer, file->size);
|
||||
/* TODO: RETREIVE ACLS */
|
||||
if(r < 0) goto update_bin_free_buffer;
|
||||
r = msc_delete_object(card, bebytes2ulong(objectId), 0);
|
||||
r = msc_delete_object(card, objectId, 0);
|
||||
if(r < 0) goto update_bin_free_buffer;
|
||||
r = msc_create_object(card, bebytes2ulong(objectId), newFileSize, 0,0,0);
|
||||
r = msc_create_object(card, objectId, newFileSize, 0,0,0);
|
||||
if(r < 0) goto update_bin_free_buffer;
|
||||
memcpy(buffer + index, buf, count);
|
||||
r = msc_update_object(card, bebytes2ulong(objectId), 0, buffer, newFileSize);
|
||||
r = msc_update_object(card, objectId, 0, buffer, newFileSize);
|
||||
if(r < 0) goto update_bin_free_buffer;
|
||||
file->size = newFileSize;
|
||||
update_bin_free_buffer:
|
||||
free(buffer);
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
} else {
|
||||
r = msc_update_object(card, bebytes2ulong(objectId), index, buf, count);
|
||||
r = msc_update_object(card, objectId, index, buf, count);
|
||||
}
|
||||
//mscfs_clear_cache(fs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* TODO: Evaluate correctness */
|
||||
static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
|
||||
{
|
||||
mscfs_t *fs = MUSCLE_FS(card);
|
||||
u8 *id = file_data->objectId;
|
||||
int objectId = bebytes2ulong(id);
|
||||
msc_id id = file_data->objectId;
|
||||
u8* oid = id.id;
|
||||
int r;
|
||||
|
||||
if(!file_data->ef) {
|
||||
|
@ -245,32 +247,44 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
|
|||
|
||||
if (card->ctx->debug >= 2) {
|
||||
sc_debug(card->ctx, "DELETING Children of: %02X%02X%02X%02X\n",
|
||||
id[0],id[1],id[2],id[3]);
|
||||
oid[0],oid[1],oid[2],oid[3]);
|
||||
}
|
||||
for(x = 0; x < fs->cache.size; x++) {
|
||||
u8 *objectId;
|
||||
msc_id objectId;
|
||||
childFile = &fs->cache.array[x];
|
||||
objectId = childFile->objectId;
|
||||
|
||||
if(0 == memcmp(id + 2, objectId, 2)) {
|
||||
if(0 == memcmp(oid + 2, objectId.id, 2)) {
|
||||
if (card->ctx->debug >= 2) {
|
||||
sc_debug(card->ctx, "DELETING: %02X%02X%02X%02X\n",
|
||||
objectId[0],objectId[1],objectId[2],objectId[3]);
|
||||
objectId.id[0],objectId.id[1],objectId.id[2],objectId.id[3]);
|
||||
}
|
||||
r = muscle_delete_mscfs_file(card, childFile);
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
|
||||
}
|
||||
}
|
||||
objectId = objectId >> 16;
|
||||
oid[0] = oid[2];
|
||||
oid[1] = oid[3];
|
||||
oid[2] = oid[3] = 0;
|
||||
// ??? objectId = objectId >> 16;
|
||||
}
|
||||
|
||||
r = msc_delete_object(card, objectId, 1);
|
||||
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
||||
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4))) {
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
}
|
||||
r = msc_delete_object(card, id, 1);
|
||||
/* Check if its the root... this file generally is virtual
|
||||
* So don't return an error if it fails */
|
||||
if((0 == memcmp(id, "\x3F\x00\x00\x00", 4))
|
||||
|| (0 == memcmp(id, "\x3F\x00\x3F\x00", 4)))
|
||||
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
||||
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4)))
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
return 0;
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
|
||||
|
||||
if(r < 0) {
|
||||
printf("ID: %02X%02X%02X%02X\n",
|
||||
oid[0],oid[1],oid[2],oid[3]);
|
||||
SC_FUNC_RETURN(card->ctx, 2,r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -328,6 +342,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
|
|||
int pathlen = path_in->len;
|
||||
int r = 0;
|
||||
int objectIndex;
|
||||
u8* oid;
|
||||
|
||||
mscfs_check_cache(fs);
|
||||
r = mscfs_loadFileInfo(fs, path_in->value, path_in->len, &file_data, &objectIndex);
|
||||
|
@ -337,15 +352,16 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
|
|||
if(requiredType >= 0 && requiredType != file_data->ef) {
|
||||
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
oid = file_data->objectId.id;
|
||||
/* Is it a file or directory */
|
||||
if(file_data->ef) {
|
||||
fs->currentPath[0] = file_data->objectId[0];
|
||||
fs->currentPath[1] = file_data->objectId[1];
|
||||
fs->currentFile[0] = file_data->objectId[2];
|
||||
fs->currentFile[1] = file_data->objectId[3];
|
||||
fs->currentPath[0] = oid[0];
|
||||
fs->currentPath[1] = oid[1];
|
||||
fs->currentFile[0] = oid[2];
|
||||
fs->currentFile[1] = oid[3];
|
||||
} else {
|
||||
fs->currentPath[0] = file_data->objectId[pathlen - 2];
|
||||
fs->currentPath[1] = file_data->objectId[pathlen - 1];
|
||||
fs->currentPath[0] = oid[pathlen - 2];
|
||||
fs->currentPath[1] = oid[pathlen - 1];
|
||||
fs->currentFile[0] = 0;
|
||||
fs->currentFile[1] = 0;
|
||||
}
|
||||
|
@ -356,7 +372,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
|
|||
file = sc_file_new();
|
||||
file->path = *path_in;
|
||||
file->size = file_data->size;
|
||||
file->id = (file_data->objectId[2] << 8) | file_data->objectId[3];
|
||||
file->id = (oid[2] << 8) | oid[3];
|
||||
memcpy(file->name, path, pathlen);
|
||||
file->namelen = pathlen;
|
||||
if(!file_data->ef) {
|
||||
|
@ -415,6 +431,9 @@ static int muscle_init(sc_card_t *card)
|
|||
int r = 0;
|
||||
muscle_private_t *priv;
|
||||
|
||||
r = sc_get_default_driver()->ops->init(card);
|
||||
if(r) return r;
|
||||
|
||||
card->name = "Muscle Card";
|
||||
card->drv_data = malloc(sizeof(muscle_private_t));
|
||||
if(!card->drv_data) {
|
||||
|
@ -430,12 +449,7 @@ static int muscle_init(sc_card_t *card)
|
|||
}
|
||||
priv->fs->udata = card;
|
||||
priv->fs->listFile = _listFile;
|
||||
//r = autodetect_class(card);
|
||||
card->cla = 0xB0;
|
||||
if (r) {
|
||||
sc_error(card->ctx, "unable to determine the right class byte\n");
|
||||
return SC_ERROR_INVALID_CARD;
|
||||
}
|
||||
|
||||
card->flags |= SC_CARD_FLAG_ONBOARD_KEY_GEN;
|
||||
card->flags |= SC_CARD_FLAG_RNG;
|
||||
card->caps |= SC_CARD_CAP_RNG;
|
||||
|
@ -467,18 +481,17 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
|
|||
mscfs_check_cache(priv->fs);
|
||||
|
||||
for(x = 0; x < fs->cache.size; x++) {
|
||||
u8 *objectId;
|
||||
objectId = fs->cache.array[x].objectId;
|
||||
u8* oid= fs->cache.array[x].objectId.id;
|
||||
if (card->ctx->debug >= 2) {
|
||||
sc_debug(card->ctx, "FILE: %02X%02X%02X%02X\n",
|
||||
objectId[0],objectId[1],objectId[2],objectId[3]);
|
||||
oid[0],oid[1],oid[2],oid[3]);
|
||||
}
|
||||
if(0 == memcmp(fs->currentPath, objectId, 2)) {
|
||||
buf[0] = objectId[2];
|
||||
buf[1] = objectId[3];
|
||||
if(0 == memcmp(fs->currentPath, oid, 2)) {
|
||||
buf[0] = oid[2];
|
||||
buf[1] = oid[3];
|
||||
if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
|
||||
buf += 2;
|
||||
count+=1;
|
||||
count+=2;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
|
|
@ -57,12 +57,12 @@ void mscfs_clear_cache(mscfs_t* fs) {
|
|||
fs->cache.size = 0;
|
||||
}
|
||||
|
||||
int mscfs_is_ignored(mscfs_t* fs, u8* objectId)
|
||||
static int mscfs_is_ignored(mscfs_t* fs, msc_id objectId)
|
||||
{
|
||||
int ignored = 0;
|
||||
const u8** ptr = ignoredFiles;
|
||||
while(ptr && *ptr && !ignored) {
|
||||
if(0 == memcmp(objectId, *ptr, 4))
|
||||
if(0 == memcmp(objectId.id, *ptr, 4))
|
||||
ignored = 1;
|
||||
ptr++;
|
||||
}
|
||||
|
@ -102,11 +102,12 @@ int mscfs_update_cache(mscfs_t* fs) {
|
|||
while(1) {
|
||||
if(!mscfs_is_ignored(fs, file.objectId)) {
|
||||
/* Check if its a directory in the root */
|
||||
if(file.objectId[2] == 0 && file.objectId[3] == 0) {
|
||||
file.objectId[2] = file.objectId[0];
|
||||
file.objectId[3] = file.objectId[1];
|
||||
file.objectId[0] = 0x3F;
|
||||
file.objectId[1] = 0x00;
|
||||
u8* oid = file.objectId.id;
|
||||
if(oid[2] == 0 && oid[3] == 0) {
|
||||
oid[2] = oid[0];
|
||||
oid[3] = oid[1];
|
||||
oid[0] = 0x3F;
|
||||
oid[1] = 0x00;
|
||||
file.ef = 0;
|
||||
} else {
|
||||
file.ef = 1; /* File is a working elementary file */
|
||||
|
@ -130,56 +131,58 @@ void mscfs_check_cache(mscfs_t* fs)
|
|||
}
|
||||
}
|
||||
|
||||
int mscfs_lookup_path(mscfs_t* fs, const u8 *path, int pathlen, u8 objectId[4], int isDirectory)
|
||||
int mscfs_lookup_path(mscfs_t* fs, const u8 *path, int pathlen, msc_id* objectId, int isDirectory)
|
||||
{
|
||||
u8* oid = objectId->id;
|
||||
if ((pathlen & 1) != 0) /* not divisble by 2 */
|
||||
return MSCFS_INVALID_ARGS;
|
||||
if(isDirectory) {
|
||||
/* Directory must be right next to root */
|
||||
if((0 == memcmp(path, "\x3F\x00", 2) && pathlen == 4)
|
||||
|| (0 == memcmp(fs->currentPath, "\x3F\x00", 2) && pathlen == 2)) {
|
||||
objectId[0] = path[pathlen - 2];
|
||||
objectId[1] = path[pathlen - 1];
|
||||
objectId[2] = objectId[3] = 0;
|
||||
oid[0] = path[pathlen - 2];
|
||||
oid[1] = path[pathlen - 1];
|
||||
oid[2] = oid[3] = 0;
|
||||
} else {
|
||||
return MSCFS_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
objectId[0] = fs->currentPath[0];
|
||||
objectId[1] = fs->currentPath[1];
|
||||
oid[0] = fs->currentPath[0];
|
||||
oid[1] = fs->currentPath[1];
|
||||
/* Chop off the root in the path */
|
||||
if(pathlen > 2 && memcmp(path, "\x3F\x00", 2) == 0) {
|
||||
path += 2;
|
||||
pathlen -= 2;
|
||||
objectId[0] = 0x3F;
|
||||
objectId[1] = 0x00;
|
||||
oid[0] = 0x3F;
|
||||
oid[1] = 0x00;
|
||||
}
|
||||
/* Limit to a single directory */
|
||||
if(pathlen > 4)
|
||||
return MSCFS_INVALID_ARGS;
|
||||
/* Reset to root */
|
||||
if(0 == memcmp(path, "\x3F\x00", 2) && pathlen == 2) {
|
||||
objectId[0] = objectId[2] = path[0];
|
||||
objectId[1] = objectId[3] = path[1];
|
||||
oid[0] = oid[2] = path[0];
|
||||
oid[1] = oid[3] = path[1];
|
||||
} else if(pathlen == 2) { /* Path preserved for current-path */
|
||||
objectId[2] = path[0];
|
||||
objectId[3] = path[1];
|
||||
oid[2] = path[0];
|
||||
oid[3] = path[1];
|
||||
} else if(pathlen == 4) {
|
||||
objectId[0] = path[0];
|
||||
objectId[1] = path[1];
|
||||
objectId[2] = path[2];
|
||||
objectId[3] = path[3];
|
||||
oid[0] = path[0];
|
||||
oid[1] = path[1];
|
||||
oid[2] = path[2];
|
||||
oid[3] = path[3];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mscfs_lookup_local(mscfs_t* fs, const int id, u8 objectId[4])
|
||||
int mscfs_lookup_local(mscfs_t* fs, const int id, msc_id* objectId)
|
||||
{
|
||||
objectId[0] = fs->currentPath[0];
|
||||
objectId[1] = fs->currentPath[1];
|
||||
objectId[2] = (id >> 8) & 0xFF;
|
||||
objectId[3] = id & 0xFF;
|
||||
u8* oid = objectId->id;
|
||||
oid[0] = fs->currentPath[0];
|
||||
oid[1] = fs->currentPath[1];
|
||||
oid[2] = (id >> 8) & 0xFF;
|
||||
oid[3] = id & 0xFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -195,33 +198,30 @@ int mscfs_check_selection(mscfs_t *fs, int requiredItem)
|
|||
|
||||
int mscfs_loadFileInfo(mscfs_t* fs, const u8 *path, int pathlen, mscfs_file_t **file_data, int* idx)
|
||||
{
|
||||
u8 fullPath[4];
|
||||
msc_id fullPath;
|
||||
int x;
|
||||
assert(fs != NULL && path != NULL && file_data != NULL);
|
||||
mscfs_lookup_path(fs, path, pathlen, fullPath, 0);
|
||||
mscfs_lookup_path(fs, path, pathlen, &fullPath, 0);
|
||||
|
||||
/* Obtain file information while checking if it exists */
|
||||
mscfs_check_cache(fs);
|
||||
if(idx) *idx = -1;
|
||||
for(x = 0; x < fs->cache.size; x++) {
|
||||
u8 *objectId;
|
||||
msc_id objectId;
|
||||
*file_data = &fs->cache.array[x];
|
||||
objectId = (*file_data)->objectId;
|
||||
if(0 == memcmp(objectId, fullPath, 4)) {
|
||||
if(0 == memcmp(objectId.id, fullPath.id, 4)) {
|
||||
if(idx) *idx = x;
|
||||
break;
|
||||
}
|
||||
*file_data = NULL;
|
||||
}
|
||||
if(*file_data == NULL && (0 == memcmp("\x3F\x00\x00\x00", fullPath, 4) || 0 == memcmp("\x3F\x00\x3F\x00", fullPath, 4 ))) {
|
||||
if(*file_data == NULL && (0 == memcmp("\x3F\x00\x00\x00", fullPath.id, 4) || 0 == memcmp("\x3F\x00\x3F\x00", fullPath.id, 4 ))) {
|
||||
static mscfs_file_t ROOT_FILE;
|
||||
ROOT_FILE.ef = 0;
|
||||
ROOT_FILE.size = 0;
|
||||
/* Faked Root ID */
|
||||
ROOT_FILE.objectId[0] = 0x3F;
|
||||
ROOT_FILE.objectId[1] = 0x00;
|
||||
ROOT_FILE.objectId[2] = 0x3F;
|
||||
ROOT_FILE.objectId[3] = 0x00;
|
||||
ROOT_FILE.objectId = rootId;
|
||||
|
||||
ROOT_FILE.read = 0;
|
||||
ROOT_FILE.write = 0x02; /* User Pin access */
|
||||
|
|
|
@ -25,8 +25,17 @@
|
|||
|
||||
#include <opensc/types.h>
|
||||
|
||||
typedef struct msc_id {
|
||||
u8 id[4];
|
||||
} msc_id;
|
||||
|
||||
|
||||
static msc_id inputId = { { 0xFF, 0xFF, 0xFF, 0xFF } };
|
||||
static msc_id outputId = { { 0xFF, 0xFF, 0xFF, 0xFE } };
|
||||
static msc_id rootId = { { 0x3F, 0x00, 0x3F, 0x00 } };
|
||||
|
||||
typedef struct mscfs_file {
|
||||
u8 objectId[4];
|
||||
msc_id objectId;
|
||||
size_t size;
|
||||
unsigned short read, write, delete;
|
||||
int ef;
|
||||
|
@ -55,10 +64,9 @@ int mscfs_update_cache(mscfs_t* fs);
|
|||
|
||||
void mscfs_check_cache(mscfs_t* fs);
|
||||
|
||||
int mscfs_lookup_path(mscfs_t* fs, const u8 *path, int pathlen, u8 objectId[4], int
|
||||
isDirectory);
|
||||
int mscfs_lookup_path(mscfs_t* fs, const u8 *path, int pathlen, msc_id* objectId, int isDirectory);
|
||||
|
||||
int mscfs_lookup_local(mscfs_t* fs, const int id, u8 objectId[4]);
|
||||
int mscfs_lookup_local(mscfs_t* fs, const int id, msc_id* objectId);
|
||||
/* -1 any, 0 DF, 1 EF */
|
||||
int mscfs_check_selection(mscfs_t *fs, int requiredItem);
|
||||
int mscfs_loadFileInfo(mscfs_t* fs, const u8 *path, int pathlen, mscfs_file_t **file_data, int* index);
|
||||
|
|
|
@ -67,7 +67,7 @@ int msc_list_objects(sc_card_t* card, u8 next, mscfs_file_t* file) {
|
|||
sc_error(card->ctx, "expected 14 bytes, got %d.\n", apdu.resplen);
|
||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||
}
|
||||
memcpy(file->objectId, fileData, 4);
|
||||
memcpy(file->objectId.id, fileData, 4);
|
||||
file->size = bebytes2ulong(fileData + 4);
|
||||
file->read = bebytes2ushort(fileData + 8);
|
||||
file->write = bebytes2ushort(fileData + 10);
|
||||
|
@ -76,7 +76,7 @@ int msc_list_objects(sc_card_t* card, u8 next, mscfs_file_t* file) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int msc_partial_read_object(sc_card_t *card, unsigned int le_objectId, int offset, u8 *data, size_t dataLength)
|
||||
int msc_partial_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
|
||||
{
|
||||
u8 buffer[9];
|
||||
sc_apdu_t apdu;
|
||||
|
@ -86,7 +86,7 @@ int msc_partial_read_object(sc_card_t *card, unsigned int le_objectId, int offse
|
|||
|
||||
if (card->ctx->debug >= 2)
|
||||
sc_debug(card->ctx, "READ: Offset: %x\tLength: %i\n", offset, dataLength);
|
||||
ulong2bebytes(buffer, le_objectId);
|
||||
memcpy(buffer, objectId.id, 4);
|
||||
ulong2bebytes(buffer + 4, offset);
|
||||
buffer[8] = (u8)dataLength;
|
||||
apdu.data = buffer;
|
||||
|
@ -117,7 +117,7 @@ int msc_partial_read_object(sc_card_t *card, unsigned int le_objectId, int offse
|
|||
|
||||
}
|
||||
|
||||
int msc_read_object(sc_card_t *card, unsigned int objectId, int offset, u8 *data, size_t dataLength)
|
||||
int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
|
||||
{
|
||||
int r;
|
||||
size_t i;
|
||||
|
@ -128,7 +128,7 @@ int msc_read_object(sc_card_t *card, unsigned int objectId, int offset, u8 *data
|
|||
return dataLength;
|
||||
}
|
||||
|
||||
int msc_zero_object(sc_card_t *card, unsigned int objectId, size_t dataLength)
|
||||
int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength)
|
||||
{
|
||||
u8 zeroBuffer[MSC_MAX_WRITE_UNIT];
|
||||
size_t i;
|
||||
|
@ -140,7 +140,7 @@ int msc_zero_object(sc_card_t *card, unsigned int objectId, size_t dataLength)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int msc_create_object(sc_card_t *card, unsigned int objectId, size_t objectSize, unsigned short read, unsigned short write, unsigned short deletion)
|
||||
int msc_create_object(sc_card_t *card, msc_id objectId, size_t objectSize, unsigned short read, unsigned short write, unsigned short deletion)
|
||||
{
|
||||
u8 buffer[14];
|
||||
sc_apdu_t apdu;
|
||||
|
@ -152,7 +152,7 @@ int msc_create_object(sc_card_t *card, unsigned int objectId, size_t objectSize,
|
|||
apdu.data = buffer,
|
||||
apdu.datalen = 14;
|
||||
|
||||
ulong2bebytes(buffer, objectId);
|
||||
memcpy(buffer, objectId.id, 4);
|
||||
ulong2bebytes(buffer + 4, objectSize);
|
||||
ushort2bebytes(buffer + 8, readAcl);
|
||||
ushort2bebytes(buffer + 10, writeAcl);
|
||||
|
@ -179,7 +179,7 @@ int msc_create_object(sc_card_t *card, unsigned int objectId, size_t objectSize,
|
|||
}
|
||||
|
||||
/* Update up to 246 bytes */
|
||||
int msc_partial_update_object(sc_card_t *card, unsigned int le_objectId, int offset, const u8 *data, size_t dataLength)
|
||||
int msc_partial_update_object(sc_card_t *card, msc_id objectId, int offset, const u8 *data, size_t dataLength)
|
||||
{
|
||||
u8 buffer[256];
|
||||
sc_apdu_t apdu;
|
||||
|
@ -189,7 +189,8 @@ int msc_partial_update_object(sc_card_t *card, unsigned int le_objectId, int off
|
|||
apdu.lc = dataLength + 9;
|
||||
if (card->ctx->debug >= 2)
|
||||
sc_debug(card->ctx, "WRITE: Offset: %x\tLength: %i\n", offset, dataLength);
|
||||
ulong2bebytes(buffer, le_objectId);
|
||||
|
||||
memcpy(buffer, objectId.id, 4);
|
||||
ulong2bebytes(buffer + 4, offset);
|
||||
buffer[8] = (u8)dataLength;
|
||||
memcpy(buffer + 9, data, dataLength);
|
||||
|
@ -216,7 +217,7 @@ int msc_partial_update_object(sc_card_t *card, unsigned int le_objectId, int off
|
|||
return dataLength;
|
||||
}
|
||||
|
||||
int msc_update_object(sc_card_t *card, unsigned int objectId, int offset, const u8 *data, size_t dataLength)
|
||||
int msc_update_object(sc_card_t *card, msc_id objectId, int offset, const u8 *data, size_t dataLength)
|
||||
{
|
||||
int r;
|
||||
size_t i;
|
||||
|
@ -227,16 +228,14 @@ int msc_update_object(sc_card_t *card, unsigned int objectId, int offset, const
|
|||
return dataLength;
|
||||
}
|
||||
|
||||
int msc_delete_object(sc_card_t *card, unsigned int objectId, int zero)
|
||||
int msc_delete_object(sc_card_t *card, msc_id objectId, int zero)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
u8 buf[4];
|
||||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x52, 0x00, zero ? 0x01 : 0x00);
|
||||
apdu.lc = 4;
|
||||
ulong2bebytes(buf, objectId);
|
||||
apdu.data = buf;
|
||||
apdu.data = objectId.id;
|
||||
apdu.datalen = 4;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
|
@ -460,10 +459,12 @@ int msc_get_challenge(sc_card_t *card, short dataLength, short seedLength, u8 *s
|
|||
}
|
||||
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_CARD_CMD_FAILED);
|
||||
}
|
||||
r = msc_read_object(card, 0xFFFFFFFFul, 2, outputData, dataLength);
|
||||
r = msc_read_object(card, inputId, 2, outputData, dataLength);
|
||||
if(r < 0)
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
r = msc_delete_object(card, 0xFFFFFFFFul,0);
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
msc_delete_object(card, inputId,0);
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
}
|
||||
}
|
||||
|
@ -566,7 +567,7 @@ int msc_extract_rsa_public_key(sc_card_t *card,
|
|||
if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
|
||||
/* Read keyType, keySize, and what should be the modulus size */
|
||||
r = msc_read_object(card, 0xFFFFFFFFul, fileLocation, buffer, 5);
|
||||
r = msc_read_object(card, inputId, fileLocation, buffer, 5);
|
||||
fileLocation += 5;
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
|
||||
|
@ -575,7 +576,7 @@ int msc_extract_rsa_public_key(sc_card_t *card,
|
|||
/* Read the modulus and the exponent length */
|
||||
assert(*modLength + 2 < buffer_size);
|
||||
|
||||
r = msc_read_object(card, 0xFFFFFFFFul, fileLocation, buffer, *modLength + 2);
|
||||
r = msc_read_object(card, inputId, fileLocation, buffer, *modLength + 2);
|
||||
fileLocation += *modLength + 2;
|
||||
if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
|
||||
|
@ -584,7 +585,7 @@ int msc_extract_rsa_public_key(sc_card_t *card,
|
|||
memcpy(*modulus, buffer, *modLength);
|
||||
*expLength = (buffer[*modLength] << 8) | buffer[*modLength + 1];
|
||||
assert(*expLength < buffer_size);
|
||||
r = msc_read_object(card, 0xFFFFFFFFul, fileLocation, buffer, *expLength);
|
||||
r = msc_read_object(card, inputId, fileLocation, buffer, *expLength);
|
||||
if(r < 0) {
|
||||
free(*modulus); *modulus = NULL;
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
|
@ -831,7 +832,6 @@ int msc_import_key(sc_card_t *card,
|
|||
keySize = data->keySize;
|
||||
int bufferSize = 0;
|
||||
u8 *buffer, *p;
|
||||
unsigned int objectId;
|
||||
u8 apduBuffer[6];
|
||||
sc_apdu_t apdu;
|
||||
int r;
|
||||
|
@ -876,24 +876,28 @@ int msc_import_key(sc_card_t *card,
|
|||
CPYVAL(dp1);
|
||||
CPYVAL(dq1);
|
||||
}
|
||||
objectId = 0xFFFFFFFEul;
|
||||
|
||||
r = msc_create_object(card, objectId, bufferSize, 0x02, 0x02, 0x02);
|
||||
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
||||
if(r < 0) {
|
||||
if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
|
||||
r = msc_delete_object(card, objectId, 0);
|
||||
r = msc_delete_object(card, outputId, 0);
|
||||
if(r < 0) {
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
free(buffer);
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
r = msc_create_object(card, objectId, bufferSize, 0x02, 0x02, 0x02);
|
||||
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
||||
if(r < 0) {
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
free(buffer);
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
r = msc_update_object(card, objectId, 0, buffer, bufferSize);
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
|
||||
r = msc_update_object(card, outputId, 0, buffer, bufferSize);
|
||||
free(buffer);
|
||||
if(r < 0) return r;
|
||||
|
||||
|
@ -909,7 +913,7 @@ int msc_import_key(sc_card_t *card,
|
|||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
msc_delete_object(card, objectId, 0);
|
||||
msc_delete_object(card, outputId, 0);
|
||||
return 0;
|
||||
}
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
|
@ -919,11 +923,15 @@ int msc_import_key(sc_card_t *card,
|
|||
apdu.sw1, apdu.sw2);
|
||||
}
|
||||
/* no error checks.. this is last ditch cleanup */
|
||||
msc_delete_object(card, objectId, 0);
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
msc_delete_object(card, outputId, 0);
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||
}
|
||||
/* no error checks.. this is last ditch cleanup */
|
||||
msc_delete_object(card, objectId, 0);
|
||||
sc_ctx_suppress_errors_on(card->ctx);
|
||||
msc_delete_object(card, outputId, 0);
|
||||
sc_ctx_suppress_errors_off(card->ctx);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_CARD_CMD_FAILED);
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@
|
|||
#include "muscle-filesystem.h"
|
||||
|
||||
int msc_list_objects(sc_card_t* card, u8 next, mscfs_file_t* file);
|
||||
int msc_partial_read_object(sc_card_t *card, unsigned int le_objectId, int offset, u8 *data, size_t dataLength);
|
||||
int msc_read_object(sc_card_t *card, unsigned int objectId, int offset, u8 *data, size_t dataLength);
|
||||
int msc_create_object(sc_card_t *card, unsigned int objectId, size_t objectSize, unsigned short read, unsigned short write, unsigned short deletion);
|
||||
int msc_partial_update_object(sc_card_t *card, unsigned int le_objectId, int offset, const u8 *data, size_t dataLength);
|
||||
int msc_update_object(sc_card_t *card, unsigned int objectId, int offset, const u8 *data, size_t dataLength);
|
||||
int msc_zero_object(sc_card_t *card, unsigned int objectId, size_t dataLength);
|
||||
int msc_partial_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength);
|
||||
int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength);
|
||||
int msc_create_object(sc_card_t *card, msc_id objectId, size_t objectSize, unsigned short read, unsigned short write, unsigned short deletion);
|
||||
int msc_partial_update_object(sc_card_t *card, msc_id objectId, int offset, const u8 *data, size_t dataLength);
|
||||
int msc_update_object(sc_card_t *card, msc_id objectId, int offset, const u8 *data, size_t dataLength);
|
||||
int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength);
|
||||
|
||||
int msc_delete_object(sc_card_t *card, unsigned int objectId, int zero);
|
||||
int msc_delete_object(sc_card_t *card, msc_id objectId, int zero);
|
||||
int msc_select_applet(sc_card_t *card, u8 *appletId, size_t appletIdLength);
|
||||
|
||||
int msc_verify_pin(sc_card_t *card, int pinNumber, const u8 *pinValue, int pinLength, int *tries);
|
||||
|
|
Loading…
Reference in New Issue