ruToken fixups

http://www.opensc-project.org/pipermail/opensc-devel/2008-April/011057.html

By Aktiv Co. Aleksey Samsonov



git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3478 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
alonbl 2008-04-18 14:08:23 +00:00
parent e19d6a93ed
commit 8d7bce4de2
12 changed files with 802 additions and 1138 deletions

View File

@ -13,7 +13,6 @@ all-local:
@$(LN_S) $(top_srcdir)/src/libopensc/pkcs15.h pkcs15.h
@$(LN_S) $(top_srcdir)/src/libopensc/types.h types.h
@$(LN_S) $(top_srcdir)/src/libopensc/ui.h ui.h
@$(LN_S) $(top_srcdir)/src/libopensc/rutoken.h rutoken.h
@$(LN_S) $(top_srcdir)/src/pkcs11/pkcs11.h pkcs11.h
@$(LN_S) $(top_srcdir)/src/pkcs11/pkcs11-opensc.h pkcs11-opensc.h
@$(LN_S) $(top_srcdir)/src/pkcs15init/keycache.h keycache.h

View File

@ -10,8 +10,7 @@ lib_LTLIBRARIES = libopensc.la
openscinclude_HEADERS = \
opensc.h pkcs15.h emv.h \
cardctl.h asn1.h log.h ui.h \
errors.h types.h compression.h \
rutoken.h
errors.h types.h compression.h
noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.h \
internal-winscard.h p15card-helper.h
pkgconfig_DATA = libopensc.pc libpkcs15init.pc libscconf.pc
@ -43,7 +42,7 @@ libopensc_la_SOURCES = \
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \
pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
pkcs15-rutoken.c pkcs15-prkey-rutoken.c \
pkcs15-rutoken.c \
compression.c p15card-helper.c \
\
libopensc.exports

View File

@ -5,7 +5,7 @@ TARGET = opensc.dll opensc_a.lib
HEADERS = \
asn1.h cardctl.h cards.h emv.h errors.h \
log.h opensc.h pkcs15.h rutoken.h types.h ui.h
log.h opensc.h pkcs15.h types.h ui.h
HEADERSDIR = $(TOPDIR)\src\include\opensc
@ -32,7 +32,7 @@ OBJECTS = \
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \
pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
pkcs15-rutoken.obj pkcs15-prkey-rutoken.obj \
pkcs15-rutoken.obj \
compression.obj p15card-helper.obj \
versioninfo.res

File diff suppressed because it is too large Load Diff

View File

@ -184,8 +184,6 @@ sc_release_context
sc_reset
sc_reset_retry_counter
sc_restore_security_env
sc_rutoken_get_prkey_from_bin
sc_rutoken_get_bin_from_prkey
sc_select_file
sc_set_card_driver
sc_set_security_env

View File

