OpenPGP: deal with DOs depending on card version
Have separate copies of pgp_objects[] data elements specific to the card's version, and extend these structures with additional information: * Some spec changes cannot be compatibly expressed in one common simple data structure without making it too complex. * depending on specification version, only deal with those DOs that are legal within that version * add information or read & write access conditions * add information for non-toplevel and/or write-only DOs * use symbolic names for constants Signed-off-by: Peter Marschall <peter@adpm.de> git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@5491 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
88e88d9317
commit
19142ee9af
|
@ -62,12 +62,32 @@ static struct sc_card_driver pgp_drv = {
|
|||
* Everything else is mapped to "file" IDs.
|
||||
*/
|
||||
|
||||
enum _type { /* DO type */
|
||||
SIMPLE = SC_FILE_TYPE_WORKING_EF,
|
||||
CONSTRUCTED = SC_FILE_TYPE_DF
|
||||
};
|
||||
|
||||
enum _version { /* 2-byte BCD-alike encoded version number */
|
||||
OPENPGP_CARD_1_0 = 0x0100,
|
||||
OPENPGP_CARD_1_1 = 0x0101,
|
||||
OPENPGP_CARD_2_0 = 0x0200
|
||||
};
|
||||
|
||||
enum _access { /* access flags for the respective DO/file */
|
||||
READ_NEVER = 0x0010,
|
||||
READ_PIN1 = 0x0011,
|
||||
READ_PIN2 = 0x0012,
|
||||
READ_PIN3 = 0x0014,
|
||||
READ_ALWAYS = 0x0018,
|
||||
READ_MASK = 0x00FF,
|
||||
WRITE_NEVER = 0x1000,
|
||||
WRITE_PIN1 = 0x1100,
|
||||
WRITE_PIN2 = 0x1200,
|
||||
WRITE_PIN3 = 0x1400,
|
||||
WRITE_ALWAYS = 0x1800,
|
||||
WRITE_MASK = 0x1F00
|
||||
};
|
||||
|
||||
struct blob {
|
||||
struct blob * next; /* pointer to next sibling */
|
||||
struct blob * parent; /* pointer to parent */
|
||||
|
@ -83,9 +103,16 @@ struct blob {
|
|||
};
|
||||
|
||||
struct do_info {
|
||||
unsigned int id;
|
||||
unsigned int constructed : 1;
|
||||
unsigned int id; /* ID of the DO in question */
|
||||
|
||||
enum _type type; /* constructed DO or not */
|
||||
enum _access access; /* R/W acces levels for the DO */
|
||||
|
||||
/* function to get the DO from the card:
|
||||
* only != NULL is DO if readable and not only a part of a constructed DO */
|
||||
int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t);
|
||||
/* function to write the DO to the card:
|
||||
* only != NULL if DO is writeable under some conditions */
|
||||
int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t);
|
||||
};
|
||||
|
||||
|
@ -100,26 +127,107 @@ static int pgp_get_pubkey(sc_card_t *, unsigned int,
|
|||
static int pgp_get_pubkey_pem(sc_card_t *, unsigned int,
|
||||
u8 *, size_t);
|
||||
|
||||
static struct do_info pgp_objects[] = {
|
||||
{ 0x004f, 0, sc_get_data, sc_put_data },
|
||||
{ 0x005e, 0, sc_get_data, sc_put_data },
|
||||
{ 0x0065, 1, sc_get_data, sc_put_data },
|
||||
{ 0x006e, 1, sc_get_data, sc_put_data },
|
||||
{ 0x007a, 1, sc_get_data, sc_put_data },
|
||||
{ 0x00c4, 0, sc_get_data, sc_put_data },
|
||||
{ 0x0101, 0, sc_get_data, sc_put_data },
|
||||
{ 0x0102, 0, sc_get_data, sc_put_data },
|
||||
{ 0x5f50, 0, sc_get_data, sc_put_data },
|
||||
{ 0x5f52, 0, sc_get_data, sc_put_data },
|
||||
{ 0x7f21, 1, sc_get_data, sc_put_data },
|
||||
{ 0xb600, 1, pgp_get_pubkey, NULL },
|
||||
{ 0xb800, 1, pgp_get_pubkey, NULL },
|
||||
{ 0xa400, 1, pgp_get_pubkey, NULL },
|
||||
{ 0xb601, 0, pgp_get_pubkey_pem,NULL },
|
||||
{ 0xb801, 0, pgp_get_pubkey_pem,NULL },
|
||||
{ 0xa401, 0, pgp_get_pubkey_pem,NULL },
|
||||
static struct do_info pgp1_objects[] = { /* OpenPGP card spec 1.1 */
|
||||
{ 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
{ 0x0065, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x006e, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x0073, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x007a, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x0081, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x0082, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x0093, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c0, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c1, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c2, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c3, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c4, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c5, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c6, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c7, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c8, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c9, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00ca, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cb, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cc, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cd, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00ce, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cf, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00d0, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 0x7f49, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0xa400, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xa401, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0xb600, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xb601, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0xb800, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xb801, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0, 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
{ 0, 0, NULL, NULL },
|
||||
static struct do_info pgp2_objects[] = { /* OpenPGP card spec 2.0 */
|
||||
{ 0x004d, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
{ 0x0065, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x006e, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x0073, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x007a, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x0081, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x0082, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x0093, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c0, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x00c1, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c2, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c3, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c4, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
{ 0x00c5, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c6, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c7, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c8, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00c9, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00ca, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cb, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cc, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cd, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00ce, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00cf, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00d0, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00d1, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00d2, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00d3, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00f4, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 0x5f50, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
{ 0x5f52, SIMPLE, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
|
||||
{ 0x7f21, CONSTRUCTED, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
{ 0x7f48, CONSTRUCTED, READ_NEVER | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x7f49, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0xa400, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xa401, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0xb600, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xb601, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0xb800, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
|
||||
{ 0xb801, SIMPLE, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey_pem, NULL },
|
||||
{ 0, 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
|
||||
|
@ -128,6 +236,7 @@ struct pgp_priv_data {
|
|||
struct blob * current; /* currently selected file */
|
||||
|
||||
enum _version bcd_version;
|
||||
struct do_info *pgp_objects;
|
||||
|
||||
sc_security_env_t sec_env;
|
||||
};
|
||||
|
@ -187,6 +296,10 @@ pgp_init(sc_card_t *card)
|
|||
if (card->type == SC_CARD_TYPE_OPENPGP_V2)
|
||||
_sc_card_add_rsa_alg(card, 2048, flags, 0);
|
||||
|
||||
/* set pointer to correct list of card objects */
|
||||
priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2)
|
||||
? pgp2_objects : pgp1_objects;
|
||||
|
||||
/* set detailed card version */
|
||||
priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2)
|
||||
? OPENPGP_CARD_2_0 : OPENPGP_CARD_1_1;
|
||||
|
@ -218,15 +331,15 @@ pgp_init(sc_card_t *card)
|
|||
/* select MF */
|
||||
priv->current = priv->mf;
|
||||
|
||||
/* Populate MF - add all blobs listed in the pgp_objects table. */
|
||||
for (info = pgp_objects; info->id > 0; info++) {
|
||||
child = pgp_new_blob(priv->mf, info->id,
|
||||
info->constructed? SC_FILE_TYPE_DF
|
||||
: SC_FILE_TYPE_WORKING_EF,
|
||||
info);
|
||||
/* catch out of memory condition */
|
||||
if (child == NULL)
|
||||
break;
|
||||
/* Populate MF - add matching blobs listed in the pgp_objects table. */
|
||||
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);
|
||||
/* catch out of memory condition */
|
||||
if (child == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* treat out of memory condition */
|
||||
|
|
Loading…
Reference in New Issue