2002-04-02 13:26:42 +00:00
|
|
|
/*
|
|
|
|
* MioCOS specific operation for PKCS15 initialization
|
|
|
|
*
|
2006-12-19 21:34:00 +00:00
|
|
|
* Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
2002-04-02 13:26:42 +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
|
|
|
|
*/
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2002-04-02 13:26:42 +00:00
|
|
|
#include <string.h>
|
2002-04-05 13:48:00 +00:00
|
|
|
#include <sys/types.h>
|
2010-03-04 08:14:36 +00:00
|
|
|
|
|
|
|
#include "libopensc/opensc.h"
|
|
|
|
#include "libopensc/cardctl.h"
|
|
|
|
#include "libopensc/log.h"
|
2002-04-02 13:26:42 +00:00
|
|
|
#include "pkcs15-init.h"
|
2002-04-04 20:42:29 +00:00
|
|
|
#include "profile.h"
|
2002-04-02 13:26:42 +00:00
|
|
|
|
2010-01-28 12:46:36 +00:00
|
|
|
#define MIOCOS_PIN_ID_MIN 1
|
|
|
|
#define MIOCOS_PIN_ID_MAX 15
|
|
|
|
|
2002-04-02 13:26:42 +00:00
|
|
|
/*
|
2002-04-04 20:42:29 +00:00
|
|
|
* Allocate a file
|
2002-04-02 13:26:42 +00:00
|
|
|
*/
|
2002-04-04 20:42:29 +00:00
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
miocos_new_file(struct sc_profile *profile, sc_card_t *card,
|
2002-04-04 20:42:29 +00:00
|
|
|
unsigned int type, unsigned int num,
|
2005-03-09 00:04:44 +00:00
|
|
|
sc_file_t **out)
|
2002-04-02 13:26:42 +00:00
|
|
|
{
|
2002-04-04 20:42:29 +00:00
|
|
|
struct sc_file *file;
|
|
|
|
struct sc_path *p;
|
2004-12-22 09:48:27 +00:00
|
|
|
char name[64];
|
|
|
|
const char *tag = NULL, *desc = NULL;
|
2002-04-04 20:42:29 +00:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
switch (type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
desc = "RSA private key";
|
|
|
|
tag = "private-key";
|
|
|
|
break;
|
|
|
|
case SC_PKCS15_TYPE_PUBKEY_RSA:
|
|
|
|
desc = "RSA public key";
|
|
|
|
tag = "public-key";
|
|
|
|
break;
|
2002-04-19 17:02:49 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY:
|
|
|
|
desc = "extractable private key";
|
|
|
|
tag = "extractable-key";
|
|
|
|
break;
|
2002-04-04 20:42:29 +00:00
|
|
|
case SC_PKCS15_TYPE_CERT:
|
|
|
|
desc = "certificate";
|
|
|
|
tag = "certificate";
|
|
|
|
break;
|
|
|
|
case SC_PKCS15_TYPE_DATA_OBJECT:
|
|
|
|
desc = "data object";
|
|
|
|
tag = "data";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (tag)
|
|
|
|
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)) {
|
2018-11-22 08:31:29 +00:00
|
|
|
sc_log(card->ctx,
|
2003-10-14 09:57:29 +00:00
|
|
|
"File type not supported by card driver");
|
2002-04-04 20:42:29 +00:00
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
}
|
|
|
|
type &= SC_PKCS15_TYPE_CLASS_MASK;
|
2002-04-02 13:26:42 +00:00
|
|
|
}
|
|
|
|
|
2002-04-04 20:42:29 +00:00
|
|
|
snprintf(name, sizeof(name), "template-%s", tag);
|
|
|
|
if (sc_profile_get_file(profile, name, &file) < 0) {
|
2018-11-22 08:31:29 +00:00
|
|
|
sc_log(card->ctx, "Profile doesn't define %s template (%s)",
|
2002-04-04 20:42:29 +00:00
|
|
|
desc, name);
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
2002-04-02 13:26:42 +00:00
|
|
|
}
|
|
|
|
|
2002-04-04 20:42:29 +00:00
|
|
|
/* Now construct file from template */
|
|
|
|
file->id += num;
|
|
|
|
|
|
|
|
p = &file->path;
|
|
|
|
*p = profile->df_info->file->path;
|
|
|
|
p->value[p->len++] = file->id >> 8;
|
|
|
|
p->value[p->len++] = file->id;
|
|
|
|
|
|
|
|
*out = file;
|
2002-04-02 13:26:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-04-04 20:42:29 +00:00
|
|
|
static int
|
2005-03-09 00:04:44 +00:00
|
|
|
miocos_update_private_key(struct sc_profile *profile, sc_card_t *card,
|
2002-04-15 13:42:10 +00:00
|
|
|
struct sc_pkcs15_prkey_rsa *rsa)
|
2002-04-04 20:42:29 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
u8 buf[266];
|
2012-04-02 21:40:05 +00:00
|
|
|
|
2002-04-04 20:42:29 +00:00
|
|
|
memcpy(buf, "\x30\x82\x01\x06\x80\x81\x80", 7);
|
2002-04-15 13:42:10 +00:00
|
|
|
memcpy(buf + 7, rsa->modulus.data, 128);
|
2002-04-04 20:42:29 +00:00
|
|
|
memcpy(buf + 7 + 128, "\x82\x81\x80", 3);
|
2002-04-15 13:42:10 +00:00
|
|
|
memcpy(buf + 10 + 128, rsa->d.data, 128);
|
2002-04-04 20:42:29 +00:00
|
|
|
r = sc_update_binary(card, 0, buf, sizeof(buf), 0);
|
|
|
|
|
|
|
|
return r;
|
2002-04-02 13:26:42 +00:00
|
|
|
}
|
|
|
|
|
2010-01-28 12:46:36 +00:00
|
|
|
/*
|
|
|
|
* Initialize the Application DF
|
|
|
|
*/
|
2012-04-02 21:40:05 +00:00
|
|
|
static int
|
2010-02-21 16:21:57 +00:00
|
|
|
miocos_create_dir(struct sc_profile *profile, sc_pkcs15_card_t *p15card,
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_file *df)
|
|
|
|
{
|
|
|
|
/* Create the application DF */
|
2010-02-21 16:21:57 +00:00
|
|
|
if (sc_pkcs15init_create_file(profile, p15card, profile->df_info->file))
|
2010-01-28 12:46:36 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate PIN reference
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-21 16:21:57 +00:00
|
|
|
miocos_select_pin_reference(struct sc_profile *profile, sc_pkcs15_card_t *p15card,
|
2011-06-05 15:46:25 +00:00
|
|
|
struct sc_pkcs15_auth_info *auth_info)
|
2010-01-28 12:46:36 +00:00
|
|
|
{
|
2011-06-05 15:46:25 +00:00
|
|
|
if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
|
|
|
|
return SC_ERROR_OBJECT_NOT_VALID;
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2011-06-05 15:46:25 +00:00
|
|
|
if (auth_info->attrs.pin.reference < MIOCOS_PIN_ID_MIN)
|
2012-04-02 21:40:05 +00:00
|
|
|
auth_info->attrs.pin.reference = MIOCOS_PIN_ID_MIN;
|
2010-01-28 12:46:36 +00:00
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create new PIN
|
|
|
|
*/
|
|
|
|
static int
|
2012-04-02 21:40:05 +00:00
|
|
|
miocos_create_pin(struct sc_profile *profile, sc_pkcs15_card_t *p15card, struct sc_file *df,
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_pkcs15_object *pin_obj,
|
|
|
|
const u8 *pin, size_t pin_len,
|
|
|
|
const u8 *puk, size_t puk_len)
|
|
|
|
{
|
2010-02-21 16:21:57 +00:00
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
2011-06-05 15:46:25 +00:00
|
|
|
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
|
|
|
|
struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin;
|
|
|
|
struct sc_pkcs15_auth_info tmpinfo;
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_cardctl_miocos_ac_info ac_info;
|
|
|
|
int r;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
|
2010-01-28 12:46:36 +00:00
|
|
|
/* Ignore SOPIN */
|
2012-04-02 21:40:05 +00:00
|
|
|
if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
|
2010-01-28 12:46:36 +00:00
|
|
|
return SC_SUCCESS;
|
|
|
|
|
2011-06-05 15:46:25 +00:00
|
|
|
auth_info->path = profile->df_info->file->path;
|
|
|
|
r = sc_select_file(p15card->card, &auth_info->path, NULL);
|
2010-01-28 12:46:36 +00:00
|
|
|
if (r)
|
|
|
|
return r;
|
|
|
|
memset(&ac_info, 0, sizeof(ac_info));
|
2011-06-05 15:46:25 +00:00
|
|
|
ac_info.ref = pin_attrs->reference;
|
2010-01-28 12:46:36 +00:00
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &tmpinfo);
|
|
|
|
ac_info.max_tries = tmpinfo.tries_left;
|
|
|
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &tmpinfo);
|
|
|
|
ac_info.max_unblock_tries = tmpinfo.tries_left;
|
|
|
|
if (pin_len > 8)
|
|
|
|
pin_len = 8;
|
|
|
|
memcpy(ac_info.key_value, pin, pin_len);
|
|
|
|
if (puk_len > 8)
|
|
|
|
puk_len = 8;
|
|
|
|
strncpy((char *) ac_info.unblock_value, (const char *) puk, puk_len);
|
2010-02-21 16:21:57 +00:00
|
|
|
r = sc_card_ctl(p15card->card, SC_CARDCTL_MIOCOS_CREATE_AC, &ac_info);
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Miocos create AC failed");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
|
2010-01-28 12:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create private key file
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-21 16:21:57 +00:00
|
|
|
miocos_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_pkcs15_object *object)
|
|
|
|
{
|
2010-02-21 16:21:57 +00:00
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
|
|
|
|
struct sc_file *file;
|
|
|
|
int r;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
|
2012-04-02 21:40:05 +00:00
|
|
|
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys.");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
|
|
|
if (key_info->modulus_length != 1024)
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys.");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2018-11-22 08:31:29 +00:00
|
|
|
sc_log(ctx, "create private key ID:%s\n", sc_pkcs15_print_id(&key_info->id));
|
2010-02-21 16:21:57 +00:00
|
|
|
r = miocos_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot create key: failed to allocate new key object");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2018-11-22 08:31:29 +00:00
|
|
|
sc_log(ctx, "Path of private key file to create %s\n", sc_print_path(&file->path));
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2010-02-21 16:21:57 +00:00
|
|
|
r = sc_pkcs15init_create_file(profile, p15card, file);
|
2010-01-28 12:46:36 +00:00
|
|
|
sc_file_free(file);
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
|
2010-01-28 12:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Store a private key
|
|
|
|
*/
|
|
|
|
static int
|
2010-02-21 16:21:57 +00:00
|
|
|
miocos_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_pkcs15_object *object,
|
|
|
|
struct sc_pkcs15_prkey *key)
|
|
|
|
{
|
2010-02-21 16:21:57 +00:00
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
2010-01-28 12:46:36 +00:00
|
|
|
struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
|
|
|
|
struct sc_pkcs15_prkey_rsa *rsa;
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
int r;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
|
2012-04-02 21:40:05 +00:00
|
|
|
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA
|
2010-01-28 12:46:36 +00:00
|
|
|
|| key->algorithm != SC_ALGORITHM_RSA)
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys.");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
|
|
|
rsa = &key->u.rsa;
|
|
|
|
if (rsa->modulus.len != 128)
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys.");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2018-11-22 08:31:29 +00:00
|
|
|
sc_log(ctx, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id),
|
2010-01-28 12:46:36 +00:00
|
|
|
sc_print_path(&key_info->path));
|
|
|
|
|
2010-02-21 16:21:57 +00:00
|
|
|
r = sc_select_file(p15card->card, &key_info->path, &file);
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store key: select key file failed");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2010-02-21 16:21:57 +00:00
|
|
|
r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store private key");
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2010-02-21 16:21:57 +00:00
|
|
|
r = miocos_update_private_key(profile, p15card->card, rsa);
|
2010-01-28 12:46:36 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
|
2010-01-28 12:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct sc_pkcs15init_operations sc_pkcs15init_miocos_operations = {
|
|
|
|
NULL, /* erase_card */
|
|
|
|
NULL, /* init_card */
|
|
|
|
miocos_create_dir,
|
|
|
|
NULL, /* create_domain */
|
|
|
|
miocos_select_pin_reference,
|
|
|
|
miocos_create_pin,
|
|
|
|
NULL, /* select_key_reference */
|
|
|
|
miocos_create_key,
|
2012-04-02 21:40:05 +00:00
|
|
|
miocos_store_key,
|
2010-01-28 12:46:36 +00:00
|
|
|
NULL, /* generate_key */
|
|
|
|
NULL, NULL, /* encode private/public key */
|
|
|
|
NULL, /* finalize_card */
|
2010-03-28 11:37:13 +00:00
|
|
|
NULL, /* delete_object */
|
2010-12-30 12:50:35 +00:00
|
|
|
NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */
|
|
|
|
NULL /* sanity_check */
|
2010-01-28 12:46:36 +00:00
|
|
|
};
|
|
|
|
|
2003-10-13 20:41:00 +00:00
|
|
|
struct sc_pkcs15init_operations *sc_pkcs15init_get_miocos_ops(void)
|
|
|
|
{
|
|
|
|
return &sc_pkcs15init_miocos_operations;
|
|
|
|
}
|