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:
aj 2006-11-30 08:14:16 +00:00
parent b9daff9b28
commit b3822c349b
5 changed files with 174 additions and 145 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);