added GoID Tool

This commit is contained in:
Frank Morgner 2018-12-04 23:06:56 +01:00
parent 141ec6ab23
commit 609e2d89cf
9 changed files with 3387 additions and 35 deletions

33
.gitignore vendored
View File

@ -59,25 +59,11 @@ tags
*.ggo
ChangeLog
doc/tools/cardos-tool
doc/tools/cryptoflex-tool
doc/tools/*-tool
doc/tools/eidenv
doc/tools/iasecc-tool
doc/tools/netkey-tool
doc/tools/openpgp-tool
doc/tools/opensc-explorer
doc/tools/opensc-tool
doc/tools/gids-tool
doc/tools/piv-tool
doc/tools/pkcs11-tool
doc/tools/pkcs15-crypt
doc/tools/pkcs15-init
doc/tools/pkcs15-tool
doc/tools/sc-hsm-tool
doc/tools/westcos-tool
doc/tools/dnie-tool
doc/tools/egk-tool
doc/tools/npa-tool
doc/tools/opensc-asn1
doc/tools/opensc-notify
doc/files/opensc.conf.5.xml
@ -85,31 +71,16 @@ doc/files/opensc.conf.5.xml
etc/opensc.conf.example
src/common/compat_getopt_main
src/minidriver/opensc-minidriver.inf
src/tools/cardos-tool
src/tools/iasecc-tool
src/tools/openpgp-tool
src/tools/sc-hsm-tool
src/tools/westcos-tool
src/tools/pkcs15-tool
src/tools/*-tool
src/tools/pkcs15-crypt
src/tools/pkcs15-init
src/tools/piv-tool
src/tools/eidenv
src/tools/opensc-explorer
src/tools/opensc-tool
src/tools/gids-tool
src/tools/rutoken-tool
src/tools/cardos-info
src/tools/cryptoflex-tool
src/tools/netkey-tool
src/tools/pkcs11-tool
src/tools/dnie-tool
src/tools/npa-tool
src/tools/sceac-example
src/tools/opensc-notify
src/tools/org.opensc.notify.desktop
src/tools/opensc-asn1
src/tools/egk-tool
win32/OpenSC.iss
win32/OpenSC.wxs

View File

@ -1638,6 +1638,8 @@ int perform_terminal_authentication(sc_card_t *card,
BUF_MEM_free(eacsmctx->auxiliary_data);
eacsmctx->auxiliary_data = BUF_MEM_create_init(auxiliary_data,
auxiliary_data_len);
if (!eacsmctx->id_icc)
eacsmctx->id_icc = BUF_MEM_new();
signature = TA_STEP5_sign(eacsmctx->ctx, eacsmctx->eph_pub_key,
eacsmctx->id_icc, eacsmctx->auxiliary_data);
if (!signature) {

View File

@ -21,17 +21,18 @@ do_subst = $(SED) \
EGK_TOOL_BUILT_SOURCES = egk-tool-cmdline.h egk-tool-cmdline.c
NPA_TOOL_BUILT_SOURCES = npa-tool-cmdline.h npa-tool-cmdline.c
GOID_TOOL_BUILT_SOURCES = goid-tool-cmdline.h goid-tool-cmdline.c
OPENSC_NOTIFY_BUILT_SOURCES = opensc-notify-cmdline.h opensc-notify-cmdline.c
OPENSC_ASN1_BUILT_SOURCES = opensc-asn1-cmdline.h opensc-asn1-cmdline.c
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/versioninfo-tools.rc $(srcdir)/versioninfo-opensc-notify.rc
EXTRA_DIST = Makefile.mak versioninfo-tools.rc.in versioninfo-opensc-notify.rc.in npa-tool.ggo.in opensc-notify.ggo.in egk-tool.ggo.in opensc-asn1.ggo.in org.opensc.notify.desktop.in exe.manifest
EXTRA_DIST = Makefile.mak versioninfo-tools.rc.in versioninfo-opensc-notify.rc.in goid-tool.ggo.in npa-tool.ggo.in opensc-notify.ggo.in egk-tool.ggo.in opensc-asn1.ggo.in org.opensc.notify.desktop.in exe.manifest
noinst_HEADERS = util.h fread_to_eof.h
noinst_PROGRAMS = sceac-example
bin_PROGRAMS = opensc-tool opensc-explorer opensc-notify \
pkcs15-tool pkcs15-crypt pkcs11-tool \
cardos-tool eidenv openpgp-tool iasecc-tool egk-tool opensc-asn1
cardos-tool eidenv openpgp-tool iasecc-tool egk-tool opensc-asn1 goid-tool
if ENABLE_OPENSSL
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool \
westcos-tool sc-hsm-tool dnie-tool gids-tool npa-tool
@ -139,6 +140,24 @@ $(EGK_TOOL_BUILT_SOURCES):
$(abs_builddir)/egk-tool.ggo: egk-tool.ggo.in
$(do_subst) < $(abs_srcdir)/egk-tool.ggo.in > $@
goid_tool_SOURCES = goid-tool.c util.c fread_to_eof.c $(GOID_TOOL_BUILT_SOURCES)
goid_tool_LDADD = $(top_builddir)/src/libopensc/libopensc.la $(OPENPACE_LIBS)
goid_tool_CFLAGS = -I$(top_srcdir)/src $(OPENPACE_CFLAGS)
goid_tool_CFLAGS += -Wno-unused-but-set-variable
if HAVE_UNKNOWN_WARNING_OPTION
goid_tool_CFLAGS += -Wno-unknown-warning-option
endif
goid-tool.c: $(abs_builddir)/goid-tool.ggo $(GOID_TOOL_BUILT_SOURCES)
# We only want *cmdline* to be generated when they have explicitly been removed.
$(GOID_TOOL_BUILT_SOURCES):
$(MAKE) $(abs_builddir)/goid-tool.ggo
$(GENGETOPT) --include-getopt --file-name=goid-tool-cmdline --output-dir=$(builddir) < $(abs_builddir)/goid-tool.ggo
$(abs_builddir)/goid-tool.ggo: goid-tool.ggo.in
$(do_subst) < $(abs_srcdir)/goid-tool.ggo.in > $@
opensc_asn1_SOURCES = opensc-asn1.c fread_to_eof.c $(OPENSC_ASN1_BUILT_SOURCES)
opensc_asn1_LDADD = $(top_builddir)/src/libopensc/libopensc.la $(OPTIONAL_ZLIB_LIBS)
opensc_asn1_CFLAGS = -I$(top_srcdir)/src $(OPTIONAL_ZLIB_CFLAGS)
@ -181,4 +200,4 @@ org.opensc.notify.desktop: org.opensc.notify.desktop.in
$(do_subst) < $(abs_srcdir)/org.opensc.notify.desktop.in > $@
clean-local:
rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop
rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/goid-tool.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop

View File

@ -6,7 +6,7 @@ default: all
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
pkcs11-tool.exe cardos-tool.exe eidenv.exe openpgp-tool.exe iasecc-tool.exe \
opensc-notify.exe egk-tool.exe opensc-asn1.exe \
opensc-notify.exe egk-tool.exe goid-tool.exe paccess-tool.exe opensc-asn1.exe \
$(PROGRAMS_OPENSSL)
OBJECTS = util.obj versioninfo-tools.res
@ -37,6 +37,11 @@ egk-tool.exe: egk-tool-cmdline.obj util.obj $(LIBS)
link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj egk-tool-cmdline.obj util.obj $(LIBS) $(ZLIB_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
goid-tool.exe: goid-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS)
cl $(COPTS) /c $*.c
link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj goid-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
opensc-asn1.exe: opensc-asn1-cmdline.obj fread_to_eof.obj $(LIBS)
cl $(COPTS) /c $*.c
link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj opensc-asn1-cmdline.obj fread_to_eof.obj $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,280 @@
/** @file goid-tool-cmdline.h
* @brief The header file for the command line option parser
* generated by GNU Gengetopt version 2.22.6
* http://www.gnu.org/software/gengetopt.
* DO NOT modify this file, since it can be overwritten
* @author GNU Gengetopt by Lorenzo Bettini */
#ifndef GOID_TOOL_CMDLINE_H
#define GOID_TOOL_CMDLINE_H
/* If we use autoconf. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> /* for FILE */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
/** @brief the program name (used for printing errors) */
#define CMDLINE_PARSER_PACKAGE "goid-tool"
#endif
#ifndef CMDLINE_PARSER_PACKAGE_NAME
/** @brief the complete program name (used for help and version) */
#define CMDLINE_PARSER_PACKAGE_NAME "goid-tool"
#endif
#ifndef CMDLINE_PARSER_VERSION
/** @brief the program version */
#define CMDLINE_PARSER_VERSION VERSION
#endif
/** @brief Where the command line options are stored */
struct gengetopt_args_info
{
const char *help_help; /**< @brief Print help and exit help description. */
const char *version_help; /**< @brief Print version and exit help description. */
char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */
char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. original value given at command line. */
const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. help description. */
unsigned int verbose_min; /**< @brief Use (several times) to be more verbose's minimum occurreces */
unsigned int verbose_max; /**< @brief Use (several times) to be more verbose's maximum occurreces */
const char *verbose_help; /**< @brief Use (several times) to be more verbose help description. */
const char *verify_pin_help; /**< @brief Verify PIN help description. */
const char *verify_bio_help; /**< @brief Verify finger print help description. */
const char *verify_pin_or_bio_help; /**< @brief Verify PIN or finger print (user's choice) help description. */
const char *new_pin_help; /**< @brief Change PIN help description. */
unsigned int new_bio_min; /**< @brief Use (several times) to change one or more biometric templates's minimum occurreces */
unsigned int new_bio_max; /**< @brief Use (several times) to change one or more biometric templates's maximum occurreces */
const char *new_bio_help; /**< @brief Use (several times) to change one or more biometric templates help description. */
const char *info_help; /**< @brief Dump Information about the SoCManager's configuration help description. */
char ** certificate_arg; /**< @brief Use (several times) to pass CV certificates. */
char ** certificate_orig; /**< @brief Use (several times) to pass CV certificates original value given at command line. */
unsigned int certificate_min; /**< @brief Use (several times) to pass CV certificates's minimum occurreces */
unsigned int certificate_max; /**< @brief Use (several times) to pass CV certificates's maximum occurreces */
const char *certificate_help; /**< @brief Use (several times) to pass CV certificates help description. */
char * key_arg; /**< @brief Private key for the CV certificate. */
char * key_orig; /**< @brief Private key for the CV certificate original value given at command line. */
const char *key_help; /**< @brief Private key for the CV certificate help description. */
const char *print_cardid_help; /**< @brief Print the card ID help description. */
char * write_cardid_arg; /**< @brief Write the specified card ID. */
char * write_cardid_orig; /**< @brief Write the specified card ID original value given at command line. */
const char *write_cardid_help; /**< @brief Write the specified card ID help description. */
const char *print_paccessid_help; /**< @brief Print the PAccess ID help description. */
char * write_paccessid_arg; /**< @brief Write the specified PAccess ID. */
char * write_paccessid_orig; /**< @brief Write the specified PAccess ID original value given at command line. */
const char *write_paccessid_help; /**< @brief Write the specified PAccess ID help description. */
int* read_dg_arg; /**< @brief Read the specified data group; use several times to read out multiple files. */
char ** read_dg_orig; /**< @brief Read the specified data group; use several times to read out multiple files original value given at command line. */
unsigned int read_dg_min; /**< @brief Read the specified data group; use several times to read out multiple files's minimum occurreces */
unsigned int read_dg_max; /**< @brief Read the specified data group; use several times to read out multiple files's maximum occurreces */
const char *read_dg_help; /**< @brief Read the specified data group; use several times to read out multiple files help description. */
char ** out_file_arg; /**< @brief Write output to a file instead of printing it; use once for each use of `--read-dg'. */
char ** out_file_orig; /**< @brief Write output to a file instead of printing it; use once for each use of `--read-dg' original value given at command line. */
unsigned int out_file_min; /**< @brief Write output to a file instead of printing it; use once for each use of `--read-dg''s minimum occurreces */
unsigned int out_file_max; /**< @brief Write output to a file instead of printing it; use once for each use of `--read-dg''s maximum occurreces */
const char *out_file_help; /**< @brief Write output to a file instead of printing it; use once for each use of `--read-dg' help description. */
int* write_dg_arg; /**< @brief Write the specified data group; use several times to write multiple files. */
char ** write_dg_orig; /**< @brief Write the specified data group; use several times to write multiple files original value given at command line. */
unsigned int write_dg_min; /**< @brief Write the specified data group; use several times to write multiple files's minimum occurreces */
unsigned int write_dg_max; /**< @brief Write the specified data group; use several times to write multiple files's maximum occurreces */
const char *write_dg_help; /**< @brief Write the specified data group; use several times to write multiple files help description. */
char ** in_file_arg; /**< @brief Read input from a file; use once for each use of `--write-dg'. */
char ** in_file_orig; /**< @brief Read input from a file; use once for each use of `--write-dg' original value given at command line. */
unsigned int in_file_min; /**< @brief Read input from a file; use once for each use of `--write-dg''s minimum occurreces */
unsigned int in_file_max; /**< @brief Read input from a file; use once for each use of `--write-dg''s maximum occurreces */
const char *in_file_help; /**< @brief Read input from a file; use once for each use of `--write-dg' help description. */
int* delete_dg_arg; /**< @brief Delete the specified data group; use several times to delete multiple files. */
char ** delete_dg_orig; /**< @brief Delete the specified data group; use several times to delete multiple files original value given at command line. */
unsigned int delete_dg_min; /**< @brief Delete the specified data group; use several times to delete multiple files's minimum occurreces */
unsigned int delete_dg_max; /**< @brief Delete the specified data group; use several times to delete multiple files's maximum occurreces */
const char *delete_dg_help; /**< @brief Delete the specified data group; use several times to delete multiple files help description. */
int* create_dg_arg; /**< @brief Create the specified data group; use several times to create multiple files. */
char ** create_dg_orig; /**< @brief Create the specified data group; use several times to create multiple files original value given at command line. */
unsigned int create_dg_min; /**< @brief Create the specified data group; use several times to create multiple files's minimum occurreces */
unsigned int create_dg_max; /**< @brief Create the specified data group; use several times to create multiple files's maximum occurreces */
const char *create_dg_help; /**< @brief Create the specified data group; use several times to create multiple files help description. */
int new_size_arg; /**< @brief File size of newly created DGs (default='256'). */
char * new_size_orig; /**< @brief File size of newly created DGs original value given at command line. */
const char *new_size_help; /**< @brief File size of newly created DGs help description. */
char * new_read_ac_arg; /**< @brief Access condition for reading newly created DGs (default='sm'). */
char * new_read_ac_orig; /**< @brief Access condition for reading newly created DGs original value given at command line. */
const char *new_read_ac_help; /**< @brief Access condition for reading newly created DGs help description. */
int* new_read_ac_chatbit_arg; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs. */
char ** new_read_ac_chatbit_orig; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs original value given at command line. */
unsigned int new_read_ac_chatbit_min; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs's minimum occurreces */
unsigned int new_read_ac_chatbit_max; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs's maximum occurreces */
const char *new_read_ac_chatbit_help; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs help description. */
char * new_write_ac_arg; /**< @brief Access condition for writing newly created DGs (default='sm'). */
char * new_write_ac_orig; /**< @brief Access condition for writing newly created DGs original value given at command line. */
const char *new_write_ac_help; /**< @brief Access condition for writing newly created DGs help description. */
int* new_write_ac_chatbit_arg; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs. */
char ** new_write_ac_chatbit_orig; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs original value given at command line. */
unsigned int new_write_ac_chatbit_min; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs's minimum occurreces */
unsigned int new_write_ac_chatbit_max; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs's maximum occurreces */
const char *new_write_ac_chatbit_help; /**< @brief Required access bits in certificate's CHAT for reading newly created DGs help description. */
unsigned int help_given ; /**< @brief Whether help was given. */
unsigned int version_given ; /**< @brief Whether version was given. */
unsigned int reader_given ; /**< @brief Whether reader was given. */
unsigned int verbose_given ; /**< @brief Whether verbose was given. */
unsigned int verify_pin_given ; /**< @brief Whether verify-pin was given. */
unsigned int verify_bio_given ; /**< @brief Whether verify-bio was given. */
unsigned int verify_pin_or_bio_given ; /**< @brief Whether verify-pin-or-bio was given. */
unsigned int new_pin_given ; /**< @brief Whether new-pin was given. */
unsigned int new_bio_given ; /**< @brief Whether new-bio was given. */
unsigned int info_given ; /**< @brief Whether info was given. */
unsigned int certificate_given ; /**< @brief Whether certificate was given. */
unsigned int key_given ; /**< @brief Whether key was given. */
unsigned int print_cardid_given ; /**< @brief Whether print-cardid was given. */
unsigned int write_cardid_given ; /**< @brief Whether write-cardid was given. */
unsigned int print_paccessid_given ; /**< @brief Whether print-paccessid was given. */
unsigned int write_paccessid_given ; /**< @brief Whether write-paccessid was given. */
unsigned int read_dg_given ; /**< @brief Whether read-dg was given. */
unsigned int out_file_given ; /**< @brief Whether out-file was given. */
unsigned int write_dg_given ; /**< @brief Whether write-dg was given. */
unsigned int in_file_given ; /**< @brief Whether in-file was given. */
unsigned int delete_dg_given ; /**< @brief Whether delete-dg was given. */
unsigned int create_dg_given ; /**< @brief Whether create-dg was given. */
unsigned int new_size_given ; /**< @brief Whether new-size was given. */
unsigned int new_read_ac_given ; /**< @brief Whether new-read-ac was given. */
unsigned int new_read_ac_chatbit_given ; /**< @brief Whether new-read-ac-chatbit was given. */
unsigned int new_write_ac_given ; /**< @brief Whether new-write-ac was given. */
unsigned int new_write_ac_chatbit_given ; /**< @brief Whether new-write-ac-chatbit was given. */
} ;
/** @brief The additional parameters to pass to parser functions */
struct cmdline_parser_params
{
int override; /**< @brief whether to override possibly already present options (default 0) */
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
} ;
/** @brief the purpose string of the program */
extern const char *gengetopt_args_info_purpose;
/** @brief the usage string of the program */
extern const char *gengetopt_args_info_usage;
/** @brief the description string of the program */
extern const char *gengetopt_args_info_description;
/** @brief all the lines making the help output */
extern const char *gengetopt_args_info_help[];
/**
* The command line parser
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser (int argc, char **argv,
struct gengetopt_args_info *args_info);
/**
* The command line parser (version with additional parameters - deprecated)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param override whether to override possibly already present options
* @param initialize whether to initialize the option structure my_args_info
* @param check_required whether to check that all required options were provided
* @return 0 if everything went fine, NON 0 if an error took place
* @deprecated use cmdline_parser_ext() instead
*/
int cmdline_parser2 (int argc, char **argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
/**
* The command line parser (version with additional parameters)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param params additional parameters for the parser
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_ext (int argc, char **argv,
struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params);
/**
* Save the contents of the option struct into an already open FILE stream.
* @param outfile the stream where to dump options
* @param args_info the option struct to dump
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_dump(FILE *outfile,
struct gengetopt_args_info *args_info);
/**
* Save the contents of the option struct into a (text) file.
* This file can be read by the config file parser (if generated by gengetopt)
* @param filename the file where to save
* @param args_info the option struct to save
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
/**
* Print the help
*/
void cmdline_parser_print_help(void);
/**
* Print the version
*/
void cmdline_parser_print_version(void);
/**
* Initializes all the fields a cmdline_parser_params structure
* to their default values
* @param params the structure to initialize
*/
void cmdline_parser_params_init(struct cmdline_parser_params *params);
/**
* Allocates dynamically a cmdline_parser_params structure and initializes
* all its fields to their default values
* @return the created and initialized cmdline_parser_params structure
*/
struct cmdline_parser_params *cmdline_parser_params_create(void);
/**
* Initializes the passed gengetopt_args_info structure's fields
* (also set default values for options that have a default)
* @param args_info the structure to initialize
*/
void cmdline_parser_init (struct gengetopt_args_info *args_info);
/**
* Deallocates the string fields of the gengetopt_args_info structure
* (but does not deallocate the structure itself)
* @param args_info the structure to deallocate
*/
void cmdline_parser_free (struct gengetopt_args_info *args_info);
/**
* Checks that all the required options were specified
* @param args_info the structure to check
* @param prog_name the name of the program that will be used to print
* possible errors
* @return
*/
int cmdline_parser_required (struct gengetopt_args_info *args_info,
const char *prog_name);
extern const char *cmdline_parser_new_read_ac_values[]; /**< @brief Possible values for new-read-ac. */
extern const char *cmdline_parser_new_write_ac_values[]; /**< @brief Possible values for new-write-ac. */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* GOID_TOOL_CMDLINE_H */

795
src/tools/goid-tool.c Normal file
View File

@ -0,0 +1,795 @@
/*
* Copyright (C) 2018 Frank Morgner <frankmorgner@gmail.com>
*
* This file is part of OpenSC.
*
* 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 "fread_to_eof.h"
#include <string.h>
#include "goid-tool-cmdline.h"
#include "libopensc/asn1.h"
#include "libopensc/log.h"
#include "libopensc/opensc.h"
#include "sm/sm-eac.h"
#ifdef ENABLE_OPENPACE
#include <eac/eac.h>
#endif
#include <stdlib.h>
#include "util.h"
#include <ctype.h>
const unsigned char aid_soc_manager[] = {
0xD2, 0x76, 0x00, 0x01, 0x72, 0x53, 0x6F, 0x43, 0x4D, 0x01
};
static const unsigned char paccess_aid[] = {
0xD2, 0x76, 0x00, 0x01, 0x72, 0x50, 0x41, 0x63, 0x63, 0x01,
};
static const char *app_name = "goid-tool";
void
print_permissions(u8 permissions)
{
size_t perms_printed = 0;
if (permissions & 0x80) {
printf("%s PIN", perms_printed ? " or" : "verification of");
perms_printed++;
}
if (permissions & 0x40) {
printf("%s BIO", perms_printed ? " or" : "verification of");
perms_printed++;
}
if (permissions & 0x20) {
printf("%s GP key", perms_printed ? " or" : "verification of");
perms_printed++;
}
printf("\n");
}
void
soc_info(sc_context_t *ctx, sc_card_t *card)
{
sc_apdu_t apdu;
unsigned char rbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 information_applets[SC_MAX_APDU_BUFFER_SIZE];
size_t information_applets_len = sizeof information_applets;
int pin_initialized = 0, bio_initialized = 0;
int pin_max_retries = 0, pin_cur_retries = 0, bio_max_retries = 0, bio_cur_retries = 0;
int pin_length = 0;
u8 pin_unblock = 0, pin_change = 0, bio_unblock = 0, bio_change = 0;
size_t pin_change_len = sizeof pin_change, pin_unblock_len = sizeof pin_unblock,
bio_change_len = sizeof bio_change, bio_unblock_len = sizeof bio_unblock;
int bio_count = 0;
u8 bio_initialized_templates[2];
size_t bio_initialized_templates_len = sizeof bio_initialized_templates;
struct sc_asn1_entry rapdu_get_information[] = {
{ "Sequence of (applet register)", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE|SC_ASN1_CONS, 0, NULL, NULL },
{ "Initialized PIN", SC_ASN1_STRUCT, SC_ASN1_APP|SC_ASN1_CONS|0x02, SC_ASN1_OPTIONAL, NULL, NULL },
{ "Initialized BIO", SC_ASN1_STRUCT, SC_ASN1_APP|SC_ASN1_CONS|0x03, SC_ASN1_OPTIONAL, NULL, NULL },
{ NULL , 0 , 0 , 0 , NULL , NULL }
};
struct sc_asn1_entry rapdu_get_information_pin[] = {
{ "Initialization state of the PIN", SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, 0, NULL, NULL },
{ "maximum remaining tries", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "current remaining tries", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "Unblock requirements Mask", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x1, 0, NULL, NULL },
{ "Change requirements Mask", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x2, 0, NULL, NULL },
{ "PIN size", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ NULL , 0 , 0 , 0 , NULL , NULL }
};
struct sc_asn1_entry rapdu_get_information_bio[] = {
{ "Initialization state of the BIO", SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, 0, NULL, NULL },
{ "maximum remaining tries", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "current remaining tries", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "Unblock requirements Mask", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x1, 0, NULL, NULL },
{ "Change requirements Mask", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x2, 0, NULL, NULL },
{ "Min minutiae", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "Max minutiae", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "number of templates", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "Bitmap of initialized templates", SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
{ "Algorithm parameters, allocation strategy", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
{ NULL , 0 , 0 , 0 , NULL , NULL }
};
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x61, 0x00, 0x00);
apdu.cla = 0x80;
apdu.resp = rbuf;
apdu.resplen = sizeof rbuf;
if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS) {
return;
}
sc_format_asn1_entry(rapdu_get_information + 0, information_applets, &information_applets_len, 0);
sc_format_asn1_entry(rapdu_get_information + 1, rapdu_get_information_pin, NULL, 0);
sc_format_asn1_entry(rapdu_get_information + 2, rapdu_get_information_bio, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 0, &pin_initialized, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 1, &pin_max_retries, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 2, &pin_cur_retries, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 3, &pin_unblock, &pin_unblock_len, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 4, &pin_change, &pin_change_len, 0);
sc_format_asn1_entry(rapdu_get_information_pin + 5, &pin_length, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 0, &bio_initialized, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 1, &bio_max_retries, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 2, &bio_cur_retries, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 3, &bio_unblock, &bio_unblock_len, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 4, &bio_change, &bio_change_len, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 7, &bio_count, NULL, 0);
sc_format_asn1_entry(rapdu_get_information_bio + 8, bio_initialized_templates, &bio_initialized_templates_len, 0);
if (sc_asn1_decode(ctx, rapdu_get_information,
apdu.resp, apdu.resplen, NULL, NULL) != SC_SUCCESS) {
return;
}
if (rapdu_get_information[0].flags & SC_ASN1_PRESENT && information_applets_len > 0) {
const unsigned char *p = information_applets, *end = information_applets + information_applets_len;
unsigned int cla = 0, tag = 0;
size_t length = information_applets_len;
if (SC_SUCCESS == sc_asn1_read_tag(&p, length, &cla, &tag, &length)
&& cla == SC_ASN1_TAG_UNIVERSAL && tag == SC_ASN1_TAG_INTEGER) {
int applet_count = 0;
/* number of applets */
if (SC_SUCCESS == sc_asn1_decode_integer(p, length, &applet_count)) {
printf("SoCManager knows %d applet%s%s\n", applet_count,
applet_count == 1 ? "" : "s", applet_count == 0 ? "" : ":");
/* AID of client applet #x */
for (p += length, length = end - p;
p < end;
p += length, length = end - p) {
size_t i;
if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
|| p == NULL || cla != SC_ASN1_TAG_CONTEXT) {
break;
}
putchar('\t');
util_hex_dump(stdout, p, length, "");
/* align with the maximum lenght of an AID */
for (i = length; i < 0x10 + 1; i++)
printf(" ");
/* i now counts the number of flags that were printed */
i = 0;
if (tag & 0x02) {
printf("%sdefault selected", i ? ", " : "");
i++;
}
if (tag & 0x01) {
printf("%sinteracts with SoCManager", i ? ", " : "");
i++;
}
if (tag & 0x04) {
printf("%sBIO enabled", i ? ", " : "");
i++;
}
if (tag & 0x08) {
printf("%sPIN enabled", i ? ", " : "");
i++;
}
printf("\n");
}
}
}
}
if (rapdu_get_information[1].flags & SC_ASN1_PRESENT) {
if (pin_initialized) {
printf("PIN is initialized with %d digits (%d of %d tries left).\n",
pin_length, pin_cur_retries, pin_max_retries);
} else {
printf("PIN is not initialized.\n");
}
printf("\tChanging PIN requires ");
print_permissions(pin_change);
printf("\tUnblocking PIN requires ");
print_permissions(pin_unblock);
}
if (rapdu_get_information[2].flags & SC_ASN1_PRESENT) {
if (bio_initialized) {
int bio_used = 0;
size_t i, j;
for (i = 0; i < sizeof bio_initialized_templates; i++) {
for (j = 0; j < 8; j++) {
if (bio_initialized_templates[i] >> j & 0x1)
bio_used++;
}
}
printf("BIO is initialized with %d of %d templates (%d of %d tries left).\n",
bio_used, bio_count, bio_cur_retries, bio_max_retries);
} else {
printf("BIO is not initialized.\n");
}
printf("\tChanging BIO requires ");
print_permissions(bio_change);
printf("\tUnblocking BIO requires ");
print_permissions(bio_unblock);
}
}
void
soc_verify(sc_card_t *card, unsigned char p2)
{
sc_apdu_t apdu;
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, p2);
if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS) {
return;
}
}
void
soc_change(sc_card_t *card, unsigned char p1, unsigned char p2)
{
sc_apdu_t apdu;
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x00, p2);
if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS) {
return;
}
}
int soc_main(struct sc_context *ctx, sc_card_t *card, struct gengetopt_args_info *cmdline)
{
int ok = 0;
sc_file_t *file = NULL;
struct sc_path path;
unsigned char soc_manager_minor = 0;
unsigned char soc_manager_major = 0;
sc_path_set(&path, SC_PATH_TYPE_DF_NAME, aid_soc_manager, sizeof aid_soc_manager, 0, 0);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
sc_select_file(card, &path, &file), "SoCManager not found.");
if (file && file->prop_attr && file->prop_attr_len) {
size_t prop_len = 0;
const u8 *prop = sc_asn1_find_tag(ctx, file->prop_attr,
file->prop_attr_len, 0xA5, &prop_len);
if (prop && prop_len) {
prop = sc_asn1_find_tag(ctx, prop,
prop_len, 0x81, &prop_len);
if (prop && prop_len == 2) {
soc_manager_major = prop[0];
soc_manager_minor = prop[1];
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"SoCManager version %u.%u",
soc_manager_major, soc_manager_minor);
}
}
}
if (cmdline->info_given) {
if ((soc_manager_major == 2 && soc_manager_minor < 7)
|| soc_manager_major < 2)
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_NOT_SUPPORTED, "Get Information only supported with version 2.07 and later.");
soc_info(ctx, card);
}
if (cmdline->verify_pin_given) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Verify finger print or PIN on the card.");
soc_verify(card, 0x80);
}
if (cmdline->verify_bio_given) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Verify finger print on the card.");
soc_verify(card, 0x40);
}
if (cmdline->verify_pin_or_bio_given) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Verify finger print or PIN on the card.");
soc_verify(card, 0xC0);
}
if (cmdline->new_pin_given) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Initialize the PIN on the card.");
soc_change(card, 0x00, 0x80);
}
if (cmdline->new_bio_given) {
size_t i = 0;
while (i < cmdline->new_bio_given) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Initialize finger print template %u on the card.",
(unsigned char) i);
soc_change(card, (unsigned char) i, 0x40);
i++;
}
}
ok = 1;
err:
return ok;
}
static int
paccess_construct_fci(struct sc_card *card, const sc_file_t *file,
u8 *out, size_t *outlen)
{
u8 *p = out;
u8 buf[64];
if (*outlen < 2)
return SC_ERROR_BUFFER_TOO_SMALL;
*p++ = 0x62;
p++;
buf[0] = (file->size >> 8) & 0xFF;
buf[1] = file->size & 0xFF;
sc_asn1_put_tag(0x80, buf, 2, p, *outlen - (p - out), &p);
buf[0] = (file->id >> 8) & 0xFF;
buf[1] = file->id & 0xFF;
sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p);
memcpy(buf, file->sec_attr, file->sec_attr_len);
sc_asn1_put_tag(0x86, buf, file->sec_attr_len,
p, *outlen - (p - out), &p);
buf[0] = file->sid & 0xFF;
sc_asn1_put_tag(0x88, buf, 1, p, *outlen - (p - out), &p);
out[1] = p - out - 2;
*outlen = p - out;
return 0;
}
int
paccess_create_file(struct sc_card *card, size_t size, int fid, u8 *sec_attr, size_t sec_attr_len, int sfid)
{
int ok = 0;
sc_file_t *file = sc_file_new();
if (!file)
goto err;
file->size = size;
file->id = fid;
file->sid = sfid;
file->sec_attr = sec_attr;
file->sec_attr_len = sec_attr_len;
card->ops->construct_fci = paccess_construct_fci;
SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
sc_create_file(card, file), "Create file failed.");
ok = 1;
err:
return ok;
}
int
paccess_delete_file(struct sc_card *card, int fid)
{
int ok = 0;
u8 buf[2];
struct sc_path path;
buf[0] = (fid >> 8) & 0xFF;
buf[1] = fid & 0xFF;
sc_path_set(&path, SC_PATH_TYPE_FILE_ID, buf, sizeof buf, 0, 0);
SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
sc_delete_file(card, &path), "Delete file failed.");
ok = 1;
err:
return ok;
}
int
paccess_get_security_attributes(struct sc_context *ctx, const char *ac, int* chatbits, size_t chatbits_len, u8 sec_attr[2])
{
int ok = 0;
memset(sec_attr, 0, 2);
if (!ac || 0 == strcmp(ac, "never")) {
/* nothing else to do */
} else if (0 == strcmp(ac, "always")) {
sec_attr[0] |= 0xFF;
} else {
size_t i;
if (0 == strcmp(ac, "ta")) {
sec_attr[0] |= 0xA0;
} else if (0 == strcmp(ac, "sm")) {
sec_attr[0] |= 0xC0;
} else {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "unknown access condition.");
}
for (i = 0; i < chatbits_len; i++) {
u8 byte = chatbits[i] / 8;
u8 bit = chatbits[i] % 8 + 1;
if (byte > 5)
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "Only CHAT bits with index 0..39 are available.");
sec_attr[0] |= 0x8 | byte;
sec_attr[1] |= bit;
}
}
ok = 1;
err:
return ok;
}
int paccess_main(struct sc_context *ctx, sc_card_t *card, struct gengetopt_args_info *cmdline)
{
int ok = 0, r;
sc_file_t *file = NULL;
struct sc_path path;
size_t i, ef_cardsecurity_len = 0, privkey_len = 0, *certs_lens = NULL;
unsigned char *ef_cardsecurity = NULL, *privkey = NULL,
**certs = NULL;
unsigned char auxiliary_data[] = {0x67, 0x00};
unsigned char paccess_minor = 0;
unsigned char paccess_major = 0;
sc_path_set(&path, SC_PATH_TYPE_DF_NAME, paccess_aid, sizeof paccess_aid, 0, 0);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
sc_select_file(card, &path, &file), "PAccess not found.");
if (file && file->prop_attr && file->prop_attr_len) {
const unsigned char *p, *end;
unsigned int cla = 0, tag = 0;
size_t length;
for (p = file->prop_attr, length = file->prop_attr_len, end = file->prop_attr + file->prop_attr_len;
p < end;
p += length, length = end - p) {
if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
|| p == NULL) {
break;
}
switch (cla | tag) {
case 0x81:
if (p && length == 2) {
paccess_major = p[0];
paccess_minor = p[1];
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"PAccess version %u.%u",
paccess_major, paccess_minor);
}
break;
case 0x82:
if (p && length == 1) {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Number of Session Contexts %u",
p[0]);
}
break;
case 0x87:
sc_debug_hex(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Certificate Authority Reference of the primary CVCA trust anchor",
p, length);
break;
case 0x88:
sc_debug_hex(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Certificate Authority Reference of the secondary CVCA trust anchor",
p, length);
break;
case 0x1fe5:
case 0x9F65:
if (p && length == 2) {
size_t max_command_size = (p[0]<<8)|p[1];
card->max_recv_size = max_command_size;
card->max_send_size = max_command_size;
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Maximum data length in command message %"SC_FORMAT_LEN_SIZE_T"u bytes",
max_command_size);
}
break;
}
}
}
if (cmdline->certificate_given || cmdline->key_given) {
if (!fread_to_eof(cmdline->key_arg,
&privkey, &privkey_len)) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "Could not parse private key.\n");
}
certs = calloc(sizeof *certs, cmdline->certificate_given + 1);
certs_lens = calloc(sizeof *certs_lens,
cmdline->certificate_given + 1);
if (!certs || !certs_lens) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, SC_ERROR_NOT_ENOUGH_MEMORY,
"Internal error.");
}
for (i = 0; i < cmdline->certificate_given; i++) {
if (!fread_to_eof(cmdline->certificate_arg[i],
(unsigned char **) &certs[i], &certs_lens[i])) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "Could not read certificate.\n");
}
}
#ifdef ENABLE_OPENPACE
EAC_init();
#endif
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
perform_terminal_authentication(card,
(const unsigned char **) certs, certs_lens,
privkey, privkey_len,
auxiliary_data, sizeof auxiliary_data),
"Terminal authentication failed.");
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
perform_chip_authentication(card,
&ef_cardsecurity, &ef_cardsecurity_len),
"Chip authentication failed.");
}
for (i = 0; i < cmdline->delete_dg_given; i++) {
int fid = 0x0100 | cmdline->delete_dg_arg[i];
if ((paccess_major == 2 && paccess_minor < 6)
|| paccess_major < 2)
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_NOT_SUPPORTED, "Create File only supported with version 2.06 and later.");
if (!paccess_delete_file(card, fid))
goto err;
}
for (i = 0; i < cmdline->create_dg_given; i++) {
u8 sec_attr[4];
int fid = 0x0100 | cmdline->create_dg_arg[i];
if ((paccess_major == 2 && paccess_minor < 6)
|| paccess_major < 2)
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_NOT_SUPPORTED, "Create File only supported with version 2.06 and later.");
if (cmdline->new_size_arg < 0)
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "`--new-size' needs a positive size.\n");
if (!paccess_get_security_attributes(ctx, cmdline->new_read_ac_arg,
cmdline->new_read_ac_chatbit_arg,
cmdline->new_read_ac_chatbit_given, sec_attr + 0)
|| !paccess_get_security_attributes(ctx, cmdline->new_write_ac_arg,
cmdline->new_write_ac_chatbit_arg,
cmdline->new_write_ac_chatbit_given, sec_attr + 2)
|| !paccess_create_file(card, cmdline->new_size_arg, fid,
sec_attr, sizeof sec_attr, cmdline->create_dg_arg[i]))
goto err;
}
if (cmdline->out_file_given > 0 && cmdline->out_file_given != cmdline->read_dg_given) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "If `--out-file' is specified, it must be used as many times as `--read-dg'.\n");
}
for (i = 0; i < cmdline->read_dg_given; i++) {
u8 *ef = NULL;
size_t ef_len = 0;
r = iso7816_read_binary_sfid(card, cmdline->read_dg_arg[i],
&ef, &ef_len);
if (r >= 0) {
if (cmdline->out_file_given == cmdline->read_dg_given) {
FILE *f = fopen(cmdline->out_file_arg[i], "wb");
if (f) {
fwrite(ef, ef_len, 1, f);
fclose(f);
} else {
sc_debug(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Error opening %s: %s\n",
cmdline->out_file_arg[i], strerror(errno));
r = SC_ERROR_FILE_NOT_FOUND;
}
} else {
char label[32];
snprintf(label, sizeof label, "Data Group %u", (unsigned char) cmdline->read_dg_arg[i]);
sc_debug_hex(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, label, ef, ef_len);
}
free(ef);
}
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error reading data group.");
}
if (cmdline->print_cardid_given) {
u8 *ef = NULL;
size_t ef_len = 0;
r = iso7816_read_binary_sfid(card, 0x1E, &ef, &ef_len);
if (r >= 0) {
const u8 *p = ef;
unsigned int cla = 0, tag = 0;
if (SC_SUCCESS == sc_asn1_read_tag(&p, ef_len,
&cla, &tag, &ef_len)
&& (tag | cla) == 0x7E
&& SC_SUCCESS == sc_asn1_read_tag(&p, ef_len,
&cla, &tag, &ef_len)
&& (tag | cla) == 0x13) {
const char *cardid = (const char *) p;
while (cardid && ef_len) {
if (isprint(*cardid)) {
printf("%c", *cardid);
} else {
printf(".");
}
cardid++;
ef_len--;
}
if (cardid)
printf("\n");
} else {
r = SC_ERROR_INVALID_DATA;
}
}
free(ef);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error reading card ID.");
}
if (cmdline->print_paccessid_given) {
u8 *ef = NULL;
size_t ef_len = 0;
r = iso7816_read_binary_sfid(card, 0x06, &ef, &ef_len);
if (r >= 0) {
const u8 *p = ef;
unsigned int cla = 0, tag = 0;
if (SC_SUCCESS == sc_asn1_read_tag(&p, ef_len,
&cla, &tag, &ef_len)
&& (tag | cla) == 0x66
&& SC_SUCCESS == sc_asn1_read_tag((const u8 **) &p, ef_len,
&cla, &tag, &ef_len)
&& (tag | cla) == 0x13) {
const char *paccessid = (const char *) p;
while (paccessid && ef_len) {
if (isprint(*paccessid)) {
printf("%c", *paccessid);
} else {
printf(".");
}
paccessid++;
ef_len--;
}
if (paccessid)
printf("\n");
} else {
r = SC_ERROR_INVALID_DATA;
}
}
free(ef);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error reading card ID.");
}
if (cmdline->in_file_given != cmdline->write_dg_given) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "If `--in-file' is specified, it must be used as many times as `--write-dg'.\n");
}
for (i = 0; i < cmdline->write_dg_given; i++) {
u8 *ef = NULL;
size_t ef_len = 0;
if (!fread_to_eof(cmdline->in_file_arg[i],
&ef, &ef_len)) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
SC_ERROR_INVALID_ARGUMENTS, "Could not read input file.\n");
}
r = iso7816_update_binary_sfid(card, cmdline->write_dg_arg[i], ef, ef_len);
free(ef);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error writing data group.");
}
if (cmdline->write_cardid_arg) {
size_t cardid_len = strlen(cmdline->write_cardid_arg);
u8 ef[256];
if (cardid_len > (sizeof ef) - 4) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, SC_ERROR_INVALID_ARGUMENTS,
"Card ID too long.");
}
ef[0] = 0x7E;
ef[1] = 2 + cardid_len;
ef[2] = 0x13;
ef[3] = cardid_len;
memcpy(ef + 4, cmdline->write_cardid_arg, cardid_len);
r = iso7816_update_binary_sfid(card, 0x1E, ef, 4 + cardid_len);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error writing card ID.");
}
if (cmdline->write_paccessid_arg) {
size_t paccessid_len = strlen(cmdline->write_paccessid_arg);
u8 ef[256];
if (paccessid_len > (sizeof ef) - 4) {
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, SC_ERROR_INVALID_ARGUMENTS,
"Card ID too long.");
}
ef[0] = 0x66;
ef[1] = 2 + paccessid_len;
ef[2] = 0x13;
ef[3] = paccessid_len;
memcpy(ef + 4, cmdline->write_paccessid_arg, paccessid_len);
r = iso7816_update_binary_sfid(card, 0x06, ef, 4 + paccessid_len);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error writing PAccess ID.");
}
ok = 1;
err:
if (certs) {
for (i = 0; certs[i]; i++) {
free((unsigned char *) certs[i]);
}
free(certs);
}
free(ef_cardsecurity);
free(certs_lens);
free(privkey);
sc_file_free(file);
return ok;
}
int
main(int argc, char **argv)
{
struct gengetopt_args_info cmdline;
struct sc_context *ctx = NULL;
struct sc_card *card = NULL;
int r, fail = 1;
sc_context_param_t ctx_param;
if (cmdline_parser(argc, argv, &cmdline) != 0)
exit(1);
memset(&ctx_param, 0, sizeof(ctx_param));
ctx_param.ver = 0;
ctx_param.app_name = app_name;
r = sc_context_create(&ctx, &ctx_param);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
exit(1);
}
if (cmdline.verbose_given > 1) {
ctx->debug = cmdline.verbose_given;
sc_ctx_log_to_file(ctx, "stderr");
}
r = sc_set_card_driver(ctx, "default");
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error selecting card driver.");
r = util_connect_card_ex(ctx, &card, cmdline.reader_arg, 0, 0, cmdline.verbose_given);
SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE_TOOL, r,
"Error connecting to card.");
if (!soc_main(ctx, card, &cmdline) || !paccess_main(ctx, card, &cmdline))
goto err;
fail = 0;
err:
sc_disconnect_card(card);
sc_release_context(ctx);
cmdline_parser_free (&cmdline);
return fail;
}
/*printf("%s:%d\n", __FILE__, __LINE__);*/

