- Updated, now registers key objects as well (untested)
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1590 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
36f170c2e7
commit
b3b3b02cf0
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* PKCS15 emulation layer for OpenPGP card.
|
||||
* To see how this works, run p15dump on your OpenPGP card.
|
||||
*
|
||||
* Copyright (C) 2003, Olaf Kirch <okir@suse.de>
|
||||
*
|
||||
|
@ -26,6 +27,22 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
static char * pgp_pin_name[3] = {
|
||||
"Signature PIN",
|
||||
"Encryption PIN",
|
||||
"Admin PIN"
|
||||
};
|
||||
static char * pgp_key_name[3] = {
|
||||
"Signature key",
|
||||
"Encryption key",
|
||||
"Authentication key"
|
||||
};
|
||||
static char * pgp_pubkey_path[3] = {
|
||||
"B600",
|
||||
"B800",
|
||||
"A400"
|
||||
};
|
||||
|
||||
/*
|
||||
* Much of this code probably needs to be shared between
|
||||
* emulators. Will move this to pkcs15-syn.c when needed.
|
||||
|
@ -55,9 +72,10 @@ sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, int type)
|
|||
}
|
||||
}
|
||||
|
||||
static sc_pkcs15_object_t *
|
||||
static int
|
||||
sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
|
||||
const char *label, void *data)
|
||||
const char *label, void *data,
|
||||
const sc_pkcs15_id_t *auth_id)
|
||||
{
|
||||
sc_pkcs15_object_t *obj;
|
||||
int df_type;
|
||||
|
@ -89,18 +107,18 @@ sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
|
|||
default:
|
||||
sc_error(p15card->card->ctx,
|
||||
"Unknown PKCS15 object type %d\n", type);
|
||||
return NULL;
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
obj->df = sc_pkcs15emu_get_df(p15card, df_type);
|
||||
sc_pkcs15_add_object(p15card, obj);
|
||||
|
||||
return obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
||||
unsigned int id, const char *label,
|
||||
const sc_pkcs15_id_t *id, const char *label,
|
||||
const sc_path_t *path, int ref, int type,
|
||||
unsigned int min_length,
|
||||
unsigned int max_length,
|
||||
|
@ -109,8 +127,7 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
|||
sc_pkcs15_pin_info_t *info;
|
||||
|
||||
info = (sc_pkcs15_pin_info_t *) calloc(1, sizeof(*info));
|
||||
info->auth_id.value[0] = id;
|
||||
info->auth_id.len = 1;
|
||||
info->auth_id = *id;
|
||||
info->min_length = min_length;
|
||||
info->max_length = max_length;
|
||||
info->stored_length = max_length;
|
||||
|
@ -118,15 +135,65 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
|||
info->reference = ref;
|
||||
info->flags = flags;
|
||||
info->tries_left = tries_left;
|
||||
info->magic = SC_PKCS15_PIN_MAGIC;
|
||||
|
||||
if (path)
|
||||
info->path = *path;
|
||||
if (type == SC_PKCS15_PIN_TYPE_BCD)
|
||||
info->stored_length /= 2;
|
||||
|
||||
sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info);
|
||||
return sc_pkcs15emu_add_object(p15card,
|
||||
SC_PKCS15_TYPE_AUTH_PIN,
|
||||
label, info, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static int
|
||||
sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_id_t *id,
|
||||
const char *label,
|
||||
int type, unsigned int modulus_length, int usage,
|
||||
const sc_path_t *path, int ref,
|
||||
sc_pkcs15_id_t *auth_id)
|
||||
{
|
||||
sc_pkcs15_prkey_info_t *info;
|
||||
|
||||
info = (sc_pkcs15_prkey_info_t *) calloc(1, sizeof(*info));
|
||||
info->id = *id;
|
||||
info->modulus_length = modulus_length;
|
||||
info->usage = usage;
|
||||
info->native = 1;
|
||||
info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
|
||||
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
info->key_reference = ref;
|
||||
|
||||
if (path)
|
||||
info->path = *path;
|
||||
|
||||
return sc_pkcs15emu_add_object(p15card,
|
||||
type, label, info, auth_id);
|
||||
}
|
||||
|
||||
static int
|
||||
sc_pkcs15emu_add_pubkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_id_t *id,
|
||||
const char *label, int type,
|
||||
unsigned int modulus_length, int usage,
|
||||
const sc_path_t *path)
|
||||
{
|
||||
sc_pkcs15_pubkey_info_t *info;
|
||||
|
||||
info = (sc_pkcs15_pubkey_info_t *) calloc(1, sizeof(*info));
|
||||
info->id = *id;
|
||||
info->modulus_length = modulus_length;
|
||||
info->usage = usage;
|
||||
info->access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
|
||||
|
||||
if (path)
|
||||
info->path = *path;
|
||||
|
||||
return sc_pkcs15emu_add_object(p15card, type, label, info, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -142,74 +209,19 @@ set_string(char **strp, const char *value)
|
|||
* code does.
|
||||
*/
|
||||
static int
|
||||
get_tlv(sc_context_t *ctx, unsigned int match_tag,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 *out, size_t out_len)
|
||||
read_file(sc_card_t *card, const char *path_name, void *buf, size_t len)
|
||||
{
|
||||
const u8 *end = in + in_len;
|
||||
sc_path_t path;
|
||||
sc_file_t *file;
|
||||
int r;
|
||||
|
||||
while (in < end) {
|
||||
unsigned int tag, len;
|
||||
int composite = 0;
|
||||
unsigned char c;
|
||||
sc_format_path(path_name, &path);
|
||||
if ((r = sc_select_file(card, &path, &file)) < 0)
|
||||
return r;
|
||||
|
||||
c = *in++;
|
||||
if (c == 0x00 || c == 0xFF)
|
||||
continue;
|
||||
|
||||
tag = c;
|
||||
if (tag & 0x20)
|
||||
composite = 1;
|
||||
while ((c & 0x1f) == 0x1f) {
|
||||
if (in >= end)
|
||||
goto eoc;
|
||||
c = *in++;
|
||||
tag = (tag << 8) | c;
|
||||
}
|
||||
|
||||
if (in >= end)
|
||||
goto eoc;
|
||||
c = *in++;
|
||||
if (c < 0x80) {
|
||||
len = c;
|
||||
} else {
|
||||
len = 0;
|
||||
c &= 0x7F;
|
||||
while (c--) {
|
||||
if (in >= end)
|
||||
goto eoc;
|
||||
len = (len << 8) | *in++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't search past end of content */
|
||||
if (in + len > end)
|
||||
goto eoc;
|
||||
|
||||
if (tag == match_tag) {
|
||||
if (len > out_len)
|
||||
len = out_len;
|
||||
memcpy(out, in, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Recurse into composite object.
|
||||
* No need for recursion check, as we check the buffer
|
||||
* length and each recursion consumes at least 2 bytes */
|
||||
if (composite) {
|
||||
r = get_tlv(ctx, match_tag, in, len, out, out_len);
|
||||
if (r != SC_ERROR_OBJECT_NOT_FOUND)
|
||||
return r;
|
||||
}
|
||||
|
||||
in += len;
|
||||
}
|
||||
|
||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||
|
||||
eoc: sc_error(ctx, "Unexpected end of contentsn");
|
||||
return SC_ERROR_OBJECT_NOT_VALID;
|
||||
if (file->size < len)
|
||||
len = file->size;
|
||||
return sc_read_binary(card, 0, buf, len, 0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -217,27 +229,15 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
sc_path_t path;
|
||||
sc_file_t *file;
|
||||
char string[256];
|
||||
u8 buffer[256], value[256];
|
||||
u8 buffer[256];
|
||||
size_t length;
|
||||
int r, i;
|
||||
|
||||
/* Select OpenPGP application.
|
||||
* We must specify a file, because the card expects a
|
||||
* case 4 APDU and barfs if it's case 2.
|
||||
*/
|
||||
sc_format_path("D276:0001:2401", &path);
|
||||
path.type = SC_PATH_TYPE_DF_NAME;
|
||||
if ((r = sc_select_file(card, &path, &file)) < 0)
|
||||
goto failed;
|
||||
sc_file_free(file);
|
||||
|
||||
set_string(&p15card->label, "OpenPGP Card");
|
||||
set_string(&p15card->manufacturer_id, "OpenPGP project");
|
||||
|
||||
if ((r = sc_get_data(card, 0x004f, buffer, sizeof(buffer))) < 0)
|
||||
if ((r = read_file(card, "004f", buffer, sizeof(buffer))) < 0)
|
||||
goto failed;
|
||||
sc_bin_to_hex(buffer, r, string, sizeof(string), 0);
|
||||
set_string(&p15card->serial_number, string);
|
||||
|
@ -247,19 +247,12 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
SC_PKCS15_CARD_FLAG_PRN_GENERATION |
|
||||
SC_PKCS15_CARD_FLAG_EID_COMPLIANT;
|
||||
|
||||
/* Get Card Holder Related Data (0065) */
|
||||
if ((r = sc_get_data(card, 0x0065, buffer, sizeof(buffer))) < 0)
|
||||
goto failed;
|
||||
length = r;
|
||||
|
||||
/* Extract preferred language */
|
||||
r = get_tlv(ctx, 0x5F2D, buffer, length, string, sizeof(string)-1);
|
||||
if (r > 0) {
|
||||
string[r] = '\0';
|
||||
set_string(&p15card->preferred_language, string);
|
||||
} else if (r != SC_ERROR_OBJECT_NOT_FOUND) {
|
||||
r = read_file(card, "00655f2d", string, sizeof(string)-1);
|
||||
if (r < 0)
|
||||
goto failed;
|
||||
}
|
||||
string[r] = '\0';
|
||||
set_string(&p15card->preferred_language, string);
|
||||
|
||||
/* Get Application Related Data (006E) */
|
||||
if ((r = sc_get_data(card, 0x006E, buffer, sizeof(buffer))) < 0)
|
||||
|
@ -273,8 +266,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
* 01-03: max length of pins 1-3
|
||||
* 04-07: tries left for pins 1-3
|
||||
*/
|
||||
r = get_tlv(ctx, 0x00c4, buffer, length, value, sizeof(value));
|
||||
if (r < 0)
|
||||
if ((r = read_file(card, "006E007300C4", buffer, sizeof(buffer))) < 0)
|
||||
goto failed;
|
||||
if (r != 7) {
|
||||
sc_error(ctx,
|
||||
|
@ -284,11 +276,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
static char *pin_name[3] = {
|
||||
"User PIN",
|
||||
"User PIN 2",
|
||||
"Admin PIN"
|
||||
};
|
||||
sc_pkcs15_id_t auth_id;
|
||||
int flags;
|
||||
|
||||
flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
|
||||
|
@ -298,9 +286,58 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
flags |= SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED |
|
||||
SC_PKCS15_PIN_FLAG_SO_PIN;
|
||||
}
|
||||
sc_pkcs15emu_add_pin(p15card, i+1, pin_name[i], NULL, i+1,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
0, value[1+i], flags, value[4+i]);
|
||||
|
||||
auth_id.value[0] = i + 1;
|
||||
auth_id.len = 1;
|
||||
sc_pkcs15emu_add_pin(p15card, &auth_id,
|
||||
pgp_pin_name[i], NULL, i+1,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
0, buffer[1+i], flags, buffer[4+i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
static int prkey_pin[3] = { 1, 2, 2 };
|
||||
static int prkey_usage[3] = {
|
||||
SC_PKCS15_PRKEY_USAGE_SIGN
|
||||
| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
|
||||
| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
|
||||
SC_PKCS15_PRKEY_USAGE_DECRYPT
|
||||
| SC_PKCS15_PRKEY_USAGE_UNWRAP,
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
|
||||
};
|
||||
sc_pkcs15_id_t id, auth_id;
|
||||
|
||||
id.value[0] = i + 1;
|
||||
id.len = 1;
|
||||
auth_id.value[0] = prkey_pin[i];
|
||||
auth_id.len = 1;
|
||||
sc_pkcs15emu_add_prkey(p15card, &id,
|
||||
pgp_key_name[i],
|
||||
SC_PKCS15_TYPE_PRKEY_RSA,
|
||||
1024, prkey_usage[i],
|
||||
NULL, 0,
|
||||
&auth_id);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
static int pubkey_usage[3] = {
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFY
|
||||
| SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
|
||||
SC_PKCS15_PRKEY_USAGE_ENCRYPT
|
||||
| SC_PKCS15_PRKEY_USAGE_WRAP,
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFY
|
||||
};
|
||||
sc_pkcs15_id_t id;
|
||||
sc_path_t path;
|
||||
|
||||
id.value[0] = i + 1;
|
||||
id.len = 1;
|
||||
sc_format_path(pgp_pubkey_path[i], &path);
|
||||
sc_pkcs15emu_add_pubkey(p15card, &id,
|
||||
pgp_key_name[i],
|
||||
SC_PKCS15_TYPE_PUBKEY_RSA,
|
||||
1024, pubkey_usage[i],
|
||||
&path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue