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:
LE TOUX Vincent 2015-12-27 13:06:16 +01:00 committed by Frank Morgner
parent 1ca22a22d1
commit 6a243449a0
22 changed files with 3281 additions and 12 deletions

View File

@ -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

View File

@ -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

2035
src/libopensc/card-gids.c Normal file

File diff suppressed because it is too large Load Diff

117
src/libopensc/card-gids.h Normal file
View File

@ -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_ */

View File

@ -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 {

View File

@ -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
}

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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

244
src/libopensc/pkcs15-gids.c Normal file
View File

@ -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

View File

@ -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 }
};

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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 },

View File

@ -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

584
src/tools/gids-tool.c Normal file
View File

@ -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(&param, 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 *)&param);
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;
}

View File

@ -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

View File

@ -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">