@ -1,377 +0,0 @@
/*
* ruToken specific operation for PKCS #15 private key functions
*
* Copyright (C) 2007 Pavel Mironchik <rutoken@rutoken.ru>
* Copyright (C) 2007 Eugene Hermann <rutoken@rutoken.ru>
*
* 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 <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <opensc/opensc.h>
#include <opensc/pkcs15.h>
#include "rutoken.h"
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#elif defined(_MSC_VER)
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
#else
#warning no uint32_t type available, please contact opensc-devel@opensc-project.org
#endif
/* BLOB definition */
typedef struct _RURSAPUBKEY {
uint32_t magic;
uint32_t bitlen;
uint32_t pubexp;
} RURSAPUBKEY;
typedef struct _RUPUBLICKEYSTRUC {
u8 bType;
u8 bVersion;
uint16_t reserved;
uint32_t aiKeyAlg;
} RUBLOBHEADER;
typedef struct _RUPRIVATEKEYBLOB {
RUBLOBHEADER blobheader;
RURSAPUBKEY rsapubkey;
u8 *modulus;
u8 *prime1;
u8 *prime2;
u8 *exponent1;
u8 *exponent2;
u8 *coefficient;
u8 *privateExponent;
} RUPRIVATEKEYBLOB;
static void ArrayReverse(u8 *buf, size_t size)
{
size_t i;
u8 tmp;
for (i=0; i < size/2; ++i)
{
tmp = buf[i];
buf[i] = buf[size-1-i];
buf[size-1-i] = tmp;
}
}
static int free_private_blob(RUPRIVATEKEYBLOB *pr_blob)
{
free(pr_blob->modulus);
free(pr_blob->prime1);
free(pr_blob->prime2);
free(pr_blob->exponent1);
free(pr_blob->exponent2);
free(pr_blob->coefficient);
free(pr_blob->privateExponent);
return 0;
}
static int bin_to_private_blob(RUPRIVATEKEYBLOB *pr_blob, const u8* buf, size_t buf_len)
{
const u8 *tmp;
size_t len = 2 + sizeof(pr_blob->blobheader) + sizeof(pr_blob->rsapubkey);
uint32_t bitlen;
if (buf_len < len)
return -1;
tmp = buf + 2;
memcpy(&pr_blob->blobheader, tmp, sizeof(pr_blob->blobheader));
tmp += sizeof(pr_blob->blobheader);
memcpy(&pr_blob->rsapubkey, tmp, sizeof(pr_blob->rsapubkey));
tmp += sizeof(pr_blob->rsapubkey);
bitlen = pr_blob->rsapubkey.bitlen;
len += bitlen/8 * 2 + bitlen/16 * 5;
if (buf_len < len)
return -1;
pr_blob->modulus = malloc(bitlen/8);
pr_blob->prime1 = malloc(bitlen/16);
pr_blob->prime2 = malloc(bitlen/16);
pr_blob->exponent1 = malloc(bitlen/16);
pr_blob->exponent2 = malloc(bitlen/16);
pr_blob->coefficient = malloc(bitlen/16);
pr_blob->privateExponent = malloc(bitlen/8);
if (!pr_blob->modulus || !pr_blob->prime1 || !pr_blob->prime2
|| !pr_blob->exponent1 || !pr_blob->exponent2
|| !pr_blob->coefficient || !pr_blob->privateExponent
)
{
free_private_blob(pr_blob);
return -1;
}
memcpy(pr_blob->modulus, tmp, bitlen/8);
tmp += bitlen/8;
memcpy(pr_blob->prime1, tmp, bitlen/16);
tmp += bitlen/16;
memcpy(pr_blob->prime2, tmp, bitlen/16);
tmp += bitlen/16;
memcpy(pr_blob->exponent1, tmp, bitlen/16);
tmp += bitlen/16;
memcpy(pr_blob->exponent2, tmp, bitlen/16);
tmp += bitlen/16;
memcpy(pr_blob->coefficient, tmp, bitlen/16);
tmp += bitlen/16;
memcpy(pr_blob->privateExponent, tmp, bitlen/8);
tmp += bitlen/8;
return 0;
}
static int create_private_blob(RUPRIVATEKEYBLOB *pr_blob, const struct sc_pkcs15_prkey_rsa *key)
{
size_t n;
const uint32_t bitlen = key->modulus.len*8;
if ( key->modulus.len != bitlen/8
|| key->p.len != bitlen/16
|| key->q.len != bitlen/16
|| key->dmp1.len != bitlen/16
|| key->dmq1.len != bitlen/16
|| key->iqmp.len != bitlen/16
|| key->d.len != bitlen/8
)
return -1;
/* blobheader */
/* u8 bType; */
pr_blob->blobheader.bType = 0x07;
/* u8 bVersion; */
pr_blob->blobheader.bVersion = 0x02;
/* u16 reserved; */
pr_blob->blobheader.reserved = 0;
/* u32 aiKeyAlg; */
pr_blob->blobheader.aiKeyAlg = 0x0000a400;
pr_blob->rsapubkey.magic = 0x32415352; /* "RSA2" */
pr_blob->rsapubkey.bitlen = bitlen;
pr_blob->rsapubkey.pubexp = 0;
for (n=0; n < key->exponent.len && n < sizeof(pr_blob->rsapubkey.pubexp); ++n)
pr_blob->rsapubkey.pubexp +=
(uint32_t)key->exponent.data[key->exponent.len - n - 1] << 8*n;
pr_blob->modulus = malloc(bitlen/8);
pr_blob->prime1 = malloc(bitlen/16);
pr_blob->prime2 = malloc(bitlen/16);
pr_blob->exponent1 = malloc(bitlen/16);
pr_blob->exponent2 = malloc(bitlen/16);
pr_blob->coefficient = malloc(bitlen/16);
pr_blob->privateExponent = malloc(bitlen/8);
if (!pr_blob->modulus || !pr_blob->prime1 || !pr_blob->prime2
|| !pr_blob->exponent1 || !pr_blob->exponent2
|| !pr_blob->coefficient || !pr_blob->privateExponent
)
{
free_private_blob(pr_blob);
return -1;
}
memcpy(pr_blob->modulus, key->modulus.data, key->modulus.len);
ArrayReverse(pr_blob->modulus, key->modulus.len);
memcpy(pr_blob->prime1, key->p.data, key->p.len);
ArrayReverse(pr_blob->prime1, key->p.len);
memcpy(pr_blob->prime2, key->q.data, key->q.len);
ArrayReverse(pr_blob->prime2, key->q.len);
memcpy(pr_blob->exponent1, key->dmp1.data, key->dmp1.len);
ArrayReverse(pr_blob->exponent1, key->dmp1.len);
memcpy(pr_blob->exponent2, key->dmq1.data, key->dmq1.len);
ArrayReverse(pr_blob->exponent2, key->dmq1.len);
memcpy(pr_blob->coefficient, key->iqmp.data, key->iqmp.len);
ArrayReverse(pr_blob->coefficient, key->iqmp.len);
memcpy(pr_blob->privateExponent, key->d.data, key->d.len);
ArrayReverse(pr_blob->privateExponent, key->d.len);
return 0;
}
static int get_sc_pksc15_prkey_rsa(const RUPRIVATEKEYBLOB *pr_blob, struct sc_pkcs15_prkey_rsa *key)
{
static const u8 Exp[3] = { 0x01, 0x00, 0x01 }; /* big endian */
const uint32_t bitlen = pr_blob->rsapubkey.bitlen;
key->modulus.data = malloc(bitlen/8);
key->modulus.len = bitlen/8;
key->p.data = malloc(bitlen/16);
key->p.len = bitlen/16;
key->q.data = malloc(bitlen/16);
key->q.len = bitlen/16;
key->dmp1.data = malloc(bitlen/16);
key->dmp1.len = bitlen/16;
key->dmq1.data = malloc(bitlen/16);
key->dmq1.len = bitlen/16; /* ?! bitlen/16 - 1; */
key->iqmp.data = malloc(bitlen/16);
key->iqmp.len = bitlen/16;
key->d.data = malloc(bitlen/8);
key->d.len = bitlen/8;
key->exponent.data = malloc(sizeof(Exp));
key->exponent.len = sizeof(Exp);
if(!key->modulus.data || !key->p.data || !key->q.data || !key->dmp1.data
|| !key->dmq1.data || !key->iqmp.data || !key->d.data
|| !key->exponent.data
)
{
free(key->modulus.data);
free(key->p.data);
free(key->q.data);
free(key->dmp1.data);
free(key->dmq1.data);
free(key->iqmp.data);
free(key->d.data);
free(key->exponent.data);
memset(key, 0, sizeof(*key));
return -1;
}
memcpy(key->exponent.data, &Exp, sizeof(Exp));
memcpy(key->modulus.data, pr_blob->modulus, key->modulus.len);
ArrayReverse(key->modulus.data, key->modulus.len);
memcpy(key->p.data, pr_blob->prime1, key->p.len);
ArrayReverse(key->p.data, key->p.len);
memcpy(key->q.data, pr_blob->prime2, key->q.len);
ArrayReverse(key->q.data, key->q.len);
memcpy(key->dmp1.data, pr_blob->exponent1, key->dmp1.len);
ArrayReverse(key->dmp1.data, key->dmp1.len);
memcpy(key->dmq1.data, pr_blob->exponent2, key->dmq1.len);
ArrayReverse(key->dmq1.data, key->dmq1.len);
memcpy(key->iqmp.data, pr_blob->coefficient, key->iqmp.len);
ArrayReverse(key->iqmp.data, key->iqmp.len);
memcpy(key->d.data, pr_blob->privateExponent, key->d.len);
ArrayReverse(key->d.data, key->d.len);
return 0;
}
static int private_blob_to_bin(const RUPRIVATEKEYBLOB *pr_blob, u8 *buf, size_t *buf_len)
{
u8 *tmp;
size_t len = 2 + sizeof(pr_blob->blobheader) + sizeof(pr_blob->rsapubkey);
if(*buf_len < len)
return -1;
buf[0] = 2;
buf[1] = 1;
tmp = buf + 2;
memcpy(tmp, &pr_blob->blobheader, sizeof(pr_blob->blobheader));
tmp += sizeof(pr_blob->blobheader);
memcpy(tmp, &pr_blob->rsapubkey, sizeof(pr_blob->rsapubkey));
tmp += sizeof(pr_blob->rsapubkey);
len += pr_blob->rsapubkey.bitlen/8 * 2 + pr_blob->rsapubkey.bitlen/16 * 5;
if (*buf_len < len)
return -1;
memcpy(tmp, pr_blob->modulus, pr_blob->rsapubkey.bitlen/8);
tmp += pr_blob->rsapubkey.bitlen/8;
memcpy(tmp, pr_blob->prime1, pr_blob->rsapubkey.bitlen/16);
tmp += pr_blob->rsapubkey.bitlen/16;
memcpy(tmp, pr_blob->prime2, pr_blob->rsapubkey.bitlen/16);
tmp += pr_blob->rsapubkey.bitlen/16;
memcpy(tmp, pr_blob->exponent1, pr_blob->rsapubkey.bitlen/16);
tmp += pr_blob->rsapubkey.bitlen/16;
memcpy(tmp, pr_blob->exponent2, pr_blob->rsapubkey.bitlen/16);
tmp += pr_blob->rsapubkey.bitlen/16;
memcpy(tmp, pr_blob->coefficient, pr_blob->rsapubkey.bitlen/16);
tmp += pr_blob->rsapubkey.bitlen/16;
memcpy(tmp, pr_blob->privateExponent, pr_blob->rsapubkey.bitlen/8);
tmp += pr_blob->rsapubkey.bitlen/8;
*buf_len = len;
return 0;
}
static int clean_prkey_private_blob(const RUPRIVATEKEYBLOB* pr_blob)
{
const uint32_t bitlen = pr_blob->rsapubkey.bitlen;
memset(pr_blob->modulus, 0, bitlen/8);
memset(pr_blob->prime1, 0, bitlen/16);
memset(pr_blob->prime2, 0, bitlen/16);
memset(pr_blob->exponent1, 0, bitlen/16);
memset(pr_blob->exponent2, 0, bitlen/16);
memset(pr_blob->coefficient, 0, bitlen/16);
memset(pr_blob->privateExponent, 0, bitlen/8);
return 0;
}
int sc_rutoken_get_prkey_from_bin(const u8 *data, size_t len, struct sc_pkcs15_prkey **key)
{
int ret = -1;
RUPRIVATEKEYBLOB pr_blob;
if (data && key)
{
*key = malloc(sizeof(struct sc_pkcs15_prkey));
if (*key)
{
memset(*key, 0, sizeof(**key));
ret = bin_to_private_blob(&pr_blob, data, len);
if (ret == 0)
{
ret = get_sc_pksc15_prkey_rsa(&pr_blob, &(*key)->u.rsa);
if (ret == 0)
(*key)->algorithm = SC_ALGORITHM_RSA;
clean_prkey_private_blob(&pr_blob);
free_private_blob(&pr_blob);
memset(&pr_blob, 0, sizeof(pr_blob));
}
}
}
return ret;
}
int sc_rutoken_get_bin_from_prkey(const struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize)
{
int r = -1;
RUPRIVATEKEYBLOB prkeyblob;
if (rsa && key && keysize)
{
r = create_private_blob(&prkeyblob, rsa);
if (r == 0)
{
r = private_blob_to_bin(&prkeyblob, key, keysize);
clean_prkey_private_blob(&prkeyblob);
free_private_blob(&prkeyblob);
memset(&prkeyblob, 0, sizeof(prkeyblob));
}
}
return r;
}

