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
|
2009-11-13 09:45:21 +00:00
|
|
|
|
#define TLV_TYPE_LV 1
|
2004-06-16 20:59:59 +00:00
|
|
|
|
#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)
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
#define COSM_TOKEN_FLAG_PRN_GENERATION 0x01
|
|
|
|
|
#define COSM_TOKEN_FLAG_LOGIN_REQUIRED 0x04
|
|
|
|
|
#define COSM_TOKEN_FLAG_USER_PIN_INITIALIZED 0x08
|
|
|
|
|
#define COSM_TOKEN_FLAG_TOKEN_INITIALIZED 0x0400
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
static int cosm_create_reference_data(struct sc_profile *, struct sc_card *,
|
|
|
|
|
struct sc_pkcs15_pin_info *,
|
|
|
|
|
const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len);
|
|
|
|
|
static int cosm_update_pin(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_pin_info *info, const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len);
|
|
|
|
|
|
|
|
|
|
int cosm_delete_file(struct sc_card *card, struct sc_profile *profile,
|
|
|
|
|
struct sc_file *df);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
cosm_write_tokeninfo (struct sc_card *card, struct sc_profile *profile,
|
|
|
|
|
char *label, unsigned p15_flags)
|
|
|
|
|
{
|
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
|
unsigned mask = SC_PKCS15_CARD_FLAG_PRN_GENERATION
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED;
|
|
|
|
|
int rv, sz, flags = 0;
|
|
|
|
|
char *buffer = NULL;
|
|
|
|
|
|
|
|
|
|
if (!card || !profile)
|
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
sc_debug(card->ctx, "cosm_write_tokeninfo() label '%s'; flags 0x%X\n", label, p15_flags);
|
|
|
|
|
if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file))
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find "COSM_TITLE"-token-info");
|
|
|
|
|
|
|
|
|
|
if (file->size < 16)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Unsufficient size of the "COSM_TITLE"-token-info file");
|
|
|
|
|
|
|
|
|
|
buffer = calloc(1, file->size);
|
|
|
|
|
if (!buffer)
|
2010-01-24 12:38:34 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "Allocation error in cosm_write_tokeninfo()");
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
|
|
|
|
if (label)
|
|
|
|
|
strncpy(buffer, label, file->size - 4);
|
|
|
|
|
else if (profile->p15_data && profile->p15_data->label)
|
|
|
|
|
snprintf(buffer, file->size - 4, profile->p15_data->label);
|
|
|
|
|
else if (profile->p15_spec && profile->p15_spec->label)
|
|
|
|
|
snprintf(buffer, file->size - 4, profile->p15_spec->label);
|
|
|
|
|
else
|
|
|
|
|
snprintf(buffer, file->size - 4, "OpenSC-Token");
|
|
|
|
|
|
|
|
|
|
sz = strlen(buffer);
|
|
|
|
|
if (sz < file->size - 4)
|
|
|
|
|
memset(buffer + sz, ' ', file->size - sz);
|
|
|
|
|
|
|
|
|
|
if (p15_flags & SC_PKCS15_CARD_FLAG_PRN_GENERATION)
|
|
|
|
|
flags |= COSM_TOKEN_FLAG_PRN_GENERATION;
|
|
|
|
|
|
|
|
|
|
if (p15_flags & SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED)
|
|
|
|
|
flags |= COSM_TOKEN_FLAG_LOGIN_REQUIRED;
|
|
|
|
|
|
|
|
|
|
if (p15_flags & SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED)
|
|
|
|
|
flags |= COSM_TOKEN_FLAG_USER_PIN_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
if (p15_flags & SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED)
|
|
|
|
|
flags |= COSM_TOKEN_FLAG_TOKEN_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
sc_debug(card->ctx, "cosm_write_tokeninfo() token label '%s'; oberthur flags 0x%X\n", buffer, flags);
|
|
|
|
|
|
|
|
|
|
memset(buffer + file->size - 4, 0, 4);
|
|
|
|
|
*(buffer + file->size - 1) = flags & 0xFF;
|
|
|
|
|
*(buffer + file->size - 2) = (flags >> 8) & 0xFF;
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_update_file(profile, card, file, buffer, file->size);
|
|
|
|
|
if (rv > 0)
|
|
|
|
|
rv = 0;
|
|
|
|
|
|
|
|
|
|
if (profile->p15_data)
|
|
|
|
|
profile->p15_data->flags = (profile->p15_data->flags & ~mask) | p15_flags;
|
|
|
|
|
|
|
|
|
|
if (profile->p15_spec)
|
|
|
|
|
profile->p15_spec->flags = (profile->p15_spec->flags & ~mask) | p15_flags;
|
|
|
|
|
|
|
|
|
|
free(buffer);
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
cosm_delete_file(struct sc_card *card, struct sc_profile *profile,
|
|
|
|
|
struct sc_file *df)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2009-11-13 09:45:21 +00:00
|
|
|
|
struct sc_path path;
|
|
|
|
|
struct sc_file *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
|
|
|
|
|
*/
|
2009-11-13 09:45:21 +00:00
|
|
|
|
static int
|
|
|
|
|
cosm_erase_card(struct sc_profile *profile, struct sc_card *card)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2009-11-13 09:45:21 +00:00
|
|
|
|
struct sc_file *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);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
sc_free_apps(card);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
static int
|
|
|
|
|
cosm_create_dir(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_file *df)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2010-01-27 18:07:14 +00:00
|
|
|
|
struct sc_context *ctx = card->ctx;
|
2009-11-13 09:45:21 +00:00
|
|
|
|
struct sc_file *file = NULL;
|
2005-08-09 07:53:59 +00:00
|
|
|
|
size_t ii;
|
2009-11-13 09:45:21 +00:00
|
|
|
|
int rv;
|
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",
|
2010-01-27 18:07:14 +00:00
|
|
|
|
#if 0
|
2007-01-02 10:06:02 +00:00
|
|
|
|
"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",
|
2010-01-27 18:07:14 +00:00
|
|
|
|
#endif
|
2007-01-02 10:06:02 +00:00
|
|
|
|
NULL
|
2005-08-09 07:53:59 +00:00
|
|
|
|
};
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
SC_FUNC_CALLED(ctx, 1);
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, df);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Failed to create DIR DF");
|
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
/* 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]);
|
2010-01-27 18:07:14 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Profile do not contains Oberthur AWP file");
|
2005-08-09 07:53:59 +00:00
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, file);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
sc_file_free(file);
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (rv != SC_ERROR_FILE_ALREADY_EXISTS)
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Failed to create Oberthur AWP file");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
rv = cosm_write_tokeninfo(card, profile, NULL,
|
|
|
|
|
SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED | SC_PKCS15_CARD_FLAG_PRN_GENERATION);
|
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
SC_FUNC_RETURN(ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
cosm_create_reference_data(struct sc_profile *profile, struct sc_card *card,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pinfo,
|
2009-11-13 09:45:21 +00:00
|
|
|
|
const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len )
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2009-11-13 09:45:21 +00:00
|
|
|
|
struct sc_pkcs15_pin_info profile_pin;
|
|
|
|
|
struct sc_pkcs15_pin_info profile_puk;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_cardctl_oberthur_createpin_info args;
|
2009-11-13 09:45:21 +00:00
|
|
|
|
unsigned char *puk_buff = NULL;
|
|
|
|
|
int rv, puk_buff_len = 0;
|
2010-01-27 18:07:14 +00:00
|
|
|
|
unsigned char oberthur_puk[16] = {
|
|
|
|
|
0x6F, 0x47, 0xD9, 0x88, 0x4B, 0x6F, 0x9D, 0xC5,
|
|
|
|
|
0x78, 0x33, 0x79, 0x8F, 0x5B, 0x7D, 0xE1, 0xA5
|
|
|
|
|
};
|
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 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
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin);
|
|
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_puk);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
memset(&args, 0, sizeof(args));
|
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;
|
2010-01-27 18:07:14 +00:00
|
|
|
|
|
|
|
|
|
if (!(pinfo->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) {
|
|
|
|
|
args.pin_tries = profile_pin.tries_left;
|
|
|
|
|
if (profile_puk.tries_left > 0) {
|
|
|
|
|
args.puk = oberthur_puk;
|
|
|
|
|
args.puk_len = sizeof(oberthur_puk);
|
|
|
|
|
args.puk_tries = 5;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
args.pin_tries = profile_puk.tries_left;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "'CREATE_PIN' card specific command failed");
|
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (!(pinfo->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) && (profile_puk.tries_left > 0)) {
|
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
|
|
|
|
|
|
if (sc_profile_get_file(profile, COSM_TITLE"-puk-file", &file))
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find PUKFILE");
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_update_file(profile, card, file, oberthur_puk, sizeof(oberthur_puk));
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Failed to update pukfile");
|
2010-01-27 18:07:14 +00:00
|
|
|
|
|
|
|
|
|
if (file)
|
|
|
|
|
sc_file_free(file);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Update PIN
|
|
|
|
|
*/
|
2009-11-13 09:45:21 +00:00
|
|
|
|
static int
|
|
|
|
|
cosm_update_pin(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_pin_info *pinfo, const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len )
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2009-11-13 09:45:21 +00:00
|
|
|
|
int rv, tries_left = -1;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_debug(card->ctx, "ref %i; flags 0x%X\n", pinfo->reference, pinfo->flags);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
|
2007-01-02 10:06:02 +00:00
|
|
|
|
if (pinfo->reference != 4)
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "cosm_update_pin() invalid SOPIN reference");
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_debug(card->ctx, "Update SOPIN ignored\n");
|
|
|
|
|
rv = SC_SUCCESS;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rv = cosm_create_reference_data(profile, card, pinfo,
|
|
|
|
|
pin, pin_len, puk, puk_len);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to change PIN");
|
|
|
|
|
|
|
|
|
|
rv = cosm_write_tokeninfo(card, profile, NULL,
|
|
|
|
|
SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_PRN_GENERATION
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED
|
|
|
|
|
| SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to update tokeninfo");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
static int
|
2009-11-13 09:45:21 +00:00
|
|
|
|
cosm_select_pin_reference(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_pin_info *pin_info)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2009-11-13 09:45:21 +00:00
|
|
|
|
struct sc_file *pinfile;
|
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", pin_info->reference, pin_info->flags);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_LOCAL)
|
|
|
|
|
pin_info->path = pinfile->path;
|
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
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)
|
2009-11-13 09:45:21 +00:00
|
|
|
|
pin_info->reference = 4;
|
2010-01-27 18:07:14 +00:00
|
|
|
|
else if (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)
|
|
|
|
|
pin_info->reference = 4;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
else
|
2009-11-13 09:45:21 +00:00
|
|
|
|
pin_info->reference = 1;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_LOCAL)
|
|
|
|
|
pin_info->reference |= 0x80;
|
|
|
|
|
}
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Store a PIN
|
|
|
|
|
*/
|
|
|
|
|
static int
|
2009-11-13 09:45:21 +00:00
|
|
|
|
cosm_create_pin(struct sc_profile *profile, struct sc_card *card, struct sc_file *df,
|
|
|
|
|
struct sc_pkcs15_object *pin_obj,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
const unsigned char *pin, size_t pin_len,
|
|
|
|
|
const unsigned char *puk, size_t puk_len)
|
|
|
|
|
{
|
2010-01-27 18:07:14 +00:00
|
|
|
|
struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *) pin_obj->data;
|
|
|
|
|
struct sc_file *pin_file;
|
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);
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_debug(card->ctx, "create '%s'; ref 0x%X; flags %X\n", pin_obj->label, pin_info->reference, pin_info->flags);
|
|
|
|
|
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pin_file) < 0)
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "\""COSM_TITLE"-AppDF\" not defined");
|
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_LOCAL)
|
|
|
|
|
pin_info->path = pin_file->path;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_file_free(pin_file);
|
|
|
|
|
|
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
|
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) {
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "SOPIN unblocking is not supported");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (pin_info->reference != 4)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid SOPIN reference");
|
|
|
|
|
type = SC_PKCS15INIT_SO_PIN;
|
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2010-01-27 18:07:14 +00:00
|
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) {
|
|
|
|
|
if (pin_info->reference != 0x84)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid User PUK reference");
|
|
|
|
|
type = SC_PKCS15INIT_USER_PUK;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (pin_info->reference != 0x81)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid User PIN reference");
|
|
|
|
|
type = SC_PKCS15INIT_USER_PIN;
|
|
|
|
|
}
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pin && pin_len) {
|
2010-01-27 18:07:14 +00:00
|
|
|
|
rv = cosm_update_pin(profile, card, pin_info, pin, pin_len, puk, puk_len);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Update PIN failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
2010-01-27 18:07:14 +00:00
|
|
|
|
sc_keycache_set_pin_name(&pin_info->path, pin_info->reference, type);
|
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
|
2009-11-13 09:45:21 +00:00
|
|
|
|
cosm_new_file(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
unsigned int type, unsigned int num, struct sc_file **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);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
sc_debug(card->ctx, "cosm_new_file() type %X; num %i\n",type, num);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
sc_debug(card->ctx, "cosm_new_file() template %s; num %i\n",_template, num);
|
2004-12-15 13:53:36 +00:00
|
|
|
|
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);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
2004-06-16 20:59:59 +00:00
|
|
|
|
}
|
2009-11-13 09:45:21 +00:00
|
|
|
|
|
2004-06-16 20:59:59 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
sc_debug(card->ctx, "cosm_new_file() file size %i; ef type %i/%i; id %04X\n",file->size,
|
2004-06-16 20:59:59 +00:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-01-25 16:42:22 +00:00
|
|
|
|
cosm_get_temporary_public_key_file(struct sc_card *card,
|
|
|
|
|
struct sc_file *prvkey_file, struct sc_file **pubkey_file)
|
|
|
|
|
{
|
|
|
|
|
struct sc_context *ctx = card->ctx;
|
|
|
|
|
const struct sc_acl_entry *entry = NULL;
|
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
if (!pubkey_file || !prvkey_file)
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
|
|
|
|
|
|
|
|
|
file = sc_file_new();
|
|
|
|
|
if (!file)
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
|
|
file->status = SC_FILE_STATUS_ACTIVATED;
|
|
|
|
|
file->type = SC_FILE_TYPE_INTERNAL_EF;
|
|
|
|
|
file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC;
|
|
|
|
|
file->id = 0x1012;
|
|
|
|
|
memcpy(&file->path, &prvkey_file->path, sizeof(file->path));
|
|
|
|
|
file->path.value[file->path.len - 2] = 0x10;
|
|
|
|
|
file->path.value[file->path.len - 1] = 0x12;
|
|
|
|
|
file->size = prvkey_file->size;
|
|
|
|
|
|
|
|
|
|
entry = sc_file_get_acl_entry(prvkey_file, SC_AC_OP_UPDATE);
|
|
|
|
|
rv = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, entry->method, entry->key_ref);
|
|
|
|
|
if (!rv)
|
|
|
|
|
rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_ENCRYPT, SC_AC_NONE, 0);
|
|
|
|
|
if (!rv)
|
|
|
|
|
rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_VERIFY_SIGNATURE, SC_AC_NONE, 0);
|
|
|
|
|
if (!rv)
|
|
|
|
|
rv = sc_file_add_acl_entry(file, SC_AC_OP_EXTERNAL_AUTHENTICATE, SC_AC_NONE, 0);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Failed to add ACL entry to the temporary public key file");
|
|
|
|
|
|
|
|
|
|
*pubkey_file = file;
|
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(card->ctx, 1, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
cosm_generate_key(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_object *object,
|
|
|
|
|
struct sc_pkcs15_pubkey *pubkey)
|
2004-06-16 20:59:59 +00:00
|
|
|
|
{
|
2010-01-25 16:42:22 +00:00
|
|
|
|
struct sc_context *ctx = card->ctx;
|
|
|
|
|
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
|
|
|
|
|
struct sc_file *file = NULL;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
struct sc_cardctl_oberthur_genkey_info args;
|
2010-01-25 16:42:22 +00:00
|
|
|
|
struct sc_file *prkf = NULL, *tmpf = NULL;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
struct sc_path path;
|
2010-01-25 16:42:22 +00:00
|
|
|
|
int rv = 0;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
|
|
|
|
|
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
|
|
|
|
|
SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: RSA only supported");
|
|
|
|
|
|
|
|
|
|
path = key_info->path;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
path.len -= 2;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
rv = sc_select_file(card, &path, &tmpf);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannot generate key: failed to select private object DF");
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannot generate key: 'CRYPTO' authentication failed");
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Cannot generate key: 'CREATE' authentication failed");
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
|
|
|
|
sc_file_free(tmpf);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &key_info->path, &prkf);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Failed to generate key: cannot select private key file");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
/* In the private key DF create the temporary public RSA file. */
|
2010-01-25 16:42:22 +00:00
|
|
|
|
rv = cosm_get_temporary_public_key_file(card, prkf, &tmpf);
|
|
|
|
|
SC_TEST_RET(card->ctx, rv, "Error while getting temporary public key file");
|
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, tmpf);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create temporary public key EF");
|
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;
|
2010-01-25 16:42:22 +00:00
|
|
|
|
args.key_bits = key_info->modulus_length;
|
|
|
|
|
args.pubkey_len = key_info->modulus_length / 8;
|
|
|
|
|
args.pubkey = (unsigned char *) malloc(key_info->modulus_length / 8);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
if (!args.pubkey)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2007-01-02 10:06:02 +00:00
|
|
|
|
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_GENERATE_KEY, &args);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
SC_TEST_RET(card->ctx, rv, "cosm_generate_key() CARDCTL_OBERTHUR_GENERATE_KEY failed");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
|
|
|
|
/* extract public key */
|
|
|
|
|
pubkey->algorithm = SC_ALGORITHM_RSA;
|
2010-01-25 16:42:22 +00:00
|
|
|
|
pubkey->u.rsa.modulus.len = key_info->modulus_length / 8;
|
|
|
|
|
pubkey->u.rsa.modulus.data = (unsigned char *) malloc(key_info->modulus_length / 8);
|
2009-11-13 09:45:21 +00:00
|
|
|
|
if (!pubkey->u.rsa.modulus.data)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
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;
|
2009-11-13 09:45:21 +00:00
|
|
|
|
pubkey->u.rsa.exponent.data = (unsigned char *) malloc(3);
|
|
|
|
|
if (!pubkey->u.rsa.exponent.data)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate exponent buf");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
|
|
|
|
|
memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len);
|
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
key_info->key_reference = 1;
|
|
|
|
|
key_info->path = prkf->path;
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2009-11-13 09:45:21 +00:00
|
|
|
|
sc_debug(card->ctx, "cosm_generate_key() now delete temporary public key\n");
|
|
|
|
|
rv = cosm_delete_file(card, profile, tmpf);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
sc_file_free(tmpf);
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-01-25 15:11:35 +00:00
|
|
|
|
/*
|
2010-01-25 16:42:22 +00:00
|
|
|
|
* Create private key file
|
2010-01-25 15:11:35 +00:00
|
|
|
|
*/
|
|
|
|
|
static int
|
2010-01-25 16:42:22 +00:00
|
|
|
|
cosm_create_key(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_object *object)
|
2010-01-25 15:11:35 +00:00
|
|
|
|
{
|
2010-01-25 16:42:22 +00:00
|
|
|
|
struct sc_context *ctx = card->ctx;
|
|
|
|
|
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
|
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
|
int rv = 0;
|
2010-01-25 15:30:33 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_FUNC_CALLED(ctx, 1);
|
|
|
|
|
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
|
|
|
|
|
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported");
|
2010-01-25 15:11:35 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
sc_debug(ctx, "create private key ID:%s\n", sc_pkcs15_print_id(&key_info->id));
|
|
|
|
|
/* Here, the path of private key file should be defined.
|
|
|
|
|
* Neverthelles, we need to instanciate private key to get the ACLs. */
|
|
|
|
|
rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Cannot create key: failed to allocate new key object");
|
2010-01-25 15:11:35 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
file->size = key_info->modulus_length;
|
|
|
|
|
memcpy(&file->path, &key_info->path, sizeof(file->path));
|
|
|
|
|
file->id = file->path.value[file->path.len - 2] * 0x100
|
|
|
|
|
+ file->path.value[file->path.len - 1];
|
2010-01-25 15:11:35 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
sc_debug(ctx, "Path of private key file to create %s\n", sc_print_path(&file->path));
|
2010-01-25 15:11:35 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
rv = sc_select_file(card, &file->path, NULL);
|
|
|
|
|
if (rv == 0) {
|
|
|
|
|
rv = cosm_delete_file(card, profile, file);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Failed to delete private key file");
|
2010-01-25 15:30:33 +00:00
|
|
|
|
}
|
2010-01-25 16:42:22 +00:00
|
|
|
|
else if (rv != SC_ERROR_FILE_NOT_FOUND) {
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Select private key file error");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = sc_pkcs15init_create_file(profile, card, file);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Failed to create private key file");
|
|
|
|
|
|
|
|
|
|
key_info->key_reference = file->path.value[file->path.len - 1];
|
|
|
|
|
|
|
|
|
|
sc_file_free(file);
|
|
|
|
|
|
|
|
|
|
SC_FUNC_RETURN(ctx, 1, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Store a private key
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
cosm_store_key(struct sc_profile *profile, struct sc_card *card,
|
|
|
|
|
struct sc_pkcs15_object *object,
|
|
|
|
|
struct sc_pkcs15_prkey *prkey)
|
|
|
|
|
{
|
|
|
|
|
struct sc_context *ctx = card->ctx;
|
|
|
|
|
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
|
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
|
struct sc_cardctl_oberthur_updatekey_info update_info;
|
|
|
|
|
int rv = 0;
|
|
|
|
|
|
|
|
|
|
SC_FUNC_CALLED(ctx, 1);
|
|
|
|
|
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA || prkey->algorithm != SC_ALGORITHM_RSA)
|
|
|
|
|
SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported");
|
|
|
|
|
|
|
|
|
|
sc_debug(ctx, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id),
|
|
|
|
|
sc_print_path(&key_info->path));
|
|
|
|
|
|
|
|
|
|
rv = sc_select_file(card, &key_info->path, &file);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "Cannot store key: select key file failed");
|
2010-01-25 15:30:33 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
rv = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_UPDATE);
|
|
|
|
|
SC_TEST_RET(ctx, rv, "No authorisation to store private key");
|
|
|
|
|
|
|
|
|
|
if (key_info->id.len > sizeof(update_info.id))
|
2007-01-02 10:06:02 +00:00
|
|
|
|
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;
|
2010-01-25 16:42:22 +00:00
|
|
|
|
update_info.data = (void *)&prkey->u.rsa;
|
2007-01-02 10:06:02 +00:00
|
|
|
|
update_info.data_len = sizeof(void *);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
update_info.id_len = key_info->id.len;
|
|
|
|
|
memcpy(update_info.id, key_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);
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_TEST_RET(ctx, rv, "Cannot update private key");
|
2004-06-16 20:59:59 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
if (file)
|
|
|
|
|
sc_file_free(file);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
|
2010-01-25 16:42:22 +00:00
|
|
|
|
SC_FUNC_RETURN(ctx, 1, rv);
|
2007-01-02 10:06:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct sc_pkcs15init_operations
|
|
|
|
|
sc_pkcs15init_oberthur_operations = {
|
2005-08-14 22:33:43 +00:00
|
|
|
|
cosm_erase_card,
|
2010-01-25 16:42:22 +00:00
|
|
|
|
NULL, /* init_card */
|
2010-01-27 18:07:14 +00:00
|
|
|
|
cosm_create_dir, /* create_dir */
|
2010-01-25 16:42:22 +00:00
|
|
|
|
NULL, /* create_domain */
|
2005-08-14 22:33:43 +00:00
|
|
|
|
cosm_select_pin_reference,
|
|
|
|
|
cosm_create_pin,
|
2010-01-25 16:42:22 +00:00
|
|
|
|
NULL, /* select_key_reference */
|
|
|
|
|
cosm_create_key, /* create_key */
|
|
|
|
|
cosm_store_key, /* store_key */
|
|
|
|
|
cosm_generate_key, /* generate_key */
|
2007-01-02 10:06:02 +00:00
|
|
|
|
NULL,
|
2010-01-25 16:42:22 +00:00
|
|
|
|
NULL, /* encode private/public key */
|
|
|
|
|
NULL, /* finalize_card */
|
2010-01-27 18:07:14 +00:00
|
|
|
|
/* Old API */
|
2010-01-28 12:14:48 +00:00
|
|
|
|
NULL, /* init_app */
|
2010-01-25 16:42:22 +00:00
|
|
|
|
NULL, /* new_pin */
|
|
|
|
|
NULL, /* cosm_new_key, */
|
|
|
|
|
NULL, /* cosm_new_file, */
|
|
|
|
|
NULL, /* 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
|
|
|
|
}
|