View File

@ -0,0 +1,87 @@
package "goid-tool"
purpose "@PACKAGE_SUMMARY@"
option "reader" r
"Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen."
string optional
option "verbose" v
"Use (several times) to be more verbose"
multiple optional
section "SoCManager Applet"
option "verify-pin" p
"Verify PIN"
optional
option "verify-bio" b
"Verify finger print"
optional
option "verify-pin-or-bio" -
"Verify PIN or finger print (user's choice)"
optional
option "new-pin" -
"Change PIN"
optional
option "new-bio" -
"Use (several times) to change one or more biometric templates"
multiple optional
option "info" -
"Dump Information about the SoCManager's configuration"
optional
section "PAccess Applet"
option "certificate" c
"Use (several times) to pass CV certificates"
string multiple optional dependon="key" typestr="FILENAME"
option "key" k
"Private key for the CV certificate"
string optional dependon="certificate" typestr="FILENAME"
option "print-cardid" -
"Print the card ID"
optional
option "write-cardid" -
"Write the specified card ID"
string optional typestr="CARDID"
option "print-paccessid" -
"Print the PAccess ID"
optional
option "write-paccessid" -
"Write the specified PAccess ID"
string optional typestr="PACCESSID"
option "read-dg" -
"Read the specified data group; use several times to read out multiple files"
int optional multiple typestr="ID"
option "out-file" -
"Write output to a file instead of printing it; use once for each use of `--read-dg'"
string optional multiple typestr="FILENAME"
option "write-dg" -
"Write the specified data group; use several times to write multiple files"
int optional multiple typestr="ID"
option "in-file" -
"Read input from a file; use once for each use of `--write-dg'"
string optional multiple typestr="FILENAME"
option "delete-dg" -
"Delete the specified data group; use several times to delete multiple files"
int optional multiple typestr="ID"
option "create-dg" -
"Create the specified data group; use several times to create multiple files"
int optional multiple typestr="ID"
option "new-size" -
"File size of newly created DGs"
int optional dependon="create-dg" typestr="SIZE" default="256"
option "new-read-ac" -
"Access condition for reading newly created DGs"
values="always","never","ta","sm" default="sm" optional dependon="create-dg"
option "new-read-ac-chatbit" -
"Required access bits in certificate's CHAT for reading newly created DGs"
int optional dependon="create-dg" multiple typestr="INDEX"
option "new-write-ac" -
"Access condition for writing newly created DGs"
values="always","never","ta","sm" default="sm" optional dependon="create-dg"
option "new-write-ac-chatbit" -
"Required access bits in certificate's CHAT for reading newly created DGs"
int optional dependon="create-dg" multiple typestr="INDEX"
text "
Report bugs to @PACKAGE_BUGREPORT@
Written by Frank Morgner <frankmorgner@gmail.com>"

View File

@ -151,6 +151,9 @@
<Component Id="egk_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\egk-tool.exe" Vital="yes"/>
</Component>
<Component Id="goid_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\goid-tool.exe" Vital="yes"/>
</Component>
<Component Id="eidenv.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\eidenv.exe" Vital="yes"/>
</Component>
@ -362,6 +365,7 @@
<ComponentRef Id="pkcs11_tool.exe"/>
<ComponentRef Id="cardos_tool.exe"/>
<ComponentRef Id="egk_tool.exe"/>
<ComponentRef Id="goid_tool.exe"/>
<ComponentRef Id="eidenv.exe"/>
<ComponentRef Id="pkcs15_tool.exe"/>
<ComponentRef Id="pkcs15_crypt.exe"/>