View File

@ -1,5 +1,5 @@
/*
* PKCS15 emulation layer for ruToken
* PKCS15 emulation layer for Rutoken
*
* Copyright (C) 2007 Pavel Mironchik <rutoken@rutoken.ru>
* Copyright (C) 2007 Eugene Hermann <rutoken@rutoken.ru>
@ -28,17 +28,15 @@
#include <assert.h>
#include <stdarg.h>
#include <opensc/opensc.h>
#include "cardctl.h"
#include <opensc/log.h>
#include <opensc/pkcs15.h>
#define RUT_LABEL "ruToken card"
#include "cardctl.h"
#define PrKDF_path "3F00FF000001"
#define PuKDF_path "3F00FF000002"
#define CDF_path "3F00FF000003"
#define DODF_path "3F00FF000004"
#define AODF_path "3F00FF00A0DF"
#define AODF_path "3F00FF000000"
static const struct
{
@ -82,8 +80,8 @@ static int add_predefined_pin(sc_pkcs15_card_t *p15card, sc_path_t *adf_path)
{
free(pin_info);
free(pin_obj);
return SC_ERROR_OUT_OF_MEMORY;
}
return SC_ERROR_OUT_OF_MEMORY;
}
pin_info->auth_id.len = 1;
pin_info->auth_id.value[0] = (u8)pinlist[i].reference;
pin_info->reference = pinlist[i].reference;
@ -97,8 +95,7 @@ static int add_predefined_pin(sc_pkcs15_card_t *p15card, sc_path_t *adf_path)
pin_info->path = *adf_path;
strncpy(pin_obj->label, pinlist[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
pin_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE;
pin_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE;
sc_pkcs15emu_add_pin_obj(p15card, pin_obj, pin_info);
free(pin_obj);
free(pin_info);
@ -119,7 +116,7 @@ static int set_card_info(sc_pkcs15_card_t *p15card)
sc_serial_number_t serialnr;
char serial[30] = {0};
u8 info[8];
/* get the card serial number */
if (sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr) < 0)
{
@ -128,21 +125,19 @@ static int set_card_info(sc_pkcs15_card_t *p15card)
}
sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0);
set_string(&p15card->serial_number, serial);
/* get ruToken information */
if (sc_card_ctl(card, SC_CARDCTL_RUTOKEN_GET_INFO, info) < 0)
{
sc_debug(ctx, "Unable to get token information\n");
return SC_ERROR_WRONG_CARD;
}
set_string(&p15card->label, RUT_LABEL);
set_string(&p15card->label, card->name);
p15card->version = (info[1] >> 4)*10 + (info[1] & 0x0f);
sc_bin_to_hex(info + 3, 3 , serial, sizeof(serial), 0);
set_string(&p15card->manufacturer_id, serial);
return SC_SUCCESS;
}
static int sc_pkcs15_rutoken_init_func(sc_pkcs15_card_t *p15card)
{
sc_context_t *ctx;
@ -152,25 +147,23 @@ static int sc_pkcs15_rutoken_init_func(sc_pkcs15_card_t *p15card)
size_t i;
int r;
unsigned int added_pin = 0;
if (!p15card || !p15card->card || !p15card->card->ctx
|| !p15card->card->ops
|| !p15card->card->ops->select_file
)
return SC_ERROR_INVALID_ARGUMENTS;
card = p15card->card;
ctx = card->ctx;
r = set_card_info(p15card);
if (r != SC_SUCCESS)
{
{
sc_error(ctx, "Unable to set card info: %s\n", sc_strerror(r));
r = SC_SUCCESS;
}
}
for (i = 0; i < sizeof(arr_profile_df)/sizeof(arr_profile_df[0]); ++i)
{
{
df = NULL;
sc_format_path(arr_profile_df[i].path, &path);
if (card->ops->select_file(card, &path, &df) == SC_ERROR_FILE_NOT_FOUND)
@ -181,7 +174,7 @@ static int sc_pkcs15_rutoken_init_func(sc_pkcs15_card_t *p15card)
if (r == SC_SUCCESS)
r = sc_pkcs15_add_df(p15card, arr_profile_df[i].type, &path, df);
if (df)
sc_file_free(df);
sc_file_free(df);
if (r != SC_SUCCESS) break;
@ -199,17 +192,16 @@ static int sc_pkcs15_rutoken_init_func(sc_pkcs15_card_t *p15card)
return r;
}
int sc_pkcs15emu_rutoken_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
int sc_pkcs15emu_rutoken_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
struct sc_card *card = p15card->card;
SC_FUNC_CALLED(card->ctx, 1);
/* check if we have the correct card OS */
if (strcmp(card->name, "rutoken card"))
if (strcmp(card->name, "Rutoken card"))
return SC_ERROR_WRONG_CARD;
sc_debug(card->ctx, "%s found", card->name);
return sc_pkcs15_rutoken_init_func(p15card);
}

View File

@ -1,7 +0,0 @@
#ifndef RUTOKEN_H
#define RUTOKEN_H
int sc_rutoken_get_prkey_from_bin(const u8 *data, size_t len, struct sc_pkcs15_prkey **key);
int sc_rutoken_get_bin_from_prkey(const struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize);
#endif

View File

@ -24,7 +24,7 @@ dist_pkgdata_DATA = \
rutoken.profile \
asepcos.profile
DEFS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS)
INCLUDES = -I$(top_srcdir)/src/common -I$(top_builddir)/src/include

View File

@ -1,5 +1,5 @@
/*
* ruToken specific operation for PKCS15 initialization
* Rutoken specific operation for PKCS15 initialization
*
* Copyright (C) 2007 Pavel Mironchik <rutoken@rutoken.ru>
* Copyright (C) 2007 Eugene Hermann <rutoken@rutoken.ru>
@ -18,10 +18,20 @@
* 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
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#elif defined(_MSC_VER)
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
#else
#warning no uint32_t type available, please contact opensc-devel@opensc-project.org
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
@ -31,11 +41,14 @@
#include <opensc/cardctl.h>
#include <opensc/log.h>
#include <opensc/pkcs15.h>
#include <opensc/rutoken.h>
#include "pkcs15-init.h"
#include "profile.h"
#define MAX_ID 255
#define RUTOKEN_MIN_ID_PRKEY 0x0000
#define RUTOKEN_MAX_ID_PRKEY 0x00FF
#define RUTOKEN_MIN_ID_OTHER (RUTOKEN_MAX_ID_PRKEY + 1)
#define RUTOKEN_MAX_ID_OTHER 0x0FFF
#define RUTOKEN_BUFLEN_LISTFILES (2 * (RUTOKEN_MAX_ID_OTHER + 1))
static const sc_SecAttrV2_t pr_sec_attr = {0x43, 1, 1, 0, 0, 0, 0, 1, 2, 2, 0, 0, 0, 0, 2};
static const sc_SecAttrV2_t pb_sec_attr = {0x42, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 2};
@ -47,10 +60,10 @@ static const sc_SecAttrV2_t p1_sec_attr = {0x43, 1, 1, 0, 0, 0, 0,-1, 1, 1, 0, 0
enum DF_IDs
{
PrKDFid = 0x1001,
PuKDFid = 0x1002,
CDFid = 0x1003,
DODFid = 0x1004,
PrKDFid = 0x0000,
PuKDFid = 0x0000,
CDFid = 0x0000,
DODFid = 0x0000,
AODFid = 0xFFFF
};
@ -75,40 +88,76 @@ static const struct
{ AODF_name, AODFid, SC_PKCS15_AODF }
};
/*
* Create/override new EF.
*/
static int rutoken_create_file(sc_card_t *card, sc_path_t *path, sc_file_t *ef)
static int rutoken_get_bin_from_prkey(const struct sc_pkcs15_prkey_rsa *rsa,
u8 *bufkey, size_t *bufkey_size)
{
int ret = SC_SUCCESS;
sc_path_t path_dir;
const uint32_t bitlen = rsa->modulus.len * 8;
size_t i, len;
SC_FUNC_CALLED(card->ctx, 1);
if ( rsa->modulus.len != bitlen/8
|| rsa->p.len != bitlen/16
|| rsa->q.len != bitlen/16
|| rsa->dmp1.len != bitlen/16
|| rsa->dmq1.len != bitlen/16
|| rsa->iqmp.len != bitlen/16
|| rsa->d.len != bitlen/8
|| rsa->exponent.len > sizeof(uint32_t)
)
return -1;
if (path)
{
sc_ctx_suppress_errors_on(card->ctx);
ret = card->ops->select_file(card, path, NULL);
sc_ctx_suppress_errors_off(card->ctx);
if (ret == SC_SUCCESS)
{
sc_path_t del_path;
del_path.len = 2;
del_path.type = SC_PATH_TYPE_FILE_ID;
del_path.value[0] = (u8)(ef->id / 256);
del_path.value[1] = (u8)(ef->id % 256);
if (card->ops->select_file(card, &del_path, NULL) == SC_SUCCESS)
ret = card->ops->delete_file(card, &del_path);
}
path_dir = *path;
path_dir.len -= 2;
ret = card->ops->select_file(card, &path_dir, NULL);
}
if (ret == SC_SUCCESS)
{
ret = card->ops->create_file(card, ef);
}
return ret;
if (*bufkey_size < 14 + sizeof(uint32_t) * 2 + bitlen/8 * 2 + bitlen/16 * 5)
return -1;
bufkey[0] = 2;
bufkey[1] = 1;
/* BLOB header */
bufkey[2] = 0x07; /* Type */
bufkey[3] = 0x02; /* Version */
/* reserve */
bufkey[4] = 0;
bufkey[5] = 0;
/* aiKeyAlg */
bufkey[6] = 0;
bufkey[7] = 0xA4;
bufkey[8] = 0;
bufkey[9] = 0;
/* RSAPUBKEY */
/* magic "RSA2" */
bufkey[10] = 0x52;
bufkey[11] = 0x53;
bufkey[12] = 0x41;
bufkey[13] = 0x32;
len = 14;
/* bitlen */
for (i = 0; i < sizeof(uint32_t); ++i)
bufkey[len++] = (bitlen >> i*8) & 0xff;
/* pubexp */
for (i = 0; i < sizeof(uint32_t); ++i)
if (i < rsa->exponent.len)
bufkey[len++] = rsa->exponent.data[rsa->exponent.len - 1 - i];
else
bufkey[len++] = 0;
#define MEMCPY_BUF_REVERSE_RSA(NAME) \
do { \
for (i = 0; i < rsa->NAME.len; ++i) \
bufkey[len++] = rsa->NAME.data[rsa->NAME.len - 1 - i]; \
} while (0)
/* PRIVATEKEYBLOB tail */
MEMCPY_BUF_REVERSE_RSA(modulus); /* modulus */
MEMCPY_BUF_REVERSE_RSA(p); /* prime1 */
MEMCPY_BUF_REVERSE_RSA(q); /* prime2 */
MEMCPY_BUF_REVERSE_RSA(dmp1); /* exponent1 */
MEMCPY_BUF_REVERSE_RSA(dmq1); /* exponent2 */
MEMCPY_BUF_REVERSE_RSA(iqmp); /* coefficient */
MEMCPY_BUF_REVERSE_RSA(d); /* privateExponent */
*bufkey_size = len;
return 0;
}
/*
@ -177,7 +226,8 @@ rutoken_select_key_reference(sc_profile_t *profile, sc_card_t *card,
}
sc_append_file_id(&key_info->path, key_info->key_reference);
return key_info->key_reference >= 0 && key_info->key_reference <= MAX_ID ?
return key_info->key_reference >= RUTOKEN_MIN_ID_PRKEY
&& key_info->key_reference <= RUTOKEN_MAX_ID_PRKEY ?
SC_SUCCESS : SC_ERROR_TOO_MANY_OBJECTS;
}
@ -195,36 +245,6 @@ rutoken_create_key(sc_profile_t *profile, sc_card_t *card,
return SC_SUCCESS;
}
/*
* Create private key files
*/
static int rutoken_create_prkeyfile(sc_card_t *card,
sc_pkcs15_prkey_info_t *key_info, size_t prsize)
{
sc_path_t path;
sc_file_t *file;
int ret;
SC_FUNC_CALLED(card->ctx, 1);
file = sc_file_new();
if (file)
{
/* create key file */
path = key_info->path;
file->type = SC_FILE_TYPE_WORKING_EF;
file->id = key_info->key_reference;
file->size = prsize;
sc_file_set_sec_attr(file, (u8*)&pr_sec_attr, SEC_ATTR_SIZE);
ret = rutoken_create_file(card, &path, file);
if (file)
sc_file_free(file);
}
else
ret = SC_ERROR_OUT_OF_MEMORY;
return ret;
}
/*
* Store a private key object.
*/
@ -237,6 +257,7 @@ rutoken_store_key(sc_profile_t *profile, sc_card_t *card,
const int nKeyBufSize = 2048;
u8 *prkeybuf = NULL;
size_t prsize;
sc_file_t *file;
int ret;
if (!profile || !profile->ops || !card || !card->ctx
@ -264,12 +285,21 @@ rutoken_store_key(sc_profile_t *profile, sc_card_t *card,
ret = profile->ops->encode_private_key(profile, card, &key->u.rsa, prkeybuf, &prsize, 0);
if (ret == 0)
{
ret = rutoken_create_prkeyfile(card, key_info, prsize);
if (ret == 0)
file = sc_file_new();
if (!file)
ret = SC_ERROR_OUT_OF_MEMORY;
else
{
ret = sc_update_binary(card, 0, prkeybuf, prsize, 0);
if (ret < 0 || (size_t)ret != prsize)
sc_debug(card->ctx, "ret=%i (%u)\n", ret, prsize);
/* create (or update) key file */
file->path = key_info->path;
file->type = SC_FILE_TYPE_WORKING_EF;
file->id = key_info->key_reference;
file->size = prsize;
sc_file_set_sec_attr(file, (u8*)&pr_sec_attr, SEC_ATTR_SIZE);
ret = sc_pkcs15init_update_file(profile, card,
file, prkeybuf, prsize);
sc_file_free(file);
}
memset(prkeybuf, 0, prsize);
}
@ -291,7 +321,7 @@ rutoken_encode_private_key(sc_profile_t *profile, sc_card_t *card,
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(card->ctx, 1);
r = sc_rutoken_get_bin_from_prkey(rsa, key, keysize);
r = rutoken_get_bin_from_prkey(rsa, key, keysize);
sc_debug(card->ctx, "sc_rutoken_get_bin_from_prkey returned %i\n", r);
return r;
}
@ -299,7 +329,7 @@ rutoken_encode_private_key(sc_profile_t *profile, sc_card_t *card,
static int rutoken_id_in(int id, const u8 *buf, int buflen)
{
int i;
for (i = 0; i*2 < buflen; i++)
for (i = 0; i*2 + 1 < buflen; i++)
if (id == (int)buf[i*2] * 0x100 + buf[i*2 + 1]) return 1;
return 0;
}
@ -308,7 +338,7 @@ static int rutoken_find_id(sc_card_t *card, const sc_path_t *path)
{
int ret = SC_SUCCESS;
sc_file_t *file = NULL;
u8 *files = malloc(2048);
u8 *files = malloc(RUTOKEN_BUFLEN_LISTFILES);
if (!files) return SC_ERROR_OUT_OF_MEMORY;
if(path)
{
@ -317,11 +347,11 @@ static int rutoken_find_id(sc_card_t *card, const sc_path_t *path)
}
if(ret == SC_SUCCESS)
{
ret = card->ops->list_files(card, files, 2048);
ret = card->ops->list_files(card, files, RUTOKEN_BUFLEN_LISTFILES);
if(ret >= 0)
{
int i;
for (i = 0; i < MAX_ID; i++)
for (i = RUTOKEN_MIN_ID_OTHER; i <= RUTOKEN_MAX_ID_OTHER; i++)
if(!rutoken_id_in(i, files, ret)) {ret = i; break;}
}
}
@ -600,7 +630,13 @@ static int rutoken_init(sc_profile_t *profile, sc_card_t *card)
df->id = arr_def_df[i].dir;
r = sc_append_file_id(&df->path, df->id);
if (r == SC_SUCCESS)
{
sc_ctx_suppress_errors_on(card->ctx);
r = card->ops->create_file(card, df);
sc_ctx_suppress_errors_off(card->ctx);
if (r == SC_ERROR_FILE_ALREADY_EXISTS)
r = SC_SUCCESS;
}
if (r != SC_SUCCESS)
sc_error(card->ctx, "Failed to create df, %s\n",
sc_strerror(r));

View File

@ -13,20 +13,20 @@ pkcs15 {
# Put the DF length into the ODF file?
encode-df-length = no;
# Have a lastUpdate field in the EF(TokenInfo)?
do-last-update = yes;
do-last-update = no;
}
# Default settings.
# This option block will always be processed.
option default_32k {
macros {
macros {
odf-size = 0;
aodf-size = 0;
dodf-size = 2048;
cdf-size = 2048;
prkdf-size = 2048;
pukdf-size = 2048;
}
}
}
# This option is for cards with very little memory.
@ -45,45 +45,45 @@ option default {
}
filesystem {
DF MF {
DF MF {
path = 3F00;
type = DF;
type = DF;
# Here comes the application DF
DF PKCS15-AppDF {
type = DF;
type = DF;
file-id = FF00;
EF PKCS15-ODF {
file-id = 00DF;
size = $odf-size;
}
}
EF PKCS15-AODF {
file-id = A0DF;
size = $aodf-size;
}
EF PKCS15-PrKDF {
file-id = 0001;
file-id = 0001;
size = $prkdf-size;
}
}
EF PKCS15-PuKDF {
file-id = 0002;
file-id = 0002;
size = $pukdf-size;
}
}
EF PKCS15-CDF {
file-id = 0003;
size = $cdf-size;
}
}
EF PKCS15-DODF {
file-id = 0004;
size = $dodf-size;
}
}
}
}
}
}

View File

@ -34,7 +34,6 @@
#include <opensc/opensc.h>
#include <opensc/cardctl.h>
#include <opensc/pkcs15.h>
#include <opensc/rutoken.h>
#include "util.h"
#define IV_SIZE 8