Add new entersafe driver for ePass 3000 tokens.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3556 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
5ef6b5ff7d
commit
27d00f9265
@ -35,14 +35,14 @@ libopensc_la_SOURCES = \
|
||||
card-setcos.c card-miocos.c card-flex.c card-gpk.c \
|
||||
card-cardos.c card-tcos.c card-emv.c card-default.c \
|
||||
card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \
|
||||
card-oberthur.c card-belpic.c card-atrust-acos.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-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c\
|
||||
\
|
||||
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-rutoken.c pkcs15-esinit.c \
|
||||
compression.c p15card-helper.c \
|
||||
\
|
||||
libopensc.exports
|
||||
|
@ -25,14 +25,14 @@ OBJECTS = \
|
||||
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-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \
|
||||
card-oberthur.obj card-belpic.obj card-atrust-acos.obj \
|
||||
card-oberthur.obj card-belpic.obj card-atrust-acos.obj card-entersafe.obj \
|
||||
card-incrypto34.obj card-piv.obj card-muscle.obj card-acos5.obj \
|
||||
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
|
||||
\
|
||||
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-rutoken.obj pkcs15-esinit.obj \
|
||||
compression.obj p15card-helper.obj \
|
||||
versioninfo.res
|
||||
|
||||
|
1588
src/libopensc/card-entersafe.c
Normal file
1588
src/libopensc/card-entersafe.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -156,7 +156,17 @@ enum {
|
||||
SC_CARDCTL_RUTOKEN_GOST_ENCIPHER,
|
||||
SC_CARDCTL_RUTOKEN_GOST_DECIPHER,
|
||||
SC_CARDCTL_RUTOKEN_FORMAT_INIT,
|
||||
SC_CARDCTL_RUTOKEN_FORMAT_END
|
||||
SC_CARDCTL_RUTOKEN_FORMAT_END,
|
||||
|
||||
/*
|
||||
* EnterSafe specific calls
|
||||
*/
|
||||
SC_CARDCTL_ENTERSAFE_BASE = _CTL_PREFIX('E', 'S', 'F'),
|
||||
SC_CARDCTL_ENTERSAFE_CREATE_FILE,
|
||||
SC_CARDCTL_ENTERSAFE_CREATE_END,
|
||||
SC_CARDCTL_ENTERSAFE_WRITE_KEY,
|
||||
SC_CARDCTL_ENTERSAFE_GENERATE_KEY,
|
||||
SC_CARDCTL_ENTERSAFE_PREINSTALL_KEYS,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -551,6 +561,87 @@ struct sc_rutoken_decipherinfo {
|
||||
u8 *outbuf;
|
||||
size_t outlen;
|
||||
};
|
||||
|
||||
/*
|
||||
* EnterSafe stuff
|
||||
*
|
||||
*/
|
||||
|
||||
#define SC_ENTERSAFE_MF_DATA 0x01
|
||||
#define SC_ENTERSAFE_DF_DATA 0x02
|
||||
#define SC_ENTERSAFE_EF_DATA 0x04
|
||||
|
||||
#define ENTERSAFE_USER_PIN_ID 0x01
|
||||
#define ENTERSAFE_SO_PIN_ID 0x02
|
||||
#define ENTERSAFE_MIN_KEY_ID 0x01
|
||||
#define ENTERSAFE_MAX_KEY_ID 0x09
|
||||
|
||||
#define ENTERSAFE_AC_EVERYONE 0x00
|
||||
#define ENTERSAFE_AC_USER 0x04
|
||||
#define ENTERSAFE_AC_USER_ 0x08
|
||||
|
||||
|
||||
#define ENTERSAFE_AC_NEVER 0xC0
|
||||
#define ENTERSAFE_AC_ALWAYS 0x10
|
||||
#define ENTERSAFE_AC_CHV 0x30
|
||||
|
||||
|
||||
typedef struct sc_entersafe_create_data_st {
|
||||
unsigned int type;
|
||||
union {
|
||||
struct {
|
||||
u8 file_id[2];
|
||||
u8 file_count;
|
||||
u8 flag;
|
||||
u8 ikf_size[2];
|
||||
u8 create_ac;
|
||||
u8 append_ac;
|
||||
u8 lock_ac;
|
||||
u8 aid[16];
|
||||
u8 init_key[16];
|
||||
} mf;
|
||||
struct {
|
||||
u8 file_id[2];
|
||||
u8 file_count;
|
||||
u8 flag;
|
||||
u8 ikf_size[2];
|
||||
u8 create_ac;
|
||||
u8 append_ac;
|
||||
u8 lock_ac;
|
||||
u8 aid[16];
|
||||
u8 init_key[16];
|
||||
} df;
|
||||
struct {
|
||||
u8 file_id[2];
|
||||
u8 size[2];
|
||||
u8 attr[2];
|
||||
u8 name;
|
||||
u8 ac[10];
|
||||
u8 sm[2];
|
||||
} ef;
|
||||
} data;
|
||||
} sc_entersafe_create_data;
|
||||
|
||||
typedef struct sc_entersafe_wkey_data_st {
|
||||
u8 key_id;
|
||||
u8 usage;
|
||||
union{
|
||||
struct sc_pkcs15_prkey_rsa* rsa;
|
||||
struct{
|
||||
u8 EC;
|
||||
u8 ver;
|
||||
u8 key_val[256];
|
||||
size_t key_len;
|
||||
} symmetric;
|
||||
}key_data;
|
||||
} sc_entersafe_wkey_data;
|
||||
|
||||
typedef struct sc_entersafe_gen_key_data_st {
|
||||
u8 key_id;
|
||||
size_t key_length;
|
||||
u8 *modulus;
|
||||
} sc_entersafe_gen_key_data;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -138,7 +138,11 @@ enum {
|
||||
|
||||
/* TUBITAK UEKAE cards */
|
||||
SC_CARD_TYPE_AKIS_BASE = 18000,
|
||||
SC_CARD_TYPE_AKIS_GENERIC
|
||||
SC_CARD_TYPE_AKIS_GENERIC,
|
||||
|
||||
/* EnterSafe cards */
|
||||
SC_CARD_TYPE_ENTERSAFE_BASE = 19000,
|
||||
SC_CARD_TYPE_ENTERSAFE_3K,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -81,6 +81,9 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
||||
#endif
|
||||
{ "acos5", (void *(*)(void)) sc_get_acos5_driver },
|
||||
{ "akis", (void *(*)(void)) sc_get_akis_driver },
|
||||
#ifdef ENABLE_OPENSSL
|
||||
{ "entersafe",(void *(*)(void)) sc_get_entersafe_driver },
|
||||
#endif
|
||||
/* The default driver should be last, as it handles all the
|
||||
* unrecognized cards. */
|
||||
{ "default", (void *(*)(void)) sc_get_default_driver },
|
||||
|
@ -1199,6 +1199,7 @@ extern sc_card_driver_t *sc_get_muscle_driver(void);
|
||||
extern sc_card_driver_t *sc_get_acos5_driver(void);
|
||||
extern sc_card_driver_t *sc_get_asepcos_driver(void);
|
||||
extern sc_card_driver_t *sc_get_akis_driver(void);
|
||||
extern sc_card_driver_t *sc_get_entersafe_driver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
89
src/libopensc/pkcs15-esinit.c
Normal file
89
src/libopensc/pkcs15-esinit.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
/* Initially written by Weitao Sun (weitao@ftsafe.com) 2008*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "pkcs15.h"
|
||||
#include "cardctl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define MANU_ID "entersafe"
|
||||
|
||||
static int entersafe_detect_card( sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
/* check if we have the correct card OS */
|
||||
if (strcmp(card->name, "entersafe"))
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int sc_pkcs15emu_entersafe_init( sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
int r, i;
|
||||
char buf[256];
|
||||
sc_path_t path;
|
||||
sc_file_t *file = NULL;
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_serial_number_t serial;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
/* 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 != SC_SUCCESS)
|
||||
return SC_ERROR_INTERNAL;
|
||||
if (p15card->serial_number)
|
||||
free(p15card->serial_number);
|
||||
p15card->serial_number = (char *) malloc(strlen(buf) + 1);
|
||||
if (!p15card->serial_number)
|
||||
return SC_ERROR_INTERNAL;
|
||||
strcpy(p15card->serial_number, buf);
|
||||
|
||||
/* the manufacturer ID, in this case Giesecke & Devrient GmbH */
|
||||
if (p15card->manufacturer_id)
|
||||
free(p15card->manufacturer_id);
|
||||
p15card->manufacturer_id = (char *) malloc(strlen(MANU_ID) + 1);
|
||||
if (!p15card->manufacturer_id)
|
||||
return SC_ERROR_INTERNAL;
|
||||
strcpy(p15card->manufacturer_id, MANU_ID);
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_entersafe_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts)
|
||||
{
|
||||
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
||||
|
||||
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
|
||||
return sc_pkcs15emu_entersafe_init(p15card);
|
||||
else {
|
||||
int r = entersafe_detect_card(p15card);
|
||||
if (r)
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
return sc_pkcs15emu_entersafe_init(p15card);
|
||||
}
|
||||
}
|
@ -54,6 +54,8 @@ extern int sc_pkcs15emu_tccardos_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t
|
||||
|
||||
extern int sc_pkcs15emu_rutoken_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||
|
||||
extern int sc_pkcs15emu_entersafe_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||
@ -71,6 +73,7 @@ static struct {
|
||||
{ "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex},
|
||||
{ "tccardos", sc_pkcs15emu_tccardos_init_ex },
|
||||
{ "rutoken", sc_pkcs15emu_rutoken_init_ex },
|
||||
{ "entersafe", sc_pkcs15emu_entersafe_init_ex },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,8 @@ dist_pkgdata_DATA = \
|
||||
pkcs15.profile \
|
||||
muscle.profile \
|
||||
rutoken.profile \
|
||||
asepcos.profile
|
||||
asepcos.profile \
|
||||
entersafe.profile
|
||||
|
||||
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
|
||||
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS)
|
||||
@ -34,6 +35,7 @@ libpkcs15init_la_SOURCES = \
|
||||
pkcs15-cardos.c pkcs15-jcop.c pkcs15-starcos.c \
|
||||
pkcs15-oberthur.c pkcs15-setcos.c pkcs15-incrypto34.c \
|
||||
pkcs15-muscle.c pkcs15-asepcos.c pkcs15-rutoken.c \
|
||||
pkcs15-entersafe.c \
|
||||
pkcs15init.exports
|
||||
if WIN32
|
||||
libpkcs15init_la_SOURCES += versioninfo.rc
|
||||
|
@ -10,6 +10,7 @@ OBJECTS = pkcs15-lib.obj profile.obj keycache.obj \
|
||||
pkcs15-cardos.obj pkcs15-jcop.obj pkcs15-starcos.obj \
|
||||
pkcs15-oberthur.obj pkcs15-setcos.obj pkcs15-incrypto34.obj \
|
||||
pkcs15-muscle.obj pkcs15-asepcos.obj pkcs15-rutoken.obj \
|
||||
pkcs15-entersafe.obj \
|
||||
versioninfo.res
|
||||
|
||||
all: install-headers $(TARGET)
|
||||
|
181
src/pkcs15init/entersafe.profile
Normal file
181
src/pkcs15init/entersafe.profile
Normal file
@ -0,0 +1,181 @@
|
||||
#
|
||||
# pkcs15 profile for entersafe
|
||||
#
|
||||
cardinfo {
|
||||
manufacturer = "EnterSafe";
|
||||
min-pin-length = 4;
|
||||
max-pin-length = 16;
|
||||
pin-encoding = ascii-numeric;
|
||||
pin-pad-char = 0x00;
|
||||
}
|
||||
|
||||
option default {
|
||||
macros {
|
||||
pin-flags = initialized, needs-padding;
|
||||
df_acl = *=NEVER;
|
||||
protected = *=$PIN,READ=NONE;
|
||||
dir-size = 128;
|
||||
tinfo-size = 128;
|
||||
unusedspace-size = 128;
|
||||
odf-size = 256;
|
||||
aodf-size = 256;
|
||||
cdf-size = 512;
|
||||
prkdf-size = 256;
|
||||
pukdf-size = 256;
|
||||
dodf-size = 256;
|
||||
info-size = 128;
|
||||
}
|
||||
}
|
||||
|
||||
option onepin {
|
||||
macros {
|
||||
pin-flags = initialized, needs-padding;
|
||||
df_acl = *=$PIN;
|
||||
protected = *=$PIN,READ=NONE;
|
||||
dir-size = 128;
|
||||
tinfo-size = 128;
|
||||
unusedspace-size = 128;
|
||||
odf-size = 256;
|
||||
aodf-size = 256;
|
||||
cdf-size = 512;
|
||||
prkdf-size = 256;
|
||||
pukdf-size = 256;
|
||||
dodf-size = 256;
|
||||
info-size = 128;
|
||||
}
|
||||
}
|
||||
|
||||
PIN so-pin {
|
||||
reference = 1;
|
||||
attempts = 3;
|
||||
flags = $pin-flags;
|
||||
}
|
||||
PIN so-puk {
|
||||
reference = 1;
|
||||
attempts = 3;
|
||||
flags = $pin-flags;
|
||||
}
|
||||
PIN user-pin {
|
||||
reference = 1;
|
||||
attempts = 3;
|
||||
flags = $pin-flags;
|
||||
}
|
||||
PIN user-puk {
|
||||
reference = 1;
|
||||
attempts = 3;
|
||||
flags = $pin-flags;
|
||||
}
|
||||
|
||||
# Additional filesystem info.
|
||||
# This is added to the file system info specified in the
|
||||
# main profile.
|
||||
filesystem {
|
||||
DF MF {
|
||||
ACL = $df_acl;
|
||||
size = 768;
|
||||
|
||||
EF dir {
|
||||
type = EF;
|
||||
size = $dir-size;
|
||||
ACL = $protected;
|
||||
file-id = 2F00;
|
||||
structure = transparent;
|
||||
}
|
||||
|
||||
DF PKCS15-AppDF {
|
||||
ACL = $df_acl;
|
||||
size = 16000;
|
||||
|
||||
# INTERNAL SECRET KEY file of the application DF
|
||||
# Note: if the WRITE ACL is commented out or no
|
||||
# sopin is specified the ACs must be activated via
|
||||
# 'pkcs15-init --finalize' (in this case the
|
||||
# AC WRITE is NEVER as the required state can't
|
||||
# be reached).
|
||||
EF p15_gpkf {
|
||||
file-id = FFFD;
|
||||
structure = transparent;
|
||||
size = 2560;
|
||||
ACL = $df_acl;
|
||||
}
|
||||
|
||||
EF PKCS15-ODF {
|
||||
size = $odf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-TokenInfo {
|
||||
size = $tinfo-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-UnusedSpace {
|
||||
size = $unusedspace-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-AODF {
|
||||
size = $aodf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-PrKDF {
|
||||
size = $prkdf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-PuKDF {
|
||||
size = $pukdf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-CDF {
|
||||
size = $cdf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
EF PKCS15-DODF {
|
||||
size = $dodf-size;
|
||||
ACL = $protected;
|
||||
}
|
||||
|
||||
template key-domain {
|
||||
# This is a dummy entry - pkcs15-init insists that
|
||||
# this is present
|
||||
EF private-key {
|
||||
file-id = FFFF;
|
||||
}
|
||||
EF public-key {
|
||||
file-id = 3003;
|
||||
size = 320;
|
||||
structure = transparent;
|
||||
ACL = *=NEVER,READ=NONE,UPDATE=$PIN;
|
||||
}
|
||||
|
||||
# Certificate template
|
||||
EF certificate {
|
||||
file-id = 3104;
|
||||
structure = transparent;
|
||||
ACL = *=NEVER,READ=NONE,UPDATE=$PIN;
|
||||
}
|
||||
|
||||
# Extractable private keys are stored in transparent EFs.
|
||||
# Encryption of the content is performed by libopensc.
|
||||
EF extractable-key {
|
||||
file-id = 3201;
|
||||
structure = transparent;
|
||||
ACL = *=NEVER,READ=NONE,UPDATE=$PIN;
|
||||
}
|
||||
|
||||
# data objects are stored in transparent EFs.
|
||||
EF data {
|
||||
file-id = 3301;
|
||||
structure = transparent;
|
||||
ACL = *=NEVER,READ=NONE,UPDATE=$PIN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
416
src/pkcs15init/pkcs15-entersafe.c
Normal file
416
src/pkcs15init/pkcs15-entersafe.c
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
/* Initially written by Weitao Sun (weitao@ftsafe.com) 2008*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <opensc/log.h>
|
||||
#include <opensc/opensc.h>
|
||||
#include <opensc/cardctl.h>
|
||||
#include "pkcs15-init.h"
|
||||
#include "profile.h"
|
||||
|
||||
static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def)
|
||||
{
|
||||
u8 def = (u8)in_def;
|
||||
const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method);
|
||||
if (!entry)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
else if (entry->method == SC_AC_CHV)
|
||||
{
|
||||
unsigned int key_ref = entry->key_ref;
|
||||
if (key_ref == SC_AC_KEY_REF_NONE)
|
||||
return def;
|
||||
else
|
||||
return ENTERSAFE_AC_ALWAYS&0x04;
|
||||
}
|
||||
else if (entry->method == SC_AC_SYMBOLIC)
|
||||
{
|
||||
return ENTERSAFE_AC_ALWAYS&0x04;
|
||||
}
|
||||
else if (entry->method == SC_AC_NEVER)
|
||||
{
|
||||
return ENTERSAFE_AC_NEVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
static int entersafe_erase_card(struct sc_profile *profile, sc_card_t *card)
|
||||
{
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
return sc_card_ctl(card,SC_CARDCTL_ERASE_CARD,0);
|
||||
}
|
||||
|
||||
static int entersafe_init_card(sc_profile_t *profile, sc_card_t *card)
|
||||
{
|
||||
int ret;
|
||||
|
||||
{/* MF */
|
||||
sc_file_t *mf_file;
|
||||
sc_entersafe_create_data mf_data;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
ret = sc_profile_get_file(profile, "MF", &mf_file);
|
||||
SC_TEST_RET(card->ctx,ret,"Get MF info failed");
|
||||
|
||||
mf_data.type = SC_ENTERSAFE_MF_DATA;
|
||||
mf_data.data.df.file_id[0]=0x3F;
|
||||
mf_data.data.df.file_id[1]=0x00;
|
||||
mf_data.data.df.file_count=0x04;
|
||||
mf_data.data.df.flag=0x11;
|
||||
mf_data.data.df.ikf_size[0]=(mf_file->size>>8)&0xFF;
|
||||
mf_data.data.df.ikf_size[1]=mf_file->size&0xFF;
|
||||
mf_data.data.df.create_ac=0x10;
|
||||
mf_data.data.df.append_ac=0xC0;
|
||||
mf_data.data.df.lock_ac=0x10;
|
||||
memcpy(mf_data.data.df.aid,mf_file->name,mf_file->namelen);
|
||||
sc_file_free(mf_file);
|
||||
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &mf_data);
|
||||
SC_TEST_RET(card->ctx,ret,"Create MF failed");
|
||||
}
|
||||
|
||||
{/* EF(DIR) */
|
||||
sc_file_t *dir_file;
|
||||
size_t fid,size;
|
||||
sc_entersafe_create_data ef_data;
|
||||
u8 *buff=0;
|
||||
|
||||
/* get dir profile */
|
||||
ret = sc_profile_get_file(profile, "dir", &dir_file);
|
||||
SC_TEST_RET(card->ctx,ret,"Get EF(DIR) info failed");
|
||||
fid=dir_file->id;
|
||||
size=dir_file->size;
|
||||
sc_file_free(dir_file);
|
||||
|
||||
ef_data.type=SC_ENTERSAFE_EF_DATA;
|
||||
ef_data.data.ef.file_id[0]=(fid>>8)&0xFF;
|
||||
ef_data.data.ef.file_id[1]=fid&0xFF;
|
||||
ef_data.data.ef.size[0]=(size>>8)&0xFF;
|
||||
ef_data.data.ef.size[1]=size&0xFF;
|
||||
ef_data.data.ef.attr[0]=0x00;
|
||||
ef_data.data.ef.attr[1]=0x00;
|
||||
ef_data.data.ef.name=0x00;
|
||||
memset(ef_data.data.ef.ac,0x10,sizeof(ef_data.data.ef.ac));
|
||||
memset(ef_data.data.ef.sm,0x00,sizeof(ef_data.data.ef.sm));
|
||||
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &ef_data);
|
||||
SC_TEST_RET(card->ctx,ret,"Create EF(DIR) failed");
|
||||
|
||||
|
||||
/* fill file by 0 */
|
||||
buff = calloc(1,size);
|
||||
if(!buff)
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
memset(buff,0,size);
|
||||
|
||||
ret = sc_update_binary(card,0,buff,size,0);
|
||||
free(buff);
|
||||
SC_TEST_RET(card->ctx,ret,"Initialize EF(DIR) failed");
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
static int entersafe_create_dir(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_file_t *df)
|
||||
{
|
||||
int ret;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
{/* df */
|
||||
sc_entersafe_create_data df_data;
|
||||
|
||||
df_data.type = SC_ENTERSAFE_DF_DATA;
|
||||
df_data.data.df.file_id[0]=(df->id >> 8) & 0xFF;
|
||||
df_data.data.df.file_id[1]=df->id & 0xFF;
|
||||
df_data.data.df.file_count=0x0F;
|
||||
df_data.data.df.flag=0x01;
|
||||
df_data.data.df.ikf_size[0]=(df->size>>8)&0xFF;
|
||||
df_data.data.df.ikf_size[1]=df->size&0xFF;
|
||||
df_data.data.df.create_ac=0x10;
|
||||
df_data.data.df.append_ac=0xC0;
|
||||
df_data.data.df.lock_ac=0x10;
|
||||
memcpy(df_data.data.df.aid,df->name,df->namelen);
|
||||
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &df_data);
|
||||
SC_TEST_RET(card->ctx,ret,"Crate DF failed");
|
||||
}
|
||||
|
||||
{/* GPKF */
|
||||
sc_file_t *gpkf_file;
|
||||
sc_entersafe_create_data ef_data;
|
||||
|
||||
/* get p15_gpkf profile */
|
||||
ret = sc_profile_get_file(profile, "p15_gpkf", &gpkf_file);
|
||||
SC_TEST_RET(card->ctx,ret,"Get GPKF info failed");
|
||||
|
||||
ef_data.type=SC_ENTERSAFE_EF_DATA;
|
||||
ef_data.data.ef.file_id[0]=(gpkf_file->id>>8)&0xFF;
|
||||
ef_data.data.ef.file_id[1]=gpkf_file->id&0xFF;
|
||||
ef_data.data.ef.size[0]=(gpkf_file->size>>8)&0xFF;
|
||||
ef_data.data.ef.size[1]=gpkf_file->size&0xFF;
|
||||
ef_data.data.ef.attr[0]=0x15;
|
||||
ef_data.data.ef.attr[1]=0x80;
|
||||
ef_data.data.ef.name=0x00;
|
||||
memset(ef_data.data.ef.ac,0x10,sizeof(ef_data.data.ef.ac));
|
||||
memset(ef_data.data.ef.sm,0x00,sizeof(ef_data.data.ef.sm));
|
||||
|
||||
sc_file_free(gpkf_file);
|
||||
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &ef_data);
|
||||
SC_TEST_RET(card->ctx,ret,"Create GPKF failed");
|
||||
}
|
||||
|
||||
{/* p15 efs */
|
||||
char* create_efs[]={
|
||||
"PKCS15-ODF",
|
||||
"PKCS15-TokenInfo",
|
||||
"PKCS15-UnusedSpace",
|
||||
"PKCS15-AODF",
|
||||
"PKCS15-PrKDF",
|
||||
"PKCS15-PuKDF",
|
||||
"PKCS15-CDF",
|
||||
"PKCS15-DODF",
|
||||
NULL,
|
||||
};
|
||||
int i;
|
||||
sc_file_t *file=0;
|
||||
sc_entersafe_create_data tmp;
|
||||
|
||||
for(i = 0; create_efs[i]; ++i) {
|
||||
if (sc_profile_get_file(profile, create_efs[i], &file)) {
|
||||
sc_error(card->ctx, "Inconsistent profile: cannot find %s", create_efs[i]);
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_ERROR_INCONSISTENT_PROFILE);
|
||||
}
|
||||
|
||||
tmp.type=SC_ENTERSAFE_EF_DATA;
|
||||
tmp.data.ef.file_id[0]=(file->id>>8)&0xFF;
|
||||
tmp.data.ef.file_id[1]=file->id&0xFF;
|
||||
tmp.data.ef.size[0]=(file->size>>8)&0xFF;
|
||||
tmp.data.ef.size[1]=file->size&0xFF;
|
||||
tmp.data.ef.attr[0]=0x00;
|
||||
tmp.data.ef.attr[1]=0x00;
|
||||
tmp.data.ef.name=0x00;
|
||||
memset(tmp.data.ef.ac,ENTERSAFE_AC_ALWAYS,sizeof(tmp.data.ef.ac));
|
||||
tmp.data.ef.ac[0]=process_acl_entry(file,SC_AC_OP_READ,ENTERSAFE_AC_ALWAYS); /* read */
|
||||
tmp.data.ef.ac[1]=process_acl_entry(file,SC_AC_OP_UPDATE,ENTERSAFE_AC_ALWAYS); /* update */
|
||||
memset(tmp.data.ef.sm,0x00,sizeof(tmp.data.ef.sm));
|
||||
|
||||
sc_file_free(file);
|
||||
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &tmp);
|
||||
SC_TEST_RET(card->ctx,ret,"Create pkcs15 file failed");
|
||||
}
|
||||
}
|
||||
|
||||
{/* Preinstall keys */
|
||||
ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_PREINSTALL_KEYS, 0);
|
||||
SC_TEST_RET(card->ctx,ret,"Preinstall keys failed");
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx,4,ret);
|
||||
}
|
||||
|
||||
static int entersafe_pin_reference(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_pkcs15_pin_info_t *pin_info)
|
||||
{
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (pin_info->reference < ENTERSAFE_USER_PIN_ID)
|
||||
pin_info->reference = ENTERSAFE_USER_PIN_ID;
|
||||
if(pin_info->reference>ENTERSAFE_USER_PIN_ID)
|
||||
return SC_ERROR_TOO_MANY_OBJECTS;
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int entersafe_create_pin(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_file_t *df, sc_pkcs15_object_t *pin_obj,
|
||||
const unsigned char *pin, size_t pin_len,
|
||||
const unsigned char *puk, size_t puk_len)
|
||||
{
|
||||
int r;
|
||||
sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
|
||||
sc_entersafe_wkey_data data;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (!pin || !pin_len || pin_len > 16)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
data.key_id=pin_info->reference;
|
||||
data.usage=0x0B;
|
||||
data.key_data.symmetric.EC=0x33;
|
||||
data.key_data.symmetric.ver=0x00;
|
||||
/* pad pin with 0 */
|
||||
memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val));
|
||||
memcpy(data.key_data.symmetric.key_val, pin, pin_len);
|
||||
data.key_data.symmetric.key_len=16;
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx,4,r);
|
||||
}
|
||||
|
||||
static int entersafe_key_reference(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_pkcs15_prkey_info_t *prkey)
|
||||
{
|
||||
struct sc_file *df = profile->df_info->file;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (prkey->key_reference < ENTERSAFE_MIN_KEY_ID)
|
||||
prkey->key_reference = ENTERSAFE_MIN_KEY_ID;
|
||||
if (prkey->key_reference > ENTERSAFE_MAX_KEY_ID)
|
||||
return SC_ERROR_TOO_MANY_OBJECTS;
|
||||
|
||||
prkey->path = df->path;
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int entersafe_create_key(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_pkcs15_object_t *obj)
|
||||
{
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int entersafe_store_key(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key)
|
||||
{
|
||||
sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||
sc_entersafe_wkey_data data;
|
||||
sc_file_t *tfile;
|
||||
const sc_acl_entry_t *acl_entry;
|
||||
int r;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (key->algorithm != SC_ALGORITHM_RSA)
|
||||
/* ignore DSA keys */
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile);
|
||||
if (r < 0)
|
||||
return r;
|
||||
acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE);
|
||||
if (acl_entry->method != SC_AC_NONE) {
|
||||
r = sc_pkcs15init_authenticate(profile, card, tfile, SC_AC_OP_UPDATE);
|
||||
if(r<0)
|
||||
r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||
}
|
||||
sc_file_free(tfile);
|
||||
SC_TEST_RET(card->ctx, r, "cant verify pin");
|
||||
|
||||
data.key_id = (u8) kinfo->key_reference;
|
||||
data.usage=0x22;
|
||||
data.key_data.rsa=&key->u.rsa;
|
||||
return sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data);
|
||||
}
|
||||
|
||||
static int entersafe_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||
sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey)
|
||||
{
|
||||
int r;
|
||||
sc_entersafe_gen_key_data gendat;
|
||||
sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||
sc_file_t *tfile;
|
||||
const sc_acl_entry_t *acl_entry;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
|
||||
r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile);
|
||||
if (r < 0)
|
||||
return r;
|
||||
acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE);
|
||||
if (acl_entry->method != SC_AC_NONE) {
|
||||
r = sc_pkcs15init_authenticate(profile, card, tfile, SC_AC_OP_UPDATE);
|
||||
if(r<0)
|
||||
r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||
}
|
||||
sc_file_free(tfile);
|
||||
SC_TEST_RET(card->ctx, r, "cant verify pin");
|
||||
|
||||
/* generate key pair */
|
||||
gendat.key_id = (u8) kinfo->key_reference;
|
||||
gendat.key_length = (size_t) kinfo->modulus_length;
|
||||
gendat.modulus = NULL;
|
||||
r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_GENERATE_KEY, &gendat);
|
||||
SC_TEST_RET(card->ctx, r, "EnterSafe generate RSA key pair failed");
|
||||
|
||||
/* get the modulus via READ PUBLIC KEY */
|
||||
if (pubkey) {
|
||||
u8 *buf;
|
||||
struct sc_pkcs15_pubkey_rsa *rsa = &pubkey->u.rsa;
|
||||
/* set the modulus */
|
||||
rsa->modulus.data = gendat.modulus;
|
||||
rsa->modulus.len = kinfo->modulus_length >> 3;
|
||||
/* set the exponent (always 0x10001) */
|
||||
buf = (u8 *) malloc(3);
|
||||
if (!buf)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x01;
|
||||
rsa->exponent.data = buf;
|
||||
rsa->exponent.len = 3;
|
||||
|
||||
pubkey->algorithm = SC_ALGORITHM_RSA;
|
||||
} else
|
||||
/* free public key */
|
||||
free(gendat.modulus);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS);
|
||||
}
|
||||
|
||||
static struct sc_pkcs15init_operations sc_pkcs15init_entersafe_operations = {
|
||||
entersafe_erase_card,
|
||||
entersafe_init_card,
|
||||
entersafe_create_dir,
|
||||
NULL, /* create_domain */
|
||||
entersafe_pin_reference,
|
||||
entersafe_create_pin,
|
||||
entersafe_key_reference,
|
||||
entersafe_create_key,
|
||||
entersafe_store_key,
|
||||
entersafe_generate_key,
|
||||
NULL, NULL, /* encode private/public key */
|
||||
NULL, /* finalize */
|
||||
NULL, NULL, NULL, NULL, NULL, /* old style api */
|
||||
NULL /* delete_object */
|
||||
};
|
||||
|
||||
struct sc_pkcs15init_operations *sc_pkcs15init_get_entersafe_ops(void)
|
||||
{
|
||||
return &sc_pkcs15init_entersafe_operations;
|
||||
}
|
@ -402,6 +402,7 @@ extern struct sc_pkcs15init_operations *sc_pkcs15init_get_incrypto34_ops(void);
|
||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_muscle_ops(void);
|
||||
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_entersafe_ops(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ static struct profile_operations {
|
||||
{ "incrypto34", (void *) sc_pkcs15init_get_incrypto34_ops },
|
||||
{ "muscle", (void*) sc_pkcs15init_get_muscle_ops },
|
||||
{ "asepcos", (void*) sc_pkcs15init_get_asepcos_ops },
|
||||
{ "entersafe",(void*) sc_pkcs15init_get_entersafe_ops },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
@ -2793,9 +2794,13 @@ sc_pkcs15init_change_attrib(struct sc_pkcs15_card *p15card,
|
||||
|
||||
r = sc_pkcs15_encode_df(card->ctx, p15card, df, &buf, &bufsize);
|
||||
if (r >= 0) {
|
||||
sc_file_t *file;
|
||||
r = sc_profile_get_file_by_path(profile, &df->path, &file);
|
||||
if(r<0) return r;
|
||||
r = sc_pkcs15init_update_file(profile, card,
|
||||
df->file, buf, bufsize);
|
||||
file, buf, bufsize);
|
||||
free(buf);
|
||||
sc_file_free(file);
|
||||
}
|
||||
|
||||
return r < 0 ? r : 0;
|
||||
@ -3269,15 +3274,25 @@ sc_pkcs15init_authenticate(struct sc_profile *pro, sc_card_t *card,
|
||||
else
|
||||
acl = sc_file_get_acl_entry(file, op);
|
||||
|
||||
sc_debug(card->ctx, "r:[0x%08x]\n",r);
|
||||
sc_debug(card->ctx, "acl:[0x%08x]\n",acl);
|
||||
|
||||
for (; r == 0 && acl; acl = acl->next) {
|
||||
if (acl->method == SC_AC_NEVER)
|
||||
{
|
||||
sc_debug(card->ctx, "never\n");
|
||||
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||
}
|
||||
if (acl->method == SC_AC_NONE)
|
||||
{
|
||||
sc_debug(card->ctx, "none\n");
|
||||
break;
|
||||
}
|
||||
if (acl->method == SC_AC_UNKNOWN) {
|
||||
sc_debug(card->ctx, "unknown acl method\n");
|
||||
break;
|
||||
}
|
||||
sc_debug(card->ctx, "verify\n");
|
||||
r = do_verify_pin(pro, card, file_tmp ? file_tmp : file,
|
||||
acl->method, acl->key_ref);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user