2004-06-16 20:59:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Oberthur specific operation for PKCS #15 initialization
|
|
|
|
|
*
|
2007-01-02 10:06:02 +00:00
|
|
|
|
* Copyright (C) 2002 Juha Yrj<EFBFBD>l<EFBFBD> <juha.yrjola@iki.fi>
|
2009-11-05 18:27:56 +00:00
|
|
|
|
* Copyright (C) 2009 Viktor Tarasov <viktor.tarasov@opentrust.com>,
|
|
|
|
|
* OpenTrust <www.opentrust.com>
|
2004-06-16 20:59:59 +00:00
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <ctype.h>
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
|
#ifdef ENABLE_OPENSSL
|
2007-01-02 10:06:02 +00:00
|
|
|
|
#include <openssl/sha.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
#include <opensc/opensc.h>
|
|
|
|
|
#include <opensc/cardctl.h>
|
|
|
|
|
#include <opensc/log.h>
|
|
|
|
|
#include "pkcs15-init.h"
|
|
|
|
|
#include "profile.h"
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#define COSM_TITLE "OberthurAWP"
|
|
|
|
|
|
|
|
|
|
#define TLV_TYPE_V 0
|
|
|
|
|
#define TLV_TYPE_LV 1
|
|
|
|
|
#define TLV_TYPE_TLV 2
|
|
|
|
|
|
2004-12-15 10:56:45 +00:00
|
|
|
|
/* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */
|
2004-06-16 20:59:59 +00:00
|
|
|
|
#define SC_DEVICE_SPECIFIC_TYPE 0x1000
|
|
|
|
|
|
|
|
|
|
#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)
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
|
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len,
|
|
|
|
|
const u8 *puk, size_t puk_len);
|
|
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
|
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
|
|
|
|
|
sc_file_t *df);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
|
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
|
|
|
|
|
sc_file_t *df)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2005-03-09 00:04:44 +00:00
|
|
|
|
sc_path_t path;
|
|
|
|
|
sc_file_t *parent;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
int rv = 0;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
sc_debug(card->ctx, "id %04X\n", df->id);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
if (df->type==SC_FILE_TYPE_DF) {
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_DELETE);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannot authenticate SC_AC_OP_DELETE");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Select the parent DF */
|
|
|
|
|
path = df->path;
|
|
|
|
|
path.len -= 2;
|
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &path, &parent);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannnot select parent");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE);
|
|
|
|
|
sc_file_free(parent);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannnot authenticate SC_AC_OP_DELETE");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
memset(&path, 0, sizeof(path));
|
|
|
|
|
path.type = SC_PATH_TYPE_FILE_ID;
|
|
|
|
|
path.value[0] = df->id >> 8;
|
|
|
|
|
path.value[1] = df->id & 0xFF;
|
|
|
|
|
path.len = 2;
|
|
|
|
|
|
|
|
|
|
rv = sc_delete_file(card, &path);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Erase the card
|
|
|
|
|
*/
|
2005-03-09 00:04:44 +00:00
|
|
|
|
static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2005-03-09 00:04:44 +00:00
|
|
|
|
sc_file_t *df = profile->df_info->file, *dir;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
int rv;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
/* Delete EF(DIR). This may not be very nice
|
|
|
|
|
* against other applications that use this file, but
|
|
|
|
|
* extremely useful for testing :)
|
|
|
|
|
* Note we need to delete if before the DF because we create
|
|
|
|
|
* it *after* the DF.
|
|
|
|
|
* */
|
|
|
|
|
if (sc_profile_get_file(profile, "DIR", &dir) >= 0) {
|
|
|
|
|
sc_debug(card->ctx, "erase file dir %04X\n",dir->id);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = cosm_delete_file(card, profile, dir);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(dir);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_debug(card->ctx, "erase file ddf %04X\n",df->id);
|
2009-11-05 18:27:56 +00:00
|
|
|
|
rv = cosm_delete_file(card, profile, df);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
if (sc_profile_get_file(profile, "private-DF", &dir) >= 0) {
|
|
|
|
|
sc_debug(card->ctx, "erase file dir %04X\n",dir->id);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = cosm_delete_file(card, profile, dir);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(dir);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sc_profile_get_file(profile, "public-DF", &dir) >= 0) {
|
|
|
|
|
sc_debug(card->ctx, "erase file dir %04X\n",dir->id);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = cosm_delete_file(card, profile, dir);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(dir);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_profile_get_file(profile, COSM_TITLE"-AppDF", &dir);
|
|
|
|
|
if (!rv) {
|
|
|
|
|
sc_debug(card->ctx, "delete %s; r %i\n", COSM_TITLE"-AppDF", rv);
|
|
|
|
|
rv = cosm_delete_file(card, profile, dir);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(dir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
sc_keycache_forget_key(NULL, -1, -1);
|
|
|
|
|
|
2009-11-05 18:27:56 +00:00
|
|
|
|
if (rv == SC_ERROR_FILE_NOT_FOUND)
|
|
|
|
|
rv = 0;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize the Application DF
|
|
|
|
|
*/
|
|
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
|
cosm_init_app(struct sc_profile *profile, sc_card_t *card,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pinfo,
|
|
|
|
|
const u8 *pin, size_t pin_len,
|
|
|
|
|
const u8 *puk, size_t puk_len)
|
|
|
|
|
{
|
2007-01-02 10:06:02 +00:00
|
|
|
|
int rv;
|
2005-08-09 07:53:59 +00:00
|
|
|
|
size_t ii;
|
2005-03-09 00:04:44 +00:00
|
|
|
|
sc_file_t *file = NULL;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
static const char *create_dfs[] = {
|
|
|
|
|
COSM_TITLE"-AppDF",
|
2005-08-09 07:53:59 +00:00
|
|
|
|
"private-DF",
|
|
|
|
|
"public-DF",
|
2007-01-02 10:06:02 +00:00
|
|
|
|
COSM_TITLE"-token-info",
|
|
|
|
|
COSM_TITLE"-puk-file",
|
|
|
|
|
COSM_TITLE"-container-list",
|
|
|
|
|
COSM_TITLE"-public-list",
|
|
|
|
|
COSM_TITLE"-private-list",
|
|
|
|
|
"PKCS15-AppDF",
|
2005-08-09 07:53:59 +00:00
|
|
|
|
"PKCS15-ODF",
|
|
|
|
|
"PKCS15-AODF",
|
|
|
|
|
"PKCS15-PrKDF",
|
|
|
|
|
"PKCS15-PuKDF",
|
|
|
|
|
"PKCS15-CDF",
|
2007-01-02 10:06:02 +00:00
|
|
|
|
"PKCS15-DODF",
|
|
|
|
|
NULL
|
2005-08-09 07:53:59 +00:00
|
|
|
|
};
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "pin_len %i; puk_len %i\n", pin_len, puk_len);
|
|
|
|
|
|
|
|
|
|
/* Oberthur AWP file system is expected.*/
|
|
|
|
|
/* Create private objects DF */
|
2007-01-02 10:06:02 +00:00
|
|
|
|
for (ii = 0; create_dfs[ii]; ii++) {
|
2005-08-09 07:53:59 +00:00
|
|
|
|
if (sc_profile_get_file(profile, create_dfs[ii], &file)) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Inconsistent profile: cannot find %s", create_dfs[ii]);
|
2005-08-09 07:53:59 +00:00
|
|
|
|
return SC_ERROR_INCONSISTENT_PROFILE;
|
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, file);
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n", rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(file);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (rv && rv!=SC_ERROR_FILE_ALREADY_EXISTS)
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "sc_pkcs15init_create_file() failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
|
static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *card,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pinfo,
|
|
|
|
|
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len )
|
|
|
|
|
{
|
|
|
|
|
int rv;
|
|
|
|
|
int puk_buff_len = 0;
|
|
|
|
|
unsigned char *puk_buff = NULL;
|
|
|
|
|
sc_pkcs15_pin_info_t profile_pin;
|
|
|
|
|
sc_pkcs15_pin_info_t profile_puk;
|
|
|
|
|
struct sc_cardctl_oberthur_createpin_info args;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "pin lens %i/%i\n", pin_len, puk_len);
|
|
|
|
|
if (!pin || pin_len>0x40)
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
if (puk && !puk_len)
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &pinfo->path, NULL);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannot select file");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin);
|
|
|
|
|
if (profile_pin.max_length > 0x100)
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCONSISTENT_PROFILE);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
if (puk) {
|
|
|
|
|
int ii, jj;
|
2004-12-22 09:48:27 +00:00
|
|
|
|
const unsigned char *ptr = puk;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2004-12-15 13:53:36 +00:00
|
|
|
|
puk_buff = (unsigned char *) malloc(0x100);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
if (!puk_buff)
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_MEMORY_FAILURE);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_puk);
|
2005-12-05 21:59:04 +00:00
|
|
|
|
if (profile_puk.max_length > 0x100) {
|
|
|
|
|
free(puk_buff);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INCONSISTENT_PROFILE;
|
2005-12-05 21:59:04 +00:00
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
memset(puk_buff, profile_puk.pad_char, 0x100);
|
2004-12-22 09:48:27 +00:00
|
|
|
|
for (ii=0; ii<8 && (size_t)(ptr-puk) < puk_len && (*ptr); ii++) {
|
2004-06-16 20:59:59 +00:00
|
|
|
|
jj = 0;
|
|
|
|
|
while (isalnum(*ptr) && jj<16) {
|
|
|
|
|
*(puk_buff + ii*0x10 + jj++) = *ptr;
|
|
|
|
|
++ptr;
|
|
|
|
|
}
|
|
|
|
|
while(!isalnum(*ptr) && (*ptr))
|
|
|
|
|
++ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
puk_buff_len = ii*0x10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_debug(card->ctx, "pinfo->reference %i; tries %i\n",
|
|
|
|
|
pinfo->reference, profile_pin.tries_left);
|
|
|
|
|
|
2004-12-22 09:48:27 +00:00
|
|
|
|
sc_debug(card->ctx, "sc_card_ctl %s\n","SC_CARDCTL_OBERTHUR_CREATE_PIN");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
args.type = SC_AC_CHV;
|
|
|
|
|
args.ref = pinfo->reference;
|
2004-12-22 09:48:27 +00:00
|
|
|
|
args.pin = pin;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
args.pin_len = pin_len;
|
|
|
|
|
args.pin_tries = profile_pin.tries_left;
|
|
|
|
|
args.puk = puk_buff;
|
|
|
|
|
args.puk_len = puk_buff_len;
|
|
|
|
|
args.puk_tries = profile_puk.tries_left;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
if (puk_buff)
|
|
|
|
|
free(puk_buff);
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update PIN
|
|
|
|
|
*/
|
2005-03-09 00:04:44 +00:00
|
|
|
|
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pinfo, const u8 *pin, size_t pin_len,
|
|
|
|
|
const u8 *puk, size_t puk_len )
|
|
|
|
|
{
|
|
|
|
|
int rv;
|
|
|
|
|
int tries_left = -1;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags);
|
|
|
|
|
|
|
|
|
|
if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx,"Pin references should be only in the profile"
|
2004-06-16 20:59:59 +00:00
|
|
|
|
"and in the card-oberthur.\n");
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (pinfo->reference != 4)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INVALID_PIN_REFERENCE;
|
|
|
|
|
|
|
|
|
|
rv = sc_change_reference_data(card, SC_AC_CHV, pinfo->reference, puk, puk_len,
|
|
|
|
|
pin, pin_len, &tries_left);
|
|
|
|
|
sc_debug(card->ctx, "return value %X; tries left %i\n", rv, tries_left);
|
|
|
|
|
if (tries_left != -1)
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Failed to change reference data for soPin: rv %X", rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rv = cosm_create_reference_data(profile, card, pinfo,
|
|
|
|
|
pin, pin_len, puk, puk_len);
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
|
|
|
|
|
sc_pkcs15_pin_info_t *pin_info)
|
|
|
|
|
{
|
|
|
|
|
sc_file_t *pinfile;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "ref %i; flags %X\n", pin_info->reference, pin_info->flags);
|
|
|
|
|
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INCONSISTENT_PROFILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pin_info->path = pinfile->path;
|
|
|
|
|
sc_file_free(pinfile);
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (!pin_info->reference) {
|
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
|
|
|
|
|
pin_info->reference = 4;
|
|
|
|
|
else
|
|
|
|
|
pin_info->reference = 1;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
if (pin_info->reference < 0 || pin_info->reference > 4)
|
|
|
|
|
return SC_ERROR_INVALID_PIN_REFERENCE;
|
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Store a PIN
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
|
|
|
|
|
sc_pkcs15_object_t *pin_obj,
|
|
|
|
|
const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len)
|
|
|
|
|
{
|
|
|
|
|
sc_pkcs15_pin_info_t *pinfo = (sc_pkcs15_pin_info_t *) pin_obj->data;
|
|
|
|
|
sc_file_t *pinfile;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
int rv = 0, type;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags);
|
|
|
|
|
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INCONSISTENT_PROFILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pinfo->path = pinfile->path;
|
|
|
|
|
sc_file_free(pinfile);
|
|
|
|
|
|
|
|
|
|
if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
|
|
|
|
|
type = SC_PKCS15INIT_SO_PIN;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (pinfo->reference != 4)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
type = SC_PKCS15INIT_USER_PIN;
|
|
|
|
|
|
2007-07-04 14:25:39 +00:00
|
|
|
|
if (pinfo->reference !=1 && pinfo->reference != 2)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INVALID_PIN_REFERENCE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pin && pin_len) {
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sc_debug(card->ctx, "User PIN not updated");
|
|
|
|
|
}
|
2007-01-02 10:06:02 +00:00
|
|
|
|
sc_debug(card->ctx, "return %i\n", rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
sc_keycache_set_pin_name(&pinfo->path, pinfo->reference, type);
|
|
|
|
|
pinfo->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Allocate a file
|
|
|
|
|
*/
|
|
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
|
cosm_new_file(struct sc_profile *profile, sc_card_t *card,
|
|
|
|
|
unsigned int type, unsigned int num, sc_file_t **out)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
|
|
|
|
struct sc_file *file;
|
2004-12-22 09:48:27 +00:00
|
|
|
|
const char *_template = NULL, *desc = NULL;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
unsigned int structure = 0xFFFFFFFF;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "type %X; num %i\n",type, num);
|
|
|
|
|
while (1) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
|
case COSM_TYPE_PRKEY_RSA:
|
|
|
|
|
desc = "RSA private key";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-private-key";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
structure = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT;
|
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_PUBKEY_RSA:
|
|
|
|
|
case COSM_TYPE_PUBKEY_RSA:
|
|
|
|
|
desc = "RSA public key";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-public-key";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
|
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_PUBKEY_DSA:
|
|
|
|
|
desc = "DSA public key";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-public-key";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY:
|
|
|
|
|
desc = "extractable private key";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-extractable-key";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_CERT:
|
|
|
|
|
desc = "certificate";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-certificate";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case SC_PKCS15_TYPE_DATA_OBJECT:
|
|
|
|
|
desc = "data object";
|
2004-12-15 13:53:36 +00:00
|
|
|
|
_template = "template-public-data";
|
2004-06-16 20:59:59 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2004-12-15 13:53:36 +00:00
|
|
|
|
if (_template)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
break;
|
|
|
|
|
/* If this is a specific type such as
|
|
|
|
|
* SC_PKCS15_TYPE_CERT_FOOBAR, fall back to
|
|
|
|
|
* the generic class (SC_PKCS15_TYPE_CERT)
|
|
|
|
|
*/
|
|
|
|
|
if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "File type %X not supported by card driver",
|
2004-06-16 20:59:59 +00:00
|
|
|
|
type);
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
type &= SC_PKCS15_TYPE_CLASS_MASK;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-15 13:53:36 +00:00
|
|
|
|
sc_debug(card->ctx, "template %s; num %i\n",_template, num);
|
|
|
|
|
if (sc_profile_get_file(profile, _template, &file) < 0) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Profile doesn't define %s template '%s'\n",
|
2004-12-15 13:53:36 +00:00
|
|
|
|
desc, _template);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file->id |= (num & 0xFF);
|
|
|
|
|
file->path.value[file->path.len-1] |= (num & 0xFF);
|
|
|
|
|
if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
|
|
|
|
|
file->ef_structure = structure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sc_debug(card->ctx, "file size %i; ef type %i/%i; id %04X\n",file->size,
|
|
|
|
|
file->type, file->ef_structure, file->id);
|
|
|
|
|
*out = file;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* RSA key generation
|
|
|
|
|
*/
|
|
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
|
cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
|
2004-12-22 09:48:27 +00:00
|
|
|
|
unsigned int idx, unsigned int keybits,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_pkcs15_pubkey_t *pubkey,
|
|
|
|
|
struct sc_pkcs15_prkey_info *info)
|
|
|
|
|
{
|
|
|
|
|
struct sc_cardctl_oberthur_genkey_info args;
|
|
|
|
|
struct sc_file *prkf = NULL, *tmpf = NULL;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
struct sc_path path;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
int rv;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
sc_debug(card->ctx, "index %i; nn %i\n", idx, keybits);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
if (keybits < 512 || keybits > 2048 || (keybits%0x20)) {
|
2009-09-14 08:46:59 +00:00
|
|
|
|
sc_debug(card->ctx, "Unsupported key size %u\n", keybits);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get private key file from profile. */
|
2004-12-22 09:48:27 +00:00
|
|
|
|
if ((rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
&prkf)) < 0)
|
|
|
|
|
goto failed;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
sc_debug(card->ctx, "prv ef type 0x%X\n",prkf->ef_structure);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
prkf->size = keybits;
|
|
|
|
|
|
|
|
|
|
/* Access condition of private object DF. */
|
|
|
|
|
path = prkf->path;
|
|
|
|
|
path.len -= 2;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &path, &tmpf);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Generate RSA: no private object DF");
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO);
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n",rv);
|
|
|
|
|
if (rv < 0)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto failed;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE);
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n",rv);
|
|
|
|
|
if (rv < 0)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto failed;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
sc_file_free(tmpf);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
/* In the private key DF create the temporary public RSA file. */
|
|
|
|
|
sc_debug(card->ctx, "ready to create public key\n");
|
|
|
|
|
sc_file_dup(&tmpf, prkf);
|
2005-08-19 17:56:56 +00:00
|
|
|
|
if (tmpf == NULL) {
|
|
|
|
|
rv = SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
goto failed;
|
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
tmpf->type = SC_FILE_TYPE_INTERNAL_EF;
|
|
|
|
|
tmpf->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
|
|
|
|
|
tmpf->id = 0x1012;
|
|
|
|
|
tmpf->path.value[tmpf->path.len - 2] = 0x10;
|
|
|
|
|
tmpf->path.value[tmpf->path.len - 1] = 0x12;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, prkf);
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n",rv);
|
|
|
|
|
if (rv) {
|
|
|
|
|
sc_debug(card->ctx, "prkf create file failed\n");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto failed;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, tmpf);
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n",rv);
|
|
|
|
|
if (rv) {
|
|
|
|
|
sc_debug(card->ctx, "pubf create failed\n");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto failed;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
args.id_prv = prkf->id;
|
|
|
|
|
args.id_pub = tmpf->id;
|
|
|
|
|
args.exponent = 0x10001;
|
|
|
|
|
args.key_bits = keybits;
|
|
|
|
|
args.pubkey_len = keybits/8;
|
2004-12-15 13:53:36 +00:00
|
|
|
|
args.pubkey = (unsigned char *) malloc(keybits/8);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
if (!args.pubkey) {
|
|
|
|
|
rv = SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
goto failed;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_GENERATE_KEY, &args);
|
|
|
|
|
if (rv < 0)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
|
|
/* extract public key */
|
|
|
|
|
pubkey->algorithm = SC_ALGORITHM_RSA;
|
|
|
|
|
pubkey->u.rsa.modulus.len = keybits / 8;
|
|
|
|
|
pubkey->u.rsa.modulus.data = (u8 *) malloc(keybits / 8);
|
|
|
|
|
if (!pubkey->u.rsa.modulus.data) {
|
|
|
|
|
rv = SC_ERROR_MEMORY_FAILURE;
|
|
|
|
|
goto failed;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-15 10:56:45 +00:00
|
|
|
|
/* FIXME and if the exponent length is not 3? */
|
2004-06-16 20:59:59 +00:00
|
|
|
|
pubkey->u.rsa.exponent.len = 3;
|
|
|
|
|
pubkey->u.rsa.exponent.data = (u8 *) malloc(3);
|
|
|
|
|
if (!pubkey->u.rsa.exponent.data) {
|
|
|
|
|
rv = SC_ERROR_MEMORY_FAILURE;
|
|
|
|
|
goto failed;
|
|
|
|
|
}
|
|
|
|
|
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
|
|
|
|
|
memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len);
|
|
|
|
|
|
|
|
|
|
info->key_reference = 1;
|
|
|
|
|
info->path = prkf->path;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (rv) {
|
|
|
|
|
sc_debug(card->ctx, "rv %i\n", rv);
|
|
|
|
|
goto failed;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_debug(card->ctx, "delete temporary public key\n");
|
|
|
|
|
if ((rv = cosm_delete_file(card, profile, tmpf)))
|
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
|
|
failed:
|
|
|
|
|
if (tmpf) sc_file_free(tmpf);
|
|
|
|
|
if (prkf) sc_file_free(prkf);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Store a private key
|
|
|
|
|
*/
|
|
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
|
cosm_new_key(struct sc_profile *profile, sc_card_t *card,
|
2004-12-22 09:48:27 +00:00
|
|
|
|
struct sc_pkcs15_prkey *key, unsigned int idx,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_prkey_info *info)
|
|
|
|
|
{
|
2009-11-05 18:27:56 +00:00
|
|
|
|
struct sc_file *prvfile = NULL;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_prkey_rsa *rsa = NULL;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
struct sc_cardctl_oberthur_updatekey_info update_info;
|
2009-11-05 18:27:56 +00:00
|
|
|
|
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
|
|
|
|
int rv;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
sc_debug(card->ctx, "index %i; id %s\n", idx, sc_pkcs15_print_id(&info->id));
|
|
|
|
|
if (key->algorithm != SC_ALGORITHM_RSA)
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
/* Create and populate the private part. */
|
2004-12-22 09:48:27 +00:00
|
|
|
|
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
&prvfile);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Update RSA: cosm_new_file failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2006-01-11 23:41:17 +00:00
|
|
|
|
rv = sc_path_print(pbuf, sizeof(pbuf), &prvfile->path);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
sc_debug(card->ctx, "rv %i\n", rv);
|
2006-01-11 23:41:17 +00:00
|
|
|
|
if (rv != SC_SUCCESS)
|
|
|
|
|
pbuf[0] = '\0';
|
|
|
|
|
sc_debug(card->ctx, " prvfile->id %i; path=%s\n", prvfile->id, pbuf);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
rsa = &key->u.rsa;
|
|
|
|
|
|
|
|
|
|
prvfile->size = rsa->modulus.len << 3;
|
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &prvfile->path, NULL);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
sc_debug(card->ctx, "rv %i", rv);
|
2009-11-05 18:27:56 +00:00
|
|
|
|
if (rv == SC_ERROR_FILE_NOT_FOUND) {
|
2007-01-02 10:06:02 +00:00
|
|
|
|
sc_debug(card->ctx, "Before create file");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, prvfile);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
}
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Update RSA: select/create key file failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation");
|
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
|
#ifdef ENABLE_OPENSSL
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (!info->id.len) {
|
|
|
|
|
SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value);
|
|
|
|
|
info->id.len = SHA_DIGEST_LENGTH;
|
|
|
|
|
sc_debug(card->ctx, "ID: %s\n", sc_pkcs15_print_id(&info->id));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (info->id.len > sizeof(update_info.id))
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
memset(&update_info, 0, sizeof(update_info));
|
|
|
|
|
update_info.type = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT;
|
|
|
|
|
update_info.data = (void *)rsa;
|
|
|
|
|
update_info.data_len = sizeof(void *);
|
|
|
|
|
update_info.id_len = info->id.len;
|
|
|
|
|
memcpy(update_info.id, info->id.value, update_info.id_len);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_UPDATE_KEY, &update_info);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Update KEY failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
info->path = prvfile->path;
|
|
|
|
|
info->modulus_length = rsa->modulus.len << 3;
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (prvfile)
|
|
|
|
|
sc_file_free(prvfile);
|
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct sc_pkcs15init_operations
|
|
|
|
|
sc_pkcs15init_oberthur_operations = {
|
2005-08-14 22:33:43 +00:00
|
|
|
|
cosm_erase_card,
|
2007-01-02 10:06:02 +00:00
|
|
|
|
NULL, /* init_card */
|
|
|
|
|
NULL, /* create_dir */
|
|
|
|
|
NULL, /* create_domain */
|
2005-08-14 22:33:43 +00:00
|
|
|
|
cosm_select_pin_reference,
|
|
|
|
|
cosm_create_pin,
|
2007-01-02 10:06:02 +00:00
|
|
|
|
NULL, /* select_key_reference */
|
|
|
|
|
NULL, /* create_key */
|
|
|
|
|
NULL, /* store_key */
|
|
|
|
|
NULL, /* generate_key */
|
|
|
|
|
NULL,
|
|
|
|
|
NULL, /* encode private/public key */
|
|
|
|
|
NULL, /* finalize_card */
|
|
|
|
|
cosm_init_app, /* old */
|
|
|
|
|
NULL, /* new_pin */
|
2005-08-14 22:33:43 +00:00
|
|
|
|
cosm_new_key,
|
|
|
|
|
cosm_new_file,
|
2005-08-22 09:20:13 +00:00
|
|
|
|
cosm_old_generate_key,
|
2007-01-02 10:06:02 +00:00
|
|
|
|
NULL
|
2005-08-10 21:31:18 +00:00
|
|
|
|
};
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
struct sc_pkcs15init_operations *
|
|
|
|
|
sc_pkcs15init_get_oberthur_ops(void)
|
|
|
|
|
{
|
2005-08-10 21:31:18 +00:00
|
|
|
|
return &sc_pkcs15init_oberthur_operations;
|
2004-12-15 14:47:31 +00:00
|
|
|
|
}
|