First support for GIDS card
- minidriver included by default in Windows - GIDS Applet is available here https://github.com/vletoux/GidsApplet - some informative technical information is available here http://www.mysmartlogon.com/knowledge-base/generic-identity-device-specification-gids-kb/ closes https://github.com/OpenSC/OpenSC/pull/651
This commit is contained in:
parent
1ca22a22d1
commit
6a243449a0
|
@ -11,7 +11,7 @@ noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.
|
|||
cardctl.h asn1.h log.h \
|
||||
errors.h types.h compression.h itacns.h iso7816.h \
|
||||
authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \
|
||||
pace.h cwa14890.h cwa-dnie.h
|
||||
pace.h cwa14890.h cwa-dnie.h card-gids.h
|
||||
|
||||
AM_CPPFLAGS = -DOPENSC_CONF_PATH=\"$(sysconfdir)/opensc.conf\" \
|
||||
-I$(top_srcdir)/src
|
||||
|
@ -41,14 +41,14 @@ libopensc_la_SOURCES = \
|
|||
card-itacns.c card-authentic.c \
|
||||
card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \
|
||||
card-dnie.c cwa14890.c cwa-dnie.c \
|
||||
card-isoApplet.c card-masktech.c \
|
||||
card-isoApplet.c card-masktech.c card-gids.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-esinit.c pkcs15-westcos.c pkcs15-pteid.c pkcs15-oberthur.c \
|
||||
pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \
|
||||
pkcs15-dnie.c \
|
||||
pkcs15-dnie.c pkcs15-gids.c \
|
||||
compression.c p15card-helper.c sm.c \
|
||||
libopensc.exports
|
||||
if WIN32
|
||||
|
|
|
@ -24,14 +24,14 @@ OBJECTS = \
|
|||
card-itacns.obj card-authentic.obj \
|
||||
card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \
|
||||
card-sc-hsm.obj card-dnie.obj card-isoApplet.obj \
|
||||
card-masktech.obj \
|
||||
card-masktech.obj card-gids.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-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-oberthur.obj \
|
||||
pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \
|
||||
pkcs15-dnie.obj \
|
||||
pkcs15-dnie.obj pkcs15-gids.obj \
|
||||
compression.obj p15card-helper.obj sm.obj \
|
||||
$(TOPDIR)\win32\versioninfo.res
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* card-gids.h: Support for GIDS smart cards.
|
||||
*
|
||||
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.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
|
||||
*/
|
||||
|
||||
#ifndef CARD_GIDS_H_
|
||||
#define CARD_GIDS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "pkcs15.h"
|
||||
|
||||
struct sc_cardctl_gids_genkey {
|
||||
sc_pkcs15_object_t *object;
|
||||
struct sc_pkcs15_pubkey* pubkey;
|
||||
};
|
||||
|
||||
struct sc_cardctl_gids_importkey {
|
||||
sc_pkcs15_object_t *object;
|
||||
sc_pkcs15_prkey_t *key;
|
||||
};
|
||||
|
||||
struct sc_cardctl_gids_save_cert {
|
||||
sc_pkcs15_object_t *certobject;
|
||||
sc_pkcs15_object_t *privkeyobject;
|
||||
struct sc_path *path;
|
||||
};
|
||||
|
||||
typedef struct sc_cardctl_gids_get_container {
|
||||
size_t containernum;
|
||||
int pubusage;
|
||||
int prvusage;
|
||||
char label[40];
|
||||
int module_length;
|
||||
sc_path_t certificatepath;
|
||||
} sc_cardctl_gids_get_container_t;
|
||||
|
||||
typedef struct sc_cardctl_gids_init_param {
|
||||
u8 init_code[24];
|
||||
size_t user_pin_len;
|
||||
u8* user_pin;
|
||||
u8 cardid[16];
|
||||
} sc_cardctl_gids_init_param_t;
|
||||
|
||||
// information about common files
|
||||
#define UserCreateDeleteDirAc_FI 0xA000
|
||||
#define EveryoneReadUserWriteAc_FI 0xA010
|
||||
#define EveryoneReadAdminWriteAc_FI 0xA012
|
||||
#define MF_FI UserCreateDeleteDirAc_FI
|
||||
#define MF_DO 0xDF1F
|
||||
#define CERT_FI EveryoneReadUserWriteAc_FI
|
||||
#define KEYMAP_FI UserCreateDeleteDirAc_FI
|
||||
#define KEYMAP_DO 0xDF20
|
||||
#define CARDAPPS_FI EveryoneReadUserWriteAc_FI
|
||||
#define CARDAPPS_DO 0xDF21
|
||||
#define CARDCF_FI EveryoneReadUserWriteAc_FI
|
||||
#define CARDCF_DO 0xDF22
|
||||
#define CMAP_FI EveryoneReadUserWriteAc_FI
|
||||
#define CMAP_DO 0xDF23
|
||||
#define CARDID_FI EveryoneReadAdminWriteAc_FI
|
||||
#define CARDID_DO 0xDF20
|
||||
#define GIDS_MAX_DO 0xDFFF
|
||||
|
||||
#define MAX_GIDS_FILE_SIZE 65000
|
||||
|
||||
typedef struct gids_mf_record {
|
||||
char directory[9];
|
||||
char filename[9];
|
||||
int dataObjectIdentifier;
|
||||
int fileIdentifier;
|
||||
} gids_mf_record_t;
|
||||
|
||||
struct gids_keymap_record {
|
||||
int state;
|
||||
unsigned char algid;
|
||||
unsigned char keytype;
|
||||
unsigned short keyref;
|
||||
unsigned short unknownWithFFFF;
|
||||
};
|
||||
|
||||
#define GIDS_MAX_CONTAINER 126
|
||||
|
||||
// stolen from cardmod.h
|
||||
#define MAX_CONTAINER_NAME_LEN 39
|
||||
#define CONTAINER_MAP_VALID_CONTAINER 1
|
||||
#define CONTAINER_MAP_DEFAULT_CONTAINER 2
|
||||
typedef struct _CONTAINER_MAP_RECORD
|
||||
{
|
||||
unsigned short wszGuid [MAX_CONTAINER_NAME_LEN + 1];
|
||||
unsigned char bFlags;
|
||||
unsigned char bReserved;
|
||||
unsigned short wSigKeySizeBits;
|
||||
unsigned short wKeyExchangeKeySizeBits;
|
||||
} CONTAINER_MAP_RECORD, *PCONTAINER_MAP_RECORD;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CARD_GIDS_H_ */
|
|
@ -262,7 +262,24 @@ enum {
|
|||
*/
|
||||
SC_CARDCTL_ISOAPPLET_BASE = _CTL_PREFIX('I','S','O'),
|
||||
SC_CARDCTL_ISOAPPLET_GENERATE_KEY,
|
||||
SC_CARDCTL_ISOAPPLET_IMPORT_KEY
|
||||
SC_CARDCTL_ISOAPPLET_IMPORT_KEY,
|
||||
|
||||
/*
|
||||
* GIDS cards
|
||||
*/
|
||||
SC_CARDCTL_GIDS_BASE = _CTL_PREFIX('G','I','D'),
|
||||
SC_CARDCTL_GIDS_GET_ALL_CONTAINERS,
|
||||
SC_CARDCTL_GIDS_GET_CONTAINER_DETAIL,
|
||||
SC_CARDCTL_GIDS_SELECT_KEY_REFERENCE,
|
||||
SC_CARDCTL_GIDS_CREATE_KEY,
|
||||
SC_CARDCTL_GIDS_GENERATE_KEY,
|
||||
SC_CARDCTL_GIDS_IMPORT_KEY,
|
||||
SC_CARDCTL_GIDS_SAVE_CERT,
|
||||
SC_CARDCTL_GIDS_DELETE_KEY,
|
||||
SC_CARDCTL_GIDS_DELETE_CERT,
|
||||
SC_CARDCTL_GIDS_INITIALIZE,
|
||||
SC_CARDCTL_GIDS_SET_ADMIN_KEY,
|
||||
SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -218,7 +218,13 @@ enum {
|
|||
|
||||
/* Masktech cards */
|
||||
SC_CARD_TYPE_MASKTECH_BASE = 29000,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC,
|
||||
|
||||
/* GIDS cards */
|
||||
SC_CARD_TYPE_GIDS_BASE = 30000,
|
||||
SC_CARD_TYPE_GIDS_GENERIC,
|
||||
SC_CARD_TYPE_GIDS_V1,
|
||||
SC_CARD_TYPE_GIDS_V2,
|
||||
};
|
||||
|
||||
extern sc_card_driver_t *sc_get_default_driver(void);
|
||||
|
@ -257,6 +263,7 @@ extern sc_card_driver_t *sc_get_epass2003_driver(void);
|
|||
extern sc_card_driver_t *sc_get_dnie_driver(void);
|
||||
extern sc_card_driver_t *sc_get_isoApplet_driver(void);
|
||||
extern sc_card_driver_t *sc_get_masktech_driver(void);
|
||||
extern sc_card_driver_t *sc_get_gids_driver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -63,6 +63,31 @@ static int detect_method(const u8* in, size_t inLen) {
|
|||
}
|
||||
}
|
||||
|
||||
static int sc_compress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) {
|
||||
/* Since compress does not offer a way to make it compress gzip... manually set it up */
|
||||
z_stream gz;
|
||||
int err;
|
||||
int window_size = 15 + 0x10;
|
||||
memset(&gz, 0, sizeof(gz));
|
||||
|
||||
gz.next_in = (u8*)in;
|
||||
gz.avail_in = inLen;
|
||||
gz.next_out = out;
|
||||
gz.avail_out = *outLen;
|
||||
|
||||
err = deflateInit2(&gz, Z_BEST_COMPRESSION, Z_DEFLATED, window_size, 9, Z_DEFAULT_STRATEGY);
|
||||
if(err != Z_OK) return zerr_to_opensc(err);
|
||||
err = deflate(&gz, Z_FINISH);
|
||||
if(err != Z_STREAM_END) {
|
||||
deflateEnd(&gz);
|
||||
return zerr_to_opensc(err);
|
||||
}
|
||||
*outLen = gz.total_out;
|
||||
|
||||
err = deflateEnd(&gz);
|
||||
return zerr_to_opensc(err);
|
||||
}
|
||||
|
||||
static int sc_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) {
|
||||
/* Since uncompress does not offer a way to make it uncompress gzip... manually set it up */
|
||||
z_stream gz;
|
||||
|
@ -88,6 +113,23 @@ static int sc_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLe
|
|||
return zerr_to_opensc(err);
|
||||
}
|
||||
|
||||
int sc_compress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) {
|
||||
unsigned long zlib_outlen;
|
||||
int rc;
|
||||
|
||||
switch(method) {
|
||||
case COMPRESSION_ZLIB:
|
||||
zlib_outlen = *outLen;
|
||||
rc = zerr_to_opensc(compress(out, &zlib_outlen, in, inLen));
|
||||
*outLen = zlib_outlen;
|
||||
return rc;
|
||||
case COMPRESSION_GZIP:
|
||||
return sc_compress_gzip(out, outLen, in, inLen);
|
||||
default:
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
}
|
||||
|
||||
int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) {
|
||||
unsigned long zlib_outlen;
|
||||
int rc;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#define COMPRESSION_GZIP 2
|
||||
#define COMPRESSION_UNKNOWN (-1)
|
||||
|
||||
int sc_compress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method);
|
||||
|
||||
int sc_decompress_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int method);
|
||||
int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method);
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
|||
{ "PIV-II", (void *(*)(void)) sc_get_piv_driver },
|
||||
{ "itacns", (void *(*)(void)) sc_get_itacns_driver },
|
||||
{ "isoApplet", (void *(*)(void)) sc_get_isoApplet_driver },
|
||||
{ "gids", (void *(*)(void)) sc_get_gids_driver },
|
||||
{ "openpgp", (void *(*)(void)) sc_get_openpgp_driver },
|
||||
/* The default driver should be last, as it handles all the
|
||||
* unrecognized cards. */
|
||||
|
|
|
@ -280,6 +280,7 @@ sc_pkcs15init_get_cardos_ops
|
|||
sc_pkcs15init_get_cryptoflex_ops
|
||||
sc_pkcs15init_get_cyberflex_ops
|
||||
sc_pkcs15init_get_gpk_ops
|
||||
sc_pkcs15init_get_gids_ops
|
||||
sc_pkcs15init_get_incrypto34_ops
|
||||
sc_pkcs15init_get_jcop_ops
|
||||
sc_pkcs15init_get_manufacturer
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* pkcs15-gids.c: Support for GIDS smart cards.
|
||||
*
|
||||
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "pkcs15.h"
|
||||
#include "common/compat_strlcpy.h"
|
||||
#include "cardctl.h"
|
||||
|
||||
#ifdef ENABLE_ZLIB
|
||||
|
||||
#include "card-gids.h"
|
||||
|
||||
/*
|
||||
* Add a key from a minidriver container
|
||||
*/
|
||||
static int sc_pkcs15emu_gids_add_prkey(sc_pkcs15_card_t * p15card, sc_cardctl_gids_get_container_t *container) {
|
||||
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_pkcs15_prkey_info_t prkey_info;
|
||||
sc_pkcs15_object_t prkey_obj;
|
||||
sc_pkcs15_pubkey_info_t pubkey_info;
|
||||
sc_pkcs15_object_t pubkey_obj;
|
||||
sc_pkcs15_cert_info_t cert_info;
|
||||
sc_pkcs15_object_t cert_obj;
|
||||
int r;
|
||||
char ch_tmp[10];
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Got args: containerIndex=%x\n", container->containernum);
|
||||
|
||||
memset(&prkey_info, 0, sizeof(prkey_info));
|
||||
memset(&prkey_obj, 0, sizeof(prkey_obj));
|
||||
|
||||
prkey_info.id.len = 1;
|
||||
prkey_info.id.value[0] = container->containernum;
|
||||
prkey_info.modulus_length = container->module_length;
|
||||
prkey_info.usage = container->prvusage;
|
||||
prkey_info.native = 1;
|
||||
prkey_info.key_reference = 0x81 + container->containernum;
|
||||
|
||||
strlcpy(prkey_obj.label, container->label, sizeof(prkey_obj.label));
|
||||
prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
||||
prkey_obj.auth_id.len = 1;
|
||||
prkey_obj.auth_id.value[0] = 0x80;
|
||||
|
||||
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to sc_pkcs15emu_add_rsa_prkey");
|
||||
|
||||
memset(&pubkey_info, 0, sizeof(pubkey_info));
|
||||
memset(&pubkey_obj, 0, sizeof(pubkey_obj));
|
||||
|
||||
strlcpy(pubkey_obj.label, container->label, sizeof(pubkey_obj.label));
|
||||
|
||||
snprintf(ch_tmp, sizeof(ch_tmp), "3FFFB0%02X", prkey_info.key_reference);
|
||||
sc_format_path(ch_tmp, &pubkey_info.path);
|
||||
pubkey_info.native = 1;
|
||||
pubkey_info.key_reference = prkey_info.key_reference;
|
||||
pubkey_info.modulus_length = prkey_info.modulus_length;
|
||||
pubkey_info.usage = container->pubusage;
|
||||
pubkey_info.id = prkey_info.id;
|
||||
|
||||
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to sc_pkcs15emu_add_rsa_pubkey");
|
||||
|
||||
if (container->certificatepath.len > 0) {
|
||||
memset(&cert_info, 0, sizeof(cert_info));
|
||||
memset(&cert_obj, 0, sizeof(cert_obj));
|
||||
|
||||
cert_info.id = prkey_info.id;
|
||||
cert_info.path.count = -1;
|
||||
cert_info.path = container->certificatepath;
|
||||
|
||||
strlcpy(cert_obj.label, container->label, sizeof(cert_obj.label));
|
||||
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
|
||||
LOG_TEST_RET(card->ctx, r, "Could not add certificate");
|
||||
} else {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "No certificate found");
|
||||
}
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects
|
||||
*
|
||||
*/
|
||||
static int sc_pkcs15emu_gids_init (sc_pkcs15_card_t * p15card)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
int r;
|
||||
size_t i;
|
||||
struct sc_pkcs15_auth_info pin_info;
|
||||
struct sc_pkcs15_object pin_obj;
|
||||
struct sc_pin_cmd_data pin_cmd_data;
|
||||
size_t recordsnum;
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_ALL_CONTAINERS, &recordsnum);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to get the containers. Uninitialized card ?");
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, NULL);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to get the serial number. Uninitialized card ?");
|
||||
|
||||
p15card->tokeninfo->serial_number = (char*) malloc(card->serialnr.len *2 +1);
|
||||
if (!p15card->tokeninfo->serial_number) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
sc_bin_to_hex(card->serialnr.value, card->serialnr.len, p15card->tokeninfo->serial_number, card->serialnr.len *2 +1, 0);
|
||||
|
||||
if (p15card->tokeninfo->label == NULL) {
|
||||
p15card->tokeninfo->label = strdup("GIDS card");
|
||||
if (p15card->tokeninfo->label == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) {
|
||||
free(p15card->tokeninfo->manufacturer_id);
|
||||
p15card->tokeninfo->manufacturer_id = NULL;
|
||||
}
|
||||
|
||||
if (p15card->tokeninfo->manufacturer_id == NULL) {
|
||||
p15card->tokeninfo->manufacturer_id = strdup("www.mysmartlogon.com");
|
||||
if (p15card->tokeninfo->manufacturer_id == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (p15card->card->type == SC_CARD_TYPE_GIDS_V2) {
|
||||
p15card->tokeninfo->version = 2;
|
||||
} else if (p15card->card->type == SC_CARD_TYPE_GIDS_V1) {
|
||||
p15card->tokeninfo->version = 1;
|
||||
}
|
||||
|
||||
memset(&pin_info, 0, sizeof(pin_info));
|
||||
memset(&pin_obj, 0, sizeof(pin_obj));
|
||||
|
||||
pin_info.auth_id.len = 1;
|
||||
pin_info.auth_id.value[0] = 0x80;
|
||||
pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
|
||||
pin_info.attrs.pin.reference = 0x80;
|
||||
pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED;
|
||||
pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
|
||||
pin_info.attrs.pin.min_length = 4;
|
||||
pin_info.attrs.pin.stored_length = 0;
|
||||
pin_info.attrs.pin.max_length = 15;
|
||||
pin_info.attrs.pin.pad_char = '\0';
|
||||
pin_info.tries_left = -1;
|
||||
pin_info.max_tries = -1;
|
||||
|
||||
memset(&pin_cmd_data, 0, sizeof(pin_cmd_data));
|
||||
pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO;
|
||||
pin_cmd_data.pin_type = SC_AC_CHV;
|
||||
pin_cmd_data.pin_reference = pin_info.attrs.pin.reference;
|
||||
|
||||
r = sc_pin_cmd(card, &pin_cmd_data, NULL);
|
||||
if (r == SC_SUCCESS) {
|
||||
pin_info.max_tries = pin_cmd_data.pin1.max_tries;
|
||||
pin_info.tries_left = pin_cmd_data.pin1.tries_left;
|
||||
}
|
||||
|
||||
strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label));
|
||||
pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE;
|
||||
|
||||
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to sc_pkcs15emu_add_pin_obj");
|
||||
|
||||
// add the PUK if it is available on the card. Not all card have a PUK
|
||||
pin_info.attrs.pin.reference = 0x81;
|
||||
pin_info.auth_id.value[0] = 0x81;
|
||||
pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN;
|
||||
pin_info.attrs.pin.reference = 0x81;
|
||||
pin_cmd_data.pin_reference = pin_info.attrs.pin.reference;
|
||||
|
||||
r = sc_pin_cmd(card, &pin_cmd_data, NULL);
|
||||
if (r == SC_SUCCESS) {
|
||||
pin_info.max_tries = pin_cmd_data.pin1.max_tries;
|
||||
pin_info.tries_left = pin_cmd_data.pin1.tries_left;
|
||||
strlcpy(pin_obj.label, "PUK", sizeof(pin_obj.label));
|
||||
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to sc_pkcs15emu_add_pin_obj with PUK");
|
||||
}
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_ALL_CONTAINERS, &recordsnum);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_card_ctl SC_CARDCTL_GIDS_GET_ALL_CONTAINERS");
|
||||
|
||||
for (i = 0; i < recordsnum; i++) {
|
||||
sc_cardctl_gids_get_container_t container;
|
||||
memset(&container, 0, sizeof(sc_cardctl_gids_get_container_t));
|
||||
container.containernum = i;
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_CONTAINER_DETAIL, &container);
|
||||
if (r < 0) {
|
||||
// one of the container information couldn't be retrieved
|
||||
// ignore it
|
||||
continue;
|
||||
}
|
||||
sc_pkcs15emu_gids_add_prkey(p15card, &container);
|
||||
}
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_gids_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts)
|
||||
{
|
||||
if (opts && (opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)) {
|
||||
return sc_pkcs15emu_gids_init(p15card);
|
||||
} else {
|
||||
if (p15card->card->type != SC_CARD_TYPE_GIDS_GENERIC && p15card->card->type != SC_CARD_TYPE_GIDS_V1 && p15card->card->type != SC_CARD_TYPE_GIDS_V2) {
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
return sc_pkcs15emu_gids_init(p15card);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int sc_pkcs15emu_gids_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts)
|
||||
{
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -71,6 +71,8 @@ extern int sc_pkcs15emu_sc_hsm_init_ex(sc_pkcs15_card_t *,
|
|||
sc_pkcs15emu_opt_t *);
|
||||
extern int sc_pkcs15emu_dnie_init_ex(sc_pkcs15_card_t *,
|
||||
sc_pkcs15emu_opt_t *);
|
||||
extern int sc_pkcs15emu_gids_init_ex(sc_pkcs15_card_t *,
|
||||
sc_pkcs15emu_opt_t *);
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
|
@ -95,6 +97,7 @@ static struct {
|
|||
{ "oberthur", sc_pkcs15emu_oberthur_init_ex },
|
||||
{ "sc-hsm", sc_pkcs15emu_sc_hsm_init_ex },
|
||||
{ "dnie", sc_pkcs15emu_dnie_init_ex },
|
||||
{ "gids", sc_pkcs15emu_gids_init_ex },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ dist_pkgdata_DATA = \
|
|||
ias_adele_admin1.profile ias_adele_admin2.profile ias_adele_common.profile \
|
||||
iasecc_generic_pki.profile iasecc_admin_eid.profile iasecc_generic_oberthur.profile \
|
||||
openpgp.profile sc-hsm.profile \
|
||||
isoApplet.profile
|
||||
isoApplet.profile gids.profile
|
||||
|
||||
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\" \
|
||||
-I$(top_srcdir)/src
|
||||
|
@ -48,4 +48,4 @@ libpkcs15init_la_SOURCES = \
|
|||
pkcs15-oberthur.c pkcs15-oberthur-awp.c \
|
||||
pkcs15-authentic.c pkcs15-iasecc.c pkcs15-openpgp.c \
|
||||
pkcs15-sc-hsm.c \
|
||||
pkcs15-isoApplet.c
|
||||
pkcs15-isoApplet.c pkcs15-gids.c
|
||||
|
|
|
@ -10,7 +10,7 @@ OBJECTS = pkcs15-lib.obj profile.obj \
|
|||
pkcs15-entersafe.obj pkcs15-rtecp.obj pkcs15-westcos.obj \
|
||||
pkcs15-myeid.obj pkcs15-authentic.obj pkcs15-iasecc.obj \
|
||||
pkcs15-epass2003.obj pkcs15-openpgp.obj pkcs15-sc-hsm.obj \
|
||||
pkcs15-isoApplet.obj
|
||||
pkcs15-isoApplet.obj pkcs15-gids.obj
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# PKCS15 r/w profile for GIDS cards
|
||||
#
|
||||
cardinfo {
|
||||
label = "GIDS";
|
||||
manufacturer = "MYSMARTLOGON";
|
||||
|
||||
max-pin-length = 16;
|
||||
min-pin-length = 4;
|
||||
pin-encoding = ascii-numeric;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* pkcs15-gids.c: Support for GIDS smart cards.
|
||||
*
|
||||
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.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 <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../libopensc/log.h"
|
||||
#include "../libopensc/opensc.h"
|
||||
#include "../libopensc/cardctl.h"
|
||||
#include "../libopensc/asn1.h"
|
||||
#include "pkcs15-init.h"
|
||||
#include "profile.h"
|
||||
|
||||
#include "../libopensc/card-gids.h"
|
||||
|
||||
/*
|
||||
* Select a key reference.
|
||||
*/
|
||||
static int
|
||||
gids_select_key_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15_prkey_info_t *key_info)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_SELECT_KEY_REFERENCE, key_info));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new key file.
|
||||
*/
|
||||
static int
|
||||
gids_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_CREATE_KEY, obj));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate a new key.
|
||||
*/
|
||||
static int
|
||||
gids_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15_object_t *obj,
|
||||
sc_pkcs15_pubkey_t *pubkey)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
struct sc_cardctl_gids_genkey call = {obj, pubkey};
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_GENERATE_KEY, &call));
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a usable private key on the card.
|
||||
*/
|
||||
static int
|
||||
gids_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *object,
|
||||
sc_pkcs15_prkey_t *key)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
|
||||
struct sc_cardctl_gids_importkey call = {object, key};
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_IMPORT_KEY, &call));
|
||||
}
|
||||
|
||||
static int
|
||||
gids_delete_object(struct sc_profile *profile, struct sc_pkcs15_card * p15card,
|
||||
struct sc_pkcs15_object *object, const struct sc_path *path) {
|
||||
sc_card_t *card = p15card->card;
|
||||
switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
||||
case SC_PKCS15_TYPE_PRKEY:
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_DELETE_KEY, object));
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT:
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_DELETE_CERT, object));
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY:
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
default:
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
static int gids_emu_update_any_df(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
|
||||
unsigned op, struct sc_pkcs15_object *object)
|
||||
{
|
||||
LOG_FUNC_CALLED(p15card->card->ctx);
|
||||
/* After storing object, pkcs15init will call this function to update DF.
|
||||
* But GIDS has no other DF than GIDS-Application, so we do nothing. */
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int gids_save_certificate(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_path *path) {
|
||||
int r;
|
||||
sc_card_t *card = p15card->card;
|
||||
struct sc_cardctl_gids_save_cert call = {object, NULL, path};
|
||||
struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
|
||||
|
||||
r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, &cert_info->id , &(call.privkeyobject));
|
||||
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
|
||||
//TODO save the certificate in the special file
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to find the private key associated to the certificate");
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_SAVE_CERT, &call));
|
||||
}
|
||||
|
||||
static int gids_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
|
||||
struct sc_pkcs15_object *object, struct sc_pkcs15_der *content,
|
||||
struct sc_path *path) {
|
||||
sc_card_t *card = p15card->card;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
||||
case SC_PKCS15_TYPE_PRKEY:
|
||||
case SC_PKCS15_TYPE_PUBKEY:
|
||||
/* For these two type, store_data just don't need to do anything.
|
||||
* All have been done already before this function is called */
|
||||
r = SC_SUCCESS;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_CERT:
|
||||
r = gids_save_certificate(p15card, object, path);
|
||||
break;
|
||||
default:
|
||||
r = SC_ERROR_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
static int gids_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15_tokeninfo_t *tokeninfo)
|
||||
{
|
||||
LOG_FUNC_CALLED(p15card->card->ctx);
|
||||
/* When unbinding pkcs15init, this function will be called.
|
||||
* But for GIDS, token info does not need to change, we do nothing. */
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static struct sc_pkcs15init_operations sc_pkcs15init_gids_operations =
|
||||
{
|
||||
NULL, /* erase_card */
|
||||
NULL, /* init_card */
|
||||
NULL, /* create_dir */
|
||||
NULL, /* create_domain */
|
||||
NULL, /* pin_reference*/
|
||||
NULL, /* create_pin */
|
||||
gids_select_key_reference, /* key_reference */
|
||||
gids_create_key, /* create_key */
|
||||
gids_store_key, /* store_key */
|
||||
gids_generate_key, /* generate_key */
|
||||
NULL, NULL, /* encode private/public key */
|
||||
NULL, /* finalize */
|
||||
gids_delete_object, /* delete_object */
|
||||
NULL, /* pkcs15init emulation emu_update_dir */
|
||||
gids_emu_update_any_df, /* pkcs15init emulation emu_update_any_df */
|
||||
gids_emu_update_tokeninfo, /* pkcs15init emulation emu_update_tokeninfo */
|
||||
NULL, /* pkcs15init emulation emu_write_info */
|
||||
gids_emu_store_data, /* pkcs15init emulation emu_store_data */
|
||||
NULL, /* sanity_check*/
|
||||
};
|
||||
|
||||
struct
|
||||
sc_pkcs15init_operations *sc_pkcs15init_get_gids_ops(void)
|
||||
{
|
||||
return &sc_pkcs15init_gids_operations;
|
||||
}
|
|
@ -423,6 +423,7 @@ extern struct sc_pkcs15init_operations *sc_pkcs15init_get_piv_ops(void);
|
|||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_openpgp_ops(void);
|
||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_sc_hsm_ops(void);
|
||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_isoApplet_ops(void);
|
||||
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_gids_ops(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ static struct profile_operations {
|
|||
{ "myeid", (void *) sc_pkcs15init_get_myeid_ops },
|
||||
{ "sc-hsm", (void *) sc_pkcs15init_get_sc_hsm_ops },
|
||||
{ "isoApplet", (void *) sc_pkcs15init_get_isoApplet_ops },
|
||||
{ "gids", (void *) sc_pkcs15init_get_gids_ops },
|
||||
#ifdef ENABLE_OPENSSL
|
||||
{ "authentic", (void *) sc_pkcs15init_get_authentic_ops },
|
||||
{ "iasecc", (void *) sc_pkcs15init_get_iasecc_ops },
|
||||
|
|
|
@ -8,7 +8,7 @@ bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \
|
|||
pkcs11-tool cardos-tool eidenv openpgp-tool iasecc-tool
|
||||
if ENABLE_OPENSSL
|
||||
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool \
|
||||
westcos-tool sc-hsm-tool dnie-tool
|
||||
westcos-tool sc-hsm-tool dnie-tool gids-tool
|
||||
endif
|
||||
|
||||
# compile with $(PTHREAD_CFLAGS) to allow debugging with gdb
|
||||
|
@ -51,6 +51,8 @@ sc_hsm_tool_SOURCES = sc-hsm-tool.c util.c
|
|||
sc_hsm_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||
dnie_tool_SOURCES = dnie-tool.c util.c
|
||||
dnie_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||
gids_tool_SOURCES = gids-tool.c util.c
|
||||
gids_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
|
||||
|
||||
if WIN32
|
||||
opensc_tool_SOURCES += versioninfo-tools.rc
|
||||
|
@ -68,4 +70,5 @@ westcos_tool_SOURCES += versioninfo-tools.rc
|
|||
openpgp_tool_SOURCES += versioninfo-tools.rc
|
||||
iasecc_tool_SOURCES += versioninfo-tools.rc
|
||||
sc_hsm_tool_SOURCES += versioninfo-tools.rc
|
||||
gids_tool_SOURCES += versioninfo-tools.rc
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,584 @@
|
|||
/*
|
||||
* gids-tool.c: Support for GIDS smart cards.
|
||||
*
|
||||
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.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
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "libopensc/opensc.h"
|
||||
#include "libopensc/cardctl.h"
|
||||
#include "libopensc/card-gids.h"
|
||||
#include "libopensc/asn1.h"
|
||||
#include "util.h"
|
||||
|
||||
static const char *app_name = "gids-tool";
|
||||
|
||||
static struct sc_aid gids_aid = { { 0xA0,0x00,0x00,0x03,0x97,0x42,0x54,0x46,0x59 }, 9 };
|
||||
|
||||
static int opt_wait = 0;
|
||||
static char *opt_reader = NULL;
|
||||
static int verbose = 0;
|
||||
|
||||
enum {
|
||||
OPT_SO_PIN = 0x100,
|
||||
OPT_PIN,
|
||||
OPT_SERIAL_NUMBER,
|
||||
OPT_NEW_KEY,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "initialize", 0, NULL, 'X' },
|
||||
{ "admin-key", 1, NULL, OPT_SO_PIN },
|
||||
{ "pin", 1, NULL, OPT_PIN },
|
||||
{ "serial-number", 1, NULL, OPT_SERIAL_NUMBER },
|
||||
{ "unblock", 0, NULL, 'U' },
|
||||
{ "change-admin-key", 0, NULL, 'C' },
|
||||
{ "new-admin-key", 1, NULL, OPT_NEW_KEY },
|
||||
{ "reader", 1, NULL, 'r' },
|
||||
{ "wait", 0, NULL, 'w' },
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
static const char *option_help[] = {
|
||||
"Initialize token",
|
||||
"Define the administrator key",
|
||||
"Define user PIN",
|
||||
"Define serial number",
|
||||
"Unblock the user PIN after an administrator authentication",
|
||||
"Change the administrator key",
|
||||
"Define the new adminastrator key",
|
||||
"Uses reader number <arg> [0]",
|
||||
"Wait for a card to be inserted",
|
||||
"Verbose operation. Use several times to enable debug output.",
|
||||
};
|
||||
|
||||
static sc_context_t *ctx = NULL;
|
||||
static sc_card_t *card = NULL;
|
||||
|
||||
static int initialize(sc_card_t *card, const char *so_pin, const char *user_pin, const char* serial)
|
||||
{
|
||||
sc_cardctl_gids_init_param_t param;
|
||||
size_t len;
|
||||
char *_so_pin = NULL, *_user_pin = NULL, *_serial = NULL;
|
||||
int r;
|
||||
|
||||
memset(¶m, 0, sizeof(sc_cardctl_gids_init_param_t));
|
||||
|
||||
if (so_pin == NULL) {
|
||||
printf("Enter admin key (48 hexadecimal characters) : \n");
|
||||
printf("Press Enter to set the admin key to 00...00\n");
|
||||
util_getpass(&_so_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_so_pin = (char *)so_pin;
|
||||
}
|
||||
|
||||
len = sizeof(param.init_code);
|
||||
r = sc_hex_to_bin(_so_pin, param.init_code, &len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
} else if (len != 24) {
|
||||
fprintf(stderr, "The admin key must be a hexadecimal string of 48 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (user_pin == NULL) {
|
||||
printf("Enter initial User-PIN (4 - 16 characters) : ");
|
||||
util_getpass(&_user_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_user_pin = (char *)user_pin;
|
||||
}
|
||||
|
||||
if (serial == NULL) {
|
||||
printf("Enter serial number (32 hexadecimal characters): \n");
|
||||
printf("Press Enter to set a random serial number\n");
|
||||
util_getpass(&_serial, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_serial = (char *)serial;
|
||||
}
|
||||
len = sizeof(param.cardid);
|
||||
r = sc_hex_to_bin(_serial, param.cardid, &len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Error decoding serial number (%s)\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) {
|
||||
memset(param.cardid, 0, sizeof(param.cardid));
|
||||
} else if (len != 32) {
|
||||
fprintf(stderr, "the serial number must be a hexadecimal string of 32 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
param.user_pin_len = strlen(_user_pin);
|
||||
|
||||
if (param.user_pin_len < 4) {
|
||||
fprintf(stderr, "PIN must be at least 4 characters long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (param.user_pin_len > 16) {
|
||||
fprintf(stderr, "PIN must not be longer than 16 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
param.user_pin = (u8 *)_user_pin;
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_INITIALIZE, (void *)¶m);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_INITIALIZE, *) failed with %s\n", sc_strerror(r));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unblock(sc_card_t* card, const char *so_pin, const char *user_pin) {
|
||||
int r;
|
||||
char *_so_pin = NULL, *_user_pin = NULL;
|
||||
size_t len;
|
||||
u8 key[24];
|
||||
struct sc_pin_cmd_data data;
|
||||
|
||||
memset(&data, 0, sizeof(struct sc_pin_cmd_data));
|
||||
|
||||
if (so_pin == NULL) {
|
||||
printf("============================================================\n");
|
||||
printf("WARNING\n");
|
||||
printf("Entering an incorrect admin key can break your card\n");
|
||||
printf("WARNING\n");
|
||||
printf("============================================================\n");
|
||||
printf("Enter admin key (48 hexadecimal characters) : ");
|
||||
util_getpass(&_so_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_so_pin = (char *)so_pin;
|
||||
}
|
||||
|
||||
len = sizeof(key);
|
||||
r = sc_hex_to_bin(_so_pin, key, &len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len != 24) {
|
||||
fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, (void *)key);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, *) failed with %s\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
printf("Administrator authentication successful\n");
|
||||
printf("Setting the new PIN\n");
|
||||
|
||||
if (user_pin == NULL) {
|
||||
printf("Enter User-PIN (4 - 16 characters) : ");
|
||||
util_getpass(&_user_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_user_pin = (char *)user_pin;
|
||||
}
|
||||
|
||||
data.pin_type = SC_AC_CHV;
|
||||
data.cmd = SC_PIN_CMD_UNBLOCK;
|
||||
data.pin2.len = strlen(_user_pin);
|
||||
data.pin2.data = (unsigned char*) _user_pin;
|
||||
data.pin_reference = 0x80;
|
||||
r = sc_pin_cmd(card, &data, NULL);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "reset pin failed with %s\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
printf("Unblock PIN done successfuly\n");
|
||||
// the card should have deauthenticated the admin, but to be sure:
|
||||
sc_logout(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int changeAdminKey(sc_card_t* card, const char *so_pin, const char* new_key) {
|
||||
char *_so_pin = NULL, *_new_key = NULL;
|
||||
size_t len;
|
||||
u8 key[24];
|
||||
int r;
|
||||
|
||||
if (so_pin == NULL) {
|
||||
printf("============================================================\n");
|
||||
printf("WARNING\n");
|
||||
printf("Entering an incorrect admin key can break your card\n");
|
||||
printf("WARNING\n");
|
||||
printf("============================================================\n");
|
||||
printf("Enter admin key (48 hexadecimal characters) : ");
|
||||
util_getpass(&_so_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_so_pin = (char *)so_pin;
|
||||
}
|
||||
|
||||
len = sizeof(key);
|
||||
r = sc_hex_to_bin(_so_pin, key, &len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len != 24) {
|
||||
fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, (void *)key);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, *) failed with %s\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_key == NULL) {
|
||||
printf("Enter new admin key (48 hexadecimal characters) : ");
|
||||
util_getpass(&_so_pin, NULL, stdin);
|
||||
printf("\n");
|
||||
} else {
|
||||
_new_key = (char *)new_key;
|
||||
}
|
||||
|
||||
len = sizeof(key);
|
||||
r = sc_hex_to_bin(_new_key, key, &len);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len != 24) {
|
||||
fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GIDS_SET_ADMIN_KEY, (void *)key);
|
||||
sc_logout(card);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_SET_ADMIN_KEY, *) failed with %s\n", sc_strerror(r));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read a DO from the card
|
||||
static int gids_get_DO(sc_card_t* card, int fileIdentifier, int dataObjectIdentifier, u8* response, size_t *responselen) {
|
||||
sc_apdu_t apdu;
|
||||
int r;
|
||||
u8 data[4] = {0x5C, 0x02, (dataObjectIdentifier&0xFF00)>>8, (dataObjectIdentifier&0xFF)};
|
||||
size_t datasize = 0;
|
||||
const u8* p;
|
||||
u8 buffer[MAX_GIDS_FILE_SIZE];
|
||||
|
||||
sc_format_apdu(card, &apdu,
|
||||
response == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xCB, (fileIdentifier&0xFF00)>>8, (fileIdentifier&0xFF));
|
||||
apdu.lc = 04;
|
||||
apdu.data = data;
|
||||
apdu.datalen = 04;
|
||||
apdu.resp = buffer;
|
||||
apdu.resplen = sizeof(buffer);
|
||||
apdu.le = 256;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = sc_asn1_find_tag(card->ctx, buffer, sizeof(buffer), dataObjectIdentifier, &datasize);
|
||||
if (!p) {
|
||||
return SC_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
if (datasize > *responselen) {
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
memcpy(response, p, datasize);
|
||||
*responselen = datasize;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int print_info(sc_card_t *card) {
|
||||
int r;
|
||||
u8 buffer[MAX_GIDS_FILE_SIZE];
|
||||
size_t size = sizeof(buffer);
|
||||
u8 masterfile[MAX_GIDS_FILE_SIZE];
|
||||
size_t masterfilesize = sizeof(masterfile);
|
||||
u8 cmapfile[MAX_GIDS_FILE_SIZE];
|
||||
size_t cmapfilesize = sizeof(cmapfile);
|
||||
u8 keymap[MAX_GIDS_FILE_SIZE];
|
||||
size_t keymapsize = sizeof(keymap);
|
||||
gids_mf_record_t *records = (gids_mf_record_t *) (masterfile+1);
|
||||
int recordcount;
|
||||
int i;
|
||||
|
||||
printf("===============================\n");
|
||||
printf("Dumping the content of the card\n");
|
||||
printf("===============================\n");
|
||||
r = gids_get_DO(card, MF_FI, MF_DO, masterfile, &masterfilesize);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "unable to retrieve the master file: %s\n", sc_strerror(r));
|
||||
fprintf(stderr, "Is that a new card ?\n");
|
||||
return r;
|
||||
}
|
||||
printf("Dumping Files:\n");
|
||||
if (masterfilesize >= 1) {
|
||||
recordcount = (int) ((masterfilesize-1) / sizeof(gids_mf_record_t));
|
||||
printf("Found %d entries in the masterfile\n", recordcount);
|
||||
for (i = 0; i < recordcount; i++) {
|
||||
if (records[i].filename[0] == 0) {
|
||||
printf(" Directory: %s\n", records[i].directory);
|
||||
printf(" FileIdentifier: 0x%x\n", records[i].fileIdentifier);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
for (i = 0; i < recordcount; i++) {
|
||||
if (records[i].filename[0] != 0) {
|
||||
printf(" File: %s\\%s\n", records[i].directory, records[i].filename);
|
||||
printf(" FileIdentifier: 0x%x\n", records[i].fileIdentifier);
|
||||
printf(" DataObjectIdentifier: 0x%x\n", records[i].dataObjectIdentifier);
|
||||
size = sizeof(buffer);
|
||||
r = gids_get_DO(card, records[i].fileIdentifier, records[i].dataObjectIdentifier, buffer, &size);
|
||||
if (r < 0) {
|
||||
printf(" unable to read the file: %s\n", sc_strerror(r));
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
// visual studio doesn't support %zu
|
||||
printf(" Size: %Iu\n", size);
|
||||
#else
|
||||
printf(" Size: %zu\n", size);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
if (strcmp(records[i].directory, "mscp") == 0 && strcmp(records[i].filename, "cmapfile") == 0 ) {
|
||||
cmapfilesize = size;
|
||||
memcpy(cmapfile, buffer, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Dumping containers:\n");
|
||||
if (cmapfilesize == sizeof(cmapfile)) {
|
||||
printf("Unable to find the container file (mscp\\cmapfile)\n");
|
||||
} else {
|
||||
PCONTAINER_MAP_RECORD cmaprecords = (PCONTAINER_MAP_RECORD) cmapfile;
|
||||
int cmaprecordnum = (cmapfilesize / sizeof(CONTAINER_MAP_RECORD));
|
||||
int keymaprecordnum = -1;
|
||||
struct gids_keymap_record* keymaprecord = ((struct gids_keymap_record*)(keymap +1));
|
||||
if (cmaprecordnum == 0) {
|
||||
printf(" no container found\n");
|
||||
} else {
|
||||
r = gids_get_DO(card, KEYMAP_FI, KEYMAP_DO, keymap, &keymapsize);
|
||||
if (r < 0) {
|
||||
printf(" the keymap couldn't be found\n");
|
||||
} else {
|
||||
keymaprecordnum = (keymapsize - 1) / sizeof(struct gids_keymap_record);
|
||||
}
|
||||
for (i = 0; i < cmaprecordnum; i++) {
|
||||
printf(" container: %d\n", i);
|
||||
wprintf(L" guid: %s\n", cmaprecords[i].wszGuid);
|
||||
printf(" bFlags: ");
|
||||
if (cmaprecords[i].bFlags & CONTAINER_MAP_VALID_CONTAINER) {
|
||||
printf("Valid container");
|
||||
if (cmaprecords[i].bFlags & CONTAINER_MAP_DEFAULT_CONTAINER) {
|
||||
printf(",Default container");
|
||||
}
|
||||
} else {
|
||||
printf("Empty container");
|
||||
}
|
||||
printf("\n");
|
||||
printf(" wSigKeySizeBits: %d\n", cmaprecords[i].wSigKeySizeBits);
|
||||
printf(" wKeyExchangeKeySizeBits: %d\n", cmaprecords[i].wKeyExchangeKeySizeBits);
|
||||
if (i < keymaprecordnum) {
|
||||
printf(" key info:\n");
|
||||
printf(" state: %d\n", keymaprecord[i].state);
|
||||
printf(" algid: %d\n", keymaprecord[i].algid);
|
||||
printf(" keyref: 0x%x\n", keymaprecord[i].keyref);
|
||||
printf(" key type: ");
|
||||
switch(keymaprecord[i].keytype) {
|
||||
case 0:
|
||||
printf("none\n");
|
||||
break;
|
||||
case 0x9C:
|
||||
printf("signature\n");
|
||||
break;
|
||||
case 0x9A:
|
||||
printf("signature + decryption\n");
|
||||
break;
|
||||
default:
|
||||
printf("unknown\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("No file system found\n");
|
||||
}
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char * const argv[])
|
||||
{
|
||||
int err = 0, r, c, long_optind = 0;
|
||||
int action_count = 0;
|
||||
int do_initialize = 0;
|
||||
int do_unblock = 0;
|
||||
int do_change_admin = 0;
|
||||
sc_path_t path;
|
||||
const char *opt_so_pin = NULL;
|
||||
const char *opt_pin = NULL;
|
||||
const char *opt_serial_number = NULL;
|
||||
const char *opt_new_key = NULL;
|
||||
sc_context_param_t ctx_param;
|
||||
|
||||
setbuf(stderr, NULL);
|
||||
setbuf(stdout, NULL);
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "XUCr:wv", options, &long_optind);
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '?')
|
||||
util_print_usage_and_die(app_name, options, option_help, NULL);
|
||||
switch (c) {
|
||||
case 'X':
|
||||
do_initialize = 1;
|
||||
action_count++;
|
||||
break;
|
||||
case OPT_SO_PIN:
|
||||
util_get_pin(optarg, &opt_so_pin);
|
||||
break;
|
||||
case OPT_PIN:
|
||||
util_get_pin(optarg, &opt_pin);
|
||||
break;
|
||||
case OPT_SERIAL_NUMBER:
|
||||
util_get_pin(optarg, &opt_serial_number);
|
||||
break;
|
||||
case OPT_NEW_KEY:
|
||||
util_get_pin(optarg, &opt_new_key);
|
||||
break;
|
||||
case 'U':
|
||||
do_unblock = 1;
|
||||
action_count++;
|
||||
break;
|
||||
case 'C':
|
||||
do_change_admin = 1;
|
||||
action_count++;
|
||||
break;
|
||||
case 'r':
|
||||
opt_reader = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'w':
|
||||
opt_wait = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTO_malloc_init();
|
||||
ERR_load_crypto_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
memset(&ctx_param, 0, sizeof(sc_context_param_t));
|
||||
ctx_param.app_name = app_name;
|
||||
|
||||
r = sc_context_create(&ctx, &ctx_param);
|
||||
if (r != SC_SUCCESS) {
|
||||
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Only change if not in opensc.conf */
|
||||
if (verbose > 1 && ctx->debug == 0) {
|
||||
ctx->debug = verbose;
|
||||
sc_ctx_log_to_file(ctx, "stderr");
|
||||
}
|
||||
|
||||
r = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose);
|
||||
if (r != SC_SUCCESS) {
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(err));
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
sc_path_set(&path, SC_FILE_TYPE_WORKING_EF, gids_aid.value, gids_aid.len, 0, 0);
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
|
||||
if (r != SC_SUCCESS) {
|
||||
fprintf(stderr, "Failed to select application: %s\n", sc_strerror(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (do_initialize && initialize(card, opt_so_pin, opt_pin, opt_serial_number))
|
||||
goto fail;
|
||||
|
||||
if (do_unblock && unblock(card, opt_so_pin, opt_pin))
|
||||
goto fail;
|
||||
|
||||
if (do_change_admin && changeAdminKey(card, opt_so_pin, opt_new_key))
|
||||
goto fail;
|
||||
|
||||
if (action_count == 0) {
|
||||
print_info(card);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
goto end;
|
||||
fail:
|
||||
err = 1;
|
||||
end:
|
||||
if (card) {
|
||||
sc_unlock(card);
|
||||
sc_disconnect_card(card);
|
||||
}
|
||||
if (ctx)
|
||||
sc_release_context(ctx);
|
||||
|
||||
ERR_print_errors_fp(stderr);
|
||||
return err;
|
||||
}
|
|
@ -50,7 +50,7 @@ OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MT.lib user32.
|
|||
!ENDIF
|
||||
|
||||
PROGRAMS_OPENSSL = cryptoflex-tool.exe pkcs15-init.exe netkey-tool.exe piv-tool.exe \
|
||||
westcos-tool.exe sc-hsm-tool.exe dnie-tool.exe
|
||||
westcos-tool.exe sc-hsm-tool.exe dnie-tool.exe gids-tool.exe
|
||||
OPENSC_FEATURES = $(OPENSC_FEATURES) openssl
|
||||
CANDLEFLAGS = -dOpenSSL="$(OPENSSL_DIR)" $(CANDLEFLAGS)
|
||||
!ENDIF
|
||||
|
|
|
@ -176,6 +176,9 @@
|
|||
<Component Id="dnie_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
|
||||
<File Source="$(var.SOURCE_DIR)\src\tools\dnie-tool.exe" Vital="yes"/>
|
||||
</Component>
|
||||
<Component Id="gids_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
|
||||
<File Source="$(var.SOURCE_DIR)\src\tools\gids-tool.exe" Vital="yes"/>
|
||||
</Component>
|
||||
<?endif ?>
|
||||
</Directory>
|
||||
<?ifdef OpenSSL ?>
|
||||
|
@ -270,6 +273,9 @@
|
|||
<Component Id="isoApplet.profile" Guid="*" Win64="$(var.Win64YesNo)">
|
||||
<File Source="$(var.SOURCE_DIR)\src\pkcs15init\isoApplet.profile"/>
|
||||
</Component>
|
||||
<Component Id="gids.profile" Guid="*" Win64="$(var.Win64YesNo)">
|
||||
<File Source="$(var.SOURCE_DIR)\src\pkcs15init\gids.profile"/>
|
||||
</Component>
|
||||
</Directory>
|
||||
<?endif ?>
|
||||
</Directory>
|
||||
|
@ -327,6 +333,7 @@
|
|||
<ComponentRef Id="westcos_tool.exe"/>
|
||||
<ComponentRef Id="sc_hsm_tool.exe"/>
|
||||
<ComponentRef Id="dnie_tool.exe"/>
|
||||
<ComponentRef Id="gids_tool.exe"/>
|
||||
<ComponentRef Id="cyberflex.profile"/>
|
||||
<ComponentRef Id="flex.profile"/>
|
||||
<ComponentRef Id="gpk.profile"/>
|
||||
|
@ -357,6 +364,7 @@
|
|||
<ComponentRef Id="schsm.profile"/>
|
||||
<ComponentRef Id="openpgp.profile"/>
|
||||
<ComponentRef Id="isoApplet.profile"/>
|
||||
<ComponentRef Id="gids.profile"/>
|
||||
<?endif ?>
|
||||
</Feature>
|
||||
<Feature Id="OpenSC_menu" Level="1" Title="Start menu entries" Description="Start menu entries: link to documentation">
|
||||
|
|
Loading…
Reference in New Issue