Browse files

Merge remote-tracking branch 'peter/OpenPGP-20110611' into proposed

  • Loading branch information...
2 parents a6b7743 + 4939432 commit a3a8ae3ef9c634e96323341e9b83ffb187b375f3 @martinpaljak martinpaljak committed Jun 15, 2011
Showing with 81 additions and 48 deletions.
  1. +81 −48 src/libopensc/card-openpgp.c
View
129 src/libopensc/card-openpgp.c
@@ -122,8 +122,7 @@ static void pgp_iterate_blobs(struct blob *, int, void (*func)());
static int pgp_get_blob(sc_card_t *card, struct blob *blob,
unsigned int id, struct blob **ret);
-static struct blob * pgp_new_blob(struct blob *, unsigned int, int,
- struct do_info *);
+static struct blob * pgp_new_blob(sc_card_t *, struct blob *, unsigned int, sc_file_t *);
static void pgp_free_blob(struct blob *);
static int pgp_get_pubkey(sc_card_t *, unsigned int,
u8 *, size_t);
@@ -161,11 +160,11 @@ static struct do_info pgp1_objects[] = { /* OpenPGP card spec 1.1 */
{ 0x00e0, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00e1, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00e2, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
- { 0x00ff, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x0101, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0102, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0103, SIMPLE, READ_PIN1 | WRITE_PIN1, sc_get_data, sc_put_data },
{ 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data },
+ { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f50, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
@@ -216,6 +215,7 @@ static struct do_info pgp2_objects[] = { /* OpenPGP card spec 2.0 */
{ 0x0102, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0103, SIMPLE, READ_PIN1 | WRITE_PIN1, sc_get_data, sc_put_data },
{ 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data },
+ { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f48, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
@@ -276,12 +276,6 @@ pgp_init(sc_card_t *card)
return SC_ERROR_OUT_OF_MEMORY;
card->drv_data = priv;
- priv->mf = calloc(1, sizeof(struct blob));
- if (!priv->mf) {
- pgp_finish(card);
- return SC_ERROR_OUT_OF_MEMORY;
- }
-
card->cla = 0x00;
/* set pointer to correct list of card objects */
@@ -309,12 +303,15 @@ pgp_init(sc_card_t *card)
card->serialnr.len = 6;
}
+ /* change file path to MF for re-use in MF */
sc_format_path("3f00", &file->path);
- file->type = SC_FILE_TYPE_DF;
- file->id = 0x3f00;
- priv->mf->file = file;
- priv->mf->id = 0x3F00;
+ /* set up the root of our fake file tree */
+ priv->mf = pgp_new_blob(card, NULL, 0x3f00, file);
+ if (!priv->mf) {
+ pgp_finish(card);
+ return SC_ERROR_OUT_OF_MEMORY;
+ }
/* select MF */
priv->current = priv->mf;
@@ -323,20 +320,16 @@ pgp_init(sc_card_t *card)
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) {
if (((info->access & READ_MASK) == READ_ALWAYS) &&
(info->get_fn != NULL)) {
- child = pgp_new_blob(priv->mf, info->id, info->type, info);
+ child = pgp_new_blob(card, priv->mf, info->id, sc_file_new());
+
/* catch out of memory condition */
- if (child == NULL)
- break;
+ if (child == NULL) {
+ pgp_finish(card);
+ return SC_ERROR_OUT_OF_MEMORY;
+ }
}
}
- /* treat out of memory condition */
- if (child == NULL) {
- pgp_finish(card);
- return SC_ERROR_OUT_OF_MEMORY;
- }
-
-
/* get card_features from ATR & DOs */
pgp_get_card_features(card);
@@ -400,7 +393,7 @@ pgp_get_card_features(sc_card_t *card)
}
/* get supported algorithms & key lengths from "algorithm attributes" DOs */
- for (i = 0x00c1; i < 0x0c3; i++) {
+ for (i = 0x00c1; i <= 0x00c3; i++) {
unsigned long flags;
/* Is this correct? */
@@ -475,26 +468,54 @@ pgp_set_blob(struct blob *blob, const u8 *data, size_t len)
/* internal: append a blob to the list of children of a given parent blob */
static struct blob *
-pgp_new_blob(struct blob *parent, unsigned int file_id,
- int file_type, struct do_info *info)
+pgp_new_blob(sc_card_t *card, struct blob *parent, unsigned int file_id,
+ sc_file_t *file)
{
- sc_file_t *file = sc_file_new();
- struct blob *blob, **p;
+ struct blob *blob = NULL;
+
+ if (file == NULL)
+ return NULL;
+
+ if ((blob = calloc(1, sizeof(struct blob))) != NULL) {
+ struct pgp_priv_data *priv = DRVDATA (card);
+ struct do_info *info;
+
+ blob->file = file;
+
+ blob->file->type = SC_FILE_TYPE_WORKING_EF; /* default */
+ blob->file->ef_structure = SC_FILE_EF_TRANSPARENT;
+ blob->file->id = file_id;
- if ((blob = calloc(1, sizeof(*blob))) != NULL) {
- blob->parent = parent;
blob->id = file_id;
- blob->file = file;
- blob->info = info;
+ blob->parent = parent;
+
+ if (parent != NULL) {
+ struct blob **p;
+
+ /* set file's path = parent's path + file's id */
+ blob->file->path = parent->file->path;
+ sc_append_file_id(&blob->file->path, file_id);
- file->type = file_type;
- file->path = parent->file->path;
- file->ef_structure = SC_FILE_EF_TRANSPARENT;
- sc_append_file_id(&file->path, file_id);
+ /* append blob to list of parent's children */
+ for (p = &parent->files; *p != NULL; p = &(*p)->next)
+ ;
+ *p = blob;
+ }
+ else {
+ u8 id_str[2];
+
+ /* no parent: set file's path = file's id */
+ sc_format_path(ushort2bebytes(id_str, file_id), &blob->file->path);
+ }
- for (p = &parent->files; *p; p = &(*p)->next)
- ;
- *p = blob;
+ /* find matching DO info: set file type depending on it */
+ for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) {
+ if (info->id == file_id) {
+ blob->info = info;
+ blob->file->type = blob->info->type;
+ break;
+ }
+ }
}
return blob;
@@ -506,6 +527,16 @@ static void
pgp_free_blob(struct blob *blob)
{
if (blob) {
+ if (blob->parent) {
+ struct blob **p;
+
+ /* remove blob from list of parent's children */
+ for (p = &blob->parent->files; *p != NULL && *p != blob; p = &(*p)->next)
+ ;
+ if (*p == blob)
+ *p = blob->next;
+ }
+
if (blob->file)
sc_file_free(blob->file);
if (blob->data)
@@ -583,7 +614,6 @@ pgp_enumerate_blob(sc_card_t *card, struct blob *blob)
while ((int) blob->len > (in - blob->data)) {
unsigned int cla, tag, tmptag;
- unsigned int type = SC_FILE_TYPE_WORKING_EF;
size_t len;
const u8 *data = in;
struct blob *new;
@@ -596,18 +626,15 @@ pgp_enumerate_blob(sc_card_t *card, struct blob *blob)
return SC_ERROR_OBJECT_NOT_VALID;
}
- /* create fake file system hierarchy by
- * using constructed DOs as DF */
- if (cla & SC_ASN1_TAG_CONSTRUCTED)
- type = SC_FILE_TYPE_DF;
-
/* undo ASN1's split of tag & class */
for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
cla <<= 8;
}
tag |= cla;
- if ((new = pgp_new_blob(blob, tag, type, NULL)) == NULL)
+ /* create fake file system hierarchy by
+ * using constructed DOs as DF */
+ if ((new = pgp_new_blob(card, blob, tag, sc_file_new())) == NULL)
return SC_ERROR_OUT_OF_MEMORY;
pgp_set_blob(new, data, len);
in = data + len;
@@ -709,8 +736,14 @@ pgp_list_files(sc_card_t *card, u8 *buf, size_t buflen)
if ((r = pgp_enumerate_blob(card, blob)) < 0)
LOG_FUNC_RETURN(card->ctx, r);
- for (k = 0, blob = blob->files; (blob != NULL) && (k + 2 <= buflen); blob = blob->next, k += 2) {
- ushort2bebytes(buf + k, blob->id);
+ for (k = 0, blob = blob->files; blob != NULL; blob = blob->next) {
+ if (blob->info != NULL && (blob->info->access & READ_MASK) != READ_NEVER) {
+ if (k + 2 > buflen)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);
+
+ ushort2bebytes(buf + k, blob->id);
+ k += 2;
+ }
}
LOG_FUNC_RETURN(card->ctx, k);

0 comments on commit a3a8ae3

Please sign in to comment.