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:
martin 2009-11-05 18:27:56 +00:00
parent 30ab50600b
commit 450e1fc5ae
5 changed files with 49 additions and 1027 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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
};