pkcs15: DIR EF can have EF_LINEAR structure
and so, in this case the checking file size is not appropriate method to validate it. ;use short call form for the log messages;
This commit is contained in:
parent
9d5404bac6
commit
954d0b9375
@ -52,9 +52,11 @@ static const struct sc_asn1_entry c_asn1_dir[] = {
|
|||||||
{ NULL, 0, 0, 0, NULL, NULL }
|
{ NULL, 0, 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|
||||||
int rec_nr)
|
static int
|
||||||
|
parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen, int rec_nr)
|
||||||
{
|
{
|
||||||
|
struct sc_context *ctx = card->ctx;
|
||||||
struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2];
|
struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2];
|
||||||
sc_app_info_t *app = NULL;
|
sc_app_info_t *app = NULL;
|
||||||
struct sc_aid aid;
|
struct sc_aid aid;
|
||||||
@ -62,6 +64,7 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|||||||
size_t label_len = sizeof(label), path_len = sizeof(path), ddo_len = sizeof(ddo);
|
size_t label_len = sizeof(label), path_len = sizeof(path), ddo_len = sizeof(ddo);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
LOG_FUNC_CALLED(ctx);
|
||||||
aid.len = sizeof(aid.value);
|
aid.len = sizeof(aid.value);
|
||||||
|
|
||||||
sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord);
|
sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord);
|
||||||
@ -72,18 +75,14 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|||||||
sc_format_asn1_entry(asn1_dirrecord + 2, path, &path_len, 0);
|
sc_format_asn1_entry(asn1_dirrecord + 2, path, &path_len, 0);
|
||||||
sc_format_asn1_entry(asn1_dirrecord + 3, ddo, &ddo_len, 0);
|
sc_format_asn1_entry(asn1_dirrecord + 3, ddo, &ddo_len, 0);
|
||||||
|
|
||||||
r = sc_asn1_decode(card->ctx, asn1_dir, *buf, *buflen, (const u8 **) buf, buflen);
|
r = sc_asn1_decode(ctx, asn1_dir, *buf, *buflen, (const u8 **) buf, buflen);
|
||||||
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
|
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
|
||||||
return r;
|
LOG_FUNC_RETURN(ctx, r);
|
||||||
if (r) {
|
LOG_TEST_RET(ctx, r, "EF(DIR) parsing failed");
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EF(DIR) parsing failed: %s\n",
|
|
||||||
sc_strerror(r));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
app = calloc(1, sizeof(struct sc_app_info));
|
app = calloc(1, sizeof(struct sc_app_info));
|
||||||
if (app == NULL)
|
if (app == NULL)
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
memcpy(&app->aid, &aid, sizeof(struct sc_aid));
|
memcpy(&app->aid, &aid, sizeof(struct sc_aid));
|
||||||
|
|
||||||
@ -95,9 +94,8 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|||||||
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) {
|
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) {
|
||||||
/* application path present: ignore AID */
|
/* application path present: ignore AID */
|
||||||
if (path_len > SC_MAX_PATH_SIZE) {
|
if (path_len > SC_MAX_PATH_SIZE) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Application path is too long.\n");
|
|
||||||
free(app);
|
free(app);
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Application path is too long.");
|
||||||
}
|
}
|
||||||
memcpy(app->path.value, path, path_len);
|
memcpy(app->path.value, path, path_len);
|
||||||
app->path.len = path_len;
|
app->path.len = path_len;
|
||||||
@ -114,7 +112,7 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|||||||
app->ddo.value = malloc(ddo_len);
|
app->ddo.value = malloc(ddo_len);
|
||||||
if (app->ddo.value == NULL) {
|
if (app->ddo.value == NULL) {
|
||||||
free(app);
|
free(app);
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate DDO value");
|
||||||
}
|
}
|
||||||
memcpy(app->ddo.value, ddo, ddo_len);
|
memcpy(app->ddo.value, ddo, ddo_len);
|
||||||
app->ddo.len = ddo_len;
|
app->ddo.len = ddo_len;
|
||||||
@ -127,9 +125,10 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
|||||||
card->app[card->app_count] = app;
|
card->app[card->app_count] = app;
|
||||||
card->app_count++;
|
card->app_count++;
|
||||||
|
|
||||||
return 0;
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sc_enum_apps(sc_card_t *card)
|
int sc_enum_apps(sc_card_t *card)
|
||||||
{
|
{
|
||||||
struct sc_context *ctx = card->ctx;
|
struct sc_context *ctx = card->ctx;
|
||||||
@ -138,7 +137,7 @@ int sc_enum_apps(sc_card_t *card)
|
|||||||
size_t file_size, jj;
|
size_t file_size, jj;
|
||||||
int r, ii, idx;
|
int r, ii, idx;
|
||||||
|
|
||||||
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
|
LOG_FUNC_CALLED(ctx);
|
||||||
if (card->app_count < 0)
|
if (card->app_count < 0)
|
||||||
card->app_count = 0;
|
card->app_count = 0;
|
||||||
|
|
||||||
@ -148,35 +147,36 @@ int sc_enum_apps(sc_card_t *card)
|
|||||||
card->ef_dir = NULL;
|
card->ef_dir = NULL;
|
||||||
}
|
}
|
||||||
r = sc_select_file(card, &path, &card->ef_dir);
|
r = sc_select_file(card, &path, &card->ef_dir);
|
||||||
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select EF.DIR file");
|
LOG_TEST_RET(ctx, r, "Cannot select EF.DIR file");
|
||||||
|
|
||||||
if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
|
if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
|
||||||
sc_file_free(card->ef_dir);
|
sc_file_free(card->ef_dir);
|
||||||
card->ef_dir = NULL;
|
card->ef_dir = NULL;
|
||||||
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD, "EF(DIR) is not a working EF.");
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_CARD, "EF(DIR) is not a working EF.");
|
||||||
}
|
}
|
||||||
ef_structure = card->ef_dir->ef_structure;
|
|
||||||
file_size = card->ef_dir->size;
|
|
||||||
if (file_size == 0)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 0);
|
|
||||||
|
|
||||||
|
ef_structure = card->ef_dir->ef_structure;
|
||||||
if (ef_structure == SC_FILE_EF_TRANSPARENT) {
|
if (ef_structure == SC_FILE_EF_TRANSPARENT) {
|
||||||
u8 *buf = NULL, *p;
|
u8 *buf = NULL, *p;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
|
|
||||||
|
file_size = card->ef_dir->size;
|
||||||
|
if (file_size == 0)
|
||||||
|
LOG_FUNC_RETURN(ctx, 0);
|
||||||
|
|
||||||
buf = malloc(file_size);
|
buf = malloc(file_size);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||||
p = buf;
|
p = buf;
|
||||||
r = sc_read_binary(card, 0, buf, file_size, 0);
|
r = sc_read_binary(card, 0, buf, file_size, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(buf);
|
free(buf);
|
||||||
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_read_binary() failed");
|
LOG_TEST_RET(ctx, r, "sc_read_binary() failed");
|
||||||
}
|
}
|
||||||
bufsize = r;
|
bufsize = r;
|
||||||
while (bufsize > 0) {
|
while (bufsize > 0) {
|
||||||
if (card->app_count == SC_MAX_CARD_APPS) {
|
if (card->app_count == SC_MAX_CARD_APPS) {
|
||||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card");
|
sc_log(ctx, "Too many applications on card");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r = parse_dir_record(card, &p, &bufsize, -1);
|
r = parse_dir_record(card, &p, &bufsize, -1);
|
||||||
@ -188,19 +188,23 @@ int sc_enum_apps(sc_card_t *card)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else { /* record structure */
|
else { /* record structure */
|
||||||
u8 buf[256], *p;
|
unsigned char buf[256], *p;
|
||||||
unsigned int rec_nr;
|
unsigned int rec_nr;
|
||||||
size_t rec_size;
|
size_t rec_size;
|
||||||
|
|
||||||
for (rec_nr = 1; ; rec_nr++) {
|
/* Arbitrary set '16' as maximal number of records to check out:
|
||||||
|
* to avoid endless loop because of some uncomplete cards/drivers */
|
||||||
|
for (rec_nr = 1; rec_nr < 16; rec_nr++) {
|
||||||
r = sc_read_record(card, rec_nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
|
r = sc_read_record(card, rec_nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
|
||||||
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
||||||
break;
|
break;
|
||||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read_record() failed");
|
LOG_TEST_RET(ctx, r, "read_record() failed");
|
||||||
|
|
||||||
if (card->app_count == SC_MAX_CARD_APPS) {
|
if (card->app_count == SC_MAX_CARD_APPS) {
|
||||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card");
|
sc_log(ctx, "Too many applications on card");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec_size = r;
|
rec_size = r;
|
||||||
p = buf;
|
p = buf;
|
||||||
parse_dir_record(card, &p, &rec_size, (int)rec_nr);
|
parse_dir_record(card, &p, &rec_size, (int)rec_nr);
|
||||||
@ -226,7 +230,7 @@ int sc_enum_apps(sc_card_t *card)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc_free_apps(sc_card_t *card)
|
void sc_free_apps(sc_card_t *card)
|
||||||
@ -266,7 +270,7 @@ static int encode_dir_record(sc_context_t *ctx, const sc_app_info_t *app,
|
|||||||
sc_format_asn1_entry(asn1_dirrecord + 3, (void *) tapp.ddo.value,
|
sc_format_asn1_entry(asn1_dirrecord + 3, (void *) tapp.ddo.value,
|
||||||
(void *) &tapp.ddo.len, 1);
|
(void *) &tapp.ddo.len, 1);
|
||||||
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
||||||
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Encode DIR record error");
|
LOG_TEST_RET(ctx, r, "Encode DIR record error");
|
||||||
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -310,7 +314,7 @@ static int update_transparent(sc_card_t *card, sc_file_t *file)
|
|||||||
}
|
}
|
||||||
r = sc_update_binary(card, 0, buf, buf_size, 0);
|
r = sc_update_binary(card, 0, buf, buf_size, 0);
|
||||||
free(buf);
|
free(buf);
|
||||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to update EF(DIR)");
|
LOG_TEST_RET(card->ctx, r, "Unable to update EF(DIR)");
|
||||||
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -342,11 +346,11 @@ static int update_single_record(sc_card_t *card, sc_app_info_t *app)
|
|||||||
r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid record number\n");
|
sc_log(card->ctx, "invalid record number\n");
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
free(rec);
|
free(rec);
|
||||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to update EF(DIR) record");
|
LOG_TEST_RET(card->ctx, r, "Unable to update EF(DIR) record");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +375,8 @@ int sc_update_dir(sc_card_t *card, sc_app_info_t *app)
|
|||||||
sc_format_path("3F002F00", &path);
|
sc_format_path("3F002F00", &path);
|
||||||
|
|
||||||
r = sc_select_file(card, &path, &file);
|
r = sc_select_file(card, &path, &file);
|
||||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to select EF(DIR)");
|
LOG_TEST_RET(card->ctx, r, "unable to select EF(DIR)");
|
||||||
|
|
||||||
if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
|
if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
|
||||||
r = update_transparent(card, file);
|
r = update_transparent(card, file);
|
||||||
else if (app == NULL)
|
else if (app == NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user