Merge [3794:3803/trunk]
git-svn-id: https://www.opensc-project.org/svnp/opensc/branches/martin/0.12@3804 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
30ab50600b
commit
450e1fc5ae
|
@ -5,7 +5,7 @@ AC_PREREQ(2.60)
|
|||
define([PACKAGE_VERSION_MAJOR], [0])
|
||||
define([PACKAGE_VERSION_MINOR], [12])
|
||||
define([PACKAGE_VERSION_FIX], [0])
|
||||
define([PACKAGE_SUFFIX], [-svn-mp])
|
||||
define([PACKAGE_SUFFIX], [-svn])
|
||||
|
||||
AC_INIT([opensc],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
@ -153,9 +153,9 @@ AC_ARG_ENABLE(
|
|||
|
||||
AC_ARG_ENABLE(
|
||||
[pcsc],
|
||||
[AS_HELP_STRING([--enable-pcsc],[enable pcsc support @<:@disabled@:>@])],
|
||||
[AS_HELP_STRING([--disable-pcsc],[disable pcsc support @<:@enabled@:>@])],
|
||||
,
|
||||
[enable_pcsc="no"]
|
||||
[enable_pcsc="yes"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
|
@ -587,7 +587,7 @@ if test "${enable_pcsc}" = "yes"; then
|
|||
DEFAULT_PCSC_PROVIDER="winscard.dll"
|
||||
;;
|
||||
*)
|
||||
DEFAULT_PCSC_PROVIDER="/usr/lib${libdir##*/lib}/libpcsclite.so"
|
||||
DEFAULT_PCSC_PROVIDER="libpcsclite.so.1"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
* CosmopolIC v5;
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
* Copyright (C) 2003 Viktor Tarasov <vtarasov@idealx.com>, idealx <www.idealx.com>
|
||||
* Copyright (C) 2009 Viktor Tarasov <viktor.tarasov@idealx.com>,
|
||||
* OpenTrust <www.opentrust.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -43,8 +44,6 @@
|
|||
#define DES_ecb_encrypt(a,b,c,d) des_ecb_encrypt(a,b,*c,d)
|
||||
#endif
|
||||
|
||||
#define NOT_YET 1
|
||||
|
||||
static struct sc_atr_table oberthur_atrs[] = {
|
||||
{ "3B:7D:18:00:00:00:31:80:71:8E:64:77:E3:01:00:82:90:00", NULL,
|
||||
"Oberthur 64k v4/2.1.1", SC_CARD_TYPE_OBERTHUR_64K, 0, NULL },
|
||||
|
@ -126,39 +125,6 @@ static int auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial);
|
|||
static int auth_select_file(sc_card_t *card, const sc_path_t *in_path,
|
||||
sc_file_t **file_out);
|
||||
|
||||
#ifndef NOT_YET
|
||||
static int auth_sm_init (struct sc_card *card, struct sc_sm_info *sm_info,
|
||||
int cmd, unsigned char *id, size_t id_len,
|
||||
unsigned char *resp, size_t *resp_len);
|
||||
static int auth_sm_execute (struct sc_card *card, struct sc_sm_info *sm_info,
|
||||
unsigned char *data, int data_len, unsigned char *out, size_t len);
|
||||
static int auth_sm_update_rsa (struct sc_card *card,
|
||||
struct sc_cardctl_oberthur_updatekey_info *data);
|
||||
static int auth_sm_reset_pin (struct sc_card *card, int type, int ref,
|
||||
const unsigned char *data, size_t len);
|
||||
static int auth_sm_read_binary (struct sc_card *card,
|
||||
unsigned char *id, size_t id_len,
|
||||
size_t offs, unsigned char *out, size_t len);
|
||||
static int auth_sm_release (struct sc_card *card, struct sc_sm_info *sm_info,
|
||||
unsigned char *data, int data_len);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* this function isn't used anywhere */
|
||||
static void _auth_print_acls(struct sc_card *card, struct sc_file *file)
|
||||
{
|
||||
int ii, jj;
|
||||
|
||||
for (jj=0; jj < SC_MAX_AC_OPS; jj++) {
|
||||
const sc_acl_entry_t *acl = sc_file_get_acl_entry(file, jj);
|
||||
|
||||
for (ii=0; acl; acl = acl->next, ii++) {
|
||||
sc_debug(card->ctx, "%i-%i: acl : meth 0x%X, ref 0x%X",
|
||||
jj, ii, acl->method, acl->key_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
auth_finish(sc_card_t *card)
|
||||
|
@ -443,42 +409,20 @@ auth_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
add_acl_entry(card, file, SC_AC_OP_CRYPTO, attr[1]);
|
||||
add_acl_entry(card, file, SC_AC_OP_LIST_FILES, attr[2]);
|
||||
add_acl_entry(card, file, SC_AC_OP_DELETE, attr[3]);
|
||||
#ifndef NOT_YET
|
||||
add_acl_entry(card, file, SC_AC_OP_PIN_SET, attr[4]);
|
||||
add_acl_entry(card, file, SC_AC_OP_PIN_CHANGE, attr[5]);
|
||||
add_acl_entry(card, file, SC_AC_OP_PIN_RESET, attr[6]);
|
||||
#endif
|
||||
}
|
||||
else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { /* EF */
|
||||
switch (file->ef_structure) {
|
||||
case SC_CARDCTL_OBERTHUR_KEY_DES:
|
||||
add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
|
||||
#if 0
|
||||
add_acl_entry(card, file, SC_AC_OP_DECRYPT, attr[1]);
|
||||
add_acl_entry(card, file, SC_AC_OP_ENCRYPT, attr[2]);
|
||||
add_acl_entry(card, file, SC_AC_OP_CHECKSUM, attr[3]);
|
||||
add_acl_entry(card, file, SC_AC_OP_VERIFY, attr[4]);
|
||||
#else
|
||||
add_acl_entry(card, file, SC_AC_OP_READ, attr[1]);
|
||||
#endif
|
||||
break;
|
||||
case SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC:
|
||||
add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
|
||||
#if 0
|
||||
add_acl_entry(card, file, SC_AC_OP_ENCRYPT, attr[2]);
|
||||
add_acl_entry(card, file, SC_AC_OP_VERIFY, attr[4]);
|
||||
#else
|
||||
add_acl_entry(card, file, SC_AC_OP_READ, attr[2]);
|
||||
#endif
|
||||
break;
|
||||
case SC_CARDCTL_OBERTHUR_KEY_RSA_CRT:
|
||||
add_acl_entry(card, file, SC_AC_OP_UPDATE, attr[0]);
|
||||
#if 0
|
||||
add_acl_entry(card, file, SC_AC_OP_DECRYPT, attr[1]);
|
||||
add_acl_entry(card, file, SC_AC_OP_SIGN, attr[3]);
|
||||
#else
|
||||
add_acl_entry(card, file, SC_AC_OP_READ, attr[1]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -889,15 +833,9 @@ encode_file_structure_V5(sc_card_t *card, const sc_file_t *file,
|
|||
ops[1] = SC_AC_OP_CRYPTO;
|
||||
ops[2] = SC_AC_OP_LIST_FILES;
|
||||
ops[3] = SC_AC_OP_DELETE;
|
||||
#ifndef NOT_YET
|
||||
ops[4] = SC_AC_OP_PIN_SET; /* SC_AC_OP_SET_REFERENCE */
|
||||
ops[5] = SC_AC_OP_PIN_CHANGE; /* SC_AC_OP_CHANGE_REFERENCE */
|
||||
ops[6] = SC_AC_OP_PIN_RESET; /* SC_AC_OP_RESET_COUNTER */
|
||||
#else
|
||||
ops[4] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_SET_REFERENCE */
|
||||
ops[5] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_CHANGE_REFERENCE */
|
||||
ops[6] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_RESET_COUNTER */
|
||||
#endif
|
||||
}
|
||||
else if (file->type == SC_FILE_TYPE_WORKING_EF) {
|
||||
if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
|
||||
|
@ -1265,13 +1203,6 @@ auth_get_default_key(sc_card_t *card, struct sc_cardctl_default_key *data)
|
|||
{
|
||||
int rv = SC_ERROR_NO_DEFAULT_KEY;
|
||||
|
||||
#ifndef NOT_YET
|
||||
if (data->method == SC_AC_PRO) {
|
||||
card->sm_level = data->key_ref | 0x60;
|
||||
rv = SC_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
@ -1304,9 +1235,6 @@ auth_generate_key(sc_card_t *card, int use_sm,
|
|||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
sc_path_t tmp_path;
|
||||
int rv = 0;
|
||||
#ifndef NOT_YET
|
||||
const sc_acl_entry_t *entry;
|
||||
#endif
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (data->key_bits < 512 || data->key_bits > 2048 ||
|
||||
|
@ -1336,46 +1264,10 @@ auth_generate_key(sc_card_t *card, int use_sm,
|
|||
apdu.data = sbuf;
|
||||
apdu.datalen = rv + 4;
|
||||
|
||||
#ifndef NOT_YET
|
||||
entry = sc_file_get_acl_entry(auth_current_df, SC_AC_OP_CRYPTO);
|
||||
if (entry && entry->method == SC_AC_PRO)
|
||||
if (card->sm_level < (entry->key_ref | 0x60))
|
||||
card->sm_level = entry->key_ref | 0x60;
|
||||
|
||||
if (card->sm_level) {
|
||||
struct sc_sm_info sm_info;
|
||||
unsigned char init_data[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int init_data_len = sizeof(init_data);
|
||||
unsigned char out[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int out_len = sizeof(init_data);
|
||||
|
||||
rv = auth_sm_init (card, &sm_info, SC_SM_CMD_TYPE_GENERATE_RSA,
|
||||
card->serialnr.value, card->serialnr.len,
|
||||
init_data, &init_data_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: init failed");
|
||||
|
||||
sm_info.p1 = data->key_bits;
|
||||
sm_info.data = apdu.data;
|
||||
sm_info.data_len = apdu.datalen;
|
||||
|
||||
rv = auth_sm_execute (card, &sm_info, init_data, init_data_len,
|
||||
out, out_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: execute failed");
|
||||
|
||||
rv = auth_sm_release (card, &sm_info, out, out_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: release failed");
|
||||
|
||||
/* TODO clean resp */
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
|
||||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, rv, "Card returned error");
|
||||
#ifndef NOT_YET
|
||||
}
|
||||
#endif
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
|
||||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, rv, "Card returned error");
|
||||
|
||||
tmp_path.type = SC_PATH_TYPE_FILE_ID;
|
||||
tmp_path.len = 2;
|
||||
|
@ -1500,19 +1392,6 @@ auth_update_key(sc_card_t *card, struct sc_cardctl_oberthur_updatekey_info *info
|
|||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
#ifndef NOT_YET
|
||||
if (auth_current_ef) {
|
||||
const sc_acl_entry_t *entry = sc_file_get_acl_entry(auth_current_ef,
|
||||
SC_AC_OP_UPDATE);
|
||||
|
||||
if (entry && entry->method == SC_AC_PRO)
|
||||
if (card->sm_level < (entry->key_ref | 0x60))
|
||||
card->sm_level = entry->key_ref | 0x60;
|
||||
}
|
||||
|
||||
if (card->sm_level)
|
||||
return auth_sm_update_rsa(card, info);
|
||||
#endif
|
||||
if (info->data_len != sizeof(void *) || !info->data)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
|
@ -1798,9 +1677,6 @@ auth_reset_retry_counter(sc_card_t *card, unsigned int type,
|
|||
size_t len;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
struct sc_pin_cmd_pin pin_info, puk_info;
|
||||
#ifndef NOT_YET
|
||||
const sc_acl_entry_t *entry;
|
||||
#endif
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_CHANGE, &pin_ref);
|
||||
|
@ -1816,15 +1692,6 @@ auth_reset_retry_counter(sc_card_t *card, unsigned int type,
|
|||
if (puklen > puk_info.pad_length || pinlen > pin_info.pad_length)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
#ifndef NOT_YET
|
||||
entry = sc_file_get_acl_entry(auth_current_df, SC_AC_OP_PIN_RESET);
|
||||
if (entry && entry->method == SC_AC_PRO) {
|
||||
card->sm_level = entry->key_ref | 0x60;
|
||||
rv = auth_sm_reset_pin(card, type, ref, pin, pinlen);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
#endif
|
||||
memset(sbuf, puk_info.pad_char, puk_info.pad_length);
|
||||
memcpy(sbuf, puk, puklen);
|
||||
len = puk_info.pad_length;
|
||||
|
@ -2043,32 +1910,12 @@ auth_read_binary(sc_card_t *card, unsigned int offset,
|
|||
u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
int rv;
|
||||
#ifndef NOT_YET
|
||||
const sc_acl_entry_t *entry;
|
||||
#endif
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx,"offset %i; size %i; flags 0x%lX\n", offset, count, flags);
|
||||
sc_debug(card->ctx,"last selected : magic %X; ef %X\n",
|
||||
auth_current_ef->magic, auth_current_ef->ef_structure);
|
||||
|
||||
/* _auth_print_acls(card, auth_current_ef); */
|
||||
|
||||
#ifndef NOT_YET
|
||||
entry = sc_file_get_acl_entry(auth_current_ef, SC_AC_OP_READ);
|
||||
sc_debug(card->ctx,"entry %p; %i\n", entry, SC_AC_OP_READ);
|
||||
if (entry && entry->method == SC_AC_PRO) {
|
||||
sc_debug(card->ctx, "needs SM level 0x%X\n", entry->key_ref >> 3);
|
||||
|
||||
card->sm_level = entry->key_ref | 0x60;
|
||||
rv = auth_sm_read_binary(card,
|
||||
auth_current_ef->path.value, auth_current_ef->path.len,
|
||||
offset, buf, count);
|
||||
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
#endif
|
||||
if (offset & ~0x7FFF)
|
||||
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid file offset");
|
||||
|
||||
|
@ -2205,259 +2052,6 @@ auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
|||
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
||||
}
|
||||
|
||||
#ifndef NOT_YET
|
||||
static int
|
||||
auth_sm_init (struct sc_card *card, struct sc_sm_info *sm_info, int cmd,
|
||||
unsigned char *id, size_t id_len,
|
||||
unsigned char *resp, size_t *resp_len)
|
||||
{
|
||||
int rv;
|
||||
struct sc_apdu apdu;
|
||||
unsigned char host_challenge[8];
|
||||
int host_challenge_len = sizeof(host_challenge);
|
||||
|
||||
sc_debug(card->ctx, "called; command 0x%X\n", cmd);
|
||||
if (!card || !sm_info || !id || !id_len || !resp || !resp_len)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
if (!card->sm.funcs.initialize || !card->sm.funcs.get_apdus)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
if ((card->sm_level & 0xE0) != 0x60)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
if (id_len > sizeof(sm_info->id))
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
if (*resp_len < 28)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
memset(sm_info, 0, sizeof(*sm_info));
|
||||
|
||||
sm_info->index = 0;
|
||||
sm_info->version = 1;
|
||||
sm_info->cmd = cmd;
|
||||
sm_info->level = (card->sm_level & 0x18) >> 3;
|
||||
|
||||
sm_info->id_len = id_len;
|
||||
memcpy(sm_info->id, id, id_len);
|
||||
|
||||
sm_info->status = 0;
|
||||
|
||||
sm_info->serialnr = card->serialnr;
|
||||
|
||||
rv = card->sm.funcs.initialize(card->ctx, sm_info,
|
||||
host_challenge, &host_challenge_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: INITIALIZE failed");
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x50,
|
||||
sm_info->version, sm_info->index);
|
||||
apdu.cla = 0x80;
|
||||
apdu.resp = resp;
|
||||
apdu.resplen = *resp_len;
|
||||
apdu.lc = 8;
|
||||
apdu.le = 12;
|
||||
apdu.data = host_challenge;
|
||||
apdu.datalen = 8;
|
||||
|
||||
rv=sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, rv, "transmit APDU failed");
|
||||
|
||||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, rv, "Card returned error");
|
||||
|
||||
if (apdu.resplen != 28)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
||||
|
||||
*resp_len = 28;
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
auth_sm_execute (struct sc_card *card, struct sc_sm_info *sm_info,
|
||||
unsigned char *data, int data_len,
|
||||
unsigned char *out, size_t len)
|
||||
{
|
||||
#define AUTH_SM_APDUS_MAX 6
|
||||
int rv, ii;
|
||||
struct sc_apdu apdus[AUTH_SM_APDUS_MAX];
|
||||
unsigned char sbufs[AUTH_SM_APDUS_MAX][SC_MAX_APDU_BUFFER_SIZE];
|
||||
unsigned char rbufs[AUTH_SM_APDUS_MAX][SC_MAX_APDU_BUFFER_SIZE];
|
||||
int nn_apdus = AUTH_SM_APDUS_MAX;
|
||||
|
||||
if (!card->sm.funcs.initialize || !card->sm.funcs.get_apdus)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
memset(&apdus, 0, sizeof(apdus));
|
||||
memset(&sbufs, 0, sizeof(sbufs));
|
||||
memset(&rbufs, 0, sizeof(rbufs));
|
||||
for (ii=0; ii<nn_apdus; ii++) {
|
||||
apdus[ii].data = &sbufs[ii][0];
|
||||
apdus[ii].resp = &rbufs[ii][0];
|
||||
apdus[ii].resplen = SC_MAX_APDU_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
rv = card->sm.funcs.get_apdus(card->ctx, sm_info,
|
||||
data, data_len, apdus, &nn_apdus);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: GET_APDUS failed");
|
||||
|
||||
sc_debug(card->ctx, "GET_APDUS: rv %i; nn cmds %i\n",
|
||||
rv, nn_apdus);
|
||||
|
||||
for (ii=0; ii < nn_apdus; ii++) {
|
||||
rv = sc_transmit_apdu(card, &apdus[ii]);
|
||||
if (rv < 0)
|
||||
break;
|
||||
|
||||
rv = sc_check_sw(card, apdus[ii].sw1, apdus[ii].sw2);
|
||||
if (rv < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv) {
|
||||
sm_info->status = rv;
|
||||
auth_sm_release (card, sm_info, NULL, 0);
|
||||
}
|
||||
|
||||
if (out && len > 0 && !rv) {
|
||||
if (len > apdus[nn_apdus-1].resplen)
|
||||
len = apdus[nn_apdus-1].resplen;
|
||||
|
||||
memcpy(out, apdus[nn_apdus-1].resp, len);
|
||||
SC_FUNC_RETURN(card->ctx, 1, len);
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
auth_sm_release (struct sc_card *card, struct sc_sm_info *sm_info,
|
||||
unsigned char *data, int data_len)
|
||||
{
|
||||
int rv;
|
||||
struct sc_apdu apdu;
|
||||
|
||||
card->sm_level = 0;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2E, 0x00, 0x60);
|
||||
apdu.cla = 0x80;
|
||||
apdu.lc = 0x0;
|
||||
apdu.le = 0x0;
|
||||
apdu.resplen = 0;
|
||||
apdu.resp = NULL;
|
||||
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
|
||||
|
||||
if (sm_info && card->sm.funcs.finalize) {
|
||||
rv = card->sm.funcs.finalize(card->ctx, sm_info, data, data_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: finalize failed");
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
auth_sm_update_rsa (struct sc_card *card,
|
||||
struct sc_cardctl_oberthur_updatekey_info *update_info)
|
||||
{
|
||||
int rv, rvv;
|
||||
struct sc_sm_info sm_info;
|
||||
unsigned char init_data[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int init_data_len = sizeof(init_data);
|
||||
|
||||
sc_debug(card->ctx, "called; SM Level 0x%X\n", card->sm_level);
|
||||
if (!update_info || !card->sm_level)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* If rsa defined, we impose Mosilla style ID. */
|
||||
if (update_info->data && (update_info->data_len == sizeof(void *))) {
|
||||
struct sc_pkcs15_prkey_rsa *rsa = (struct sc_pkcs15_prkey_rsa *)update_info->data;
|
||||
|
||||
SHA1(rsa->modulus.data, rsa->modulus.len, update_info->id);
|
||||
update_info->id_len = SHA_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
rv = auth_sm_init (card, &sm_info, SC_SM_CMD_TYPE_UPDATE_RSA,
|
||||
update_info->id, update_info->id_len, init_data, &init_data_len);
|
||||
if (!rv)
|
||||
rv = auth_sm_execute (card, &sm_info,
|
||||
init_data, init_data_len, NULL, 0);
|
||||
|
||||
rvv = auth_sm_release (card, &sm_info, NULL, 0);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, (rv ? rv : rvv));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
auth_sm_reset_pin (struct sc_card *card, int type, int ref,
|
||||
const u8 *data, size_t len)
|
||||
{
|
||||
int rv;
|
||||
struct sc_sm_info sm_info;
|
||||
unsigned char init_data[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int init_data_len = sizeof(init_data);
|
||||
|
||||
sc_debug(card->ctx, "called; PIN ref 0x%X; data length %i\n", ref, len);
|
||||
|
||||
rv = auth_sm_init (card, &sm_info, SC_SM_CMD_TYPE_RESET_PIN,
|
||||
card->serialnr.value, card->serialnr.len, init_data, &init_data_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: init failed");
|
||||
|
||||
sm_info.p1 = ref;
|
||||
sm_info.data = data;
|
||||
sm_info.data_len = len;
|
||||
|
||||
rv = auth_sm_execute (card, &sm_info, init_data, init_data_len, NULL, 0);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: execute failed");
|
||||
|
||||
rv = auth_sm_release (card, &sm_info, NULL, 0);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: release failed");
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
auth_sm_read_binary (struct sc_card *card, unsigned char *id, size_t id_len,
|
||||
size_t offs, unsigned char *out, size_t len)
|
||||
{
|
||||
int rv;
|
||||
struct sc_sm_info sm_info;
|
||||
unsigned char init_data[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int init_data_len = sizeof(init_data);
|
||||
|
||||
sc_debug(card->ctx, "called; offs %i; len %i\n", offs, len);
|
||||
|
||||
if (len > 0xF0) {
|
||||
sc_debug(card->ctx, "Not yet: reading length cannot be more then 240 bytes.");
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
rv = auth_sm_init (card, &sm_info, SC_SM_CMD_TYPE_READ_BINARY,
|
||||
id, id_len, init_data, &init_data_len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: init failed");
|
||||
|
||||
sm_info.p1 = offs;
|
||||
sm_info.p2 = len;
|
||||
|
||||
rv = auth_sm_execute (card, &sm_info, init_data, init_data_len, out, len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: execute failed");
|
||||
|
||||
len = rv;
|
||||
|
||||
rv = auth_sm_release (card, &sm_info, out, len);
|
||||
SC_TEST_RET(card->ctx, rv, "SM: release failed");
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sc_card_driver *
|
||||
sc_get_driver(void)
|
||||
{
|
||||
|
|
|
@ -184,6 +184,7 @@ static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card)
|
|||
unlock_card(fw_data);
|
||||
|
||||
rc = sc_pkcs15_unbind(fw_data->p15_card);
|
||||
free(fw_data);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
}
|
||||
|
||||
|
@ -262,6 +263,24 @@ __pkcs15_release_object(struct pkcs15_any_object *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
__pkcs15_delete_object(struct pkcs15_fw_data *fw_data, struct pkcs15_any_object *obj)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (fw_data->num_objects == 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
for (i = 0; i < fw_data->num_objects; ++i)
|
||||
if (fw_data->objects[i] == obj) {
|
||||
fw_data->objects[i] = fw_data->objects[--fw_data->num_objects];
|
||||
if (__pkcs15_release_object(obj) > 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int public_key_created(struct pkcs15_fw_data *fw_data,
|
||||
const unsigned int num_objects,
|
||||
const u8 *id,
|
||||
|
@ -917,6 +936,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
static CK_RV pkcs15_release_token(struct sc_pkcs11_card *p11card, void *fw_token)
|
||||
{
|
||||
unlock_card((struct pkcs15_fw_data *) p11card->fw_data);
|
||||
free(fw_token);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
@ -2679,6 +2699,14 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
|||
|
||||
/* Delete object in smartcard */
|
||||
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
||||
/* FIXME: PIN revalidation missing, following belongs libopensc */
|
||||
if (rv >= 0) {
|
||||
/* pool_find_and_delete is called, therefore correct refcont
|
||||
* Oppose to pkcs15_add_object */
|
||||
--((struct pkcs15_any_object*)object)->refcount;
|
||||
/* Delete object in pkcs15 */
|
||||
rv = __pkcs15_delete_object(fw_data, (struct pkcs15_any_object*)object);
|
||||
}
|
||||
|
||||
sc_pkcs15init_unbind(profile);
|
||||
sc_unlock(card->card);
|
||||
|
|
|
@ -390,6 +390,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
pad = RSA_NO_PADDING;
|
||||
break;
|
||||
default:
|
||||
EVP_PKEY_free(pkey);
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
|
||||
|
@ -400,7 +401,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
|
||||
rsa_out = (unsigned char *) malloc(RSA_size(rsa));
|
||||
if (rsa_out == NULL) {
|
||||
free(rsa);
|
||||
RSA_free(rsa);
|
||||
return CKR_DEVICE_MEMORY;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* Oberthur specific operation for PKCS #15 initialization
|
||||
*
|
||||
* Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
* Copyright (C) 2003 Idealx <www.idealx.org>
|
||||
* Viktor Tarasov <vtarasov@idealx.com>
|
||||
* Copyright (C) 2009 Viktor Tarasov <viktor.tarasov@opentrust.com>,
|
||||
* OpenTrust <www.opentrust.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -46,17 +46,6 @@
|
|||
|
||||
#define COSM_TITLE "OberthurAWP"
|
||||
|
||||
#define COSM_TLV_TAG 0x00
|
||||
#define COSM_LIST_TAG 0xFF
|
||||
#define COSM_TAG_CONTAINER 0x0000
|
||||
#define COSM_TAG_CERT 0x0001
|
||||
#define COSM_TAG_PRVKEY_RSA 0x04B1
|
||||
#define COSM_TAG_PUBKEY_RSA 0x0349
|
||||
#define COSM_TAG_DES 0x0679
|
||||
#define COSM_TAG_DATA 0x0001
|
||||
#define COSM_IMPORTED 0x0000
|
||||
#define COSM_GENERATED 0x0004
|
||||
|
||||
#define TLV_TYPE_V 0
|
||||
#define TLV_TYPE_LV 1
|
||||
#define TLV_TYPE_TLV 2
|
||||
|
@ -64,15 +53,9 @@
|
|||
/* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */
|
||||
#define SC_DEVICE_SPECIFIC_TYPE 0x1000
|
||||
|
||||
#define COSM_PUBLIC_LIST (SC_DEVICE_SPECIFIC_TYPE | 0x02)
|
||||
#define COSM_PRIVATE_LIST (SC_DEVICE_SPECIFIC_TYPE | 0x03)
|
||||
#define COSM_CONTAINER_LIST (SC_DEVICE_SPECIFIC_TYPE | 0x04)
|
||||
#define COSM_TOKENINFO (SC_DEVICE_SPECIFIC_TYPE | 0x05)
|
||||
|
||||
#define COSM_TYPE_PRKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PRKEY_RSA)
|
||||
#define COSM_TYPE_PUBKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PUBKEY_RSA)
|
||||
|
||||
#define NOT_YET 1
|
||||
|
||||
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
|
||||
struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len,
|
||||
|
@ -142,7 +125,7 @@ static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
|
|||
}
|
||||
|
||||
sc_debug(card->ctx, "erase file ddf %04X\n",df->id);
|
||||
rv=cosm_delete_file(card, profile, df);
|
||||
rv = cosm_delete_file(card, profile, df);
|
||||
|
||||
if (sc_profile_get_file(profile, "private-DF", &dir) >= 0) {
|
||||
sc_debug(card->ctx, "erase file dir %04X\n",dir->id);
|
||||
|
@ -170,8 +153,8 @@ static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
|
|||
done:
|
||||
sc_keycache_forget_key(NULL, -1, -1);
|
||||
|
||||
if (rv==SC_ERROR_FILE_NOT_FOUND)
|
||||
rv=0;
|
||||
if (rv == SC_ERROR_FILE_NOT_FOUND)
|
||||
rv = 0;
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
@ -604,14 +587,6 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
|
|||
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
|
||||
memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len);
|
||||
|
||||
#ifndef NOT_YET
|
||||
rv = sc_pkcs15_encode_pubkey(card->ctx, pubkey, &info->value.value, &info->value.len);
|
||||
sc_debug(card->ctx, "rv %i\n",rv);
|
||||
if (rv) {
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
info->key_reference = 1;
|
||||
info->path = prkf->path;
|
||||
|
||||
|
@ -640,14 +615,11 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card,
|
|||
struct sc_pkcs15_prkey *key, unsigned int idx,
|
||||
struct sc_pkcs15_prkey_info *info)
|
||||
{
|
||||
sc_file_t *prvfile = NULL;
|
||||
struct sc_file *prvfile = NULL;
|
||||
struct sc_pkcs15_prkey_rsa *rsa = NULL;
|
||||
#ifndef NOT_YET
|
||||
sc_pkcs15_pubkey_t pubkey;
|
||||
#endif
|
||||
int rv;
|
||||
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
||||
struct sc_cardctl_oberthur_updatekey_info update_info;
|
||||
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx, "index %i; id %s\n", idx, sc_pkcs15_print_id(&info->id));
|
||||
|
@ -671,7 +643,7 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card,
|
|||
|
||||
rv = sc_select_file(card, &prvfile->path, NULL);
|
||||
sc_debug(card->ctx, "rv %i", rv);
|
||||
if (rv==SC_ERROR_FILE_NOT_FOUND) {
|
||||
if (rv == SC_ERROR_FILE_NOT_FOUND) {
|
||||
sc_debug(card->ctx, "Before create file");
|
||||
rv = sc_pkcs15init_create_file(profile, card, prvfile);
|
||||
}
|
||||
|
@ -704,573 +676,12 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card,
|
|||
info->path = prvfile->path;
|
||||
info->modulus_length = rsa->modulus.len << 3;
|
||||
|
||||
#ifndef NOT_YET
|
||||
/* extract public key */
|
||||
pubkey.algorithm = SC_ALGORITHM_RSA;
|
||||
pubkey.u.rsa.modulus.len = rsa->modulus.len;
|
||||
pubkey.u.rsa.modulus.data = (u8 *) malloc(rsa->modulus.len);
|
||||
if (!pubkey.u.rsa.modulus.data)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_MEMORY_FAILURE);
|
||||
|
||||
pubkey.u.rsa.exponent.len = rsa->exponent.len;
|
||||
pubkey.u.rsa.exponent.data = (u8 *) malloc(rsa->exponent.len);
|
||||
if (!pubkey.u.rsa.exponent.data)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_MEMORY_FAILURE);
|
||||
|
||||
memcpy(pubkey.u.rsa.exponent.data, rsa->exponent.data, rsa->exponent.len);
|
||||
memcpy(pubkey.u.rsa.modulus.data, rsa->modulus.data, rsa->modulus.len);
|
||||
|
||||
rv = sc_pkcs15_encode_pubkey(card->ctx, &pubkey, &info->value.value, &info->value.len);
|
||||
SC_TEST_RET(card->ctx, rv, "Update RSA: encode public key failed");
|
||||
|
||||
free(pubkey.u.rsa.modulus.data);
|
||||
free(pubkey.u.rsa.exponent.data);
|
||||
#endif
|
||||
|
||||
if (prvfile)
|
||||
sc_file_free(prvfile);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
#ifdef COSM_EXTENDED
|
||||
static int
|
||||
cosm_delete_object (struct sc_profile *profile, struct sc_card *card,
|
||||
unsigned int type, const void *data, const sc_path_t *path)
|
||||
{
|
||||
struct sc_file *file = sc_file_new();
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||
file->id = path->value[path->len-2] * 0x100 + path->value[path->len-1];
|
||||
memcpy(&file->path, path, sizeof(file->path));
|
||||
|
||||
rv = cosm_delete_file(card, profile, file);
|
||||
|
||||
sc_file_free(file);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
static int
|
||||
cosm_path_to_index (struct sc_pkcs15_object *object, int *index, sc_pkcs15_der_t *out_der)
|
||||
{
|
||||
struct sc_path path;
|
||||
sc_pkcs15_der_t der;
|
||||
|
||||
if (!object || !index || !out_der)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
||||
case SC_PKCS15_TYPE_PRKEY:
|
||||
path = ((struct sc_pkcs15_prkey_info *)object->data)->path;
|
||||
der = ((struct sc_pkcs15_prkey_info *)object->data)->value;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY:
|
||||
path = ((struct sc_pkcs15_pubkey_info *)object->data)->path;
|
||||
der = ((struct sc_pkcs15_pubkey_info *)object->data)->value;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT:
|
||||
path = ((struct sc_pkcs15_cert_info *)object->data)->path;
|
||||
der = ((struct sc_pkcs15_cert_info *)object->data)->value;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_DATA_OBJECT:
|
||||
path = ((struct sc_pkcs15_data_info *)object->data)->path;
|
||||
der = ((struct sc_pkcs15_data_info *)object->data)->value;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
}
|
||||
|
||||
out_der->value = der.value;
|
||||
out_der->len = der.len;
|
||||
*index = path.value[path.len-1] & 0xFF;
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_set_id (struct sc_context *ctx, struct sc_pkcs15_object *object,
|
||||
unsigned char *in, int in_len)
|
||||
{
|
||||
struct sc_pkcs15_id *id;
|
||||
|
||||
SC_FUNC_CALLED(ctx, 1);
|
||||
sc_debug(ctx, "in_len %i, type 0x%X\n", in_len, object->type);
|
||||
if (!object || !in || !in_len || in_len > SC_PKCS15_MAX_ID_SIZE)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
||||
case SC_PKCS15_TYPE_PRKEY:
|
||||
id = &((struct sc_pkcs15_prkey_info *)object->data)->id;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY:
|
||||
id = &((struct sc_pkcs15_pubkey_info *)object->data)->id;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT:
|
||||
id = &((struct sc_pkcs15_cert_info *)object->data)->id;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_DATA_OBJECT:
|
||||
id = &((struct sc_pkcs15_data_info *)object->data)->id;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
}
|
||||
|
||||
memcpy(id->value, in, in_len);
|
||||
id->len = in_len;
|
||||
|
||||
sc_debug(ctx, "id %s\n", sc_pkcs15_print_id(id));
|
||||
SC_FUNC_RETURN(ctx, 1, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_update_df_delete_object(struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile,
|
||||
struct sc_pkcs15_object *object)
|
||||
{
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
||||
|
||||
rv = cosm_ext_remove_data (profile, p15card->card, object);
|
||||
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_update_df_new_object(struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile,
|
||||
struct sc_pkcs15_object *object)
|
||||
{
|
||||
struct sc_pkcs15_pubkey pubkey;
|
||||
struct sc_pkcs15_der der;
|
||||
struct sc_pkcs15_tokeninfo tokeninfo;
|
||||
struct cosm_key_info ikey;
|
||||
struct cosm_cert_info icert;
|
||||
struct cosm_data_info idata;
|
||||
struct sc_card *card = p15card->card;
|
||||
struct sc_file *info_file=NULL, *obj_file=NULL;
|
||||
int index, prvkey_id, rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (!p15card || !profile)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
else if (!object)
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
||||
|
||||
if (object->type == SC_PKCS15_TYPE_AUTH_PIN) {
|
||||
sc_debug(card->ctx, "P15 Label %s\n", p15card->label);
|
||||
p15card->label = realloc(p15card->label,
|
||||
strlen(p15card->label) + strlen(labelPinDomain) + 5);
|
||||
if (!p15card->label)
|
||||
return SC_ERROR_MEMORY_FAILURE;
|
||||
|
||||
strcat(p15card->label, " (");
|
||||
strcat(p15card->label, labelPinDomain);
|
||||
strcat(p15card->label, ")");
|
||||
|
||||
memset(&tokeninfo, 0, sizeof(tokeninfo));
|
||||
|
||||
tokeninfo.label = p15card->label;
|
||||
|
||||
sc_debug(card->ctx, "Before cosm_update_tokeninfo()");
|
||||
rv = cosm_update_tokeninfo(p15card, profile, &tokeninfo);
|
||||
return rv;
|
||||
}
|
||||
|
||||
sc_debug(p15card->card->ctx, "object %s; type 0x%X; der length %i; data %p\n",
|
||||
object->label, object->type, object->der.len, object->data);
|
||||
rv = cosm_path_to_index (object, &index, &der);
|
||||
if (rv) {
|
||||
sc_debug(p15card->card->ctx, "return %i", rv);
|
||||
return rv;
|
||||
}
|
||||
sc_debug(p15card->card->ctx, "der.value %p; der.len %i\n", der.value, der.len);
|
||||
|
||||
rv = cosm_oberthur_new_file(profile, card, object->type,
|
||||
index, &info_file, &obj_file);
|
||||
if (rv) {
|
||||
sc_debug(p15card->card->ctx, "return %i", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
switch (object->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_RSA:
|
||||
case SC_PKCS15_TYPE_PUBKEY_RSA:
|
||||
pubkey.algorithm = SC_ALGORITHM_RSA;
|
||||
|
||||
rv = sc_pkcs15_decode_pubkey(card->ctx, &pubkey, der.value, der.len);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_encode_key_info(card, &pubkey.u.rsa, object->type, &ikey);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_set_key_info(profile, card, info_file, &ikey, NULL);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_update_object_list(profile, card, object->type, index);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Look for the container that contains corresponding certificate to
|
||||
* include the key object.
|
||||
* Create a new container, if there is no corresponding certificate.
|
||||
*/
|
||||
rv = cosm_update_container(profile, card, object->type, &ikey.id, index, NULL);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_set_id (card->ctx, object, ikey.id.value, ikey.id.len);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
cosm_free_key_info(&ikey);
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT_X509:
|
||||
rv = cosm_encode_cert_info(card, &der, &icert);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_set_certificate_info(profile, card, info_file, &icert);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_update_object_list(profile, card, object->type, index);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Look for the container that contains corresponding key to
|
||||
* include this certificate object.
|
||||
* Create a new container, if there is no corresponding key.
|
||||
*/
|
||||
rv = cosm_update_container(profile, card, object->type, &icert.key.id, index,
|
||||
&prvkey_id);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
sc_debug(card->ctx, "rv %i; friend 0x%X\n", rv, prvkey_id);
|
||||
if (prvkey_id)
|
||||
rv = cosm_update_key_info(profile, card, prvkey_id, &icert);
|
||||
|
||||
rv = cosm_set_id (card->ctx, object, icert.key.id.value, icert.key.id.len);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
cosm_free_cert_info(&icert);
|
||||
break;
|
||||
case SC_PKCS15_TYPE_DATA_OBJECT:
|
||||
rv = cosm_encode_data_info(card, &der,
|
||||
(sc_pkcs15_data_info_t *)object->data, &idata);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_set_data_info(profile, card, info_file, &idata);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
rv = cosm_update_object_list(profile, card, object->type, index);
|
||||
sc_debug(card->ctx, "rv %i\n", rv);
|
||||
if (rv)
|
||||
break;
|
||||
|
||||
cosm_free_data_info(&idata);
|
||||
break;
|
||||
default:
|
||||
sc_debug(card->ctx, "Unsupported type %i\n", object->type);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
sc_debug(card->ctx, "rv %i\n",rv);
|
||||
|
||||
if (rv > 0)
|
||||
rv = 0;
|
||||
|
||||
if (info_file)
|
||||
sc_file_free(info_file);
|
||||
if (obj_file)
|
||||
sc_file_free(obj_file);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_update_df(struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile,
|
||||
int op,
|
||||
struct sc_pkcs15_object *object)
|
||||
{
|
||||
switch(op) {
|
||||
case SC_AC_OP_ERASE:
|
||||
return cosm_update_df_delete_object(p15card, profile, object);
|
||||
case SC_AC_OP_CREATE:
|
||||
return cosm_update_df_new_object(p15card, profile, object);
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_update_dir (struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile, struct sc_app_info *info)
|
||||
{
|
||||
sc_debug(p15card->card->ctx, "return 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cosm_update_tokeninfo (struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile, struct sc_pkcs15_tokeninfo *info)
|
||||
{
|
||||
int rv, sz;
|
||||
char *buffer = NULL;
|
||||
struct sc_file *file = NULL;
|
||||
|
||||
if (!p15card || !profile || !info)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
||||
|
||||
if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) {
|
||||
sc_debug(p15card->card->ctx,
|
||||
"Inconsistent profile: cannot find "COSM_TITLE"-token-info");
|
||||
return SC_ERROR_INCONSISTENT_PROFILE;
|
||||
}
|
||||
|
||||
buffer = malloc(file->size + 1);
|
||||
if (!buffer)
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, SC_ERROR_MEMORY_FAILURE);
|
||||
|
||||
if (info->label) {
|
||||
strncpy(buffer, info->label, file->size);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, file->size, "IDX-SCM");
|
||||
}
|
||||
|
||||
sc_debug(p15card->card->ctx, "buffer: '%s'", info->label);
|
||||
*(buffer + file->size) = '\0';
|
||||
|
||||
sc_debug(p15card->card->ctx, "buffer '%s'\n", buffer);
|
||||
sz = strlen(buffer);
|
||||
if (sz < file->size)
|
||||
memset(buffer + sz, ' ', file->size - sz);
|
||||
|
||||
memcpy(buffer + file->size - 4, "\0\0\x4\xD", 4);
|
||||
rv = sc_pkcs15init_update_file(profile, p15card->card, file, buffer, file->size);
|
||||
|
||||
free(buffer);
|
||||
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
int cosm_write_info (struct sc_card *card,
|
||||
struct sc_profile *profile, struct sc_pkcs15_object *object)
|
||||
{
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cosm_change_label(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
|
||||
struct sc_pkcs15_object *object,
|
||||
void *value, int len)
|
||||
{
|
||||
struct sc_card *card = p15card->card;
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx, "len %i\n", len);
|
||||
if (len >= SC_PKCS15_MAX_LABEL_SIZE)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
memcpy(object->label, value, len);
|
||||
object->label[len] = '\0';
|
||||
#if 0
|
||||
/* TODO */
|
||||
#else
|
||||
rv = 0;
|
||||
#endif
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cosm_change_id(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
|
||||
struct sc_pkcs15_object *object, struct sc_pkcs15_id *in_id)
|
||||
{
|
||||
struct sc_card *card = p15card->card;
|
||||
struct sc_pkcs15_id *id;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
if (!object || !in_id)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
||||
case SC_PKCS15_TYPE_PRKEY:
|
||||
id = &(((sc_pkcs15_prkey_info_t *) object->data)->id);
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY:
|
||||
id = &(((sc_pkcs15_pubkey_info_t *) object->data)->id);
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT:
|
||||
id = &(((sc_pkcs15_cert_info_t *) object->data)->id);
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (id->len != in_id->len || memcmp(id->value, in_id->value, id->len)) {
|
||||
sc_debug(card->ctx, "obj.id %s; in.id %s\n",
|
||||
sc_pkcs15_print_id(id), sc_pkcs15_print_id(in_id));
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cosm_change_attrib(struct sc_pkcs15_card *p15card,
|
||||
struct sc_profile *profile, struct sc_pkcs15_object *object,
|
||||
int new_attrib_type, void *new_value, int new_len)
|
||||
{
|
||||
struct sc_card *card = p15card->card;
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
sc_debug(card->ctx, "attribute type 0x%X; len %i\n", new_attrib_type, new_len);
|
||||
if (!p15card || !object || !new_value || new_len < 1)
|
||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||
|
||||
switch(new_attrib_type) {
|
||||
case P15_ATTR_TYPE_LABEL:
|
||||
rv = cosm_change_label(p15card, profile, object, new_value, new_len);
|
||||
break;
|
||||
case P15_ATTR_TYPE_ID:
|
||||
if (new_len != sizeof(struct sc_pkcs15_id))
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
rv = cosm_change_id(p15card, profile, object, (struct sc_pkcs15_id *)new_value);
|
||||
break;
|
||||
default:
|
||||
rv = SC_ERROR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 1, rv);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cosm_select_id (struct sc_pkcs15_card *p15card, int type,
|
||||
sc_pkcs15_id_t *id, void *data)
|
||||
{
|
||||
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
||||
#ifdef ENABLE_OPENSSL
|
||||
if (!data || !id)
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
if (type == SC_PKCS15_TYPE_PRKEY) {
|
||||
struct sc_pkcs15_prkey *key = (struct sc_pkcs15_prkey *)data;
|
||||
if (key->algorithm == SC_ALGORITHM_RSA) {
|
||||
struct sc_pkcs15_prkey_rsa *rsa = &key->u.rsa;
|
||||
|
||||
SHA1(rsa->modulus.data, rsa->modulus.len, id->value);
|
||||
id->len = SHA_DIGEST_LENGTH;
|
||||
sc_debug(p15card->card->ctx, "private key ID %s\n", sc_pkcs15_print_id(id));
|
||||
}
|
||||
}
|
||||
else if (type == SC_PKCS15_TYPE_CERT) {
|
||||
struct sc_pkcs15_der *der = (struct sc_pkcs15_der *)data;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
X509 *x = NULL;
|
||||
BIO *mem = NULL;
|
||||
BIGNUM *bn = NULL;
|
||||
unsigned char *buff = NULL;
|
||||
int rv, bn_size;
|
||||
|
||||
rv = SC_ERROR_INTERNAL;
|
||||
id->len = 0;
|
||||
do {
|
||||
mem = BIO_new_mem_buf(der->value, der->len);
|
||||
if (!mem)
|
||||
break;
|
||||
x = d2i_X509_bio(mem, NULL);
|
||||
if (!x)
|
||||
break;
|
||||
pkey=X509_get_pubkey(x);
|
||||
if (!pkey || pkey->type != EVP_PKEY_RSA)
|
||||
break;
|
||||
bn = pkey->pkey.rsa->n;
|
||||
bn_size = BN_num_bytes(pkey->pkey.rsa->n);
|
||||
|
||||
buff = OPENSSL_malloc(bn_size);
|
||||
if (!buff)
|
||||
break;
|
||||
if (BN_bn2bin(bn, buff) != bn_size)
|
||||
break;
|
||||
if (!SHA1(buff, bn_size, id->value))
|
||||
break;
|
||||
id->len = SHA_DIGEST_LENGTH;
|
||||
|
||||
sc_debug(p15card->card->ctx, "cert ID %s\n", sc_pkcs15_print_id(id));
|
||||
rv = SC_SUCCESS;
|
||||
} while (0);
|
||||
|
||||
if (x)
|
||||
X509_free(x);
|
||||
if (mem)
|
||||
BIO_free(mem);
|
||||
if (buff)
|
||||
OPENSSL_free(buff);
|
||||
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, rv);
|
||||
}
|
||||
else if (type == SC_PKCS15_TYPE_PUBKEY) {
|
||||
struct sc_pkcs15_pubkey *key = (struct sc_pkcs15_pubkey *)data;
|
||||
|
||||
if (key->algorithm == SC_ALGORITHM_RSA) {
|
||||
struct sc_pkcs15_pubkey_rsa *rsa = &key->u.rsa;
|
||||
|
||||
SHA1(rsa->modulus.data, rsa->modulus.len, id->value);
|
||||
id->len = SHA_DIGEST_LENGTH;
|
||||
sc_debug(p15card->card->ctx, "public key ID %s\n", sc_pkcs15_print_id(id));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SC_FUNC_RETURN(p15card->card->ctx, 1, 0);
|
||||
}
|
||||
#endif /* COSM_EXTENDED */
|
||||
|
||||
static struct sc_pkcs15init_operations
|
||||
sc_pkcs15init_oberthur_operations = {
|
||||
|
@ -1292,18 +703,6 @@ sc_pkcs15init_oberthur_operations = {
|
|||
cosm_new_key,
|
||||
cosm_new_file,
|
||||
cosm_old_generate_key,
|
||||
|
||||
#ifdef COSM_EXTENDED
|
||||
cosm_delete_object, /* delete_object */
|
||||
NULL, /* ext_store_data */
|
||||
NULL, /* ext_remove_data */
|
||||
cosm_update_df, /* ext_update_df */
|
||||
cosm_update_dir, /* ext_update_dir */
|
||||
cosm_update_tokeninfo, /* ext_update_tokeninfo */
|
||||
cosm_write_info, /* ext_write_info */
|
||||
cosm_change_attrib, /* ext_pkcs15init_change_attrib */
|
||||
cosm_select_id, /* ext_select_id */
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue