Merged [3783:3794/trunk]
git-svn-id: https://www.opensc-project.org/svnp/opensc/branches/martin/0.12@3795 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
56fb57603b
commit
30ab50600b
|
@ -25,23 +25,19 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static enum LOAD_KEY {
|
||||
LOAD_KEY_MODULUS = 0x80,
|
||||
LOAD_KEY_PUBLIC_EXPONENT = 0x81,
|
||||
LOAD_KEY_PRIME_P = 0x83,
|
||||
LOAD_KEY_PRIME_Q = 0x84,
|
||||
LOAD_KEY_DP1 = 0x85,
|
||||
LOAD_KEY_DQ1 = 0x86,
|
||||
LOAD_KEY_INVQ = 0x87
|
||||
};
|
||||
#define LOAD_KEY_MODULUS 0x80
|
||||
#define LOAD_KEY_PUBLIC_EXPONENT 0x81
|
||||
#define LOAD_KEY_PRIME_P 0x83
|
||||
#define LOAD_KEY_PRIME_Q 0x84
|
||||
#define LOAD_KEY_DP1 0x85
|
||||
#define LOAD_KEY_DQ1 0x86
|
||||
#define LOAD_KEY_INVQ 0x87
|
||||
|
||||
static struct sc_card_operations myeid_ops;
|
||||
static struct sc_card_driver myeid_drv = {
|
||||
"MyEID cards with PKCS#15 applet",
|
||||
"myeid",
|
||||
&myeid_ops,
|
||||
NULL, 0, NULL
|
||||
&myeid_ops
|
||||
};
|
||||
|
||||
static const char *myeid_atrs[] = {
|
||||
|
@ -93,6 +89,7 @@ static int myeid_init(struct sc_card *card)
|
|||
/* State that we have an RNG */
|
||||
card->caps |= SC_CARD_CAP_RNG;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -107,9 +104,9 @@ static int acl_to_byte(const struct sc_acl_entry *e)
|
|||
case SC_AC_TERM:
|
||||
case SC_AC_AUT:
|
||||
if (e->key_ref == SC_AC_KEY_REF_NONE)
|
||||
return -1;
|
||||
return 0x00;
|
||||
if (e->key_ref < 1 || e->key_ref > 14)
|
||||
return -1;
|
||||
return 0x00;
|
||||
return e->key_ref;
|
||||
case SC_AC_NEVER:
|
||||
return 0x0F;
|
||||
|
@ -182,28 +179,28 @@ static int myeid_select_file(struct sc_card *card, const struct sc_path *in_path
|
|||
struct sc_file **file)
|
||||
{
|
||||
int r;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
r = iso_ops->select_file(card, in_path, file);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (file != NULL) {
|
||||
if (r == 0 && file != NULL) {
|
||||
parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_read_binary(struct sc_card *card, unsigned int idx,
|
||||
u8 * buf, size_t count, unsigned long flags)
|
||||
{
|
||||
return iso_ops->read_binary(card, idx, buf, count, flags);
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->read_binary(card, idx, buf, count, flags));
|
||||
}
|
||||
|
||||
static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||
{
|
||||
struct sc_apdu apdu;
|
||||
int r;
|
||||
int r,i;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, 0xA1);
|
||||
apdu.resp = buf;
|
||||
|
@ -225,9 +222,10 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
const u8 *tag = NULL;
|
||||
int r ;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
r = iso_ops->process_fci(card, file, buf, buflen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
|
||||
if(file->type == SC_FILE_EF_UNKNOWN)
|
||||
{
|
||||
|
@ -237,16 +235,23 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
file->type = SC_FILE_TYPE_INTERNAL_EF;
|
||||
}
|
||||
}
|
||||
if(file->sec_attr_len >= 3)
|
||||
{
|
||||
sc_debug(card->ctx, "id (%X) sec_attr (%X %X %X) \n", file->id,
|
||||
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
const sc_acl_entry_t *read, *update, *delete;
|
||||
u8 buf[40];
|
||||
int i;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
/* PrivateKey
|
||||
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
|
||||
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
|
||||
|
@ -283,6 +288,41 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
buf[15] = file->sec_attr[0];
|
||||
buf[16] = file->sec_attr[1];
|
||||
buf[17] = file->sec_attr[2];
|
||||
|
||||
sc_debug(card->ctx, "id (%X), sec_attr %X %X %X\n", file->id,
|
||||
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE);
|
||||
|
||||
switch (file->type) {
|
||||
case SC_FILE_TYPE_WORKING_EF:
|
||||
|
||||
read = sc_file_get_acl_entry(file, SC_AC_OP_READ);
|
||||
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
||||
|
||||
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
||||
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
||||
break;
|
||||
case SC_FILE_TYPE_INTERNAL_EF:
|
||||
|
||||
read = sc_file_get_acl_entry(file, SC_AC_OP_CRYPTO);
|
||||
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
||||
|
||||
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
||||
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
||||
break;
|
||||
case SC_FILE_TYPE_DF:
|
||||
|
||||
update = sc_file_get_acl_entry(file, SC_AC_OP_CREATE);
|
||||
|
||||
buf[15] = (acl_to_byte(update) << 4) | acl_to_byte(update);
|
||||
buf[16] = (acl_to_byte(delete) << 4) | 0x0F;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Proprietary Information */
|
||||
|
@ -312,10 +352,10 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
{
|
||||
buf[25] = 0x84;
|
||||
buf[26] = (u8)file->namelen;
|
||||
|
||||
for(i=0;i < (int)file->namelen;i++)
|
||||
{
|
||||
buf[i + 26] = file->name[i];
|
||||
}
|
||||
|
||||
buf[1] = 0x19 + file->namelen + 2;
|
||||
}
|
||||
break;
|
||||
|
@ -327,7 +367,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
*outlen = buf[1]+2;
|
||||
memcpy(out, buf, *outlen);
|
||||
|
||||
return 0;
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
||||
|
@ -337,9 +377,12 @@ static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
|||
size_t buflen;
|
||||
int r;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
r = encode_file_structure(card, file, sbuf, &buflen);
|
||||
if (r)
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
|
||||
apdu.data = sbuf;
|
||||
apdu.datalen = buflen;
|
||||
|
@ -348,44 +391,48 @@ static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
|||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
if (apdu.sw1 == 0x6A && apdu.sw2 == 0x89)
|
||||
return SC_ERROR_FILE_ALREADY_EXISTS;
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_ALREADY_EXISTS);
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, r, "Card returned error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no record oriented file services */
|
||||
static int myeid_read_record_unsupp(struct sc_card *card, unsigned int rec_nr,
|
||||
u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static int myeid_wrupd_record_unsupp(struct sc_card *card, unsigned int rec_nr,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static int myeid_append_record_unsupp(struct sc_card *card, const u8 *buf,
|
||||
size_t count, unsigned long flags)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
static int myeid_write_binary(struct sc_card *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
return iso_ops->write_binary(card, idx, buf, count, flags);
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->write_binary(card, idx, buf, count, flags));
|
||||
}
|
||||
|
||||
|
||||
static int myeid_update_binary(struct sc_card *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
return iso_ops->update_binary(card, idx, buf, count, flags);
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->update_binary(card, idx, buf, count, flags));
|
||||
}
|
||||
|
||||
static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
||||
|
@ -408,9 +455,33 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
|||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
|
||||
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_FUNC_RETURN(card->ctx, 1, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
|
||||
static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n",
|
||||
data->pin_reference, data->pin1.len, data->pin2.len);
|
||||
|
||||
if(data->pin1.len > 8 || data->pin2.len > 8)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_PIN_LENGTH);
|
||||
|
||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||
if(data->cmd == SC_PIN_CMD_VERIFY)
|
||||
{
|
||||
u8 buf[8];
|
||||
memset(buf, 0xFF, sizeof(buf));
|
||||
memcpy(&buf[0], (u8 *)data->pin1.data, data->pin1.len); /* copy pin*/
|
||||
data->pin1.data = buf;
|
||||
data->pin1.len = 8;
|
||||
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->pin_cmd(card, data, tries_left));
|
||||
}
|
||||
|
||||
static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env,
|
||||
int se_num)
|
||||
|
@ -421,7 +492,7 @@ static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env
|
|||
int r, locked = 0;
|
||||
|
||||
assert(card != NULL && env != NULL);
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
|
||||
{
|
||||
|
@ -504,12 +575,14 @@ static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env
|
|||
err:
|
||||
if (locked)
|
||||
sc_unlock(card);
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_set_security_env(struct sc_card *card,
|
||||
const struct sc_security_env *env, int se_num)
|
||||
{
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
||||
{
|
||||
sc_security_env_t tmp;
|
||||
|
@ -543,6 +616,8 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
|||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
assert(card != NULL && data != NULL && out != NULL);
|
||||
if (datalen > 256)
|
||||
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
@ -591,6 +666,8 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
|||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
assert(card != NULL && crgram != NULL && out != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, 2);
|
||||
if (crgram_len > 256)
|
||||
|
@ -733,6 +810,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
|
|||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int r, len;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
len = 0;
|
||||
if(value_len == 0 || value == NULL)
|
||||
return 0;
|
||||
|
@ -795,7 +873,6 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
|
|||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
|
||||
}
|
||||
|
||||
/* Generate or store a key */
|
||||
|
@ -804,8 +881,9 @@ static int myeid_generate_store_key(struct sc_card *card,
|
|||
{
|
||||
struct sc_apdu apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int r,len;
|
||||
int r=0,len;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
/* Setup key-generation paramters */
|
||||
if (data->op_type == OP_TYPE_GENERATE)
|
||||
{
|
||||
|
@ -831,8 +909,6 @@ static int myeid_generate_store_key(struct sc_card *card,
|
|||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, r, "GENERATE_KEY returned error");
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -850,10 +926,10 @@ static int myeid_generate_store_key(struct sc_card *card,
|
|||
data->mod, data->mod_len)) >= 0 &&
|
||||
(r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT,
|
||||
data->pubexp, data->pubexp_len)) >= 0)
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_activate_card(struct sc_card *card)
|
||||
|
@ -862,6 +938,7 @@ static int myeid_activate_card(struct sc_card *card)
|
|||
u8 sbuf[] ="\xA0\x00\x00\x00\x63\x50\x4B\x43\x53\x2D\x31\x35";
|
||||
sc_apdu_t apdu;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x44, 0x04, 0x00);
|
||||
apdu.cla = 0x00;
|
||||
apdu.data = sbuf;
|
||||
|
@ -883,6 +960,7 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
|||
sc_apdu_t apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0);
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
|
@ -907,28 +985,38 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
|||
/* copy and return serial number */
|
||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||
|
||||
return SC_SUCCESS;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||
{
|
||||
int r = SC_ERROR_NOT_SUPPORTED;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
switch(cmd) {
|
||||
case SC_CARDCTL_MYEID_PUTDATA:
|
||||
return myeid_putdata(card,
|
||||
r = myeid_putdata(card,
|
||||
(struct sc_cardctl_myeid_data_obj*) ptr);
|
||||
break;
|
||||
case SC_CARDCTL_MYEID_GETDATA:
|
||||
return myeid_getdata(card,
|
||||
r = myeid_getdata(card,
|
||||
(struct sc_cardctl_myeid_data_obj*) ptr);
|
||||
break;
|
||||
case SC_CARDCTL_MYEID_GENERATE_KEY:
|
||||
return myeid_generate_store_key(card,
|
||||
r = myeid_generate_store_key(card,
|
||||
(struct sc_cardctl_myeid_gen_store_key_info *) ptr);
|
||||
break;
|
||||
case SC_CARDCTL_MYEID_ACTIVATE_CARD:
|
||||
return myeid_activate_card(card);
|
||||
r = myeid_activate_card(card);
|
||||
break;
|
||||
case SC_CARDCTL_GET_SERIALNR:
|
||||
return myeid_get_serialnr(card, (sc_serial_number_t *)ptr);
|
||||
r = myeid_get_serialnr(card, (sc_serial_number_t *)ptr);
|
||||
break;
|
||||
case SC_CARDCTL_LIFECYCLE_SET:
|
||||
case SC_CARDCTL_LIFECYCLE_GET:
|
||||
break;
|
||||
}
|
||||
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
/* "The PINs are "global" in a PKCS#15 sense, meaning that they remain valid
|
||||
|
@ -938,7 +1026,8 @@ static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
|||
*/
|
||||
static int myeid_logout(struct sc_card *card)
|
||||
{
|
||||
return 0; /* Can't */
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
static struct sc_card_driver * sc_get_driver(void)
|
||||
|
@ -968,7 +1057,7 @@ static struct sc_card_driver * sc_get_driver(void)
|
|||
myeid_ops.logout = myeid_logout;
|
||||
myeid_ops.process_fci = myeid_process_fci;
|
||||
myeid_ops.card_ctl = myeid_card_ctl;
|
||||
|
||||
myeid_ops.pin_cmd = myeid_pin_cmd;
|
||||
return &myeid_drv;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,19 +144,12 @@ static int westcos_check_sw(sc_card_t * card, unsigned int sw1,
|
|||
return iso_ops->check_sw(card, sw1, sw2);
|
||||
}
|
||||
|
||||
typedef struct mon_atr {
|
||||
size_t len;
|
||||
int flags;
|
||||
u8 *atr, *mask;
|
||||
} mon_atr_t;
|
||||
|
||||
static mon_atr_t atrs[] = {
|
||||
{13, 0x00,
|
||||
"\x3f\x69\x00\x00\x00\x64\x01\x00\x00\x00\x80\x90\x00",
|
||||
"\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\xf0\xff\xff"},
|
||||
{12, JAVACARD,
|
||||
"\x3b\x95\x94\x80\x1F\xC3\x80\x73\xC8\x21\x13\x54",
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"}
|
||||
static struct sc_atr_table westcos_atrs[] = {
|
||||
/* westcos 2ko */
|
||||
{ "3F:69:00:00:00:64:01:00:00:00:80:90:00", "ff:ff:ff:ff:ff:ff:ff:00:00:00:f0:ff:ff", NULL, 0x00, 0, NULL },
|
||||
/* westcos applet */
|
||||
{ "3B:95:94:80:1F:C3:80:73:C8:21:13:54", "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff", NULL, JAVACARD, 0, NULL },
|
||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
static int westcos_finish(sc_card_t * card)
|
||||
|
@ -172,59 +165,35 @@ static int westcos_finish(sc_card_t * card)
|
|||
|
||||
static int westcos_match_card(sc_card_t * card)
|
||||
{
|
||||
u8 *p, j;
|
||||
size_t i;
|
||||
mon_atr_t *matr;
|
||||
if (card->ctx->debug >= 1)
|
||||
sc_debug(card->ctx, "westcos_match_card %d, %X:%X:%X\n",
|
||||
card->atr_len, card->atr[0], card->atr[1],
|
||||
card->atr[2]);
|
||||
for (i = 0; i < sizeof(atrs) / sizeof(*atrs); i++) {
|
||||
matr = &atrs[i];
|
||||
if (matr->len != card->atr_len)
|
||||
continue;
|
||||
p = card->atr;
|
||||
for (j = 0; j < card->atr_len; j++) {
|
||||
if (((matr->mask[j]) & (*p)) != (matr->atr[j]))
|
||||
break;
|
||||
p++;
|
||||
if (*p == ':')
|
||||
p++;
|
||||
}
|
||||
if (j >= card->atr_len) {
|
||||
if (matr->flags & JAVACARD) {
|
||||
int r;
|
||||
sc_apdu_t apdu;
|
||||
u8 aid[] = {
|
||||
0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01
|
||||
};
|
||||
sc_format_apdu(card, &apdu,
|
||||
SC_APDU_CASE_3_SHORT, 0xA4, 0x04,
|
||||
0);
|
||||
apdu.cla = 0x00;
|
||||
apdu.lc = sizeof(aid);
|
||||
apdu.datalen = sizeof(aid);
|
||||
apdu.data = aid;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r)
|
||||
continue;
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if (r)
|
||||
continue;
|
||||
}
|
||||
card->drv_data = malloc(sizeof(priv_data_t));
|
||||
if (card->drv_data == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memset(card->drv_data, 0, sizeof(card->drv_data));
|
||||
if (matr->flags & JAVACARD) {
|
||||
priv_data_t *priv_data =
|
||||
(priv_data_t *) card->drv_data;
|
||||
priv_data->flags |= JAVACARD;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int i;
|
||||
|
||||
i = _sc_match_atr(card, westcos_atrs, &card->type);
|
||||
if (i < 0)
|
||||
return 0;
|
||||
|
||||
/* JAVACARD, look for westcos applet */
|
||||
if (i == 1) {
|
||||
int r;
|
||||
sc_apdu_t apdu;
|
||||
u8 aid[] = {
|
||||
0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01
|
||||
};
|
||||
sc_format_apdu(card, &apdu,
|
||||
SC_APDU_CASE_3_SHORT, 0xA4, 0x04,
|
||||
0);
|
||||
apdu.cla = 0x00;
|
||||
apdu.lc = sizeof(aid);
|
||||
apdu.datalen = sizeof(aid);
|
||||
apdu.data = aid;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r)
|
||||
return 0;
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if (r)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int westcos_init(sc_card_t * card)
|
||||
|
@ -232,8 +201,19 @@ static int westcos_init(sc_card_t * card)
|
|||
int r;
|
||||
const char *default_key;
|
||||
unsigned long exponent, flags;
|
||||
if (card == NULL || card->drv_data == NULL)
|
||||
if (card == NULL)// || card->drv_data == NULL)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
card->drv_data = malloc(sizeof(priv_data_t));
|
||||
if (card->drv_data == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memset(card->drv_data, 0, sizeof(card->drv_data));
|
||||
if (card->type & JAVACARD) {
|
||||
priv_data_t *priv_data =
|
||||
(priv_data_t *) card->drv_data;
|
||||
priv_data->flags |= JAVACARD;
|
||||
}
|
||||
|
||||
card->cla = 0x00;
|
||||
card->max_send_size = 240;
|
||||
card->max_recv_size = 240;
|
||||
|
@ -260,9 +240,9 @@ static int westcos_init(sc_card_t * card)
|
|||
priv_data_t *priv_data = (priv_data_t *) (card->drv_data);
|
||||
priv_data->default_key.key_reference = 0;
|
||||
priv_data->default_key.key_len =
|
||||
sizeof(priv_data->default_key.key_value);
|
||||
sizeof(priv_data->default_key.key_value);
|
||||
r = sc_hex_to_bin(default_key, priv_data->default_key.key_value,
|
||||
&(priv_data->default_key.key_len));
|
||||
&(priv_data->default_key.key_len));
|
||||
if (r)
|
||||
return (r);
|
||||
}
|
||||
|
|
|
@ -488,8 +488,8 @@ typedef struct sc_cardctl_asepcos_activate_file {
|
|||
|
||||
typedef struct {
|
||||
int key_reference;
|
||||
int key_len; //8, 16 or 24
|
||||
u8 key_value[24];
|
||||
size_t key_len; //8, 16 or 24
|
||||
u8 key_value[24];
|
||||
}sc_autkey_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -32,7 +32,7 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
|||
{
|
||||
int i, r;
|
||||
int modulus_length = 0, usage = 0;
|
||||
u8 buf[256];
|
||||
char buf[256];
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
sc_serial_number_t serial;
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
#include <openssl/rsa.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/opensslconf.h> /* for OPENSSL_NO_EC */
|
||||
#ifndef OPENSSL_NO_EC
|
||||
#include <openssl/ec.h>
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
|
||||
|
||||
static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *);
|
||||
|
@ -248,7 +251,7 @@ sc_pkcs11_gen_keypair_soft(CK_KEY_TYPE keytype, CK_ULONG keybits,
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC)
|
||||
|
||||
static void reverse(unsigned char *buf, size_t len)
|
||||
{
|
||||
|
@ -328,7 +331,7 @@ static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
return CKR_GENERAL_ERROR;
|
||||
return ret_vrf == 1 ? CKR_OK : CKR_SIGNATURE_INVALID;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */
|
||||
|
||||
/* If no hash function was used, finish with RSA_public_decrypt().
|
||||
* If a hash function was used, we can make a big shortcut by
|
||||
|
@ -346,11 +349,12 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
|
||||
if (mech == CKM_GOSTR3410)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC)
|
||||
return gostr3410_verify_data(pubkey, pubkey_len,
|
||||
pubkey_params, pubkey_params_len,
|
||||
data, data_len, signat, signat_len);
|
||||
#else
|
||||
(void)pubkey_params, (void)pubkey_params_len; /* no warning */
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,20 +1,77 @@
|
|||
#
|
||||
# PKCS15 r/w profile for MyEID cards
|
||||
#
|
||||
|
||||
cardinfo {
|
||||
label = "MyEID";
|
||||
manufacturer = "Aventra Ltd.";
|
||||
min-pin-length = 4;
|
||||
max-pin-length = 8;
|
||||
pin-encoding = ascii-numeric;
|
||||
pin-pad-char = 0x00;
|
||||
pin-pad-char = 0xFF;
|
||||
}
|
||||
|
||||
#
|
||||
# The following controls some aspects of the PKCS15 we put onto
|
||||
# the card.
|
||||
#
|
||||
pkcs15 {
|
||||
# Put certificates into the CDF itself?
|
||||
direct-certificates = no;
|
||||
# Put the DF length into the ODF file?
|
||||
encode-df-length = no;
|
||||
# Have a lastUpdate field in the EF(TokenInfo)?
|
||||
do-last-update = no;
|
||||
}
|
||||
|
||||
option default {
|
||||
macros {
|
||||
#protected = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
#unprotected = READ=NONE, UPDATE=CHV1, DELETE=CHV1;
|
||||
|
||||
unusedspace-size = 512;
|
||||
odf-size = 256;
|
||||
aodf-size = 384;
|
||||
cdf-size = 512;
|
||||
prkdf-size = 1485;
|
||||
pukdf-size = 1200;
|
||||
dodf-size = 256;
|
||||
}
|
||||
}
|
||||
|
||||
# Define reasonable limits for PINs and PUK
|
||||
# Note that we do not set a file path or reference
|
||||
# here; that is done dynamically.
|
||||
PIN user-pin {
|
||||
reference = 1;
|
||||
auth-id = 1;
|
||||
min-length = 4;
|
||||
max-length = 8;
|
||||
attempts = 3;
|
||||
flags = initialized, needs-padding;
|
||||
}
|
||||
|
||||
PIN user-puk {
|
||||
min-length = 4;
|
||||
max-length = 8;
|
||||
attempts = 10;
|
||||
flags = needs-padding;
|
||||
}
|
||||
|
||||
PIN so-pin {
|
||||
reference = 2;
|
||||
auth-id = 2;
|
||||
min-length = 4;
|
||||
max-length = 8;
|
||||
attempts = 4;
|
||||
flags = initialized, soPin, needs-padding;
|
||||
}
|
||||
|
||||
PIN so-puk {
|
||||
min-length = 4;
|
||||
max-length = 8;
|
||||
attempts = 9;
|
||||
flags = needs-padding;
|
||||
}
|
||||
|
||||
# Additional filesystem info.
|
||||
|
@ -22,32 +79,114 @@ PIN user-puk {
|
|||
# main profile.
|
||||
filesystem {
|
||||
DF MF {
|
||||
path = 3F00;
|
||||
type = DF;
|
||||
acl = DELETE=CHV2; #Erase PIN
|
||||
|
||||
# This is the DIR file
|
||||
EF DIR {
|
||||
file-id = 2F00;
|
||||
structure = transparent;
|
||||
size = 128;
|
||||
acl = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
DF PKCS15-AppDF {
|
||||
type = DF;
|
||||
file-id = 5015;
|
||||
acl = DELETE=NONE, CREATE=CHV1;
|
||||
|
||||
EF PKCS15-ODF {
|
||||
file-id = 5031;
|
||||
structure = transparent;
|
||||
size = $odf-size;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-TokenInfo {
|
||||
file-id = 5032;
|
||||
structure = transparent;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-UnusedSpace {
|
||||
file-id = 5033;
|
||||
structure = transparent;
|
||||
size = $unusedspace-size;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-AODF {
|
||||
file-id = 4401;
|
||||
structure = transparent;
|
||||
size = $aodf-size;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-PrKDF {
|
||||
file-id = 4402;
|
||||
structure = transparent;
|
||||
size = $prkdf-size;
|
||||
acl = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-PuKDF {
|
||||
file-id = 4403;
|
||||
structure = transparent;
|
||||
size = $pukdf-size;
|
||||
acl = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-CDF {
|
||||
file-id = 4404;
|
||||
structure = transparent;
|
||||
size = $cdf-size;
|
||||
acl = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
EF PKCS15-DODF {
|
||||
file-id = 4405;
|
||||
structure = transparent;
|
||||
size = $dodf-size;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
EF template-private-key {
|
||||
type = internal-ef;
|
||||
file-id = 4B01; # This is the base FileID
|
||||
size = 266; # 266 is enough for 1024-bit keys
|
||||
ACL = *=NEVER, CRYPTO=$PIN, UPDATE=$PIN;
|
||||
file-id = 4B01;
|
||||
size = 1024;
|
||||
ACL = CRYPTO=CHV1, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
EF template-public-key {
|
||||
structure = transparent;
|
||||
file-id = 5501;
|
||||
ACL = *=NEVER, READ=NONE, UPDATE=$PIN;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
EF template-certificate {
|
||||
file-id = 4301;
|
||||
ACL = *=NEVER, READ=NONE, UPDATE=$PIN;
|
||||
structure = transparent;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
template key-domain {
|
||||
# This is a dummy entry - pkcs15-init insists that
|
||||
# this is present
|
||||
EF private-key {
|
||||
file-id = 4B00;
|
||||
type = internal-ef;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
EF public-key {
|
||||
file-id = 4300;
|
||||
structure = transparent;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
|
||||
# Certificate template
|
||||
EF certificate {
|
||||
file-id = 5300;
|
||||
structure = transparent;
|
||||
ACL = READ=NONE, UPDATE=CHV1, DELETE=CHV2;
|
||||
}
|
||||
EF template-extractable-key {
|
||||
file-id = 7000;
|
||||
ACL = *=NEVER, READ=$PIN, UPDATE=$PIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Define an SO pin
|
||||
# This PIN is not used yet.
|
||||
#PIN sopin {
|
||||
# file = sopinfile;
|
||||
# reference = 0;
|
||||
#}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -31,7 +32,7 @@
|
|||
#include "keycache.h"
|
||||
#include "profile.h"
|
||||
|
||||
#define MYEID_MAX_PINS 5
|
||||
#define MYEID_MAX_PINS 14
|
||||
|
||||
unsigned char MYEID_DEFAULT_PUBKEY[] = {0x01, 0x00, 0x01};
|
||||
#define MYEID_DEFAULT_PUBKEY_LEN sizeof(MYEID_DEFAULT_PUBKEY)
|
||||
|
@ -44,7 +45,26 @@ static int myeid_create_pin_internal(sc_profile_t *, sc_card_t *,
|
|||
int, sc_pkcs15_pin_info_t *, const u8 *, size_t,
|
||||
const u8 *, size_t);
|
||||
|
||||
static int myeid_puk_retries(sc_profile_t *, int);
|
||||
static int myeid_puk_retries(sc_profile_t *profile, sc_pkcs15_pin_info_t *pin_info);
|
||||
|
||||
static int acl_to_byte(const struct sc_acl_entry *e)
|
||||
{
|
||||
switch (e->method) {
|
||||
case SC_AC_NONE:
|
||||
return 0x00;
|
||||
case SC_AC_CHV:
|
||||
case SC_AC_TERM:
|
||||
case SC_AC_AUT:
|
||||
if (e->key_ref == SC_AC_KEY_REF_NONE)
|
||||
return 0x00;
|
||||
if (e->key_ref < 1 || e->key_ref > MYEID_MAX_PINS)
|
||||
return 0x00;
|
||||
return e->key_ref;
|
||||
case SC_AC_NEVER:
|
||||
return 0x0F;
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase the card.
|
||||
|
@ -52,17 +72,17 @@ static int myeid_puk_retries(sc_profile_t *, int);
|
|||
static int myeid_erase_card(sc_profile_t *profile, sc_card_t *card)
|
||||
{
|
||||
struct sc_cardctl_myeid_data_obj data_obj;
|
||||
sc_pkcs15_pin_info_t pin_info;
|
||||
sc_pkcs15_pin_info_t sopin_info, pin_info;
|
||||
|
||||
u8 data[8];
|
||||
int r;
|
||||
|
||||
/* Just delete the entire MF */
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
/* The SO pin has pin reference 1 -- not that it matters much
|
||||
* because pkcs15-init will ask to enter all pins, even if we
|
||||
* did a --so-pin on the command line. */
|
||||
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin_info);
|
||||
sc_keycache_set_pin_name(NULL, pin_info.reference, SC_PKCS15INIT_SO_PIN);
|
||||
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin_info);
|
||||
|
||||
/* Select parent DF and verify PINs/key as necessary */
|
||||
r = sc_pkcs15init_authenticate(profile, card, profile->mf_info->file, SC_AC_OP_DELETE);
|
||||
|
@ -71,23 +91,72 @@ static int myeid_erase_card(sc_profile_t *profile, sc_card_t *card)
|
|||
|
||||
data[0]= 0xFF;
|
||||
data[1]= 0xFF;
|
||||
data[2]= 0x33;
|
||||
data[2]= 0x11;
|
||||
data[3]= 0x3F;
|
||||
data[4]= 0xFF;
|
||||
data[5]= 0x33;
|
||||
data[6]= 0x3F;
|
||||
data[5]= 0x11;
|
||||
data[6]= 0xFF;
|
||||
data[7]= 0xFF;
|
||||
|
||||
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info);
|
||||
if(pin_info.reference > 0 && pin_info.reference <= MYEID_MAX_PINS &&
|
||||
sopin_info.reference > 0 && sopin_info.reference <= MYEID_MAX_PINS)
|
||||
{
|
||||
data[2] = (pin_info.reference << 4)| pin_info.reference;
|
||||
data[3] = (sopin_info.reference << 4) | 0x0F;
|
||||
data[5] = data[2];
|
||||
}
|
||||
|
||||
data_obj.P1 = 0x01;
|
||||
data_obj.P2 = 0xE0;
|
||||
data_obj.Data = data;
|
||||
data_obj.DataLen = 0x08;
|
||||
|
||||
sc_debug(card->ctx, "so_pin(%d), user pin (%d)\n",
|
||||
sopin_info.reference, pin_info.reference);
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_MYEID_PUTDATA, &data_obj);
|
||||
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_init_card(sc_profile_t *profile,
|
||||
sc_card_t *card)
|
||||
{
|
||||
struct sc_path path;
|
||||
sc_file_t *file;
|
||||
int r;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
sc_format_path("3F00", &path);
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a DF
|
||||
*/
|
||||
static int myeid_create_dir(sc_profile_t *profile, sc_card_t *card, sc_file_t *df)
|
||||
{
|
||||
int r=0;
|
||||
struct sc_file *file;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (!profile || !card || !df)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
sc_debug(card->ctx, "id (%x)\n",df->id);
|
||||
|
||||
if(df->id == 0x5015)
|
||||
{
|
||||
sc_debug(card->ctx, "only Select (%x)\n",df->id);
|
||||
r = sc_select_file(card, &df->path, NULL);
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
/*
|
||||
* Select the PIN reference
|
||||
*/
|
||||
|
@ -95,20 +164,27 @@ static int myeid_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
|
|||
sc_pkcs15_pin_info_t *pin_info)
|
||||
{
|
||||
sc_pkcs15_pin_info_t pin_info_prof;
|
||||
int type;
|
||||
|
||||
pin_info_prof.reference = 1; /* Default SO PIN ref. */
|
||||
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin_info_prof);
|
||||
|
||||
/* For the SO pin, we take the first available pin reference = 1 */
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
|
||||
pin_info->reference = pin_info_prof.reference;
|
||||
/* sc_pkcs15init_create_pin() starts checking if 0 is an acceptable
|
||||
* pin reference, which isn't for the myeid cards. And since the
|
||||
* value 1 has been assigned to the SO pin, we'll jump to 2. */
|
||||
else if (pin_info->reference == 0)
|
||||
pin_info->reference = pin_info_prof.reference + 1;
|
||||
{
|
||||
type = SC_PKCS15INIT_SO_PIN;
|
||||
sc_debug(card->ctx, "PIN_FLAG_SO_PIN, ref (%d), tries_left (%d)\n",
|
||||
pin_info->reference,pin_info->tries_left);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = SC_PKCS15INIT_USER_PIN;
|
||||
sc_debug(card->ctx, "PIN_FLAG_PIN, ref (%d), tries_left (%d)\n",
|
||||
pin_info->reference, pin_info->tries_left);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pin_info->reference <= 0 || pin_info->reference > MYEID_MAX_PINS)
|
||||
pin_info->reference = 1;
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -138,6 +214,7 @@ static int myeid_new_file(sc_profile_t *profile, sc_card_t *card,
|
|||
char name[64], *tag;
|
||||
int r;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA)
|
||||
tag = "private-key";
|
||||
else if (type == SC_PKCS15_TYPE_PUBKEY_RSA)
|
||||
|
@ -178,21 +255,23 @@ static int myeid_new_file(sc_profile_t *profile, sc_card_t *card,
|
|||
}
|
||||
|
||||
*out = file;
|
||||
return 0;
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
static int myeid_encode_private_key(sc_profile_t *profile, sc_card_t *card,
|
||||
struct sc_pkcs15_prkey_rsa *rsa, u8 *key,
|
||||
size_t *keysize, int key_ref)
|
||||
{
|
||||
return 0;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
static int myeid_encode_public_key(sc_profile_t *profile, sc_card_t *card,
|
||||
struct sc_pkcs15_prkey_rsa *rsa, u8 *key,
|
||||
size_t *keysize, int key_ref)
|
||||
{
|
||||
return 0;
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -232,9 +311,13 @@ static int myeid_generate_store_key(sc_profile_t *profile, sc_card_t *card,
|
|||
sc_pkcs15_prkey_info_t *info)
|
||||
{
|
||||
struct sc_cardctl_myeid_gen_store_key_info args;
|
||||
struct sc_cardctl_myeid_data_obj data_obj;
|
||||
unsigned char raw_pubkey[256];
|
||||
int r;
|
||||
unsigned int mod_len;
|
||||
sc_file_t *prkf = NULL;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
/* Parameter check */
|
||||
if ( (keybits < 1024) || (keybits > 2048) || (keybits & 0X7)) {
|
||||
sc_debug(card->ctx,
|
||||
|
@ -303,7 +386,7 @@ done:
|
|||
if (prkf)
|
||||
sc_file_free(prkf);
|
||||
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -314,36 +397,30 @@ static int myeid_create_pin_internal(sc_profile_t *profile, sc_card_t *card,
|
|||
const u8 *pin, size_t pin_len,
|
||||
const u8 *puk, size_t puk_len)
|
||||
{
|
||||
u8 data[19];
|
||||
u8 data[20];
|
||||
int so_pin_ref;
|
||||
int r;
|
||||
int r,type, puk_tries;
|
||||
struct sc_cardctl_myeid_data_obj data_obj;
|
||||
sc_file_t *pinfile = NULL;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx, "pin (%d), pin_len (%d), puk_len(%d) \n",
|
||||
pin_info->reference, pin_len, puk_len);
|
||||
|
||||
if (pin_info->reference >= MYEID_MAX_PINS)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
if (pin == NULL || puk == NULL || pin_len < 4 || puk_len < 4)
|
||||
return SC_ERROR_INVALID_PIN_LENGTH;
|
||||
|
||||
/* Verify required access rights if needed (i.e. if the
|
||||
* pin file isn't in the CREATE life cycle state). */
|
||||
if (!ignore_ac)
|
||||
{
|
||||
/* Re-ink the SO pin to the MF because there is the pin file */
|
||||
so_pin_ref = sc_keycache_find_named_pin(&profile->df_info->file->path,
|
||||
SC_PKCS15INIT_SO_PIN);
|
||||
if (so_pin_ref >= 0)
|
||||
sc_keycache_set_pin_name(&profile->mf_info->file->path,
|
||||
so_pin_ref, SC_PKCS15INIT_SO_PIN);
|
||||
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
|
||||
type = SC_PKCS15INIT_SO_PIN;
|
||||
else
|
||||
type = SC_PKCS15INIT_USER_PIN;
|
||||
|
||||
r = sc_profile_get_file(profile, "pinfile", &pinfile);
|
||||
if (r >= 0)
|
||||
r = sc_pkcs15init_authenticate(profile, card, pinfile, SC_AC_OP_UPDATE);
|
||||
sc_file_free(pinfile);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
sc_debug(card->ctx, "pin type (%s)\n",
|
||||
(type == SC_PKCS15INIT_SO_PIN) ? "SO_PIN": "USER_PIN");
|
||||
|
||||
memset(data, 0xFF, sizeof(data));
|
||||
/* Make command to add a pin-record */
|
||||
data_obj.P1 = 01;
|
||||
data_obj.P2 = pin_info->reference; /* myeid pin number */
|
||||
|
@ -351,40 +428,40 @@ static int myeid_create_pin_internal(sc_profile_t *profile, sc_card_t *card,
|
|||
memcpy(&data[0], (u8 *)pin, pin_len); /* copy pin*/
|
||||
memcpy(&data[8], (u8 *)puk, puk_len); /* copy puk */
|
||||
|
||||
|
||||
/* Optional PIN locking
|
||||
* data[17] = pin_info->tries_left & 0x0F;
|
||||
* data[18] = myeid_puk_retries(profile, pin_info->reference) & 0x0F;
|
||||
*/
|
||||
|
||||
data[16] = 0x00;
|
||||
data[17] = 0x00;
|
||||
data[18] = 0x00;
|
||||
data[19] = 0x00; /* FIXME, array is only 0..18 */
|
||||
|
||||
data_obj.Data = data;
|
||||
data_obj.DataLen = 0x10;
|
||||
data_obj.DataLen = 16;
|
||||
|
||||
puk_tries = myeid_puk_retries(profile, pin_info);
|
||||
if(pin_info->tries_left > 0 && pin_info->tries_left < 15 &&
|
||||
puk_tries > 0 && puk_tries < 15)
|
||||
{
|
||||
/* Optional PIN locking */
|
||||
data[16] = (pin_info->tries_left & 0x0F);
|
||||
data[17] = (puk_tries & 0x0F);
|
||||
data_obj.DataLen = 19;
|
||||
}
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_MYEID_PUTDATA, &data_obj);
|
||||
|
||||
return r;
|
||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||
}
|
||||
|
||||
static int myeid_puk_retries(sc_profile_t *profile, int pin_ref)
|
||||
static int myeid_puk_retries(sc_profile_t *profile, sc_pkcs15_pin_info_t *pin_info)
|
||||
{
|
||||
sc_pkcs15_pin_info_t pin_info;
|
||||
sc_pkcs15_pin_info_t puk_info;
|
||||
|
||||
pin_info.reference = 1; /* Default SO PIN ref. */
|
||||
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin_info);
|
||||
|
||||
/* If pin_ref is the SO PIN, get the SO PUK info, otherwise the User PUK info */
|
||||
sc_profile_get_pin_info(profile,
|
||||
pin_ref == pin_info.reference ?
|
||||
(pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) ?
|
||||
SC_PKCS15INIT_SO_PUK : SC_PKCS15INIT_USER_PUK,
|
||||
&pin_info);
|
||||
&puk_info);
|
||||
|
||||
if ((pin_info.tries_left < 0) || (pin_info.tries_left > 15))
|
||||
return 3; /* Little extra safety */
|
||||
return pin_info.tries_left;
|
||||
if ((puk_info.tries_left < 0) || (puk_info.tries_left >= 15))
|
||||
return -1;
|
||||
return puk_info.tries_left;
|
||||
}
|
||||
|
||||
/* For Myeid, all objects are files that can be deleted in any order */
|
||||
|
@ -392,13 +469,14 @@ static int myeid_delete_object(struct sc_profile *profile,
|
|||
struct sc_card *card, unsigned int type,
|
||||
const void *data, const sc_path_t *path)
|
||||
{
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
return sc_pkcs15init_delete_by_path(profile, card, path);
|
||||
}
|
||||
|
||||
static struct sc_pkcs15init_operations sc_pkcs15init_myeid_operations = {
|
||||
myeid_erase_card,
|
||||
NULL, /* init_card */
|
||||
NULL, /* create_dir */
|
||||
myeid_init_card, /* init_card */
|
||||
myeid_create_dir, /* create_dir */
|
||||
NULL, /* create_domain */
|
||||
myeid_select_pin_reference,
|
||||
myeid_create_pin,
|
||||
|
|
|
@ -268,9 +268,9 @@ static int westcos_pkcs15init_generate_key(sc_profile_t *profile,
|
|||
#ifndef ENABLE_OPENSSL
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
#else
|
||||
int r = SC_ERROR_UNKNOWN;
|
||||
long lg;
|
||||
char *p;
|
||||
int r = SC_ERROR_UNKNOWN;
|
||||
long lg;
|
||||
u8 *p;
|
||||
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||
RSA *rsa = NULL;
|
||||
BIGNUM *bn = NULL;
|
||||
|
|
|
@ -62,9 +62,7 @@ static int new_pin = 0;
|
|||
static int debloque = 0;
|
||||
|
||||
static char *get_filename = NULL;
|
||||
static char *get_path = NULL;
|
||||
static char *put_filename = NULL;
|
||||
static char *put_path = NULL;
|
||||
|
||||
static int do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src)
|
||||
{
|
||||
|
@ -90,7 +88,7 @@ static void print_openssl_erreur(void)
|
|||
fprintf(stderr, "%s\n", ERR_error_string(r, NULL));
|
||||
}
|
||||
|
||||
static verify_pin(sc_card_t *card, int pin_reference, char *pin_value)
|
||||
static int verify_pin(sc_card_t *card, int pin_reference, char *pin_value)
|
||||
{
|
||||
int r, tries_left = -1;
|
||||
struct sc_pin_cmd_data data;
|
||||
|
@ -117,7 +115,7 @@ static verify_pin(sc_card_t *card, int pin_reference, char *pin_value)
|
|||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
data.pin1.data = pin_value;
|
||||
data.pin1.data = (u8*)pin_value;
|
||||
data.pin1.len = strlen(pin_value);
|
||||
}
|
||||
|
||||
|
@ -140,7 +138,7 @@ static verify_pin(sc_card_t *card, int pin_reference, char *pin_value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static change_pin(sc_card_t *card,
|
||||
static int change_pin(sc_card_t *card,
|
||||
int pin_reference,
|
||||
char *pin_value1,
|
||||
char *pin_value2)
|
||||
|
@ -170,10 +168,10 @@ static change_pin(sc_card_t *card,
|
|||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
data.pin1.data = pin_value1;
|
||||
data.pin1.data = (u8*)pin_value1;
|
||||
data.pin1.len = strlen(pin_value1);
|
||||
|
||||
data.pin2.data = pin_value2;
|
||||
data.pin2.data = (u8*)pin_value2;
|
||||
data.pin2.len = strlen(pin_value2);
|
||||
|
||||
}
|
||||
|
@ -198,7 +196,7 @@ static change_pin(sc_card_t *card,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static debloque_pin(sc_card_t *card,
|
||||
static int debloque_pin(sc_card_t *card,
|
||||
int pin_reference,
|
||||
char *puk_value,
|
||||
char *pin_value)
|
||||
|
@ -228,10 +226,10 @@ static debloque_pin(sc_card_t *card,
|
|||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
data.pin1.data = puk_value;
|
||||
data.pin1.data = (u8*)puk_value;
|
||||
data.pin1.len = strlen(puk_value);
|
||||
|
||||
data.pin2.data = pin_value;
|
||||
data.pin2.data = (u8*)pin_value;
|
||||
data.pin2.len = strlen(pin_value);
|
||||
|
||||
}
|
||||
|
@ -351,7 +349,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int r;
|
||||
int i = 1;
|
||||
u8 *p;
|
||||
char *p;
|
||||
int card_presente = 0;
|
||||
sc_context_param_t ctx_param;
|
||||
sc_reader_t *lecteur = NULL;
|
||||
|
@ -589,7 +587,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
pin_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||
pin_cmd.len = strlen(pin);
|
||||
pin_cmd.data = pin;
|
||||
pin_cmd.data = (u8*)pin;
|
||||
pin_cmd.max_length = 8;
|
||||
|
||||
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||
|
@ -613,7 +611,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
puk_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||
puk_cmd.len = strlen(puk);
|
||||
puk_cmd.data = puk;
|
||||
puk_cmd.data = (u8*)puk;
|
||||
puk_cmd.max_length = 8;
|
||||
|
||||
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||
|
@ -651,10 +649,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(keylen)
|
||||
{
|
||||
int lg;
|
||||
size_t lg;
|
||||
struct sc_pkcs15_pubkey key;
|
||||
struct sc_pkcs15_pubkey_rsa *dst = &(key.u.rsa);
|
||||
|
||||
u8 *pdata;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.algorithm = SC_ALGORITHM_RSA;
|
||||
|
||||
|
@ -687,7 +686,7 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
{
|
||||
fprintf(stderr,
|
||||
"RSA_generate_key_ex return %d\n", ERR_get_error());
|
||||
"RSA_generate_key_ex return %ld\n", ERR_get_error());
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -696,11 +695,11 @@ int main(int argc, char *argv[])
|
|||
if(!i2d_RSAPrivateKey_bio(mem, rsa))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"i2d_RSAPrivateKey_bio return %d\n", ERR_get_error());
|
||||
"i2d_RSAPrivateKey_bio return %ld\n", ERR_get_error());
|
||||
goto out;
|
||||
}
|
||||
|
||||
lg = BIO_get_mem_data(mem, &p);
|
||||
lg = BIO_get_mem_data(mem, &pdata);
|
||||
|
||||
sc_format_path("0001", &path);
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
|
@ -750,7 +749,7 @@ int main(int argc, char *argv[])
|
|||
printf("Private key length is %d\n", lg);
|
||||
|
||||
printf("Write private key.\n");
|
||||
r = sc_update_binary(card,0,p,lg,0);
|
||||
r = sc_update_binary(card,0,pdata,lg,0);
|
||||
if(r<0) goto out;
|
||||
printf("Private key correctly written.\n");
|
||||
|
||||
|
@ -761,7 +760,7 @@ int main(int argc, char *argv[])
|
|||
|| !do_convert_bignum(&dst->exponent, rsa->e))
|
||||
goto out;
|
||||
|
||||
r = sc_pkcs15_encode_pubkey(ctx, &key, &p, &lg);
|
||||
r = sc_pkcs15_encode_pubkey(ctx, &key, &pdata, &lg);
|
||||
if(r) goto out;
|
||||
|
||||
printf("Public key length %d\n", lg);
|
||||
|
@ -771,7 +770,7 @@ int main(int argc, char *argv[])
|
|||
if(r) goto out;
|
||||
|
||||
printf("Write public key.\n");
|
||||
r = sc_update_binary(card,0,p,lg,0);
|
||||
r = sc_update_binary(card,0,pdata,lg,0);
|
||||
if(r<0) goto out;
|
||||
printf("Public key correctly written.\n");
|
||||
|
||||
|
@ -779,9 +778,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(cert)
|
||||
{
|
||||
BIO *bio;
|
||||
X509 *xp;
|
||||
|
||||
BIO *bio;
|
||||
X509 *xp;
|
||||
u8 *pdata;
|
||||
|
||||
bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(bio, cert) <= 0)
|
||||
{
|
||||
|
@ -798,7 +798,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
int lg = cert2der(xp, &p);
|
||||
int lg = cert2der(xp, &pdata);
|
||||
|
||||
sc_format_path("0002", &path);
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
|
@ -807,14 +807,14 @@ int main(int argc, char *argv[])
|
|||
/* FIXME: verifier taille fichier compatible... */
|
||||
printf("Write certificate %s.\n", cert);
|
||||
|
||||
r = sc_update_binary(card,0,p,lg,0);
|
||||
r = sc_update_binary(card,0,pdata,lg,0);
|
||||
if(r<0)
|
||||
{
|
||||
if(p) free(p);
|
||||
if(pdata) free(pdata);
|
||||
goto out;
|
||||
}
|
||||
if(xp) X509_free(xp);
|
||||
if(p) free(p);
|
||||
if(pdata) free(pdata);
|
||||
|
||||
printf("Certificate correctly written.\n");
|
||||
}
|
||||
|
@ -950,5 +950,6 @@ out:
|
|||
if (ctx)
|
||||
sc_release_context(ctx);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue