r3717:3719 from trunk
git-svn-id: https://www.opensc-project.org/svnp/opensc/branches/martin/0.12@3720 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
89e18e51dd
commit
d3201511c7
3
NEWS
3
NEWS
@ -6,6 +6,9 @@ http://www.opensc-project.org/opensc/wiki/WhatsNew
|
|||||||
Also see the svn changelog using svn command
|
Also see the svn changelog using svn command
|
||||||
or doc/nonpersistent/ChangeLog.
|
or doc/nonpersistent/ChangeLog.
|
||||||
|
|
||||||
|
New in 0.??.==; 200?-??-??; ??
|
||||||
|
* New westcos driver by François Leblanc
|
||||||
|
|
||||||
New in 0.11.9; 2009-07-29; Andreas Jellinghaus
|
New in 0.11.9; 2009-07-29; Andreas Jellinghaus
|
||||||
* New rutoken_ecp driver by Aktiv Co. / Aleksey Samsonov
|
* New rutoken_ecp driver by Aktiv Co. / Aleksey Samsonov
|
||||||
* Allow more keys/certificates/files etc. with entersafe tokens
|
* Allow more keys/certificates/files etc. with entersafe tokens
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
<xi:include href="cardos-tool.xml"/>
|
<xi:include href="cardos-tool.xml"/>
|
||||||
<xi:include href="cryptoflex-tool.xml"/>
|
<xi:include href="cryptoflex-tool.xml"/>
|
||||||
<xi:include href="netkey-tool.xml"/>
|
<xi:include href="netkey-tool.xml"/>
|
||||||
|
<xi:include href="westcos-tool.xml"/>
|
||||||
</reference>
|
</reference>
|
||||||
</book>
|
</book>
|
||||||
|
|
||||||
|
140
doc/tools/westcos-tool.xml
Normal file
140
doc/tools/westcos-tool.xml
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<refentry id="westcos-tool">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>westcos-tool</refentrytitle>
|
||||||
|
<manvolnum>1</manvolnum>
|
||||||
|
<refmiscinfo>opensc</refmiscinfo>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>westcos-tool</refname>
|
||||||
|
<refpurpose>utility for manipulating data structure
|
||||||
|
on westcos smart card and similar security tokens</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Synopsis</title>
|
||||||
|
<para>
|
||||||
|
<command>westcos-tool</command> [OPTIONS]
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
The <command>westcos-tool</command> utility is used to manipulate
|
||||||
|
the westcos data structures on 2 Ko smart cards. Users can create PINs,
|
||||||
|
keys and certificates stored on the token. User PIN authentication is
|
||||||
|
performed for those operations that require it.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-G</option></term>
|
||||||
|
<listitem><para>Generate a private key on smart card. The smart card must be
|
||||||
|
not finalized and pin installed (ig. file for pin must be created, see option
|
||||||
|
-i). By default key length is 1536 bits. User authentication is required for
|
||||||
|
this operation. </para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-L</option> <varname>length</varname></term>
|
||||||
|
<listitem><para>Change the length of private key, use with <option>-G</option>.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-i</option></term>
|
||||||
|
<listitem><para>Install pin file in token, you must provide pin value
|
||||||
|
with <option>-pin</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-pin</option> <varname>value</varname></term>
|
||||||
|
<listitem><para>set value of pin.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-puk</option> <varname>value</varname></term>
|
||||||
|
<listitem><para>set value of puk (or value of new pin for change pin
|
||||||
|
command see <option>-n</option>).</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-n</option></term>
|
||||||
|
<listitem><para>Changes a PIN stored on the token. User authentication
|
||||||
|
is required for this operation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-u</option></term>
|
||||||
|
<listitem><para>Unblocks a PIN stored on the token. Knowledge of the Pin
|
||||||
|
Unblock Key (PUK) is required for this operation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-cert</option> <varname>file</varname> </term>
|
||||||
|
<listitem><para>Write certificate <varname>file</varname> in pem format on the
|
||||||
|
card. User authentication is required for this operation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-F</option></term>
|
||||||
|
<listitem><para>Finalize the card, once finalize default key is invalidate so pin and puk
|
||||||
|
can'be changed anymore without user authentification. Warning, smart cards not finalized are
|
||||||
|
unsecure because pin can be changed without user authentification (knowledge of default key
|
||||||
|
is enougth).</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-r</option> <varname>n</varname></term>
|
||||||
|
<listitem><para>Forces <command>westcos-tool</command> to use reader
|
||||||
|
number <varname>n</varname> for operations.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-gf</option> <varname>path</varname></term>
|
||||||
|
<listitem><para>Get the file <varname>path</varname> the file is written
|
||||||
|
on disk with <varname>path</varname> name. User authentication
|
||||||
|
is required for this operation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-pf</option> <varname>path</varname></term>
|
||||||
|
<listitem><para>Put the file with name <varname>path</varname> from disk
|
||||||
|
to card the file is written in <varname>path</varname>. User authentication
|
||||||
|
is required for this operation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-v</option></term>
|
||||||
|
<listitem><para>Causes <command>westcos-tool</command> to be more
|
||||||
|
verbose. Specify this flag several times to enable debug output
|
||||||
|
in the OpenSC library.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-h</option></term>
|
||||||
|
<listitem><para>Print help message on screen.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>opensc(7)</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Authors</title>
|
||||||
|
<para><command>westcos-tool</command> was written by
|
||||||
|
Francois Leblanc <email>francois.leblanc@cev-sa.com</email>.</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
@ -40,12 +40,12 @@ libopensc_la_SOURCES = \
|
|||||||
card-oberthur.c card-belpic.c card-atrust-acos.c card-entersafe.c \
|
card-oberthur.c card-belpic.c card-atrust-acos.c card-entersafe.c \
|
||||||
card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \
|
card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \
|
||||||
card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
|
card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
|
||||||
card-rtecp.c \
|
card-rtecp.c card-westcos.c \
|
||||||
\
|
\
|
||||||
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
||||||
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.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-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
|
||||||
pkcs15-esinit.c \
|
pkcs15-esinit.c p15emu-westcos.c \
|
||||||
compression.c p15card-helper.c \
|
compression.c p15card-helper.c \
|
||||||
\
|
\
|
||||||
libopensc.exports
|
libopensc.exports
|
||||||
|
@ -22,6 +22,7 @@ OBJECTS = \
|
|||||||
\
|
\
|
||||||
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj \
|
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj \
|
||||||
\
|
\
|
||||||
|
card-westcos.obj crc_AetB.obj \
|
||||||
card-setcos.obj card-miocos.obj card-flex.obj card-gpk.obj \
|
card-setcos.obj card-miocos.obj card-flex.obj card-gpk.obj \
|
||||||
card-cardos.obj card-tcos.obj card-emv.obj card-default.obj \
|
card-cardos.obj card-tcos.obj card-emv.obj card-default.obj \
|
||||||
card-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \
|
card-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \
|
||||||
@ -30,6 +31,7 @@ OBJECTS = \
|
|||||||
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
|
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
|
||||||
card-rtecp.obj \
|
card-rtecp.obj \
|
||||||
\
|
\
|
||||||
|
p15emu-westcos.obj \
|
||||||
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
||||||
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.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-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
|
||||||
|
1355
src/libopensc/card-westcos.c
Normal file
1355
src/libopensc/card-westcos.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -175,6 +175,19 @@ enum {
|
|||||||
SC_CARDCTL_RTECP_INIT,
|
SC_CARDCTL_RTECP_INIT,
|
||||||
SC_CARDCTL_RTECP_INIT_END,
|
SC_CARDCTL_RTECP_INIT_END,
|
||||||
SC_CARDCTL_RTECP_GENERATE_KEY,
|
SC_CARDCTL_RTECP_GENERATE_KEY,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Westcos specific
|
||||||
|
*/
|
||||||
|
SC_CARDCTL_WESTCOS_FREEZE = _CTL_PREFIX('W', 'T', 'C'),
|
||||||
|
SC_CARDCTL_WESTCOS_CREATE_MF,
|
||||||
|
SC_CARDCTL_WESTCOS_COMMIT,
|
||||||
|
SC_CARDCTL_WESTCOS_ROLLBACK,
|
||||||
|
SC_CARDCTL_WESTCOS_AUT_KEY,
|
||||||
|
SC_CARDCTL_WESTCOS_CHANGE_KEY,
|
||||||
|
SC_CARDCTL_WESTCOS_SET_DEFAULT_KEY,
|
||||||
|
SC_CARDCTL_WESTCOS_LOAD_DATA,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -461,6 +474,22 @@ typedef struct sc_cardctl_asepcos_activate_file {
|
|||||||
#define OP_TYPE_GENERATE 0
|
#define OP_TYPE_GENERATE 0
|
||||||
#define OP_TYPE_STORE 1
|
#define OP_TYPE_STORE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Westcos
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int key_reference;
|
||||||
|
int key_len; //8, 16 or 24
|
||||||
|
u8 key_value[24];
|
||||||
|
}sc_autkey_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sc_autkey_t master_key;
|
||||||
|
sc_autkey_t new_key;
|
||||||
|
u8 key_template[7];
|
||||||
|
}sc_changekey_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RuToken types and constants
|
* RuToken types and constants
|
||||||
*/
|
*/
|
||||||
|
@ -174,6 +174,7 @@ extern sc_card_driver_t *sc_get_akis_driver(void);
|
|||||||
extern sc_card_driver_t *sc_get_entersafe_driver(void);
|
extern sc_card_driver_t *sc_get_entersafe_driver(void);
|
||||||
extern sc_card_driver_t *sc_get_rutoken_driver(void);
|
extern sc_card_driver_t *sc_get_rutoken_driver(void);
|
||||||
extern sc_card_driver_t *sc_get_rtecp_driver(void);
|
extern sc_card_driver_t *sc_get_rtecp_driver(void);
|
||||||
|
extern sc_card_driver_t *sc_get_westcos_driver(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
|||||||
#endif
|
#endif
|
||||||
{ "rutoken", (void *(*)(void)) sc_get_rutoken_driver },
|
{ "rutoken", (void *(*)(void)) sc_get_rutoken_driver },
|
||||||
{ "rutoken_ecp",(void *(*)(void)) sc_get_rtecp_driver },
|
{ "rutoken_ecp",(void *(*)(void)) sc_get_rtecp_driver },
|
||||||
|
{ "westcos", (void *(*)(void)) sc_get_westcos_driver },
|
||||||
/* emv is not really used, not sure if it works, but it conflicts with
|
/* emv is not really used, not sure if it works, but it conflicts with
|
||||||
muscle and rutoken driver, thus has to be after them */
|
muscle and rutoken driver, thus has to be after them */
|
||||||
{ "emv", (void *(*)(void)) sc_get_emv_driver },
|
{ "emv", (void *(*)(void)) sc_get_emv_driver },
|
||||||
|
251
src/libopensc/p15emu-westcos.c
Normal file
251
src/libopensc/p15emu-westcos.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* p15emu-westcos.c: pkcs15 emulation for westcos card
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 francois.leblanc@cev-sa.com
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "pkcs15.h"
|
||||||
|
#include "cardctl.h"
|
||||||
|
#include "compat_strlcpy.h"
|
||||||
|
|
||||||
|
static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
|
{
|
||||||
|
int i, r;
|
||||||
|
int modulus_length = 0, usage = 0;
|
||||||
|
u8 buf[256];
|
||||||
|
sc_card_t *card = p15card->card;
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
sc_serial_number_t serial;
|
||||||
|
sc_path_t path;
|
||||||
|
sc_file_t *file = NULL;
|
||||||
|
sc_format_path("3F00", &path);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
if (file)
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
if (p15card->label != NULL)
|
||||||
|
free(p15card->label);
|
||||||
|
p15card->label = strdup("westcos");
|
||||||
|
if (p15card->manufacturer_id != NULL)
|
||||||
|
free(p15card->manufacturer_id);
|
||||||
|
p15card->manufacturer_id = strdup("CEV");
|
||||||
|
|
||||||
|
/* get serial number */
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||||
|
r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
if (p15card->serial_number != NULL)
|
||||||
|
free(p15card->serial_number);
|
||||||
|
p15card->serial_number = strdup(buf);
|
||||||
|
p15card->version = buf[6];
|
||||||
|
p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED;
|
||||||
|
sc_format_path("AAAA", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if (!r) {
|
||||||
|
for (i = 0; i < 1; i++) {
|
||||||
|
unsigned int flags;
|
||||||
|
struct sc_pkcs15_pin_info pin_info;
|
||||||
|
struct sc_pkcs15_object pin_obj;
|
||||||
|
memset(&pin_info, 0, sizeof(pin_info));
|
||||||
|
memset(&pin_obj, 0, sizeof(pin_obj));
|
||||||
|
flags = SC_PKCS15_PIN_FLAG_INITIALIZED;
|
||||||
|
if (i == 1) {
|
||||||
|
flags |=
|
||||||
|
SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED |
|
||||||
|
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN;
|
||||||
|
}
|
||||||
|
pin_info.auth_id.len = 1;
|
||||||
|
pin_info.auth_id.value[0] = i + 1;
|
||||||
|
pin_info.reference = i;
|
||||||
|
pin_info.flags = flags;
|
||||||
|
pin_info.type = SC_PKCS15_PIN_TYPE_BCD;
|
||||||
|
pin_info.min_length = 4;
|
||||||
|
pin_info.stored_length = 8;
|
||||||
|
pin_info.max_length = 8;
|
||||||
|
pin_info.pad_char = 0xff;
|
||||||
|
pin_info.path = path;
|
||||||
|
pin_info.tries_left = -1;
|
||||||
|
if (i == 1)
|
||||||
|
strlcpy(pin_obj.label, "Unblock",
|
||||||
|
sizeof(pin_obj.label));
|
||||||
|
|
||||||
|
else
|
||||||
|
strlcpy(pin_obj.label, "User",
|
||||||
|
sizeof(pin_obj.label));
|
||||||
|
pin_obj.flags =
|
||||||
|
SC_PKCS15_CO_FLAG_MODIFIABLE |
|
||||||
|
SC_PKCS15_CO_FLAG_PRIVATE;
|
||||||
|
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj,
|
||||||
|
&pin_info);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file)
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
sc_format_path("0002", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if (!r) {
|
||||||
|
struct sc_pkcs15_cert_info cert_info;
|
||||||
|
struct sc_pkcs15_object cert_obj;
|
||||||
|
struct sc_pkcs15_pubkey_info pubkey_info;
|
||||||
|
struct sc_pkcs15_object pubkey_obj;
|
||||||
|
struct sc_pkcs15_pubkey *pkey = NULL;
|
||||||
|
memset(&cert_info, 0, sizeof(cert_info));
|
||||||
|
memset(&cert_obj, 0, sizeof(cert_obj));
|
||||||
|
cert_info.id.len = 1;
|
||||||
|
cert_info.id.value[0] = 0x45;
|
||||||
|
cert_info.authority = 0;
|
||||||
|
cert_info.path = path;
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_pkcs15_read_certificate(p15card, &cert_info,
|
||||||
|
(sc_pkcs15_cert_t
|
||||||
|
**) (&cert_obj.data));
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if (!r) {
|
||||||
|
sc_pkcs15_cert_t *cert =
|
||||||
|
(sc_pkcs15_cert_t *) (cert_obj.data);
|
||||||
|
strlcpy(cert_obj.label, "User certificat",
|
||||||
|
sizeof(cert_obj.label));
|
||||||
|
cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
|
||||||
|
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj,
|
||||||
|
&cert_info);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
pkey = &cert->key;
|
||||||
|
}
|
||||||
|
memset(&pubkey_info, 0, sizeof(pubkey_info));
|
||||||
|
memset(&pubkey_obj, 0, sizeof(pubkey_obj));
|
||||||
|
pubkey_info.id.len = 1;
|
||||||
|
pubkey_info.id.value[0] = 0x45;
|
||||||
|
pubkey_info.modulus_length = modulus_length;
|
||||||
|
pubkey_info.key_reference = 1;
|
||||||
|
pubkey_info.native = 1;
|
||||||
|
pubkey_info.usage =
|
||||||
|
SC_PKCS15_PRKEY_USAGE_VERIFY |
|
||||||
|
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
|
||||||
|
SC_PKCS15_PRKEY_USAGE_ENCRYPT |
|
||||||
|
SC_PKCS15_PRKEY_USAGE_WRAP;
|
||||||
|
pubkey_info.path = path;
|
||||||
|
strlcpy(pubkey_obj.label, "Public Key",
|
||||||
|
sizeof(pubkey_obj.label));
|
||||||
|
pubkey_obj.auth_id.len = 1;
|
||||||
|
pubkey_obj.auth_id.value[0] = 1;
|
||||||
|
pubkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
||||||
|
pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
|
||||||
|
if (pkey == NULL) {
|
||||||
|
pubkey_obj.data = &pubkey_info;
|
||||||
|
r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &pkey);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
//force rechargement clef et maj infos lors de sc_pkcs15emu_add_rsa_pubkey (sinon modulus = 0)
|
||||||
|
pubkey_obj.flags = 0;
|
||||||
|
}
|
||||||
|
if (pkey->algorithm == SC_ALGORITHM_RSA) {
|
||||||
|
modulus_length = (int)(pkey->u.rsa.modulus.len * 8);
|
||||||
|
}
|
||||||
|
pubkey_info.modulus_length = modulus_length;
|
||||||
|
pubkey_obj.data = pkey;
|
||||||
|
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj,
|
||||||
|
&pubkey_info);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!usage) {
|
||||||
|
usage =
|
||||||
|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT |
|
||||||
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
|
||||||
|
}
|
||||||
|
if (file)
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
sc_format_path("0001", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if (!r) {
|
||||||
|
struct sc_pkcs15_prkey_info prkey_info;
|
||||||
|
struct sc_pkcs15_object prkey_obj;
|
||||||
|
memset(&prkey_info, 0, sizeof(prkey_info));
|
||||||
|
memset(&prkey_obj, 0, sizeof(prkey_obj));
|
||||||
|
prkey_info.id.len = 1;
|
||||||
|
prkey_info.id.value[0] = 0x45;
|
||||||
|
prkey_info.usage =
|
||||||
|
SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT
|
||||||
|
| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
|
||||||
|
prkey_info.native = 1;
|
||||||
|
prkey_info.key_reference = 1;
|
||||||
|
prkey_info.modulus_length = modulus_length;
|
||||||
|
prkey_info.path = path;
|
||||||
|
strlcpy(prkey_obj.label, "Private Key",
|
||||||
|
sizeof(prkey_obj.label));
|
||||||
|
prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
||||||
|
prkey_obj.auth_id.len = 1;
|
||||||
|
prkey_obj.auth_id.value[0] = 1;
|
||||||
|
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj,
|
||||||
|
&prkey_info);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
r = 0;
|
||||||
|
out:if (file)
|
||||||
|
sc_file_free(file);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int westcos_detect_card(sc_pkcs15_card_t * p15card)
|
||||||
|
{
|
||||||
|
sc_card_t *card = p15card->card;
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
char *name = "WESTCOS";
|
||||||
|
if (ctx->debug >= 1)
|
||||||
|
sc_debug(ctx, "westcos_detect_card (%s)", card->name);
|
||||||
|
if (strncmp(card->name, name, strlen(name)))
|
||||||
|
return SC_ERROR_WRONG_CARD;
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_pkcs15emu_westcos_init_ex(sc_pkcs15_card_t * p15card,
|
||||||
|
sc_pkcs15emu_opt_t * opts)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
sc_card_t *card = p15card->card;
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
if (ctx->debug >= 1)
|
||||||
|
sc_debug(ctx, "sc_pkcs15_init_func_ex westcos\n");
|
||||||
|
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
|
||||||
|
return sc_pkcs15emu_westcos_init(p15card);
|
||||||
|
r = westcos_detect_card(p15card);
|
||||||
|
if (r)
|
||||||
|
return SC_ERROR_WRONG_CARD;
|
||||||
|
return sc_pkcs15emu_westcos_init(p15card);
|
||||||
|
}
|
@ -28,6 +28,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ltdl.h>
|
#include <ltdl.h>
|
||||||
|
|
||||||
|
extern int sc_pkcs15emu_westcos_init_ex(sc_pkcs15_card_t *p15card,
|
||||||
|
sc_pkcs15emu_opt_t *opts);
|
||||||
extern int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *,
|
extern int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *,
|
||||||
sc_pkcs15emu_opt_t *);
|
sc_pkcs15emu_opt_t *);
|
||||||
extern int sc_pkcs15emu_infocamere_init_ex(sc_pkcs15_card_t *,
|
extern int sc_pkcs15emu_infocamere_init_ex(sc_pkcs15_card_t *,
|
||||||
@ -58,6 +60,7 @@ static struct {
|
|||||||
const char * name;
|
const char * name;
|
||||||
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||||
} builtin_emulators[] = {
|
} builtin_emulators[] = {
|
||||||
|
{ "westcos", sc_pkcs15emu_westcos_init_ex },
|
||||||
{ "openpgp", sc_pkcs15emu_openpgp_init_ex },
|
{ "openpgp", sc_pkcs15emu_openpgp_init_ex },
|
||||||
{ "infocamere", sc_pkcs15emu_infocamere_init_ex },
|
{ "infocamere", sc_pkcs15emu_infocamere_init_ex },
|
||||||
{ "starcert", sc_pkcs15emu_starcert_init_ex },
|
{ "starcert", sc_pkcs15emu_starcert_init_ex },
|
||||||
|
@ -24,7 +24,8 @@ dist_pkgdata_DATA = \
|
|||||||
rutoken.profile \
|
rutoken.profile \
|
||||||
asepcos.profile \
|
asepcos.profile \
|
||||||
entersafe.profile \
|
entersafe.profile \
|
||||||
rutoken_ecp.profile
|
rutoken_ecp.profile \
|
||||||
|
westcos.profile
|
||||||
|
|
||||||
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
|
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
|
||||||
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS)
|
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS)
|
||||||
@ -32,6 +33,7 @@ INCLUDES = -I$(top_srcdir)/src/common -I$(top_builddir)/src/include
|
|||||||
|
|
||||||
libpkcs15init_la_SOURCES = \
|
libpkcs15init_la_SOURCES = \
|
||||||
pkcs15-lib.c profile.c keycache.c \
|
pkcs15-lib.c profile.c keycache.c \
|
||||||
|
pkcs15-westcos.c \
|
||||||
pkcs15-gpk.c pkcs15-miocos.c pkcs15-cflex.c \
|
pkcs15-gpk.c pkcs15-miocos.c pkcs15-cflex.c \
|
||||||
pkcs15-cardos.c pkcs15-jcop.c pkcs15-starcos.c \
|
pkcs15-cardos.c pkcs15-jcop.c pkcs15-starcos.c \
|
||||||
pkcs15-oberthur.c pkcs15-setcos.c pkcs15-incrypto34.c \
|
pkcs15-oberthur.c pkcs15-setcos.c pkcs15-incrypto34.c \
|
||||||
|
@ -10,7 +10,7 @@ OBJECTS = pkcs15-lib.obj profile.obj keycache.obj \
|
|||||||
pkcs15-cardos.obj pkcs15-jcop.obj pkcs15-starcos.obj \
|
pkcs15-cardos.obj pkcs15-jcop.obj pkcs15-starcos.obj \
|
||||||
pkcs15-oberthur.obj pkcs15-setcos.obj pkcs15-incrypto34.obj \
|
pkcs15-oberthur.obj pkcs15-setcos.obj pkcs15-incrypto34.obj \
|
||||||
pkcs15-muscle.obj pkcs15-asepcos.obj pkcs15-rutoken.obj \
|
pkcs15-muscle.obj pkcs15-asepcos.obj pkcs15-rutoken.obj \
|
||||||
pkcs15-entersafe.obj pkcs15-rtecp.obj \
|
pkcs15-entersafe.obj pkcs15-rtecp.obj pkcs15-westcos.obj \
|
||||||
versioninfo.res
|
versioninfo.res
|
||||||
|
|
||||||
all: install-headers $(TARGET)
|
all: install-headers $(TARGET)
|
||||||
|
@ -404,6 +404,7 @@ extern struct sc_pkcs15init_operations *sc_pkcs15init_get_asepcos_ops(void);
|
|||||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_rutoken_ops(void);
|
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_rutoken_ops(void);
|
||||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_entersafe_ops(void);
|
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_entersafe_ops(void);
|
||||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_rtecp_ops(void);
|
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_rtecp_ops(void);
|
||||||
|
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_westcos_ops(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,7 @@ static struct profile_operations {
|
|||||||
{ "asepcos", (void*) sc_pkcs15init_get_asepcos_ops },
|
{ "asepcos", (void*) sc_pkcs15init_get_asepcos_ops },
|
||||||
{ "entersafe",(void*) sc_pkcs15init_get_entersafe_ops },
|
{ "entersafe",(void*) sc_pkcs15init_get_entersafe_ops },
|
||||||
{ "rutoken_ecp", (void *) sc_pkcs15init_get_rtecp_ops },
|
{ "rutoken_ecp", (void *) sc_pkcs15init_get_rtecp_ops },
|
||||||
|
{ "westcos", (void *) sc_pkcs15init_get_westcos_ops },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
464
src/pkcs15init/pkcs15-westcos.c
Normal file
464
src/pkcs15init/pkcs15-westcos.c
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
/*
|
||||||
|
* pkcs15-westcos.c: pkcs15 support for westcos card
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 francois.leblanc@cev-sa.com
|
||||||
|
*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <opensc/opensc.h>
|
||||||
|
#include <opensc/cardctl.h>
|
||||||
|
#include "pkcs15-init.h"
|
||||||
|
#include "profile.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_OPENSSL
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int sc_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Get private and public key file
|
||||||
|
*/
|
||||||
|
static int _westcos_get_keyfiles(sc_profile_t *profile, sc_card_t *card,
|
||||||
|
const sc_path_t *df_path,
|
||||||
|
sc_file_t **prkf, sc_file_t **pukf)
|
||||||
|
{
|
||||||
|
sc_path_t path = *df_path;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Get the private key file */
|
||||||
|
r = SC_ERROR_NOT_SUPPORTED; //sc_profile_get_file_by_path(profile, &path, prkf);
|
||||||
|
if (r < 0) {
|
||||||
|
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
||||||
|
|
||||||
|
r = sc_path_print(pbuf, sizeof(pbuf), &path);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
pbuf[0] = '\0';
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the public key file */
|
||||||
|
path.len -= 2;
|
||||||
|
sc_append_file_id(&path, 0x1012);
|
||||||
|
r = SC_ERROR_NOT_SUPPORTED; //sc_profile_get_file_by_path(profile, &path, pukf);
|
||||||
|
if (r < 0) {
|
||||||
|
sc_file_free(*prkf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* currently unused */
|
||||||
|
|
||||||
|
static int westcos_pkcs15init_init_card(sc_profile_t *profile,
|
||||||
|
sc_card_t *card)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct sc_path path;
|
||||||
|
|
||||||
|
sc_format_path("3F00", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r) return (r);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int westcos_pkcs15init_create_dir(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
sc_file_t *df)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Create the application DF */
|
||||||
|
r = sc_pkcs15init_create_file(profile, card, df);
|
||||||
|
//if(r) return r;
|
||||||
|
|
||||||
|
r = sc_select_file(card, &df->path, NULL);
|
||||||
|
if(r) return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Create a PIN domain (i.e. a sub-directory holding a user PIN)
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15init_create_domain(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
const sc_pkcs15_id_t *id,
|
||||||
|
sc_file_t **ret)
|
||||||
|
{
|
||||||
|
return SC_ERROR_NOT_SUPPORTED; //sc_pkcs15_create_pin_domain(profile, card, id, ret);
|
||||||
|
}
|
||||||
|
#endif /* currently unused */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the PIN reference
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15_select_pin_reference(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
sc_pkcs15_pin_info_t *pin_info)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
|
||||||
|
pin_info->reference = 1;
|
||||||
|
} else {
|
||||||
|
pin_info->reference = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new PIN inside a DF
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15_create_pin(sc_profile_t *profile,
|
||||||
|
sc_card_t *card, sc_file_t *df,
|
||||||
|
sc_pkcs15_object_t *pin_obj,
|
||||||
|
const u8 *pin, size_t pin_len,
|
||||||
|
const u8 *puk, size_t puk_len)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
sc_file_t *file = sc_file_new();
|
||||||
|
sc_path_t path;
|
||||||
|
|
||||||
|
if(pin_len>9 || puk_len>9 || pin_len<0 || puk_len<0)
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
file->type = SC_FILE_TYPE_INTERNAL_EF;
|
||||||
|
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||||
|
file->shareable = 0;
|
||||||
|
|
||||||
|
file->id = 0xAAAA;
|
||||||
|
file->size = 37;
|
||||||
|
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NONE, 0);
|
||||||
|
if(r) return r;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_NONE, 0);
|
||||||
|
if(r) return r;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_NONE, 0);
|
||||||
|
if(r) return r;
|
||||||
|
|
||||||
|
r = sc_create_file(card, file);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
if(r != SC_ERROR_FILE_ALREADY_EXISTS)
|
||||||
|
return (r);
|
||||||
|
|
||||||
|
sc_format_path("3F005015AAAA", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r) return (r);
|
||||||
|
}
|
||||||
|
|
||||||
|
//r = sc_pkcs15init_create_file(profile, card, file);
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
sc_file_free(file);
|
||||||
|
|
||||||
|
if(pin != NULL)
|
||||||
|
{
|
||||||
|
sc_changekey_t ck;
|
||||||
|
struct sc_pin_cmd_pin pin_cmd;
|
||||||
|
|
||||||
|
memset(&pin_cmd, 0, sizeof(pin_cmd));
|
||||||
|
memset(&ck, 0, sizeof(ck));
|
||||||
|
|
||||||
|
memcpy(ck.key_template, "\x1e\x00\x00\x10", 4);
|
||||||
|
|
||||||
|
pin_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||||
|
pin_cmd.len = pin_len;
|
||||||
|
pin_cmd.data = pin;
|
||||||
|
pin_cmd.max_length = 8;
|
||||||
|
|
||||||
|
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||||
|
sizeof(ck.new_key.key_value), &pin_cmd, 1);
|
||||||
|
if(ck.new_key.key_len<0)
|
||||||
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
|
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck);
|
||||||
|
if(r) return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(puk != NULL)
|
||||||
|
{
|
||||||
|
sc_changekey_t ck;
|
||||||
|
struct sc_pin_cmd_pin puk_cmd;
|
||||||
|
|
||||||
|
memset(&puk_cmd, 0, sizeof(puk_cmd));
|
||||||
|
memset(&ck, 0, sizeof(ck));
|
||||||
|
|
||||||
|
memcpy(ck.key_template, "\x1e\x00\x00\x20", 4);
|
||||||
|
|
||||||
|
puk_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||||
|
puk_cmd.len = puk_len;
|
||||||
|
puk_cmd.data = puk;
|
||||||
|
puk_cmd.max_length = 8;
|
||||||
|
|
||||||
|
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||||
|
sizeof(ck.new_key.key_value), &puk_cmd, 1);
|
||||||
|
if(ck.new_key.key_len<0)
|
||||||
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
|
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck);
|
||||||
|
if(r) return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new key file
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15init_create_key(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
sc_pkcs15_object_t *obj)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
size_t size;
|
||||||
|
sc_file_t *keyfile = NULL;
|
||||||
|
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||||
|
|
||||||
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (key_info->modulus_length) {
|
||||||
|
case 128: size = 112; break;
|
||||||
|
case 256: size = 184; break;
|
||||||
|
case 512: size = 336; break;
|
||||||
|
case 768: size = 480; break;
|
||||||
|
case 1024: size = 616; break;
|
||||||
|
case 1536: size = 912; break;
|
||||||
|
case 2048: size = 1200; break;
|
||||||
|
default:
|
||||||
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyfile = sc_file_new();
|
||||||
|
if(keyfile == NULL)
|
||||||
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
keyfile->path = key_info->path;
|
||||||
|
|
||||||
|
keyfile->type = SC_FILE_TYPE_WORKING_EF;
|
||||||
|
keyfile->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||||
|
keyfile->shareable = 0;
|
||||||
|
keyfile->size = size;
|
||||||
|
|
||||||
|
r = sc_file_add_acl_entry(keyfile, SC_AC_OP_READ, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(keyfile, SC_AC_OP_UPDATE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(keyfile, SC_AC_OP_ERASE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
r = sc_pkcs15init_create_file(profile, card, keyfile);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
if(r != SC_ERROR_FILE_ALREADY_EXISTS)
|
||||||
|
goto out;
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(keyfile)
|
||||||
|
sc_file_free(keyfile);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store a private key
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15init_store_key(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
sc_pkcs15_object_t *obj,
|
||||||
|
sc_pkcs15_prkey_t *key)
|
||||||
|
{
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int r;
|
||||||
|
sc_file_t *keyfile;
|
||||||
|
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||||
|
|
||||||
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = SC_ERROR_NOT_SUPPORTED; //sc_profile_get_file_by_path(profile, &key_info->path, &keyfile);
|
||||||
|
if (r < 0) return r;
|
||||||
|
|
||||||
|
//r = sc_pkcs15init_update_file(profile, card, keyfile, &key->der.data, &key->der.len);
|
||||||
|
|
||||||
|
//sc_file_free(keyfile);
|
||||||
|
return r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate key
|
||||||
|
*/
|
||||||
|
static int westcos_pkcs15init_generate_key(sc_profile_t *profile,
|
||||||
|
sc_card_t *card,
|
||||||
|
sc_pkcs15_object_t *obj,
|
||||||
|
sc_pkcs15_pubkey_t *pubkey)
|
||||||
|
{
|
||||||
|
int r = SC_ERROR_UNKNOWN;
|
||||||
|
long lg;
|
||||||
|
char *p;
|
||||||
|
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||||
|
#ifdef ENABLE_OPENSSL
|
||||||
|
RSA *rsa = RSA_new();
|
||||||
|
BIGNUM *bn = BN_new();
|
||||||
|
BIO *mem = BIO_new(BIO_s_mem());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ENABLE_OPENSSL
|
||||||
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
|
#else
|
||||||
|
sc_file_t *prkf = NULL;
|
||||||
|
|
||||||
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(/*keyfile == NULL ||*/ rsa == NULL || bn == NULL || mem == NULL)
|
||||||
|
{
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pkcs11 re-route routine cryptage vers la carte fixe default to use openssl */
|
||||||
|
rsa->meth = RSA_PKCS1_SSLeay();
|
||||||
|
|
||||||
|
if(!BN_set_word(bn, RSA_F4) ||
|
||||||
|
!RSA_generate_key_ex(rsa, key_info->modulus_length, bn, NULL))
|
||||||
|
{
|
||||||
|
r = SC_ERROR_UNKNOWN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pubkey != NULL)
|
||||||
|
{
|
||||||
|
if(!i2d_RSAPublicKey_bio(mem, rsa))
|
||||||
|
{
|
||||||
|
r = SC_ERROR_UNKNOWN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lg = BIO_get_mem_data(mem, &p);
|
||||||
|
|
||||||
|
pubkey->algorithm = SC_ALGORITHM_RSA;
|
||||||
|
|
||||||
|
r = sc_pkcs15_decode_pubkey(card->ctx, pubkey, p, lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
BIO_reset(mem);
|
||||||
|
|
||||||
|
if(!i2d_RSAPrivateKey_bio(mem, rsa))
|
||||||
|
{
|
||||||
|
r = SC_ERROR_UNKNOWN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lg = BIO_get_mem_data(mem, &p);
|
||||||
|
|
||||||
|
/* Get the private key file */
|
||||||
|
r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
||||||
|
|
||||||
|
r = sc_path_print(pbuf, sizeof(pbuf), &key_info->path);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
pbuf[0] = '\0';
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_pkcs15init_update_file(profile, card, prkf, p, lg);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(mem)
|
||||||
|
BIO_free(mem);
|
||||||
|
if(bn)
|
||||||
|
BN_free(bn);
|
||||||
|
if(rsa)
|
||||||
|
RSA_free(rsa);
|
||||||
|
if(prkf)
|
||||||
|
sc_file_free(prkf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int westcos_pkcs15init_finalize_card(sc_card_t *card)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* be sure authentificate card */
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_AUT_KEY, NULL);
|
||||||
|
if(r) return (r);
|
||||||
|
|
||||||
|
return sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sc_pkcs15init_operations sc_pkcs15init_westcos_operations = {
|
||||||
|
NULL, /* erase_card */
|
||||||
|
westcos_pkcs15init_init_card, /* init_card */
|
||||||
|
westcos_pkcs15init_create_dir, /* create_dir */
|
||||||
|
NULL, /* create_domain */
|
||||||
|
westcos_pkcs15_select_pin_reference,/* select_pin_reference */
|
||||||
|
westcos_pkcs15_create_pin, /* create_pin */
|
||||||
|
NULL, /* select_key_reference */
|
||||||
|
westcos_pkcs15init_create_key, /* create_key */
|
||||||
|
westcos_pkcs15init_store_key, /* store_key */
|
||||||
|
westcos_pkcs15init_generate_key, /* generate_key */
|
||||||
|
NULL, NULL, /* encode private/public key */
|
||||||
|
westcos_pkcs15init_finalize_card, /* finalize_card */
|
||||||
|
NULL,NULL,NULL,NULL, /* old style app */
|
||||||
|
NULL, /* old_generate_key */
|
||||||
|
NULL /* delete_object */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_pkcs15init_operations* sc_pkcs15init_get_westcos_ops(void)
|
||||||
|
{
|
||||||
|
return &sc_pkcs15init_westcos_operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
183
src/pkcs15init/westcos.profile
Normal file
183
src/pkcs15init/westcos.profile
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
|
||||||
|
cardinfo {
|
||||||
|
label = "westcos";
|
||||||
|
manufacturer = "CEV";
|
||||||
|
|
||||||
|
max-pin-length = 8;
|
||||||
|
min-pin-length = 4;
|
||||||
|
pin-encoding = BCD;
|
||||||
|
pin-pad-char = 0xff;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default settings.
|
||||||
|
# This option block will always be processed.
|
||||||
|
option default {
|
||||||
|
macros {
|
||||||
|
protected = *=$PIN, READ=NONE;
|
||||||
|
unprotected = *=NONE;
|
||||||
|
private = *=$PIN;
|
||||||
|
so-pin-flags = local, initialized, needs-padding; #, soPin;
|
||||||
|
so-min-pin-length = 6;
|
||||||
|
so-pin-attempts = 2;
|
||||||
|
so-auth-id = 1; #FF;
|
||||||
|
so-puk-attempts = 4;
|
||||||
|
so-min-puk-length = 6;
|
||||||
|
unusedspace-size = 128;
|
||||||
|
odf-size = 256;
|
||||||
|
aodf-size = 256;
|
||||||
|
cdf-size = 512;
|
||||||
|
prkdf-size = 256;
|
||||||
|
pukdf-size = 256;
|
||||||
|
dodf-size = 256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PIN so-pin {
|
||||||
|
auth-id = 1;
|
||||||
|
reference = 1;
|
||||||
|
attempts = 3;
|
||||||
|
min-length = 4;
|
||||||
|
max-length = 8;
|
||||||
|
flags = local, initialized, needs-padding;
|
||||||
|
}
|
||||||
|
PIN so-puk {
|
||||||
|
auth-id = 2;
|
||||||
|
reference = 2;
|
||||||
|
attempts = 10;
|
||||||
|
min-length = 4;
|
||||||
|
max-length = 8;
|
||||||
|
flags = local, initialized, needs-padding;
|
||||||
|
}
|
||||||
|
PIN user-pin {
|
||||||
|
auth-id = 1;
|
||||||
|
reference = 1;
|
||||||
|
attempts = 3;
|
||||||
|
min-length = 4;
|
||||||
|
max-length = 8;
|
||||||
|
flags = local, initialized, needs-padding;
|
||||||
|
}
|
||||||
|
PIN user-puk {
|
||||||
|
auth-id = 2;
|
||||||
|
reference = 2;
|
||||||
|
attempts = 10;
|
||||||
|
min-length = 4;
|
||||||
|
max-length = 8;
|
||||||
|
flags = local, initialized, needs-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem {
|
||||||
|
DF MF {
|
||||||
|
path = 3F00;
|
||||||
|
type = DF;
|
||||||
|
|
||||||
|
# This is the DIR file
|
||||||
|
EF DIR {
|
||||||
|
type = EF;
|
||||||
|
file-id = 2F00;
|
||||||
|
size = 128;
|
||||||
|
acl = $unprotected;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Here comes the application DF
|
||||||
|
DF PKCS15-AppDF {
|
||||||
|
type = DF;
|
||||||
|
file-id = 5015;
|
||||||
|
aid = A0:00:00:00:63:50:4B:43:53:2D:31:35;
|
||||||
|
acl = $unprotected;
|
||||||
|
size = 5000;
|
||||||
|
|
||||||
|
EF PKCS15-ODF {
|
||||||
|
file-id = 5031;
|
||||||
|
size = $odf-size;
|
||||||
|
acl = $unprotected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-TokenInfo {
|
||||||
|
file-id = 5032;
|
||||||
|
acl = $unprotected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-UnusedSpace {
|
||||||
|
file-id = 5033;
|
||||||
|
size = $unusedspace-size;
|
||||||
|
acl = $unprotected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-AODF {
|
||||||
|
file-id = 4401;
|
||||||
|
size = $aodf-size;
|
||||||
|
acl = $protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-PrKDF {
|
||||||
|
file-id = 4402;
|
||||||
|
size = $prkdf-size;
|
||||||
|
acl = $protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-PuKDF {
|
||||||
|
file-id = 4403;
|
||||||
|
size = $pukdf-size;
|
||||||
|
acl = $protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-CDF {
|
||||||
|
file-id = 4404;
|
||||||
|
size = $cdf-size;
|
||||||
|
acl = $protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF PKCS15-DODF {
|
||||||
|
file-id = 4405;
|
||||||
|
size = $dodf-size;
|
||||||
|
ACL = $protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# This template defines files for keys, certificates etc.
|
||||||
|
#
|
||||||
|
# When instantiating the template, each file id will be
|
||||||
|
# combined with the last octet of the object's pkcs15 id
|
||||||
|
# to form a unique file ID.
|
||||||
|
template key-domain {
|
||||||
|
EF private-key {
|
||||||
|
file-id = 0100;
|
||||||
|
structure = transparent;
|
||||||
|
acl = *=NEVER, READ=$PIN, UPDATE=$PIN, WRITE=$PIN, DELETE=$PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
EF public-key {
|
||||||
|
file-id = 0200;
|
||||||
|
structure = transparent;
|
||||||
|
acl = *=NEVER, READ=NONE, UPDATE=$PIN, WRITE=$PIN, DELETE=$PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Certificate template
|
||||||
|
EF certificate {
|
||||||
|
file-id = 0300;
|
||||||
|
structure = transparent;
|
||||||
|
acl = *=NEVER, READ=NONE, UPDATE=$PIN, WRITE=$PIN, DELETE=$PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
# data objects are stored in transparent EFs.
|
||||||
|
EF data {
|
||||||
|
file-id = 0400;
|
||||||
|
structure = transparent;
|
||||||
|
acl = *=NEVER, READ=NONE, UPDATE=$PIN, WRITE=$PIN, DELETE=$PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
# private data objects are stored in transparent EFs.
|
||||||
|
EF privdata {
|
||||||
|
file-id = 0500;
|
||||||
|
structure = transparent;
|
||||||
|
acl = *=NEVER, READ=$PIN, UPDATE=$PIN, WRITE=$PIN, DELETE=$PIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ noinst_HEADERS = util.h
|
|||||||
bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \
|
bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \
|
||||||
pkcs11-tool cardos-tool eidenv rutoken-tool
|
pkcs11-tool cardos-tool eidenv rutoken-tool
|
||||||
if ENABLE_OPENSSL
|
if ENABLE_OPENSSL
|
||||||
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool
|
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool westcos-tool
|
||||||
endif
|
endif
|
||||||
dist_bin_SCRIPTS = cardos-info
|
dist_bin_SCRIPTS = cardos-info
|
||||||
if WIN32
|
if WIN32
|
||||||
@ -44,6 +44,8 @@ netkey_tool_SOURCES = netkey-tool.c
|
|||||||
netkey_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
netkey_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||||
rutoken_tool_SOURCES = rutoken-tool.c util.c
|
rutoken_tool_SOURCES = rutoken-tool.c util.c
|
||||||
rutoken_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
rutoken_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||||
|
westcos_tool_SOURCES = westcos-tool.c
|
||||||
|
westcos_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||||
|
|
||||||
if WIN32
|
if WIN32
|
||||||
opensc_tool_SOURCES += versioninfo.rc
|
opensc_tool_SOURCES += versioninfo.rc
|
||||||
@ -58,6 +60,7 @@ cardos_tool_SOURCES += versioninfo.rc
|
|||||||
eidenv_SOURCES += versioninfo.rc
|
eidenv_SOURCES += versioninfo.rc
|
||||||
netkey_tool_SOURCES += versioninfo.rc
|
netkey_tool_SOURCES += versioninfo.rc
|
||||||
rutoken_tool_SOURCES += versioninfo.rc
|
rutoken_tool_SOURCES += versioninfo.rc
|
||||||
|
westcos_tool_SOURCES += versioninfo.rc
|
||||||
else
|
else
|
||||||
dist_noinst_DATA = versioninfo.rc
|
dist_noinst_DATA = versioninfo.rc
|
||||||
endif
|
endif
|
||||||
|
@ -5,7 +5,7 @@ TOPDIR = ..\..
|
|||||||
|
|
||||||
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
|
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
|
||||||
pkcs11-tool.exe cardos-info.exe eidenv.exe rutoken-tool.exe \
|
pkcs11-tool.exe cardos-info.exe eidenv.exe rutoken-tool.exe \
|
||||||
netkey-tool.exe \
|
netkey-tool.exe westcos-tool.exe \
|
||||||
$(PROGRAMS_OPENSSL)
|
$(PROGRAMS_OPENSSL)
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
942
src/tools/westcos-tool.c
Normal file
942
src/tools/westcos-tool.c
Normal file
@ -0,0 +1,942 @@
|
|||||||
|
/*
|
||||||
|
* westcos-tool.exe: tool for westcos card
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 francois.leblanc@cev-sa.com
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <opensc/opensc.h>
|
||||||
|
#include <opensc/errors.h>
|
||||||
|
#include <opensc/pkcs15.h>
|
||||||
|
#include <opensc/cardctl.h>
|
||||||
|
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
|
static char *version ="0.0.6";
|
||||||
|
|
||||||
|
static char *nom_card = "WESTCOS";
|
||||||
|
|
||||||
|
static int finalise = 0;
|
||||||
|
static int verbose = 0;
|
||||||
|
static int install_pin = 0;
|
||||||
|
static int remplace = 0;
|
||||||
|
|
||||||
|
static char *pin = NULL;
|
||||||
|
static char *puk = NULL;
|
||||||
|
static char *cert = NULL;
|
||||||
|
|
||||||
|
static int keylen = 0;
|
||||||
|
|
||||||
|
static int no_lecteur = -1;
|
||||||
|
|
||||||
|
static int new_pin = 0;
|
||||||
|
static int debloque = 0;
|
||||||
|
|
||||||
|
static char *get_filename = NULL;
|
||||||
|
static char *get_path = NULL;
|
||||||
|
static char *put_filename = NULL;
|
||||||
|
static char *put_path = NULL;
|
||||||
|
|
||||||
|
static int do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src)
|
||||||
|
{
|
||||||
|
if (src == 0) return 0;
|
||||||
|
dst->len = BN_num_bytes(src);
|
||||||
|
dst->data = (u8 *) malloc(dst->len);
|
||||||
|
BN_bn2bin(src, dst->data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int charge = 0;
|
||||||
|
static void print_openssl_erreur(void)
|
||||||
|
{
|
||||||
|
long r;
|
||||||
|
|
||||||
|
if (!charge)
|
||||||
|
{
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
charge = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((r = ERR_get_error()) != 0)
|
||||||
|
fprintf(stderr, "%s\n", ERR_error_string(r, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static verify_pin(sc_card_t *card, int pin_reference, char *pin_value)
|
||||||
|
{
|
||||||
|
int r, tries_left = -1;
|
||||||
|
struct sc_pin_cmd_data data;
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.cmd = SC_PIN_CMD_VERIFY;
|
||||||
|
|
||||||
|
data.pin_type = SC_AC_CHV;
|
||||||
|
|
||||||
|
data.pin_reference = pin_reference;
|
||||||
|
|
||||||
|
data.flags = SC_PIN_CMD_NEED_PADDING;
|
||||||
|
|
||||||
|
if (card->slot->capabilities & SC_SLOT_CAP_PIN_PAD)
|
||||||
|
{
|
||||||
|
printf("Please enter PIN on the reader's pin pad.\n");
|
||||||
|
data.pin1.prompt = "Please enter PIN";
|
||||||
|
data.flags |= SC_PIN_CMD_USE_PINPAD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(pin_value == NULL)
|
||||||
|
{
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.pin1.data = pin_value;
|
||||||
|
data.pin1.len = strlen(pin_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_pin_cmd(card, &data, &tries_left);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
if (r == SC_ERROR_PIN_CODE_INCORRECT)
|
||||||
|
{
|
||||||
|
if (tries_left >= 0)
|
||||||
|
printf("Error %d attemps left.\n", tries_left);
|
||||||
|
else
|
||||||
|
printf("Wrong pin.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "The pin can be verify: %s\n", sc_strerror(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("Pin correct.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static change_pin(sc_card_t *card,
|
||||||
|
int pin_reference,
|
||||||
|
char *pin_value1,
|
||||||
|
char *pin_value2)
|
||||||
|
{
|
||||||
|
int r, tries_left = -1;
|
||||||
|
struct sc_pin_cmd_data data;
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.cmd = SC_PIN_CMD_CHANGE;
|
||||||
|
|
||||||
|
data.pin_type = SC_AC_CHV;
|
||||||
|
|
||||||
|
data.pin_reference = pin_reference;
|
||||||
|
|
||||||
|
data.flags = SC_PIN_CMD_NEED_PADDING;
|
||||||
|
|
||||||
|
if (card->slot->capabilities & SC_SLOT_CAP_PIN_PAD)
|
||||||
|
{
|
||||||
|
printf("Please enter PIN on the reader's pin pad.\n");
|
||||||
|
data.pin1.prompt = "Please enter PIN";
|
||||||
|
data.flags |= SC_PIN_CMD_USE_PINPAD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(pin_value1 == NULL || pin_value2 == NULL)
|
||||||
|
{
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.pin1.data = pin_value1;
|
||||||
|
data.pin1.len = strlen(pin_value1);
|
||||||
|
|
||||||
|
data.pin2.data = pin_value2;
|
||||||
|
data.pin2.len = strlen(pin_value2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_pin_cmd(card, &data, &tries_left);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
if (r == SC_ERROR_PIN_CODE_INCORRECT)
|
||||||
|
{
|
||||||
|
if (tries_left >= 0)
|
||||||
|
printf("Error %d attemps left.\n", tries_left);
|
||||||
|
else
|
||||||
|
printf("Wrong pin.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Can't change pin: %s\n",
|
||||||
|
sc_strerror(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("Pin changed.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static debloque_pin(sc_card_t *card,
|
||||||
|
int pin_reference,
|
||||||
|
char *puk_value,
|
||||||
|
char *pin_value)
|
||||||
|
{
|
||||||
|
int r, tries_left = -1;
|
||||||
|
struct sc_pin_cmd_data data;
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.cmd = SC_PIN_CMD_UNBLOCK;
|
||||||
|
|
||||||
|
data.pin_type = SC_AC_CHV;
|
||||||
|
|
||||||
|
data.pin_reference = pin_reference;
|
||||||
|
|
||||||
|
data.flags = SC_PIN_CMD_NEED_PADDING;
|
||||||
|
|
||||||
|
if (card->slot->capabilities & SC_SLOT_CAP_PIN_PAD)
|
||||||
|
{
|
||||||
|
printf("Please enter PIN on the reader's pin pad.\n");
|
||||||
|
data.pin1.prompt = "Please enter PIN";
|
||||||
|
data.flags |= SC_PIN_CMD_USE_PINPAD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(pin == NULL || puk == NULL)
|
||||||
|
{
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.pin1.data = puk_value;
|
||||||
|
data.pin1.len = strlen(puk_value);
|
||||||
|
|
||||||
|
data.pin2.data = pin_value;
|
||||||
|
data.pin2.len = strlen(pin_value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_pin_cmd(card, &data, &tries_left);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
if (r == SC_ERROR_PIN_CODE_INCORRECT)
|
||||||
|
{
|
||||||
|
if (tries_left >= 0)
|
||||||
|
printf("Error %d attemps left.\n", tries_left);
|
||||||
|
else
|
||||||
|
printf("Wrong pin.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Can't unblock pin: %s\n",
|
||||||
|
sc_strerror(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("Code debloque.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cert2der(X509 *cert, u8 **value)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
u8 *p;
|
||||||
|
len = i2d_X509(cert, NULL);
|
||||||
|
p = *value = (u8*)malloc(len);
|
||||||
|
i2d_X509(cert, &p);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int creation_fichier_cert(sc_card_t *card)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int size;
|
||||||
|
sc_path_t path;
|
||||||
|
sc_file_t *file = NULL;
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
|
||||||
|
sc_format_path("3F00", &path);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
size = (file->size) - 32;
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
{
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_format_path("0002", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
if(r != SC_ERROR_FILE_NOT_FOUND) goto out;
|
||||||
|
|
||||||
|
file = sc_file_new();
|
||||||
|
if(file == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "memory error.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||||
|
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||||
|
file->shareable = 0;
|
||||||
|
|
||||||
|
file->size = size;
|
||||||
|
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NONE, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
file->path = path;
|
||||||
|
r = sc_create_file(card, file);
|
||||||
|
if(r) goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(file)
|
||||||
|
sc_file_free(file);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
printf("Tools for westcos card.\n");
|
||||||
|
printf("version %s.\n\n", version);
|
||||||
|
printf("\t -G Generate key 1536 default.\n");
|
||||||
|
printf("\t -L [length] Key length 512,1024,1536.\n");
|
||||||
|
printf("\t -i Install pin.\n");
|
||||||
|
printf("\t -pin [value] Pin.\n");
|
||||||
|
printf("\t -puk [value] Puk.\n");
|
||||||
|
printf("\t -n Change pin (new pin in puk option).\n");
|
||||||
|
printf("\t -u Unblock pin.\n");
|
||||||
|
printf("\t -cert [file] Write certificate (in pem format).\n");
|
||||||
|
printf("\t -F Finalize card "\
|
||||||
|
"(!!! MANDATORY FOR SECURITY !!!).\n");
|
||||||
|
printf("\t -r [n] Use reader number [n]"\
|
||||||
|
" (default: autodetect).\n");
|
||||||
|
printf("\t -gf [path] Read file [path].\n");
|
||||||
|
printf("\t -pf [path] Write file [path].\n");
|
||||||
|
printf("\t -v verbose.\n");
|
||||||
|
printf("\t -h This message.\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int i = 1;
|
||||||
|
u8 *p;
|
||||||
|
int card_presente = 0;
|
||||||
|
sc_context_param_t ctx_param;
|
||||||
|
sc_reader_t *lecteur = NULL;
|
||||||
|
sc_card_t *card = NULL;
|
||||||
|
sc_context_t *ctx = NULL;
|
||||||
|
sc_file_t *file = NULL;
|
||||||
|
sc_path_t path;
|
||||||
|
RSA *rsa = RSA_new();
|
||||||
|
BIGNUM *bn = BN_new();
|
||||||
|
BIO *mem = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
|
if(rsa == NULL || bn == NULL || mem == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Not enougth memory.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i<argc)
|
||||||
|
{
|
||||||
|
p = argv[i++];
|
||||||
|
if(strcmp(p, "-gf") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
get_filename = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-pf") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
put_filename = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-F") == 0)
|
||||||
|
{
|
||||||
|
finalise = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-i") == 0)
|
||||||
|
{
|
||||||
|
install_pin = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-R") == 0)
|
||||||
|
{
|
||||||
|
remplace = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-G") == 0)
|
||||||
|
{
|
||||||
|
if(keylen == 0) keylen = 1536;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-L") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
keylen = atoi(argv[i++]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-pin") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
pin = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-puk") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
puk = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-cert") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
cert = argv[i++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-n") == 0)
|
||||||
|
{
|
||||||
|
new_pin = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-u") == 0)
|
||||||
|
{
|
||||||
|
debloque = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(p, "-r") == 0)
|
||||||
|
{
|
||||||
|
if(i<argc)
|
||||||
|
{
|
||||||
|
no_lecteur = atoi(argv[i++]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcmp(p, "-h") || !strcmp(p,"--help"))
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strncmp(p, "-v", 2))
|
||||||
|
{
|
||||||
|
char *n = p+1;
|
||||||
|
while(*n++ == 'v') verbose++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Unknown %s \n", p);
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx_param, 0, sizeof(ctx_param));
|
||||||
|
ctx_param.ver = 0;
|
||||||
|
ctx_param.app_name = argv[0];
|
||||||
|
|
||||||
|
r = sc_context_create(&ctx, &ctx_param);
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (verbose > 1)
|
||||||
|
ctx->debug = verbose-1;
|
||||||
|
|
||||||
|
if(no_lecteur == -1)
|
||||||
|
{
|
||||||
|
for(i = 0; i<sc_ctx_get_reader_count(ctx); i++)
|
||||||
|
{
|
||||||
|
lecteur = sc_ctx_get_reader(ctx, i);
|
||||||
|
if(sc_detect_card_presence(lecteur, 0))
|
||||||
|
{
|
||||||
|
r = sc_connect_card(lecteur, 0, &card);
|
||||||
|
if(r>=0)
|
||||||
|
{
|
||||||
|
printf("card->name = %s\n", card->name);
|
||||||
|
if(strncmp(card->name, nom_card, strlen(nom_card)) == 0)
|
||||||
|
{
|
||||||
|
card_presente = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sc_disconnect_card(card,0);
|
||||||
|
card = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(no_lecteur < sc_ctx_get_reader_count(ctx))
|
||||||
|
{
|
||||||
|
lecteur = sc_ctx_get_reader(ctx, no_lecteur);
|
||||||
|
r = sc_connect_card(lecteur, 0, &card);
|
||||||
|
if(r>=0)
|
||||||
|
{
|
||||||
|
card_presente = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc_disconnect_card(card,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!card_presente) goto out;
|
||||||
|
|
||||||
|
sc_lock(card);
|
||||||
|
|
||||||
|
sc_format_path("3F00", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
if(install_pin)
|
||||||
|
{
|
||||||
|
sc_format_path("AAAA", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
if(r != SC_ERROR_FILE_NOT_FOUND) goto out;
|
||||||
|
|
||||||
|
file = sc_file_new();
|
||||||
|
if(file == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Not enougth memory.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->type = SC_FILE_TYPE_INTERNAL_EF;
|
||||||
|
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||||
|
file->shareable = 0;
|
||||||
|
|
||||||
|
file->id = 0xAAAA;
|
||||||
|
file->size = 37;
|
||||||
|
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NONE, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_NONE, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_NONE, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
//sc_format_path("3F00AAAA", &(file->path));
|
||||||
|
file->path = path;
|
||||||
|
r = sc_create_file(card, file);
|
||||||
|
if(r) goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pin != NULL)
|
||||||
|
{
|
||||||
|
sc_changekey_t ck;
|
||||||
|
struct sc_pin_cmd_pin pin_cmd;
|
||||||
|
|
||||||
|
memset(&pin_cmd, 0, sizeof(pin_cmd));
|
||||||
|
memset(&ck, 0, sizeof(ck));
|
||||||
|
|
||||||
|
memcpy(ck.key_template, "\x1e\x00\x00\x10", 4);
|
||||||
|
|
||||||
|
pin_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||||
|
pin_cmd.len = strlen(pin);
|
||||||
|
pin_cmd.data = pin;
|
||||||
|
pin_cmd.max_length = 8;
|
||||||
|
|
||||||
|
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||||
|
sizeof(ck.new_key.key_value), &pin_cmd, 1);
|
||||||
|
if(ck.new_key.key_len<0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck);
|
||||||
|
if(r) goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(puk != NULL)
|
||||||
|
{
|
||||||
|
sc_changekey_t ck;
|
||||||
|
struct sc_pin_cmd_pin puk_cmd;
|
||||||
|
|
||||||
|
memset(&puk_cmd, 0, sizeof(puk_cmd));
|
||||||
|
memset(&ck, 0, sizeof(ck));
|
||||||
|
|
||||||
|
memcpy(ck.key_template, "\x1e\x00\x00\x20", 4);
|
||||||
|
|
||||||
|
puk_cmd.encoding = SC_PIN_ENCODING_GLP;
|
||||||
|
puk_cmd.len = strlen(puk);
|
||||||
|
puk_cmd.data = puk;
|
||||||
|
puk_cmd.max_length = 8;
|
||||||
|
|
||||||
|
ck.new_key.key_len = sc_build_pin(ck.new_key.key_value,
|
||||||
|
sizeof(ck.new_key.key_value), &puk_cmd, 1);
|
||||||
|
if(ck.new_key.key_len<0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck);
|
||||||
|
if(r) goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_pin)
|
||||||
|
{
|
||||||
|
if(change_pin(card, 0, pin, puk))
|
||||||
|
printf("Wrong pin.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(debloque)
|
||||||
|
{
|
||||||
|
if(debloque_pin(card, 0, puk, pin))
|
||||||
|
printf("Error unblocking pin.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("verify pin.\n");
|
||||||
|
{
|
||||||
|
if(verify_pin(card, 0, pin))
|
||||||
|
{
|
||||||
|
printf("Wrong pin.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keylen)
|
||||||
|
{
|
||||||
|
int lg;
|
||||||
|
struct sc_pkcs15_pubkey key;
|
||||||
|
struct sc_pkcs15_pubkey_rsa *dst = &(key.u.rsa);
|
||||||
|
|
||||||
|
memset(&key, 0, sizeof(key));
|
||||||
|
key.algorithm = SC_ALGORITHM_RSA;
|
||||||
|
|
||||||
|
printf("Generate key of length %d.\n", keylen);
|
||||||
|
|
||||||
|
if(!BN_set_word(bn, RSA_F4) ||
|
||||||
|
!RSA_generate_key_ex(rsa, keylen, bn, NULL))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"RSA_generate_key_ex return %d\n", ERR_get_error());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsa->meth = RSA_PKCS1_SSLeay();
|
||||||
|
|
||||||
|
if(!i2d_RSAPrivateKey_bio(mem, rsa))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"i2d_RSAPrivateKey_bio return %d\n", ERR_get_error());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lg = BIO_get_mem_data(mem, &p);
|
||||||
|
|
||||||
|
sc_format_path("0001", &path);
|
||||||
|
sc_ctx_suppress_errors_on(ctx);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
sc_ctx_suppress_errors_off(ctx);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
if(r != SC_ERROR_FILE_NOT_FOUND) goto out;
|
||||||
|
|
||||||
|
file = sc_file_new();
|
||||||
|
if(file == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Not enougth memory.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||||
|
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||||
|
file->shareable = 0;
|
||||||
|
|
||||||
|
file->size = ((lg/4)+1)*4;
|
||||||
|
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_CHV, 0);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
file->path = path;
|
||||||
|
|
||||||
|
printf("File key creation %s, size %d.\n", file->path.value,
|
||||||
|
file->size);
|
||||||
|
|
||||||
|
r = sc_create_file(card, file);
|
||||||
|
if(r) goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!remplace)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Key file already exist,"\
|
||||||
|
" use -R to replace it.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Private key length is %d\n", lg);
|
||||||
|
|
||||||
|
printf("Write private key.\n");
|
||||||
|
r = sc_update_binary(card,0,p,lg,0);
|
||||||
|
if(r<0) goto out;
|
||||||
|
printf("Private key correctly written.\n");
|
||||||
|
|
||||||
|
r = creation_fichier_cert(card);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
if (!do_convert_bignum(&dst->modulus, rsa->n)
|
||||||
|
|| !do_convert_bignum(&dst->exponent, rsa->e))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
r = sc_pkcs15_encode_pubkey(ctx, &key, &p, &lg);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
printf("Public key length %d\n", lg);
|
||||||
|
|
||||||
|
sc_format_path("3F000002", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
printf("Write public key.\n");
|
||||||
|
r = sc_update_binary(card,0,p,lg,0);
|
||||||
|
if(r<0) goto out;
|
||||||
|
printf("Public key correctly written.\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cert)
|
||||||
|
{
|
||||||
|
BIO *bio;
|
||||||
|
X509 *xp;
|
||||||
|
|
||||||
|
bio = BIO_new(BIO_s_file());
|
||||||
|
if (BIO_read_filename(bio, cert) <= 0)
|
||||||
|
{
|
||||||
|
BIO_free(bio);
|
||||||
|
fprintf(stderr, "Can't open file %s.\n", cert);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
xp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
BIO_free(bio);
|
||||||
|
if (xp == NULL)
|
||||||
|
{
|
||||||
|
print_openssl_erreur();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int lg = cert2der(xp, &p);
|
||||||
|
|
||||||
|
sc_format_path("0002", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r) goto out;
|
||||||
|
|
||||||
|
/* FIXME: verifier taille fichier compatible... */
|
||||||
|
printf("Write certificate %s.\n", cert);
|
||||||
|
|
||||||
|
r = sc_update_binary(card,0,p,lg,0);
|
||||||
|
if(r<0)
|
||||||
|
{
|
||||||
|
if(p) free(p);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(xp) X509_free(xp);
|
||||||
|
if(p) free(p);
|
||||||
|
|
||||||
|
printf("Certificate correctly written.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(finalise)
|
||||||
|
{
|
||||||
|
int mode = SC_CARDCTRL_LIFECYCLE_USER;
|
||||||
|
|
||||||
|
if(card->atr[10] != 0x82)
|
||||||
|
{
|
||||||
|
sc_format_path("0001", &path);
|
||||||
|
r = sc_select_file(card, &path, NULL);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
printf("This card don't have private key"\
|
||||||
|
" and can't be finalize.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
printf("Finalize card...\n");
|
||||||
|
if(sc_card_ctl(card, SC_CARDCTL_WESTCOS_AUT_KEY, NULL) ||
|
||||||
|
sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &mode))
|
||||||
|
{
|
||||||
|
printf("Error finalizing card,"\
|
||||||
|
" card isn't secure.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Card correctly finalized.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(get_filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
u8 *b;
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
{
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_format_path(get_filename, &path);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
printf("Error file not found.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = (u8*)malloc(file->size);
|
||||||
|
if(b == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Not enougth memory.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_read_binary(card, 0, b, file->size, 0);
|
||||||
|
if(r<0)
|
||||||
|
{
|
||||||
|
printf("Error reading file.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(get_filename, "wb");
|
||||||
|
fwrite(b, 1, file->size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(put_filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
u8 *b;
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
{
|
||||||
|
sc_file_free(file);
|
||||||
|
file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_format_path(put_filename, &path);
|
||||||
|
r = sc_select_file(card, &path, &file);
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
printf("File not found.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = (u8*)malloc(file->size);
|
||||||
|
if(b == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Not enougth memory.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(b, 0, file->size);
|
||||||
|
|
||||||
|
fp = fopen(put_filename, "rb");
|
||||||
|
fread(b, 1, file->size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
r = sc_update_binary(card, 0, b, file->size, 0);
|
||||||
|
if(r<0)
|
||||||
|
{
|
||||||
|
free(b);
|
||||||
|
printf("Error writing file.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
if(mem)
|
||||||
|
BIO_free(mem);
|
||||||
|
if(bn)
|
||||||
|
BN_free(bn);
|
||||||
|
if(rsa)
|
||||||
|
RSA_free(rsa);
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
sc_file_free(file);
|
||||||
|
|
||||||
|
if (card)
|
||||||
|
{
|
||||||
|
sc_unlock(card);
|
||||||
|
sc_disconnect_card(card, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx)
|
||||||
|
sc_release_context(ctx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user