Move branches/martin/0.12 to trunk
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3848 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
commit
2005bc2e92
9
NEWS
9
NEWS
|
@ -6,15 +6,8 @@ http://www.opensc-project.org/opensc/wiki/WhatsNew
|
||||||
Also see the svn changelog using svn command
|
Also see the svn changelog using svn command
|
||||||
or doc/nonpersistent/ChangeLog.
|
or doc/nonpersistent/ChangeLog.
|
||||||
|
|
||||||
New in 0.11.11-rc2; 2009-10-24; Andreas Jellinghaus
|
New in 0.??.==; 200?-??-??; ??
|
||||||
* Now again compatible with OpenSSL 0.9.7 and OpenSSL 1.0.0
|
|
||||||
* A few warnings and minor bugs were fixed
|
|
||||||
* Updated myeid driver by Aventra
|
|
||||||
|
|
||||||
New in 0.11.10; 2009-10-20; Andreas Jellinghaus
|
|
||||||
* New westcos driver by François Leblanc
|
* New westcos driver by François Leblanc
|
||||||
* Initial support for MyEid card (Aventra)
|
|
||||||
* GOST algorithm supported by Rutoken driver (Aleksey Samsonov)
|
|
||||||
|
|
||||||
New in 0.11.9; 2009-07-29; Andreas Jellinghaus
|
New in 0.11.9; 2009-07-29; Andreas Jellinghaus
|
||||||
* New rutoken_ecp driver by Aktiv Co. / Aleksey Samsonov
|
* New rutoken_ecp driver by Aktiv Co. / Aleksey Samsonov
|
||||||
|
|
44
configure.ac
44
configure.ac
|
@ -3,8 +3,8 @@ dnl -*- mode: m4; -*-
|
||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
|
|
||||||
define([PACKAGE_VERSION_MAJOR], [0])
|
define([PACKAGE_VERSION_MAJOR], [0])
|
||||||
define([PACKAGE_VERSION_MINOR], [11])
|
define([PACKAGE_VERSION_MINOR], [12])
|
||||||
define([PACKAGE_VERSION_FIX], [11])
|
define([PACKAGE_VERSION_FIX], [0])
|
||||||
define([PACKAGE_SUFFIX], [-svn])
|
define([PACKAGE_SUFFIX], [-svn])
|
||||||
|
|
||||||
AC_INIT([opensc],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX])
|
AC_INIT([opensc],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX])
|
||||||
|
@ -158,13 +158,6 @@ AC_ARG_ENABLE(
|
||||||
[enable_pcsc="yes"]
|
[enable_pcsc="yes"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_ENABLE(
|
|
||||||
[nsplugin],
|
|
||||||
[AS_HELP_STRING([--enable-nsplugin],[enable nsplugin (signer) @<:@disabled@:>@])],
|
|
||||||
,
|
|
||||||
[enable_nsplugin="no"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
[man],
|
[man],
|
||||||
[AS_HELP_STRING([--disable-man],[disable installation of manuals @<:@enabled for none Windows@:>@])],
|
[AS_HELP_STRING([--disable-man],[disable installation of manuals @<:@enabled for none Windows@:>@])],
|
||||||
|
@ -206,13 +199,6 @@ AC_ARG_WITH(
|
||||||
[with_pcsc_provider="detect"]
|
[with_pcsc_provider="detect"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_WITH(
|
|
||||||
[pinentry],
|
|
||||||
[AS_HELP_STRING([--with-pinentry=PROG],[run PROG as PIN-entry for OpenSC Signer @<:/usr/bin/gpinentry:>@])],
|
|
||||||
,
|
|
||||||
[with_pinentry="/usr/bin/gpinentry"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dnl Checks for programs.
|
dnl Checks for programs.
|
||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
@ -300,7 +286,7 @@ AC_HEADER_SYS_WAIT
|
||||||
AC_CHECK_HEADERS([ \
|
AC_CHECK_HEADERS([ \
|
||||||
errno.h fcntl.h malloc.h stdlib.h \
|
errno.h fcntl.h malloc.h stdlib.h \
|
||||||
inttypes.h string.h strings.h \
|
inttypes.h string.h strings.h \
|
||||||
sys/time.h unistd.h locale.h getopt.h
|
sys/time.h unistd.h locale.h getopt.h sys/mman.h
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
@ -597,21 +583,6 @@ if test "${enable_pcsc}" = "yes"; then
|
||||||
AC_DEFINE([ENABLE_PCSC], [1], [Define if PC/SC is to be enabled])
|
AC_DEFINE([ENABLE_PCSC], [1], [Define if PC/SC is to be enabled])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION,
|
|
||||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
|
|
||||||
dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS
|
|
||||||
AM_PATH_LIBASSUAN(
|
|
||||||
,
|
|
||||||
[have_assuan="yes"],
|
|
||||||
[have_assuan="no"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if test "${enable_nsplugin}" = "yes"; then
|
|
||||||
if test "x${have_assuan}" != "xyes" -o "x${have_openssl}" != "xyes"; then
|
|
||||||
AC_MSG_ERROR([nsplugin requires assuan and openssl])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
OPENSC_FEATURES=""
|
OPENSC_FEATURES=""
|
||||||
if test "${enable_zlib}" = "yes"; then
|
if test "${enable_zlib}" = "yes"; then
|
||||||
OPENSC_FEATURES="${OPENSC_FEATURES} zlib"
|
OPENSC_FEATURES="${OPENSC_FEATURES} zlib"
|
||||||
|
@ -642,12 +613,10 @@ if test "${enable_pcsc}" = "yes"; then
|
||||||
OPENSC_FEATURES="${OPENSC_FEATURES} pcsc(${DEFAULT_PCSC_PROVIDER})"
|
OPENSC_FEATURES="${OPENSC_FEATURES} pcsc(${DEFAULT_PCSC_PROVIDER})"
|
||||||
OPTIONAL_PCSC_CFLAGS="${PCSC_CFLAGS}"
|
OPTIONAL_PCSC_CFLAGS="${PCSC_CFLAGS}"
|
||||||
fi
|
fi
|
||||||
test "${enable_nsplugin}" = "yes" && OPENSC_FEATURES="${OPENSC_FEATURES} nsplugin"
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED([OPENSC_VERSION_MAJOR], [${OPENSC_VERSION_MAJOR}], [OpenSC version major component])
|
AC_DEFINE_UNQUOTED([OPENSC_VERSION_MAJOR], [${OPENSC_VERSION_MAJOR}], [OpenSC version major component])
|
||||||
AC_DEFINE_UNQUOTED([OPENSC_VERSION_MINOR], [${OPENSC_VERSION_MINOR}], [OpenSC version minor component])
|
AC_DEFINE_UNQUOTED([OPENSC_VERSION_MINOR], [${OPENSC_VERSION_MINOR}], [OpenSC version minor component])
|
||||||
AC_DEFINE_UNQUOTED([OPENSC_VERSION_FIX], [${OPENSC_VERSION_FIX}], [OpenSC version fix component])
|
AC_DEFINE_UNQUOTED([OPENSC_VERSION_FIX], [${OPENSC_VERSION_FIX}], [OpenSC version fix component])
|
||||||
test "${with_pinentry}" != "no" && AC_DEFINE_UNQUOTED([PIN_ENTRY], ["${with_pinentry}"], [PIN-entry program for OpenSC Signer])
|
|
||||||
AC_DEFINE_UNQUOTED([OPENSC_FEATURES], ["${OPENSC_FEATURES}"], [Enabled OpenSC features])
|
AC_DEFINE_UNQUOTED([OPENSC_FEATURES], ["${OPENSC_FEATURES}"], [Enabled OpenSC features])
|
||||||
|
|
||||||
openscincludedir="\$(includedir)/opensc"
|
openscincludedir="\$(includedir)/opensc"
|
||||||
|
@ -687,7 +656,6 @@ AM_CONDITIONAL([ENABLE_READLINE], [test "${enable_readline}" = "yes"])
|
||||||
AM_CONDITIONAL([ENABLE_ICONV], [test "${enable_iconv}" = "yes"])
|
AM_CONDITIONAL([ENABLE_ICONV], [test "${enable_iconv}" = "yes"])
|
||||||
AM_CONDITIONAL([ENABLE_OPENSSL], [test "${enable_openssl}" = "yes"])
|
AM_CONDITIONAL([ENABLE_OPENSSL], [test "${enable_openssl}" = "yes"])
|
||||||
AM_CONDITIONAL([ENABLE_OPENCT], [test "${enable_openct}" = "yes"])
|
AM_CONDITIONAL([ENABLE_OPENCT], [test "${enable_openct}" = "yes"])
|
||||||
AM_CONDITIONAL([ENABLE_NSPLUGIN], [test "${enable_nsplugin}" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_DOC], [test "${enable_doc}" = "yes"])
|
AM_CONDITIONAL([ENABLE_DOC], [test "${enable_doc}" = "yes"])
|
||||||
AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
|
AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
|
||||||
AM_CONDITIONAL([CYGWIN], [test "${CYGWIN}" = "yes"])
|
AM_CONDITIONAL([CYGWIN], [test "${CYGWIN}" = "yes"])
|
||||||
|
@ -723,8 +691,6 @@ AC_CONFIG_FILES([
|
||||||
src/pkcs11/Makefile
|
src/pkcs11/Makefile
|
||||||
src/pkcs15init/Makefile
|
src/pkcs15init/Makefile
|
||||||
src/scconf/Makefile
|
src/scconf/Makefile
|
||||||
src/signer/Makefile
|
|
||||||
src/signer/npinclude/Makefile
|
|
||||||
src/tests/Makefile
|
src/tests/Makefile
|
||||||
src/tests/regression/Makefile
|
src/tests/regression/Makefile
|
||||||
src/tools/Makefile
|
src/tools/Makefile
|
||||||
|
@ -751,10 +717,8 @@ iconv support: ${enable_iconv}
|
||||||
OpenSSL support: ${enable_openssl}
|
OpenSSL support: ${enable_openssl}
|
||||||
PC/SC support: ${enable_pcsc}
|
PC/SC support: ${enable_pcsc}
|
||||||
OpenCT support: ${enable_openct}
|
OpenCT support: ${enable_openct}
|
||||||
NSPlugin support: ${enable_nsplugin}
|
|
||||||
|
|
||||||
PC/SC default provider: ${DEFAULT_PCSC_PROVIDER}
|
PC/SC default provider: ${DEFAULT_PCSC_PROVIDER}
|
||||||
pinentry: ${with_pinentry}
|
|
||||||
|
|
||||||
Host: ${host}
|
Host: ${host}
|
||||||
Compiler: ${CC}
|
Compiler: ${CC}
|
||||||
|
@ -776,8 +740,6 @@ OPENSSL_LIBS: ${OPENSSL_LIBS}
|
||||||
OPENCT_CFLAGS: ${OPENCT_CFLAGS}
|
OPENCT_CFLAGS: ${OPENCT_CFLAGS}
|
||||||
OPENCT_LIBS: ${OPENCT_LIBS}
|
OPENCT_LIBS: ${OPENCT_LIBS}
|
||||||
PCSC_CFLAGS: ${PCSC_CFLAGS}
|
PCSC_CFLAGS: ${PCSC_CFLAGS}
|
||||||
LIBASSUAN_CFLAGS: ${LIBASSUAN_CFLAGS}
|
|
||||||
LIBASSUAN_LIBS: ${LIBASSUAN_LIBS}
|
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,10 @@
|
||||||
auto-detected.
|
auto-detected.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--wait, -w</option></term>
|
||||||
|
<listitem><para>Wait for a card to be inserted</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--verbose, -v</option></term>
|
<term><option>--verbose, -v</option></term>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
|
@ -152,18 +156,6 @@
|
||||||
and <varname>size</varname> is the size of the new file.</para></listitem>
|
and <varname>size</varname> is the size of the new file.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>pksign</option></term>
|
|
||||||
<listitem><para>create a public key signature. NOTE: This command is currently not implemented.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>pkdecrypt</option></term>
|
|
||||||
<listitem><para>perform a public key decryption. NOTE: This command is currently not implemented.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>erase</option></term>
|
<term><option>erase</option></term>
|
||||||
<listitem><para>erase the card, if the card supports it.</para></listitem>
|
<listitem><para>erase the card, if the card supports it.</para></listitem>
|
||||||
|
|
|
@ -31,11 +31,20 @@
|
||||||
<title>Options</title>
|
<title>Options</title>
|
||||||
<para>
|
<para>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--info, -i</option></term>
|
||||||
|
<listitem><para>Print information about OpenSC, such as version and enabled components</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--atr, -a</option></term>
|
<term><option>--atr, -a</option></term>
|
||||||
<listitem><para>Print the Answer To Reset (ATR) of the card,
|
<listitem><para>Print the Answer To Reset (ATR) of the card,
|
||||||
output is in hex byte format</para></listitem>
|
output is in hex byte format</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--name, -n</option></term>
|
||||||
|
<listitem><para>Print the name of the inserted card (driver)</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--serial</option></term>
|
<term><option>--serial</option></term>
|
||||||
<listitem><para>Print the card serial number (normally the ICCSN), output is in hex byte
|
<listitem><para>Print the card serial number (normally the ICCSN), output is in hex byte
|
||||||
|
@ -70,6 +79,10 @@ in the system.</para></listitem>
|
||||||
<term><option>--card-driver</option> driver, <option>-c</option> driver</term>
|
<term><option>--card-driver</option> driver, <option>-c</option> driver</term>
|
||||||
<listitem><para>Use the given card driver. The default is auto-detected.</para></listitem>
|
<listitem><para>Use the given card driver. The default is auto-detected.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--wait, -w</option></term>
|
||||||
|
<listitem><para>Wait for a card to be inserted</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--verbose, -v</option></term>
|
<term><option>--verbose, -v</option></term>
|
||||||
<listitem><para>Causes <command>opensc-tool</command> to be more verbose. Specify this flag several times
|
<listitem><para>Causes <command>opensc-tool</command> to be more verbose. Specify this flag several times
|
||||||
|
|
|
@ -341,6 +341,17 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--use-default-transport-keys</option>,
|
||||||
|
<option>-T</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Tells <command>pkcs15-init</command> to not ask for the transport
|
||||||
|
keys and use default keys, as known by the card driver.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--so-pin, --so-puk, --pin, --puk</option></term>
|
<term><option>--so-pin, --so-puk, --pin, --puk</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -16,20 +16,12 @@ app default {
|
||||||
|
|
||||||
# The file to which debug output will be written
|
# The file to which debug output will be written
|
||||||
#
|
#
|
||||||
# A special value of 'stdout' is recognized.
|
# Special values 'stdout' and 'stderr' are recognized.
|
||||||
# Default: stdout
|
# Default: stderr
|
||||||
#
|
#
|
||||||
# debug_file = /tmp/opensc-debug.log;
|
# debug_file = /tmp/opensc-debug.log;
|
||||||
# debug_file = "C:\Documents and Settings\All Users\Documents\opensc-debug.log";
|
# debug_file = "C:\Documents and Settings\All Users\Documents\opensc-debug.log";
|
||||||
|
|
||||||
# The file to which errors will be written
|
|
||||||
#
|
|
||||||
# A special value of 'stderr' is recognized.
|
|
||||||
# Default: stderr
|
|
||||||
#
|
|
||||||
# error_file = /tmp/opensc-errors.log;
|
|
||||||
# error_file = "C:\Documents and Settings\All Users\Documents\opensc-errors.log";
|
|
||||||
|
|
||||||
# PKCS#15 initialization / personalization
|
# PKCS#15 initialization / personalization
|
||||||
# profiles directory for pkcs15-init.
|
# profiles directory for pkcs15-init.
|
||||||
# Default: @pkgdatadir@
|
# Default: @pkgdatadir@
|
||||||
|
@ -86,8 +78,8 @@ app default {
|
||||||
# transaction_reset = true;
|
# transaction_reset = true;
|
||||||
#
|
#
|
||||||
# Enable pinpad if detected (PC/SC v2.0.2 Part 10)
|
# Enable pinpad if detected (PC/SC v2.0.2 Part 10)
|
||||||
# Default: false
|
# Default: true
|
||||||
# enable_pinpad = true;
|
# enable_pinpad = false;
|
||||||
#
|
#
|
||||||
# Use specific pcsc provider.
|
# Use specific pcsc provider.
|
||||||
# Default: @DEFAULT_PCSC_PROVIDER@
|
# Default: @DEFAULT_PCSC_PROVIDER@
|
||||||
|
@ -256,14 +248,25 @@ app default {
|
||||||
# WARNING: Caching shouldn't be used in setuid root
|
# WARNING: Caching shouldn't be used in setuid root
|
||||||
# applications.
|
# applications.
|
||||||
# Default: false
|
# Default: false
|
||||||
|
# use_file_caching = true;
|
||||||
|
#
|
||||||
|
# Use PIN caching?
|
||||||
|
# Default: true
|
||||||
|
# use_pin_caching = false;
|
||||||
|
#
|
||||||
|
# How many times to use a PIN from cache before re-authenticating it?
|
||||||
|
# Default: 10
|
||||||
|
# pin_cache_counter = 3;
|
||||||
#
|
#
|
||||||
use_caching = true;
|
|
||||||
# Enable pkcs15 emulation.
|
# Enable pkcs15 emulation.
|
||||||
# Default: yes
|
# Default: yes
|
||||||
# enable_pkcs15_emulation = no;
|
# enable_pkcs15_emulation = no;
|
||||||
#
|
#
|
||||||
# Prefer pkcs15 emulation code before
|
# Prefer pkcs15 emulation code before
|
||||||
# the normal pkcs15 processing.
|
# the normal pkcs15 processing.
|
||||||
|
# Some cards (like esteid and pteid) work in emu-only mode,
|
||||||
|
# and do not depend on this option.
|
||||||
|
#
|
||||||
# Default: no
|
# Default: no
|
||||||
# try_emulation_first = yes;
|
# try_emulation_first = yes;
|
||||||
#
|
#
|
||||||
|
@ -293,7 +296,7 @@ app default {
|
||||||
# so you can turn it off, if it misbehaves.
|
# so you can turn it off, if it misbehaves.
|
||||||
# this option only affects cardos cards right now.
|
# this option only affects cardos cards right now.
|
||||||
# Default: yes
|
# Default: yes
|
||||||
# enable_sign_with_decrypt_workaround = yes;
|
# enable_sign_with_decrypt_workaround = no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,19 +356,7 @@ app opensc-pkcs11 {
|
||||||
#
|
#
|
||||||
# Default: true
|
# Default: true
|
||||||
# lock_login = false;
|
# lock_login = false;
|
||||||
|
|
||||||
# Normally, the pkcs11 module will not cache PINs
|
|
||||||
# presented via C_Login. However, some cards
|
|
||||||
# may not work properly with OpenSC; for instance
|
|
||||||
# when you have two keys on your card that get
|
|
||||||
# stored in two different directories.
|
|
||||||
#
|
#
|
||||||
# In this case, you can turn on PIN caching by setting
|
|
||||||
# cache_pins = true
|
|
||||||
#
|
|
||||||
# Default: true
|
|
||||||
# cache_pins = false;
|
|
||||||
|
|
||||||
# Set this value to true if you want to allow off-card
|
# Set this value to true if you want to allow off-card
|
||||||
# keypair generation (in software on your pc)
|
# keypair generation (in software on your pc)
|
||||||
#
|
#
|
||||||
|
|
|
@ -92,7 +92,6 @@ f none usr/include/opensc/rsaref/win32.h 0644 root bin
|
||||||
f none usr/include/opensc/scconf.h 0644 root bin
|
f none usr/include/opensc/scconf.h 0644 root bin
|
||||||
f none usr/include/opensc/opensc.h 0644 root bin
|
f none usr/include/opensc/opensc.h 0644 root bin
|
||||||
f none usr/include/opensc/pkcs15.h 0644 root bin
|
f none usr/include/opensc/pkcs15.h 0644 root bin
|
||||||
f none usr/include/opensc/emv.h 0644 root bin
|
|
||||||
f none usr/include/opensc/cardctl.h 0644 root bin
|
f none usr/include/opensc/cardctl.h 0644 root bin
|
||||||
f none usr/include/opensc/asn1.h 0644 root bin
|
f none usr/include/opensc/asn1.h 0644 root bin
|
||||||
f none usr/include/opensc/log.h 0644 root bin
|
f none usr/include/opensc/log.h 0644 root bin
|
||||||
|
|
|
@ -3,4 +3,4 @@ EXTRA_DIST = Makefile.mak
|
||||||
|
|
||||||
# Order IS important
|
# Order IS important
|
||||||
SUBDIRS = common include scconf libopensc pkcs15init pkcs11 \
|
SUBDIRS = common include scconf libopensc pkcs15init pkcs11 \
|
||||||
tests tools openssh signer
|
tests tools openssh
|
||||||
|
|
|
@ -6,7 +6,6 @@ all-local:
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/asn1.h asn1.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/asn1.h asn1.h
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/cardctl.h cardctl.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/cardctl.h cardctl.h
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/cards.h cards.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/cards.h cards.h
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/emv.h emv.h
|
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/errors.h errors.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/errors.h errors.h
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/log.h log.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/log.h log.h
|
||||||
@$(LN_S) $(top_srcdir)/src/libopensc/opensc.h opensc.h
|
@$(LN_S) $(top_srcdir)/src/libopensc/opensc.h opensc.h
|
||||||
|
|
|
@ -8,7 +8,7 @@ EXTRA_DIST = Makefile.mak
|
||||||
bin_SCRIPTS = opensc-config
|
bin_SCRIPTS = opensc-config
|
||||||
lib_LTLIBRARIES = libopensc.la
|
lib_LTLIBRARIES = libopensc.la
|
||||||
openscinclude_HEADERS = \
|
openscinclude_HEADERS = \
|
||||||
opensc.h pkcs15.h emv.h \
|
opensc.h pkcs15.h \
|
||||||
cardctl.h asn1.h log.h ui.h \
|
cardctl.h asn1.h log.h ui.h \
|
||||||
errors.h types.h compression.h
|
errors.h types.h compression.h
|
||||||
noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.h \
|
noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.h \
|
||||||
|
@ -30,7 +30,7 @@ libopensc_la_SOURCES = \
|
||||||
pkcs15-wrap.c pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \
|
pkcs15-wrap.c pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \
|
||||||
pkcs15-gemsafeV1.c \
|
pkcs15-gemsafeV1.c \
|
||||||
\
|
\
|
||||||
emv.c muscle.c muscle-filesystem.c \
|
muscle.c muscle-filesystem.c \
|
||||||
\
|
\
|
||||||
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c \
|
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c \
|
||||||
\
|
\
|
||||||
|
@ -40,12 +40,12 @@ libopensc_la_SOURCES = \
|
||||||
card-oberthur.c card-belpic.c card-atrust-acos.c card-entersafe.c \
|
card-oberthur.c card-belpic.c card-atrust-acos.c card-entersafe.c \
|
||||||
card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \
|
card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \
|
||||||
card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
|
card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
|
||||||
card-rtecp.c card-westcos.c card-myeid.c \
|
card-rtecp.c card-westcos.c card-myeid.c card-ias.c\
|
||||||
\
|
\
|
||||||
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
||||||
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \
|
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \
|
||||||
pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
|
pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
|
||||||
pkcs15-esinit.c p15emu-westcos.c \
|
pkcs15-esinit.c p15emu-westcos.c pkcs15-pteid.c \
|
||||||
compression.c p15card-helper.c \
|
compression.c p15card-helper.c \
|
||||||
\
|
\
|
||||||
libopensc.exports
|
libopensc.exports
|
||||||
|
|
|
@ -4,7 +4,7 @@ TOPDIR = ..\..
|
||||||
TARGET = opensc.dll opensc_a.lib
|
TARGET = opensc.dll opensc_a.lib
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
asn1.h cardctl.h cards.h emv.h errors.h \
|
asn1.h cardctl.h cards.h errors.h \
|
||||||
log.h opensc.h pkcs15.h types.h ui.h
|
log.h opensc.h pkcs15.h types.h ui.h
|
||||||
|
|
||||||
HEADERSDIR = $(TOPDIR)\src\include\opensc
|
HEADERSDIR = $(TOPDIR)\src\include\opensc
|
||||||
|
@ -18,7 +18,7 @@ OBJECTS = \
|
||||||
pkcs15-wrap.obj pkcs15-algo.obj pkcs15-cache.obj pkcs15-syn.obj \
|
pkcs15-wrap.obj pkcs15-algo.obj pkcs15-cache.obj pkcs15-syn.obj \
|
||||||
pkcs15-gemsafeV1.obj \
|
pkcs15-gemsafeV1.obj \
|
||||||
\
|
\
|
||||||
emv.obj muscle.obj muscle-filesystem.obj \
|
muscle.obj muscle-filesystem.obj \
|
||||||
\
|
\
|
||||||
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj \
|
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj \
|
||||||
\
|
\
|
||||||
|
@ -28,13 +28,13 @@ OBJECTS = \
|
||||||
card-oberthur.obj card-belpic.obj card-atrust-acos.obj card-entersafe.obj \
|
card-oberthur.obj card-belpic.obj card-atrust-acos.obj card-entersafe.obj \
|
||||||
card-incrypto34.obj card-piv.obj card-muscle.obj card-acos5.obj \
|
card-incrypto34.obj card-piv.obj card-muscle.obj card-acos5.obj \
|
||||||
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
|
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
|
||||||
card-rtecp.obj card-westcos.obj card-myeid.obj \
|
card-rtecp.obj card-westcos.obj card-myeid.obj card-ias.obj \
|
||||||
\
|
\
|
||||||
p15emu-westcos.obj \
|
p15emu-westcos.obj \
|
||||||
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
||||||
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \
|
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \
|
||||||
pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
|
pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
|
||||||
pkcs15-esinit.obj \
|
pkcs15-esinit.obj pkcs15-pteid.c \
|
||||||
compression.obj p15card-helper.obj \
|
compression.obj p15card-helper.obj \
|
||||||
versioninfo.res
|
versioninfo.res
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ static int sc_apdu2bytes(sc_context_t *ctx, const sc_apdu_t *apdu,
|
||||||
if (apdu->lc > 255) {
|
if (apdu->lc > 255) {
|
||||||
/* ... so if Lc is greater than 255 bytes
|
/* ... so if Lc is greater than 255 bytes
|
||||||
* an error has occurred on a higher level */
|
* an error has occurred on a higher level */
|
||||||
sc_error(ctx, "invalid Lc length for CASE 3 "
|
sc_debug(ctx, "invalid Lc length for CASE 3 "
|
||||||
"extended APDU (need ENVELOPE)");
|
"extended APDU (need ENVELOPE)");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
|
||||||
{
|
{
|
||||||
if (len < 2) {
|
if (len < 2) {
|
||||||
/* no SW1 SW2 ... something went terrible wrong */
|
/* no SW1 SW2 ... something went terrible wrong */
|
||||||
sc_error(ctx, "invalid response: SW1 SW2 missing");
|
sc_debug(ctx, "invalid response: SW1 SW2 missing");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
/* set the SW1 and SW2 status bytes (the last two bytes of
|
/* set the SW1 and SW2 status bytes (the last two bytes of
|
||||||
|
@ -273,7 +273,7 @@ static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
|
||||||
} else if ((apdu->cse & SC_APDU_EXT) != 0) {
|
} else if ((apdu->cse & SC_APDU_EXT) != 0) {
|
||||||
/* check if the card support extended APDUs */
|
/* check if the card support extended APDUs */
|
||||||
if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0) {
|
if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0) {
|
||||||
sc_error(card->ctx, "card doesn't support extended APDUs");
|
sc_debug(card->ctx, "card doesn't support extended APDUs");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* length check for extended APDU */
|
/* length check for extended APDU */
|
||||||
|
@ -284,12 +284,12 @@ static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
|
||||||
|
|
||||||
switch (apdu->cse & SC_APDU_SHORT_MASK) {
|
switch (apdu->cse & SC_APDU_SHORT_MASK) {
|
||||||
case SC_APDU_CASE_1:
|
case SC_APDU_CASE_1:
|
||||||
/* no data is send or received */
|
/* no data is sent or received */
|
||||||
if (apdu->datalen != 0 || apdu->lc != 0 || apdu->le != 0)
|
if (apdu->datalen != 0 || apdu->lc != 0 || apdu->le != 0)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case SC_APDU_CASE_2_SHORT:
|
case SC_APDU_CASE_2_SHORT:
|
||||||
/* no data is send */
|
/* no data is sent */
|
||||||
if (apdu->datalen != 0 || apdu->lc != 0)
|
if (apdu->datalen != 0 || apdu->lc != 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* data is expected */
|
/* data is expected */
|
||||||
|
@ -300,7 +300,7 @@ static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case SC_APDU_CASE_3_SHORT:
|
case SC_APDU_CASE_3_SHORT:
|
||||||
/* data is send */
|
/* data is sent */
|
||||||
if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0)
|
if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* no data is expected */
|
/* no data is expected */
|
||||||
|
@ -311,7 +311,7 @@ static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case SC_APDU_CASE_4_SHORT:
|
case SC_APDU_CASE_4_SHORT:
|
||||||
/* data is send */
|
/* data is sent */
|
||||||
if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0)
|
if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* data is expected */
|
/* data is expected */
|
||||||
|
@ -325,12 +325,12 @@ static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid APDU case %d\n", apdu->cse);
|
sc_debug(card->ctx, "Invalid APDU case %d\n", apdu->cse);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
error:
|
error:
|
||||||
sc_error(card->ctx, "Invalid Case %d %s APDU:\n"
|
sc_debug(card->ctx, "Invalid Case %d %s APDU:\n"
|
||||||
"cse=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%lu le=%lu\n"
|
"cse=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%lu le=%lu\n"
|
||||||
"resp=%p resplen=%lu data=%p datalen=%lu",
|
"resp=%p resplen=%lu data=%p datalen=%lu",
|
||||||
apdu->cse & SC_APDU_SHORT_MASK,
|
apdu->cse & SC_APDU_SHORT_MASK,
|
||||||
|
@ -366,7 +366,7 @@ static void sc_detect_apdu_cse(const sc_card_t *card, sc_apdu_t *apdu)
|
||||||
/** Sends a single APDU to the card reader and calls
|
/** Sends a single APDU to the card reader and calls
|
||||||
* GET RESPONSE to get the return data if necessary.
|
* GET RESPONSE to get the return data if necessary.
|
||||||
* @param card sc_card_t object for the smartcard
|
* @param card sc_card_t object for the smartcard
|
||||||
* @param apdu APDU to be send
|
* @param apdu APDU to be sent
|
||||||
* @return SC_SUCCESS on success and an error value otherwise
|
* @return SC_SUCCESS on success and an error value otherwise
|
||||||
*/
|
*/
|
||||||
static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
|
@ -391,7 +391,7 @@ static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
r = card->reader->ops->transmit(card->reader, card->slot, apdu);
|
r = card->reader->ops->transmit(card->reader, card->slot, apdu);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
sc_error(ctx, "unable to transmit APDU");
|
sc_debug(ctx, "unable to transmit APDU");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* ok, the APDU was successfully transmitted. Now we have two
|
/* ok, the APDU was successfully transmitted. Now we have two
|
||||||
|
@ -416,7 +416,7 @@ static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
/* re-transmit the APDU with new Le length */
|
/* re-transmit the APDU with new Le length */
|
||||||
r = card->reader->ops->transmit(card->reader, card->slot, apdu);
|
r = card->reader->ops->transmit(card->reader, card->slot, apdu);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(ctx, "unable to transmit APDU");
|
sc_debug(ctx, "unable to transmit APDU");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -451,7 +451,7 @@ static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
|
|
||||||
if (card->ops->get_response == NULL) {
|
if (card->ops->get_response == NULL) {
|
||||||
/* this should _never_ happen */
|
/* this should _never_ happen */
|
||||||
sc_error(ctx, "no GET RESPONSE command\n");
|
sc_debug(ctx, "no GET RESPONSE command\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
|
|
||||||
r = sc_lock(card); /* acquire card lock*/
|
r = sc_lock(card); /* acquire card lock*/
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to acquire lock");
|
sc_debug(card->ctx, "unable to acquire lock");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
|
|
||||||
r = sc_check_apdu(card, &tapdu);
|
r = sc_check_apdu(card, &tapdu);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "inconsistent APDU while chaining");
|
sc_debug(card->ctx, "inconsistent APDU while chaining");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +593,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu)
|
||||||
r = do_single_transmit(card, apdu);
|
r = do_single_transmit(card, apdu);
|
||||||
/* all done => release lock */
|
/* all done => release lock */
|
||||||
if (sc_unlock(card) != SC_SUCCESS)
|
if (sc_unlock(card) != SC_SUCCESS)
|
||||||
sc_error(card->ctx, "sc_unlock failed");
|
sc_debug(card->ctx, "sc_unlock failed");
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,7 +307,7 @@ const u8 *sc_asn1_find_tag(sc_context_t *ctx, const u8 * buf,
|
||||||
if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS)
|
if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (left < (size_t)(p - buf)) {
|
if (left < (size_t)(p - buf)) {
|
||||||
sc_error(ctx, "invalid TLV object\n");
|
sc_debug(ctx, "invalid TLV object\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
left -= (p - buf);
|
left -= (p - buf);
|
||||||
|
@ -327,7 +327,7 @@ const u8 *sc_asn1_find_tag(sc_context_t *ctx, const u8 * buf,
|
||||||
}
|
}
|
||||||
/* otherwise continue reading tags */
|
/* otherwise continue reading tags */
|
||||||
if (left < taglen) {
|
if (left < taglen) {
|
||||||
sc_error(ctx, "invalid TLV object\n");
|
sc_debug(ctx, "invalid TLV object\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
left -= taglen;
|
left -= taglen;
|
||||||
|
@ -373,7 +373,7 @@ const u8 *sc_asn1_skip_tag(sc_context_t *ctx, const u8 ** buf, size_t *buflen,
|
||||||
return NULL;
|
return NULL;
|
||||||
len -= (p - *buf); /* header size */
|
len -= (p - *buf); /* header size */
|
||||||
if (taglen > len) {
|
if (taglen > len) {
|
||||||
sc_error(ctx, "too long ASN.1 object (size %d while only %d available)\n",
|
sc_debug(ctx, "too long ASN.1 object (size %d while only %d available)\n",
|
||||||
taglen, len);
|
taglen, len);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +723,7 @@ static int asn1_write_element(sc_context_t *ctx, unsigned int tag,
|
||||||
|
|
||||||
t = tag & 0x1F;
|
t = tag & 0x1F;
|
||||||
if (t != (tag & SC_ASN1_TAG_MASK)) {
|
if (t != (tag & SC_ASN1_TAG_MASK)) {
|
||||||
sc_error(ctx, "Long tags not supported\n");
|
sc_debug(ctx, "Long tags not supported\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
switch (tag & SC_ASN1_CLASS_MASK) {
|
switch (tag & SC_ASN1_CLASS_MASK) {
|
||||||
|
@ -989,7 +989,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
||||||
case SC_ASN1_BOOLEAN:
|
case SC_ASN1_BOOLEAN:
|
||||||
if (parm != NULL) {
|
if (parm != NULL) {
|
||||||
if (objlen != 1) {
|
if (objlen != 1) {
|
||||||
sc_error(ctx, "invalid ASN.1 object length: %d\n", objlen);
|
sc_debug(ctx, "invalid ASN.1 object length: %d\n", objlen);
|
||||||
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
} else
|
} else
|
||||||
*((int *) parm) = obj[0] ? 1 : 0;
|
*((int *) parm) = obj[0] ? 1 : 0;
|
||||||
|
@ -1133,11 +1133,11 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
||||||
r = callback_func(ctx, entry->arg, obj, objlen, depth);
|
r = callback_func(ctx, entry->arg, obj, objlen, depth);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "invalid ASN.1 type: %d\n", entry->type);
|
sc_debug(ctx, "invalid ASN.1 type: %d\n", entry->type);
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "decoding of ASN.1 object '%s' failed: %s\n", entry->name,
|
sc_debug(ctx, "decoding of ASN.1 object '%s' failed: %s\n", entry->name,
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1167,7 +1167,7 @@ static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1,
|
||||||
* to complain about */
|
* to complain about */
|
||||||
if (asn1->name == NULL)
|
if (asn1->name == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
sc_error(ctx, "End of ASN.1 stream, "
|
sc_debug(ctx, "End of ASN.1 stream, "
|
||||||
"non-optional field \"%s\" not found\n",
|
"non-optional field \"%s\" not found\n",
|
||||||
asn1->name);
|
asn1->name);
|
||||||
return SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
return SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
||||||
|
@ -1204,7 +1204,7 @@ static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1,
|
||||||
continue;
|
continue;
|
||||||
if (entry->flags & SC_ASN1_OPTIONAL)
|
if (entry->flags & SC_ASN1_OPTIONAL)
|
||||||
continue;
|
continue;
|
||||||
sc_error(ctx, "mandatory ASN.1 object '%s' not found\n", entry->name);
|
sc_debug(ctx, "mandatory ASN.1 object '%s' not found\n", entry->name);
|
||||||
if (ctx->debug && left) {
|
if (ctx->debug && left) {
|
||||||
u8 line[128], *linep = line;
|
u8 line[128], *linep = line;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -1281,7 +1281,7 @@ static int asn1_encode_entry(sc_context_t *ctx, const struct sc_asn1_entry *entr
|
||||||
while (list->name != NULL) {
|
while (list->name != NULL) {
|
||||||
if (list->flags & SC_ASN1_PRESENT) {
|
if (list->flags & SC_ASN1_PRESENT) {
|
||||||
if (choice) {
|
if (choice) {
|
||||||
sc_error(ctx,
|
sc_debug(ctx,
|
||||||
"ASN.1 problem: more than "
|
"ASN.1 problem: more than "
|
||||||
"one CHOICE when encoding %s: "
|
"one CHOICE when encoding %s: "
|
||||||
"%s and %s both present\n",
|
"%s and %s both present\n",
|
||||||
|
@ -1300,7 +1300,7 @@ static int asn1_encode_entry(sc_context_t *ctx, const struct sc_asn1_entry *entr
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->type != SC_ASN1_NULL && parm == NULL) {
|
if (entry->type != SC_ASN1_NULL && parm == NULL) {
|
||||||
sc_error(ctx, "unexpected parm == NULL\n");
|
sc_debug(ctx, "unexpected parm == NULL\n");
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,11 +1396,11 @@ static int asn1_encode_entry(sc_context_t *ctx, const struct sc_asn1_entry *entr
|
||||||
r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
|
r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "invalid ASN.1 type: %d\n", entry->type);
|
sc_debug(ctx, "invalid ASN.1 type: %d\n", entry->type);
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "encoding of ASN.1 object '%s' failed: %s\n", entry->name,
|
sc_debug(ctx, "encoding of ASN.1 object '%s' failed: %s\n", entry->name,
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
if (buf)
|
if (buf)
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -1430,13 +1430,13 @@ no_object:
|
||||||
r = asn1_write_element(ctx, entry->tag,
|
r = asn1_write_element(ctx, entry->tag,
|
||||||
buf, buflen, obj, objlen);
|
buf, buflen, obj, objlen);
|
||||||
if (r)
|
if (r)
|
||||||
sc_error(ctx, "error writing ASN.1 tag and length: %s\n",
|
sc_debug(ctx, "error writing ASN.1 tag and length: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
} else if (!(entry->flags & SC_ASN1_PRESENT)) {
|
} else if (!(entry->flags & SC_ASN1_PRESENT)) {
|
||||||
sc_error(ctx, "cannot encode non-optional ASN.1 object: not given by caller\n");
|
sc_debug(ctx, "cannot encode non-optional ASN.1 object: not given by caller\n");
|
||||||
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
} else {
|
} else {
|
||||||
sc_error(ctx, "cannot encode empty non-optional ASN.1 object\n");
|
sc_debug(ctx, "cannot encode empty non-optional ASN.1 object\n");
|
||||||
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
r = SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
if (buf)
|
if (buf)
|
||||||
|
|
|
@ -54,11 +54,6 @@ static int acos5_init(sc_card_t * card)
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acos5_finish(sc_card_t * card)
|
|
||||||
{
|
|
||||||
return SC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acos5_select_file_by_path(sc_card_t * card,
|
static int acos5_select_file_by_path(sc_card_t * card,
|
||||||
const sc_path_t * in_path,
|
const sc_path_t * in_path,
|
||||||
sc_file_t ** file_out)
|
sc_file_t ** file_out)
|
||||||
|
@ -225,7 +220,6 @@ static struct sc_card_driver *sc_get_driver(void)
|
||||||
|
|
||||||
acos5_ops.match_card = acos5_match_card;
|
acos5_ops.match_card = acos5_match_card;
|
||||||
acos5_ops.init = acos5_init;
|
acos5_ops.init = acos5_init;
|
||||||
acos5_ops.finish = acos5_finish;
|
|
||||||
acos5_ops.select_file = acos5_select_file;
|
acos5_ops.select_file = acos5_select_file;
|
||||||
acos5_ops.card_ctl = acos5_card_ctl;
|
acos5_ops.card_ctl = acos5_card_ctl;
|
||||||
acos5_ops.list_files = acos5_list_files;
|
acos5_ops.list_files = acos5_list_files;
|
||||||
|
|
|
@ -168,7 +168,7 @@ akis_list_files(sc_card_t *card, u8 *buf, size_t buflen)
|
||||||
|
|
||||||
while (left > 19) {
|
while (left > 19) {
|
||||||
if (p[0] != 0x2f && p[0] != 0x3d) {
|
if (p[0] != 0x2f && p[0] != 0x3d) {
|
||||||
sc_error(card->ctx, "Malformatted list reply %02x", p[0]);
|
sc_debug(card->ctx, "Malformatted list reply %02x", p[0]);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
if (buflen >= 2) {
|
if (buflen >= 2) {
|
||||||
|
@ -202,7 +202,7 @@ akis_process_fci(sc_card_t *card, sc_file_t *file,
|
||||||
*/
|
*/
|
||||||
p = sc_asn1_find_tag(card->ctx, buf, buflen, 0x90, &len);
|
p = sc_asn1_find_tag(card->ctx, buf, buflen, 0x90, &len);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
sc_error(card->ctx, "Security tag missing");
|
sc_debug(card->ctx, "Security tag missing");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
perms = p[0];
|
perms = p[0];
|
||||||
|
@ -272,7 +272,7 @@ akis_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
type = 0x45;
|
type = 0x45;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "This EF structure is not supported yet");
|
sc_debug(card->ctx, "This EF structure is not supported yet");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
apdu.p1 = type;
|
apdu.p1 = type;
|
||||||
|
@ -284,7 +284,7 @@ akis_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
} else if (file->type == SC_FILE_TYPE_DF) {
|
} else if (file->type == SC_FILE_TYPE_DF) {
|
||||||
apdu.ins = 0x10;
|
apdu.ins = 0x10;
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "Unknown file type");
|
sc_debug(card->ctx, "Unknown file type");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ akis_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
type = 0x08;
|
type = 0x08;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "File type has to be FID or PATH");
|
sc_debug(card->ctx, "File type has to be FID or PATH");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x16, type, 0x00);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x16, type, 0x00);
|
||||||
|
@ -354,7 +354,6 @@ akis_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left
|
||||||
p1 = 1;
|
p1 = 1;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, p2);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, p2);
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
buf[0] = data->pin1.len;
|
buf[0] = data->pin1.len;
|
||||||
memcpy(buf+1, data->pin1.data, data->pin1.len);
|
memcpy(buf+1, data->pin1.data, data->pin1.len);
|
||||||
|
@ -372,7 +371,7 @@ akis_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_error(card->ctx, "Other pin cmds not supported yet");
|
sc_debug(card->ctx, "Other pin cmds not supported yet");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,6 @@ static struct sc_atr_table asepcos_atrs[] = {
|
||||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int asepcos_finish(sc_card_t *card)
|
|
||||||
{
|
|
||||||
return SC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int asepcos_match_card(sc_card_t *card)
|
static int asepcos_match_card(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int i = _sc_match_atr(card, asepcos_atrs, &card->type);
|
int i = _sc_match_atr(card, asepcos_atrs, &card->type);
|
||||||
|
@ -64,7 +59,7 @@ static int asepcos_select_asepcos_applet(sc_card_t *card)
|
||||||
|
|
||||||
r = sc_select_file(card, &tpath, NULL);
|
r = sc_select_file(card, &tpath, NULL);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to select ASEPCOS applet");
|
sc_debug(card->ctx, "unable to select ASEPCOS applet");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +160,7 @@ static int asepcos_parse_sec_attr(sc_card_t *card, sc_file_t *file, const u8 *bu
|
||||||
while (len != 0) {
|
while (len != 0) {
|
||||||
unsigned int amode, tlen = 3;
|
unsigned int amode, tlen = 3;
|
||||||
if (len < 5 && p[0] != 0x80 && p[1] != 0x01) {
|
if (len < 5 && p[0] != 0x80 && p[1] != 0x01) {
|
||||||
sc_error(card->ctx, "invalid access mode encoding");
|
sc_debug(card->ctx, "invalid access mode encoding");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
amode = p[2];
|
amode = p[2];
|
||||||
|
@ -192,7 +187,7 @@ static int asepcos_parse_sec_attr(sc_card_t *card, sc_file_t *file, const u8 *bu
|
||||||
return r;
|
return r;
|
||||||
tlen += 2 + p[4]; /* FIXME */
|
tlen += 2 + p[4]; /* FIXME */
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "invalid security condition");
|
sc_debug(card->ctx, "invalid security condition");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
p += tlen;
|
p += tlen;
|
||||||
|
@ -306,7 +301,7 @@ static int asepcos_select_file(sc_card_t *card, const sc_path_t *in_path,
|
||||||
if (r == SC_SUCCESS && file != NULL) {
|
if (r == SC_SUCCESS && file != NULL) {
|
||||||
r = asepcos_parse_sec_attr(card, *file, (*file)->sec_attr, (*file)->sec_attr_len);
|
r = asepcos_parse_sec_attr(card, *file, (*file)->sec_attr, (*file)->sec_attr_len);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
sc_error(card->ctx, "error parsing security attributes");
|
sc_debug(card->ctx, "error parsing security attributes");
|
||||||
}
|
}
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
@ -482,7 +477,7 @@ static int asepcos_set_security_attributes(sc_card_t *card, sc_file_t *file)
|
||||||
*p++ = (st.fileid >> 8 ) & 0xff;
|
*p++ = (st.fileid >> 8 ) & 0xff;
|
||||||
*p++ = st.fileid & 0xff;
|
*p++ = st.fileid & 0xff;
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "unknow auth method: '%d'", ent->method);
|
sc_debug(card->ctx, "unknow auth method: '%d'", ent->method);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,7 +504,6 @@ static int asepcos_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_le
|
||||||
* to tell the card the we want everything available (note: we
|
* to tell the card the we want everything available (note: we
|
||||||
* always have Le <= crgram_len) */
|
* always have Le <= crgram_len) */
|
||||||
apdu.le = (outlen >= 256 && crgram_len < 256) ? 256 : outlen;
|
apdu.le = (outlen >= 256 && crgram_len < 256) ? 256 : outlen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
apdu.data = crgram;
|
apdu.data = crgram;
|
||||||
apdu.lc = crgram_len;
|
apdu.lc = crgram_len;
|
||||||
|
@ -550,7 +544,7 @@ static int asepcos_compute_signature(sc_card_t *card, const u8 *data, size_t dat
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
||||||
sc_error(card->ctx, "error creating signature");
|
sc_debug(card->ctx, "error creating signature");
|
||||||
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +622,7 @@ static int asepcos_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
/* set security attributes */
|
/* set security attributes */
|
||||||
r = asepcos_set_security_attributes(card, file);
|
r = asepcos_set_security_attributes(card, file);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to set security attributes");
|
sc_debug(card->ctx, "unable to set security attributes");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
|
@ -674,7 +668,7 @@ static int asepcos_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
/* set security attributes */
|
/* set security attributes */
|
||||||
r = asepcos_set_security_attributes(card, file);
|
r = asepcos_set_security_attributes(card, file);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to set security attributes");
|
sc_debug(card->ctx, "unable to set security attributes");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return asepcos_activate_file(card, file->id, 1);
|
return asepcos_activate_file(card, file->id, 1);
|
||||||
|
@ -701,7 +695,7 @@ static int asepcos_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
/* set security attributes */
|
/* set security attributes */
|
||||||
r = asepcos_set_security_attributes(card, file);
|
r = asepcos_set_security_attributes(card, file);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to set security attributes");
|
sc_debug(card->ctx, "unable to set security attributes");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return asepcos_activate_file(card, file->id, 1);
|
return asepcos_activate_file(card, file->id, 1);
|
||||||
|
@ -735,7 +729,7 @@ static int asepcos_list_files(sc_card_t *card, u8 *buf, size_t blen)
|
||||||
return r;
|
return r;
|
||||||
if (tfile->prop_attr_len != 6 || tfile->prop_attr == NULL) {
|
if (tfile->prop_attr_len != 6 || tfile->prop_attr == NULL) {
|
||||||
sc_file_free(tfile);
|
sc_file_free(tfile);
|
||||||
sc_error(card->ctx, "unable to parse proprietary FCI attributes");
|
sc_debug(card->ctx, "unable to parse proprietary FCI attributes");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
dfFID = (tfile->prop_attr[2] << 8) | tfile->prop_attr[3];
|
dfFID = (tfile->prop_attr[2] << 8) | tfile->prop_attr[3];
|
||||||
|
@ -990,9 +984,6 @@ static int asepcos_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
||||||
default:
|
default:
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/* all PIN related APDUs are sensitive */
|
|
||||||
apdu->sensitive = 1;
|
|
||||||
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,7 +1004,7 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
/* check PIN length */
|
/* check PIN length */
|
||||||
if (pdata->pin1.len < 4 || pdata->pin1.len > 16) {
|
if (pdata->pin1.len < 4 || pdata->pin1.len > 16) {
|
||||||
sc_error(card->ctx, "invalid PIN1 length");
|
sc_debug(card->ctx, "invalid PIN1 length");
|
||||||
return SC_ERROR_INVALID_PIN_LENGTH;
|
return SC_ERROR_INVALID_PIN_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,11 +1016,11 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
break;
|
break;
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
sc_error(card->ctx, "APDU transmit failed");
|
sc_debug(card->ctx, "APDU transmit failed");
|
||||||
break;
|
break;
|
||||||
case SC_PIN_CMD_CHANGE:
|
case SC_PIN_CMD_CHANGE:
|
||||||
if (pdata->pin2.len < 4 || pdata->pin2.len > 16) {
|
if (pdata->pin2.len < 4 || pdata->pin2.len > 16) {
|
||||||
sc_error(card->ctx, "invalid PIN2 length");
|
sc_debug(card->ctx, "invalid PIN2 length");
|
||||||
return SC_ERROR_INVALID_PIN_LENGTH;
|
return SC_ERROR_INVALID_PIN_LENGTH;
|
||||||
}
|
}
|
||||||
/* 1. step: verify the old pin */
|
/* 1. step: verify the old pin */
|
||||||
|
@ -1038,7 +1029,7 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
break;
|
break;
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "APDU transmit failed");
|
sc_debug(card->ctx, "APDU transmit failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
||||||
|
@ -1052,12 +1043,12 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
break;
|
break;
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
sc_error(card->ctx, "APDU transmit failed");
|
sc_debug(card->ctx, "APDU transmit failed");
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
break;
|
break;
|
||||||
case SC_PIN_CMD_UNBLOCK:
|
case SC_PIN_CMD_UNBLOCK:
|
||||||
if (pdata->pin2.len < 4 || pdata->pin2.len > 16) {
|
if (pdata->pin2.len < 4 || pdata->pin2.len > 16) {
|
||||||
sc_error(card->ctx, "invalid PIN2 length");
|
sc_debug(card->ctx, "invalid PIN2 length");
|
||||||
return SC_ERROR_INVALID_PIN_LENGTH;
|
return SC_ERROR_INVALID_PIN_LENGTH;
|
||||||
}
|
}
|
||||||
/* 1. step: verify the puk */
|
/* 1. step: verify the puk */
|
||||||
|
@ -1066,7 +1057,7 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
break;
|
break;
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "APDU transmit failed");
|
sc_debug(card->ctx, "APDU transmit failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* 2, step: unblock and change the pin */
|
/* 2, step: unblock and change the pin */
|
||||||
|
@ -1075,13 +1066,13 @@ static int asepcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *pdata,
|
||||||
break;
|
break;
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "APDU transmit failed");
|
sc_debug(card->ctx, "APDU transmit failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "error: unknow cmd type");
|
sc_debug(card->ctx, "error: unknow cmd type");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
/* Clear the buffer - it may contain pins */
|
/* Clear the buffer - it may contain pins */
|
||||||
|
@ -1102,7 +1093,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
asepcos_ops = *iso_ops;
|
asepcos_ops = *iso_ops;
|
||||||
asepcos_ops.match_card = asepcos_match_card;
|
asepcos_ops.match_card = asepcos_match_card;
|
||||||
asepcos_ops.init = asepcos_init;
|
asepcos_ops.init = asepcos_init;
|
||||||
asepcos_ops.finish = asepcos_finish;
|
|
||||||
asepcos_ops.select_file = asepcos_select_file;
|
asepcos_ops.select_file = asepcos_select_file;
|
||||||
asepcos_ops.set_security_env = asepcos_set_security_env;
|
asepcos_ops.set_security_env = asepcos_set_security_env;
|
||||||
asepcos_ops.decipher = asepcos_decipher;
|
asepcos_ops.decipher = asepcos_decipher;
|
||||||
|
|
|
@ -624,11 +624,9 @@ static int atrust_acos_set_security_env(struct sc_card *card,
|
||||||
apdu.datalen = p - sbuf;
|
apdu.datalen = p - sbuf;
|
||||||
apdu.lc = p - sbuf;
|
apdu.lc = p - sbuf;
|
||||||
apdu.le = 0;
|
apdu.le = 0;
|
||||||
/* suppress errors, as don't know whether to use
|
/* we don't know whether to use
|
||||||
* COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
|
* COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
ex_data->fix_digestInfo = 0;
|
ex_data->fix_digestInfo = 0;
|
||||||
|
@ -708,7 +706,6 @@ static int atrust_acos_compute_signature(struct sc_card *card,
|
||||||
|
|
||||||
apdu.lc = 0;
|
apdu.lc = 0;
|
||||||
apdu.datalen = 0;
|
apdu.datalen = 0;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
@ -783,7 +780,6 @@ static int atrust_acos_decipher(struct sc_card *card,
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86);
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
|
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
|
||||||
memcpy(sbuf + 1, crgram, crgram_len);
|
memcpy(sbuf + 1, crgram, crgram_len);
|
||||||
|
@ -816,7 +812,7 @@ static int atrust_acos_check_sw(struct sc_card *card, unsigned int sw1,
|
||||||
return SC_NO_ERROR;
|
return SC_NO_ERROR;
|
||||||
if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
|
if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "Verification failed (remaining tries: %d)\n",
|
sc_debug(card->ctx, "Verification failed (remaining tries: %d)\n",
|
||||||
(sw2 & 0x0f));
|
(sw2 & 0x0f));
|
||||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||||
}
|
}
|
||||||
|
@ -889,9 +885,7 @@ static int atrust_acos_logout(struct sc_card *card)
|
||||||
apdu.datalen = 2;
|
apdu.datalen = 2;
|
||||||
apdu.resplen = 0;
|
apdu.resplen = 0;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");
|
||||||
|
|
||||||
if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
|
if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
|
||||||
|
|
|
@ -286,7 +286,7 @@ struct pcsc_slot_data {
|
||||||
SCARDHANDLE pcsc_card;
|
SCARDHANDLE pcsc_card;
|
||||||
}; /* comes from reader-pcsc.c */
|
}; /* comes from reader-pcsc.c */
|
||||||
#define GET_SLOT_DATA(r) ((struct pcsc_slot_data *) (r)->drv_data)
|
#define GET_SLOT_DATA(r) ((struct pcsc_slot_data *) (r)->drv_data)
|
||||||
#define PCSC_ERROR(ctx, desc, rv) sc_error(ctx, desc ": %lx\n", rv);
|
#define PCSC_ERROR(ctx, desc, rv) sc_debug(ctx, desc ": %lx\n", rv);
|
||||||
|
|
||||||
#endif /* BELPIC_PIN_PAD */
|
#endif /* BELPIC_PIN_PAD */
|
||||||
|
|
||||||
|
@ -1035,7 +1035,7 @@ static int belpic_init(sc_card_t *card)
|
||||||
#ifdef HAVE_GUI
|
#ifdef HAVE_GUI
|
||||||
r = scgui_init();
|
r = scgui_init();
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
sc_error(card->ctx, "scgui_init() returned error %d\n", i);
|
sc_debug(card->ctx, "scgui_init() returned error %d\n", i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BELPIC_PIN_PAD
|
#ifdef BELPIC_PIN_PAD
|
||||||
|
@ -1209,7 +1209,7 @@ static int belpic_pp_verify(sc_card_t *card, SCR_Card * scr_card,
|
||||||
if (r1 == SCGUI_CANCEL)
|
if (r1 == SCGUI_CANCEL)
|
||||||
return r;
|
return r;
|
||||||
else if (r1 != SCGUI_OK) {
|
else if (r1 != SCGUI_OK) {
|
||||||
sc_error(card->ctx, "scgui_ask_message returned %d\n", r1);
|
sc_debug(card->ctx, "scgui_ask_message returned %d\n", r1);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1272,7 +1272,7 @@ static int belpic_pp_change(sc_card_t *card, SCR_Card * scr_card,
|
||||||
if (r1 == SCGUI_CANCEL)
|
if (r1 == SCGUI_CANCEL)
|
||||||
return r;
|
return r;
|
||||||
else if (r1 != SCGUI_OK) {
|
else if (r1 != SCGUI_OK) {
|
||||||
sc_error(card->ctx, "scgui_ask_message returned %d\n", r1);
|
sc_debug(card->ctx, "scgui_ask_message returned %d\n", r1);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1417,7 +1417,7 @@ static int belpic_askpin_verify(sc_card_t *card, int pin_usage)
|
||||||
if (r1 == SCGUI_CANCEL)
|
if (r1 == SCGUI_CANCEL)
|
||||||
return r;
|
return r;
|
||||||
else if (r1 != SCGUI_OK) {
|
else if (r1 != SCGUI_OK) {
|
||||||
sc_error(card->ctx, "scgui_ask_message returned %d\n", r1);
|
sc_debug(card->ctx, "scgui_ask_message returned %d\n", r1);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,7 +1470,7 @@ static int belpic_set_security_env(sc_card_t *card,
|
||||||
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
|
else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
|
||||||
sbuf[2] = 0x04;
|
sbuf[2] = 0x04;
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "Set Sec Env: unsupported algo 0X%0X\n",
|
sc_debug(card->ctx, "Set Sec Env: unsupported algo 0X%0X\n",
|
||||||
env->algorithm_flags);
|
env->algorithm_flags);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -1506,7 +1506,7 @@ static int belpic_set_security_env(sc_card_t *card,
|
||||||
#ifdef HAVE_GUI
|
#ifdef HAVE_GUI
|
||||||
r = belpic_askpin_verify(card, SCR_USAGE_SIGN);
|
r = belpic_askpin_verify(card, SCR_USAGE_SIGN);
|
||||||
if (r != 0 && r != SC_ERROR_KEYPAD_CANCELLED)
|
if (r != 0 && r != SC_ERROR_KEYPAD_CANCELLED)
|
||||||
sc_error(card->ctx, "Verify PIN in SET command returned %d\n", r);
|
sc_debug(card->ctx, "Verify PIN in SET command returned %d\n", r);
|
||||||
else
|
else
|
||||||
sc_debug(card->ctx, "Verify PIN in SET command returned %d\n", r);
|
sc_debug(card->ctx, "Verify PIN in SET command returned %d\n", r);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -42,7 +42,7 @@ static struct sc_atr_table cardos_atrs[] = {
|
||||||
/* 4.0 */
|
/* 4.0 */
|
||||||
{ "3b:e2:00:ff:c1:10:31:fe:55:c8:02:9c", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
{ "3b:e2:00:ff:c1:10:31:fe:55:c8:02:9c", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
||||||
/* Italian eID card, postecert */
|
/* Italian eID card, postecert */
|
||||||
{ "3b:e9:00:ff:c1:10:31:fe:55:00:64:05:00:c8:02:31:80:00:47", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
{ "3b:e9:00:ff:c1:10:31:fe:55:00:64:05:00:c8:02:31:80:00:47", NULL, NULL, SC_CARD_TYPE_CARDOS_CIE_V1, 0, NULL },
|
||||||
/* Italian eID card, infocamere */
|
/* Italian eID card, infocamere */
|
||||||
{ "3b:fb:98:00:ff:c1:10:31:fe:55:00:64:05:20:47:03:31:80:00:90:00:f3", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
{ "3b:fb:98:00:ff:c1:10:31:fe:55:00:64:05:20:47:03:31:80:00:90:00:f3", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
||||||
/* Another Italian InfocamereCard */
|
/* Another Italian InfocamereCard */
|
||||||
|
@ -53,11 +53,6 @@ static struct sc_atr_table cardos_atrs[] = {
|
||||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cardos_finish(sc_card_t *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cardos_match_card(sc_card_t *card)
|
static int cardos_match_card(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -65,6 +60,9 @@ static int cardos_match_card(sc_card_t *card)
|
||||||
i = _sc_match_atr(card, cardos_atrs, &card->type);
|
i = _sc_match_atr(card, cardos_atrs, &card->type);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
/* Do not change card type for CIE! */
|
||||||
|
if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
|
||||||
|
return 1;
|
||||||
if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
|
if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
|
||||||
int rv;
|
int rv;
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
|
@ -255,13 +253,13 @@ static int cardos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
|
||||||
for (i = 0; i < err_count; i++) {
|
for (i = 0; i < err_count; i++) {
|
||||||
if (cardos_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
if (cardos_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
||||||
if ( cardos_errors[i].errorstr )
|
if ( cardos_errors[i].errorstr )
|
||||||
sc_error(card->ctx, "%s\n",
|
sc_debug(card->ctx, "%s\n",
|
||||||
cardos_errors[i].errorstr);
|
cardos_errors[i].errorstr);
|
||||||
return cardos_errors[i].errorno;
|
return cardos_errors[i].errorno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
sc_debug(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
||||||
return SC_ERROR_CARD_CMD_FAILED;
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +289,7 @@ get_next_part:
|
||||||
SC_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
|
SC_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
|
||||||
|
|
||||||
if (apdu.resplen > 256) {
|
if (apdu.resplen > 256) {
|
||||||
sc_error(card->ctx, "directory listing > 256 bytes, cutting");
|
sc_debug(card->ctx, "directory listing > 256 bytes, cutting");
|
||||||
r = 256;
|
r = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +299,7 @@ get_next_part:
|
||||||
/* is there a file informatin block (0x6f) ? */
|
/* is there a file informatin block (0x6f) ? */
|
||||||
p = sc_asn1_find_tag(card->ctx, p, len, 0x6f, &tlen);
|
p = sc_asn1_find_tag(card->ctx, p, len, 0x6f, &tlen);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
sc_error(card->ctx, "directory tag missing");
|
sc_debug(card->ctx, "directory tag missing");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
if (tlen == 0)
|
if (tlen == 0)
|
||||||
|
@ -309,7 +307,7 @@ get_next_part:
|
||||||
break;
|
break;
|
||||||
q = sc_asn1_find_tag(card->ctx, p, tlen, 0x86, &ilen);
|
q = sc_asn1_find_tag(card->ctx, p, tlen, 0x86, &ilen);
|
||||||
if (q == NULL || ilen != 2) {
|
if (q == NULL || ilen != 2) {
|
||||||
sc_error(card->ctx, "error parsing file id TLV object");
|
sc_debug(card->ctx, "error parsing file id TLV object");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
/* put file id in buf */
|
/* put file id in buf */
|
||||||
|
@ -451,7 +449,7 @@ static int cardos_acl_to_bytes(sc_card_t *card, const sc_file_t *file,
|
||||||
else
|
else
|
||||||
byte = acl_to_byte(sc_file_get_acl_entry(file, idx[i]));
|
byte = acl_to_byte(sc_file_get_acl_entry(file, idx[i]));
|
||||||
if (byte < 0) {
|
if (byte < 0) {
|
||||||
sc_error(card->ctx, "Invalid ACL\n");
|
sc_debug(card->ctx, "Invalid ACL\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
buf[i] = byte;
|
buf[i] = byte;
|
||||||
|
@ -581,7 +579,7 @@ static int cardos_construct_fcp(sc_card_t *card, const sc_file_t *file,
|
||||||
buf[4] |= (u8) file->record_count;
|
buf[4] |= (u8) file->record_count;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "unknown EF type: %u", file->type);
|
sc_debug(card->ctx, "unknown EF type: %u", file->type);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (file->ef_structure == SC_FILE_EF_CYCLIC ||
|
if (file->ef_structure == SC_FILE_EF_CYCLIC ||
|
||||||
|
@ -657,7 +655,7 @@ static int cardos_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
|
|
||||||
r = cardos_construct_fcp(card, file, sbuf, &len);
|
r = cardos_construct_fcp(card, file, sbuf, &len);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "unable to create FCP");
|
sc_debug(card->ctx, "unable to create FCP");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +683,8 @@ cardos_restore_security_env(sc_card_t *card, int se_num)
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 3, se_num);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0, se_num);
|
||||||
|
apdu.p1 = (card->type == SC_CARD_TYPE_CARDOS_CIE_V1 ? 0xF3 : 0x03);
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
@ -719,12 +718,18 @@ cardos_set_security_env(sc_card_t *card,
|
||||||
|
|
||||||
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
||||||
|| env->key_ref_len != 1) {
|
|| env->key_ref_len != 1) {
|
||||||
sc_error(card->ctx, "No or invalid key reference\n");
|
sc_debug(card->ctx, "No or invalid key reference\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
key_id = env->key_ref[0];
|
key_id = env->key_ref[0];
|
||||||
|
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 1, 0);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
|
||||||
|
if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1) {
|
||||||
|
cardos_restore_security_env(card, 0x30);
|
||||||
|
apdu.p1 = 0xF1;
|
||||||
|
} else {
|
||||||
|
apdu.p1 = 0x01;
|
||||||
|
}
|
||||||
switch (env->operation) {
|
switch (env->operation) {
|
||||||
case SC_SEC_OPERATION_DECIPHER:
|
case SC_SEC_OPERATION_DECIPHER:
|
||||||
apdu.p2 = 0xB8;
|
apdu.p2 = 0xB8;
|
||||||
|
@ -774,7 +779,6 @@ do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
|
||||||
apdu.data = data;
|
apdu.data = data;
|
||||||
apdu.lc = datalen;
|
apdu.lc = datalen;
|
||||||
apdu.datalen = datalen;
|
apdu.datalen = datalen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
|
@ -822,9 +826,7 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
|
||||||
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH))) {
|
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH))) {
|
||||||
if (ctx->debug >= 3)
|
if (ctx->debug >= 3)
|
||||||
sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
|
sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = do_compute_signature(card, data, datalen, out, outlen);
|
r = do_compute_signature(card, data, datalen, out, outlen);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (r >= SC_SUCCESS)
|
if (r >= SC_SUCCESS)
|
||||||
SC_FUNC_RETURN(ctx, 4, r);
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
}
|
}
|
||||||
|
@ -849,9 +851,7 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
|
||||||
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) {
|
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) {
|
||||||
if (ctx->debug >= 3)
|
if (ctx->debug >= 3)
|
||||||
sc_debug(ctx, "trying to sign raw hash value with prefix\n");
|
sc_debug(ctx, "trying to sign raw hash value with prefix\n");
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = do_compute_signature(card, buf, tmp_len, out, outlen);
|
r = do_compute_signature(card, buf, tmp_len, out, outlen);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (r >= SC_SUCCESS)
|
if (r >= SC_SUCCESS)
|
||||||
SC_FUNC_RETURN(ctx, 4, r);
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
}
|
}
|
||||||
|
@ -906,7 +906,7 @@ cardos_lifecycle_get(sc_card_t *card, int *mode)
|
||||||
*mode = SC_CARDCTRL_LIFECYCLE_OTHER;
|
*mode = SC_CARDCTRL_LIFECYCLE_OTHER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
|
sc_debug(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,7 +1173,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
cardos_ops = *iso_ops;
|
cardos_ops = *iso_ops;
|
||||||
cardos_ops.match_card = cardos_match_card;
|
cardos_ops.match_card = cardos_match_card;
|
||||||
cardos_ops.init = cardos_init;
|
cardos_ops.init = cardos_init;
|
||||||
cardos_ops.finish = cardos_finish;
|
|
||||||
cardos_ops.select_file = cardos_select_file;
|
cardos_ops.select_file = cardos_select_file;
|
||||||
cardos_ops.create_file = cardos_create_file;
|
cardos_ops.create_file = cardos_create_file;
|
||||||
cardos_ops.set_security_env = cardos_set_security_env;
|
cardos_ops.set_security_env = cardos_set_security_env;
|
||||||
|
|
|
@ -29,11 +29,6 @@ static struct sc_card_driver default_drv = {
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int default_finish(sc_card_t *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int default_match_card(sc_card_t *card)
|
static int default_match_card(sc_card_t *card)
|
||||||
{
|
{
|
||||||
return 1; /* always match */
|
return 1; /* always match */
|
||||||
|
@ -84,12 +79,12 @@ static int autodetect_class(sc_card_t *card)
|
||||||
if (card->ctx->debug >= 2)
|
if (card->ctx->debug >= 2)
|
||||||
sc_debug(card->ctx, "SELECT FILE returned %d bytes\n",
|
sc_debug(card->ctx, "SELECT FILE returned %d bytes\n",
|
||||||
apdu.resplen);
|
apdu.resplen);
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
if (rbuf[0] == 0x6F) {
|
if (rbuf[0] == 0x6F) {
|
||||||
if (card->ctx->debug >= 2)
|
if (card->ctx->debug >= 2)
|
||||||
sc_debug(card->ctx, "SELECT FILE seems to behave according to ISO 7816-4\n");
|
sc_debug(card->ctx, "SELECT FILE seems to behave according to ISO 7816-4\n");
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
if (rbuf[0] == 0x00 && rbuf[1] == 0x00) {
|
if (rbuf[0] == 0x00 && rbuf[1] == 0x00) {
|
||||||
struct sc_card_driver *drv;
|
struct sc_card_driver *drv;
|
||||||
|
@ -97,24 +92,24 @@ static int autodetect_class(sc_card_t *card)
|
||||||
sc_debug(card->ctx, "SELECT FILE seems to return Schlumberger 'flex stuff\n");
|
sc_debug(card->ctx, "SELECT FILE seems to return Schlumberger 'flex stuff\n");
|
||||||
drv = sc_get_cryptoflex_driver();
|
drv = sc_get_cryptoflex_driver();
|
||||||
card->ops->select_file = drv->ops->select_file;
|
card->ops->select_file = drv->ops->select_file;
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int default_init(sc_card_t *card)
|
static int default_init(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
card->name = "Unidentified card";
|
card->name = "Unsupported card";
|
||||||
card->drv_data = NULL;
|
card->drv_data = NULL;
|
||||||
r = autodetect_class(card);
|
r = autodetect_class(card);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(card->ctx, "unable to determine the right class byte\n");
|
sc_debug(card->ctx, "unable to determine the right class byte\n");
|
||||||
return SC_ERROR_INVALID_CARD;
|
return SC_ERROR_INVALID_CARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sc_card_driver * sc_get_driver(void)
|
static struct sc_card_driver * sc_get_driver(void)
|
||||||
|
@ -124,14 +119,11 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
default_ops = *iso_drv->ops;
|
default_ops = *iso_drv->ops;
|
||||||
default_ops.match_card = default_match_card;
|
default_ops.match_card = default_match_card;
|
||||||
default_ops.init = default_init;
|
default_ops.init = default_init;
|
||||||
default_ops.finish = default_finish;
|
|
||||||
|
|
||||||
return &default_drv;
|
return &default_drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
struct sc_card_driver * sc_get_default_driver(void)
|
struct sc_card_driver * sc_get_default_driver(void)
|
||||||
{
|
{
|
||||||
return sc_get_driver();
|
return sc_get_driver();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
static struct sc_card_operations emv_ops;
|
static struct sc_card_operations emv_ops;
|
||||||
static struct sc_card_driver emv_drv = {
|
static struct sc_card_driver emv_drv = {
|
||||||
"EMV compatible cards",
|
"EMV cards (unsupported)",
|
||||||
"emv",
|
"emv",
|
||||||
&emv_ops,
|
&emv_ops,
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
|
@ -31,7 +31,7 @@ static struct sc_card_driver emv_drv = {
|
||||||
|
|
||||||
static int emv_finish(sc_card_t *card)
|
static int emv_finish(sc_card_t *card)
|
||||||
{
|
{
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_atr(const u8 *atr, size_t atr_len, int *t0_out, int *tx1, int *tx2,
|
static int parse_atr(const u8 *atr, size_t atr_len, int *t0_out, int *tx1, int *tx2,
|
||||||
|
@ -120,7 +120,7 @@ static int emv_init(sc_card_t *card)
|
||||||
card->drv_data = NULL;
|
card->drv_data = NULL;
|
||||||
card->cla = 0x00;
|
card->cla = 0x00;
|
||||||
|
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emv_select_file(sc_card_t *card, const sc_path_t *path,
|
static int emv_select_file(sc_card_t *card, const sc_path_t *path,
|
||||||
|
@ -137,7 +137,7 @@ static int emv_select_file(sc_card_t *card, const sc_path_t *path,
|
||||||
(*file)->type = SC_FILE_TYPE_DF;
|
(*file)->type = SC_FILE_TYPE_DF;
|
||||||
if (file != NULL && (*file)->namelen)
|
if (file != NULL && (*file)->namelen)
|
||||||
(*file)->type = SC_FILE_TYPE_DF;
|
(*file)->type = SC_FILE_TYPE_DF;
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sc_card_driver * sc_get_driver(void)
|
static struct sc_card_driver * sc_get_driver(void)
|
||||||
|
@ -147,15 +147,13 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
emv_ops = *iso_drv->ops;
|
emv_ops = *iso_drv->ops;
|
||||||
emv_ops.match_card = emv_match_card;
|
emv_ops.match_card = emv_match_card;
|
||||||
emv_ops.init = emv_init;
|
emv_ops.init = emv_init;
|
||||||
emv_ops.finish = emv_finish;
|
emv_ops.finish = emv_finish;
|
||||||
emv_ops.select_file = emv_select_file;
|
emv_ops.select_file = emv_select_file;
|
||||||
|
|
||||||
return &emv_drv;
|
return &emv_drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
struct sc_card_driver * sc_get_emv_driver(void)
|
struct sc_card_driver * sc_get_emv_driver(void)
|
||||||
{
|
{
|
||||||
return sc_get_driver();
|
return sc_get_driver();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -195,18 +195,18 @@ static int entersafe_cipher_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
||||||
|
|
||||||
if(!EVP_EncryptUpdate(&ctx,buff,&apdu->lc,buff,buffsize)){
|
if(!EVP_EncryptUpdate(&ctx,buff,&apdu->lc,buff,buffsize)){
|
||||||
sc_error(card->ctx, "entersafe encryption error.");
|
sc_debug(card->ctx, "entersafe encryption error.");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EVP_CIPHER_CTX_cleanup(&ctx)){
|
if (!EVP_CIPHER_CTX_cleanup(&ctx)){
|
||||||
sc_error(card->ctx, "entersafe encryption error.");
|
sc_debug(card->ctx, "entersafe encryption error.");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(apdu->lc!=buffsize)
|
if(apdu->lc!=buffsize)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "entersafe build cipher apdu failed.");
|
sc_debug(card->ctx, "entersafe build cipher apdu failed.");
|
||||||
SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,7 +907,6 @@ static int entersafe_compute_with_prkey(sc_card_t *card,
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
apdu.le = 256;
|
apdu.le = 256;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
|
r = entersafe_transmit_apdu(card, &apdu,0,0,0,0);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
|
@ -317,7 +317,7 @@ cryptoflex_process_file_attrs(sc_card_t *card, sc_file_t *file,
|
||||||
file->type = SC_FILE_TYPE_DF;
|
file->type = SC_FILE_TYPE_DF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "invalid file type: 0x%02X\n", *p);
|
sc_debug(ctx, "invalid file type: 0x%02X\n", *p);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -386,7 +386,7 @@ cyberflex_process_file_attrs(sc_card_t *card, sc_file_t *file,
|
||||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "invalid file type: 0x%02X\n", *p);
|
sc_debug(ctx, "invalid file type: 0x%02X\n", *p);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ cyberflex_process_file_attrs(sc_card_t *card, sc_file_t *file,
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "invalid file type: 0x%02X\n", *p);
|
sc_debug(ctx, "invalid file type: 0x%02X\n", *p);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
switch (file->ef_structure) {
|
switch (file->ef_structure) {
|
||||||
|
@ -571,7 +571,7 @@ static int select_file_id(sc_card_t *card, const u8 *buf, size_t buflen,
|
||||||
if (apdu.resplen < 14)
|
if (apdu.resplen < 14)
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
if (apdu.resp[0] == 0x6F) {
|
if (apdu.resp[0] == 0x6F) {
|
||||||
sc_error(card->ctx, "unsupported: card returned FCI\n");
|
sc_debug(card->ctx, "unsupported: card returned FCI\n");
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED; /* FIXME */
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED; /* FIXME */
|
||||||
}
|
}
|
||||||
file = sc_file_new();
|
file = sc_file_new();
|
||||||
|
@ -672,7 +672,7 @@ static int cryptoflex_list_files(sc_card_t *card, u8 *buf, size_t buflen)
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (apdu.resplen != 4) {
|
if (apdu.resplen != 4) {
|
||||||
sc_error(card->ctx, "expected 4 bytes, got %d.\n", apdu.resplen);
|
sc_debug(card->ctx, "expected 4 bytes, got %d.\n", apdu.resplen);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
memcpy(buf, rbuf + 2, 2);
|
memcpy(buf, rbuf + 2, 2);
|
||||||
|
@ -707,7 +707,7 @@ static int cyberflex_list_files(sc_card_t *card, u8 *buf, size_t buflen)
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (apdu.resplen != 6) {
|
if (apdu.resplen != 6) {
|
||||||
sc_error(card->ctx, "expected 6 bytes, got %d.\n", apdu.resplen);
|
sc_debug(card->ctx, "expected 6 bytes, got %d.\n", apdu.resplen);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
memcpy(buf, rbuf + 4, 2);
|
memcpy(buf, rbuf + 4, 2);
|
||||||
|
@ -725,7 +725,7 @@ static int flex_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
|
||||||
|
@ -810,7 +810,7 @@ cryptoflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
|
||||||
p[6] = 0x06;
|
p[6] = 0x06;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid EF structure\n");
|
sc_debug(card->ctx, "Invalid EF structure\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p[7] = 0xFF; /* allow Decrease and Increase */
|
p[7] = 0xFF; /* allow Decrease and Increase */
|
||||||
|
@ -906,7 +906,7 @@ cyberflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
|
||||||
p[4] = 0x1D;
|
p[4] = 0x1D;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid EF structure\n");
|
sc_debug(card->ctx, "Invalid EF structure\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p[5] = 0x01; /* status?? */
|
p[5] = 0x01; /* status?? */
|
||||||
|
@ -945,7 +945,7 @@ static int flex_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
* abstracting the Cryptoflex/Cyberflex differences */
|
* abstracting the Cryptoflex/Cyberflex differences */
|
||||||
r = card->ops->construct_fci(card, file, sbuf, &sendlen);
|
r = card->ops->construct_fci(card, file, sbuf, &sendlen);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(card->ctx, "File structure encoding failed.\n");
|
sc_debug(card->ctx, "File structure encoding failed.\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (file->type != SC_FILE_TYPE_DF && file->ef_structure != SC_FILE_EF_TRANSPARENT)
|
if (file->type != SC_FILE_TYPE_DF && file->ef_structure != SC_FILE_EF_TRANSPARENT)
|
||||||
|
@ -982,33 +982,33 @@ static int flex_set_security_env(sc_card_t *card,
|
||||||
|
|
||||||
if (env->operation != SC_SEC_OPERATION_SIGN &&
|
if (env->operation != SC_SEC_OPERATION_SIGN &&
|
||||||
env->operation != SC_SEC_OPERATION_DECIPHER) {
|
env->operation != SC_SEC_OPERATION_DECIPHER) {
|
||||||
sc_error(card->ctx, "Invalid crypto operation supplied.\n");
|
sc_debug(card->ctx, "Invalid crypto operation supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (env->algorithm != SC_ALGORITHM_RSA) {
|
if (env->algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Invalid crypto algorithm supplied.\n");
|
sc_debug(card->ctx, "Invalid crypto algorithm supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
|
if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
|
||||||
(env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
|
(env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
|
||||||
sc_error(card->ctx, "Card supports only raw RSA.\n");
|
sc_debug(card->ctx, "Card supports only raw RSA.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
||||||
if (env->key_ref_len != 1 ||
|
if (env->key_ref_len != 1 ||
|
||||||
(env->key_ref[0] != 0 && env->key_ref[0] != 1)) {
|
(env->key_ref[0] != 0 && env->key_ref[0] != 1)) {
|
||||||
sc_error(card->ctx, "Invalid key reference supplied.\n");
|
sc_debug(card->ctx, "Invalid key reference supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
prv->rsa_key_ref = env->key_ref[0];
|
prv->rsa_key_ref = env->key_ref[0];
|
||||||
}
|
}
|
||||||
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
|
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
|
||||||
sc_error(card->ctx, "Algorithm reference not supported.\n");
|
sc_debug(card->ctx, "Algorithm reference not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
|
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
|
||||||
if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
|
if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
|
||||||
sc_error(card->ctx, "File reference is not 0012.\n");
|
sc_debug(card->ctx, "File reference is not 0012.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1030,11 +1030,11 @@ cryptoflex_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
size_t i, i2;
|
size_t i, i2;
|
||||||
|
|
||||||
if (data_len != 64 && data_len != 96 && data_len != 128 && data_len != 256) {
|
if (data_len != 64 && data_len != 96 && data_len != 128 && data_len != 256) {
|
||||||
sc_error(card->ctx, "Illegal input length: %d\n", data_len);
|
sc_debug(card->ctx, "Illegal input length: %d\n", data_len);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (outlen < data_len) {
|
if (outlen < data_len) {
|
||||||
sc_error(card->ctx, "Output buffer too small.\n");
|
sc_debug(card->ctx, "Output buffer too small.\n");
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x00, prv->rsa_key_ref);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x00, prv->rsa_key_ref);
|
||||||
|
@ -1066,7 +1066,6 @@ cryptoflex_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
apdu.resplen = outlen > sizeof(sbuf) ? sizeof(sbuf) : outlen;
|
apdu.resplen = outlen > sizeof(sbuf) ? sizeof(sbuf) : outlen;
|
||||||
apdu.le = apdu.resplen > 256 ? 256 : apdu.resplen;
|
apdu.le = apdu.resplen > 256 ? 256 : apdu.resplen;
|
||||||
apdu.resp = sbuf;
|
apdu.resp = sbuf;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
@ -1090,13 +1089,13 @@ cyberflex_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
case 96: alg_id = 0xC6; break;
|
case 96: alg_id = 0xC6; break;
|
||||||
case 128: alg_id = 0xC8; break;
|
case 128: alg_id = 0xC8; break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Illegal input length: %d\n", data_len);
|
sc_debug(card->ctx, "Illegal input length: %d\n", data_len);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
key_id = prv->rsa_key_ref + 1; /* Why? */
|
key_id = prv->rsa_key_ref + 1; /* Why? */
|
||||||
|
|
||||||
if (outlen < data_len) {
|
if (outlen < data_len) {
|
||||||
sc_error(card->ctx, "Output buffer too small.\n");
|
sc_debug(card->ctx, "Output buffer too small.\n");
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x88, alg_id, key_id);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x88, alg_id, key_id);
|
||||||
|
@ -1106,7 +1105,6 @@ cyberflex_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
apdu.data = data;
|
apdu.data = data;
|
||||||
apdu.resplen = outlen;
|
apdu.resplen = outlen;
|
||||||
apdu.resp = out;
|
apdu.resp = out;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
@ -1163,7 +1161,7 @@ static int flex_generate_key(sc_card_t *card, struct sc_cardctl_cryptoflex_genke
|
||||||
case 1024: p2 = 0x80; break;
|
case 1024: p2 = 0x80; break;
|
||||||
case 2048: p2 = 0x00; break;
|
case 2048: p2 = 0x00; break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Illegal key length: %d\n", data->key_bits);
|
sc_debug(card->ctx, "Illegal key length: %d\n", data->key_bits);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,7 +1277,6 @@ static int flex_build_verify_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
||||||
apdu->data = sbuf;
|
apdu->data = sbuf;
|
||||||
apdu->datalen = len;
|
apdu->datalen = len;
|
||||||
apdu->lc = len;
|
apdu->lc = len;
|
||||||
apdu->sensitive = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Initially written by David Mattes (david.mattes@boeing.com) */
|
/* Initially written by David Mattes (david.mattes@boeing.com) */
|
||||||
|
/* Portuguese eID card support by Joao Poupino (joao.poupino@ist.utl.pt) */
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "cardctl.h"
|
#include "cardctl.h"
|
||||||
|
@ -32,20 +33,27 @@ static struct sc_card_driver gemsafe_drv = {
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *gemexpresso_atrs[] = {
|
/* Known ATRs */
|
||||||
/* standard version */
|
static struct sc_atr_table gemsafe_atrs[] = {
|
||||||
"3B:7B:94:00:00:80:65:B0:83:01:01:74:83:00:90:00",
|
/* standard version */
|
||||||
"3B:6B:00:00:80:65:B0:83:01:01:74:83:00:90:00",
|
{"3B:7B:94:00:00:80:65:B0:83:01:01:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
|
||||||
/* fips 140 version */
|
{"3B:6B:00:00:80:65:B0:83:01:01:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
|
||||||
"3B:6B:00:00:80:65:B0:83:01:03:74:83:00:90:00",
|
/* fips 140 version */
|
||||||
/* TODO: add more ATRs */
|
{"3B:6B:00:00:80:65:B0:83:01:03:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
|
||||||
"3B:7A:94:00:00:80:65:A2:01:01:01:3D:72:D6:43",
|
/* Undefined */
|
||||||
"3B:7D:94:00:00:80:31:80:65:B0:83:01:01:90:83:00:90:00",
|
{"3B:7A:94:00:00:80:65:A2:01:01:01:3D:72:D6:43", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
|
||||||
NULL
|
{"3B:7D:94:00:00:80:31:80:65:B0:83:01:01:90:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
|
||||||
|
/* Portuguese eID cards */
|
||||||
|
{"3B:7D:95:00:00:80:31:80:65:B0:83:11:C0:A9:83:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
|
||||||
|
{"3B:7D:95:00:00:80:31:80:65:B0:83:11:C0:A9:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
|
||||||
|
{NULL, NULL, NULL, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x18, 0x0A,
|
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x18, 0x0A,
|
||||||
0x00, 0x00, 0x01, 0x63, 0x42, 0x00};
|
0x00, 0x00, 0x01, 0x63, 0x42, 0x00};
|
||||||
|
|
||||||
|
static const u8 gemsafe_pteid_aid[] = {0x60, 0x46, 0x32, 0xFF, 0x00, 0x00, 0x02};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x63, 0x50,
|
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x63, 0x50,
|
||||||
0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35};
|
0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35};
|
||||||
|
@ -113,27 +121,12 @@ static int gp_select_applet(sc_card_t *card, const u8 *aid, size_t aid_len)
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gemsafe_match_card(struct sc_card *card)
|
static int gemsafe_match_card(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int i, match = -1;
|
int i;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
i = _sc_match_atr(card, gemsafe_atrs, &card->type);
|
||||||
|
if (i < 0)
|
||||||
for (i = 0; gemexpresso_atrs[i] != NULL; i++) {
|
|
||||||
u8 defatr[SC_MAX_ATR_SIZE];
|
|
||||||
size_t len = sizeof(defatr);
|
|
||||||
const char *atrp = gemexpresso_atrs[i];
|
|
||||||
|
|
||||||
if (sc_hex_to_bin(atrp, defatr, &len))
|
|
||||||
continue;
|
|
||||||
if (len != card->atr_len)
|
|
||||||
continue;
|
|
||||||
if (memcmp(card->atr, defatr, len) != 0)
|
|
||||||
continue;
|
|
||||||
match = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (match == -1)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -153,12 +146,17 @@ static int gemsafe_init(struct sc_card *card)
|
||||||
if (!exdata)
|
if (!exdata)
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
exdata->aid_len = sizeof(exdata->aid);
|
exdata->aid_len = sizeof(exdata->aid);
|
||||||
/* try to get a AID from the config file */
|
if(card->type == SC_CARD_TYPE_GEMSAFEV1_GENERIC) {
|
||||||
r = get_conf_aid(card, exdata->aid, &exdata->aid_len);
|
/* try to get a AID from the config file */
|
||||||
if (r < 0) {
|
r = get_conf_aid(card, exdata->aid, &exdata->aid_len);
|
||||||
/* failed, use default value */
|
if (r < 0) {
|
||||||
memcpy(exdata->aid, gemsafe_def_aid, sizeof(gemsafe_def_aid));
|
/* failed, use default value */
|
||||||
exdata->aid_len = sizeof(gemsafe_def_aid);
|
memcpy(exdata->aid, gemsafe_def_aid, sizeof(gemsafe_def_aid));
|
||||||
|
exdata->aid_len = sizeof(gemsafe_def_aid);
|
||||||
|
}
|
||||||
|
} else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
|
||||||
|
memcpy(exdata->aid, gemsafe_pteid_aid, sizeof(gemsafe_pteid_aid));
|
||||||
|
exdata->aid_len = sizeof(gemsafe_pteid_aid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* increase lock_count here to prevent sc_unlock to select
|
/* increase lock_count here to prevent sc_unlock to select
|
||||||
|
@ -343,18 +341,18 @@ static int gemsafe_process_fci(struct sc_card *card, struct sc_file *file,
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 gemsafe_flags2algref(const struct sc_security_env *env)
|
static u8 gemsafe_flags2algref(struct sc_card *card, const struct sc_security_env *env)
|
||||||
{
|
{
|
||||||
u8 ret = 0;
|
u8 ret = 0;
|
||||||
|
|
||||||
if (env->operation == SC_SEC_OPERATION_SIGN) {
|
if (env->operation == SC_SEC_OPERATION_SIGN) {
|
||||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||||
ret = 0x12;
|
ret = card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ? 0x02 : 0x12;
|
||||||
else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)
|
else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)
|
||||||
ret = 0x11;
|
ret = 0x11;
|
||||||
} else if (env->operation == SC_SEC_OPERATION_DECIPHER) {
|
} else if (env->operation == SC_SEC_OPERATION_DECIPHER) {
|
||||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||||
ret = 0x12;
|
ret = card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ? 0x02 : 0x12;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -388,7 +386,7 @@ static int gemsafe_set_security_env(struct sc_card *card,
|
||||||
|
|
||||||
if (!(se_env.flags & SC_SEC_ENV_ALG_REF_PRESENT)) {
|
if (!(se_env.flags & SC_SEC_ENV_ALG_REF_PRESENT)) {
|
||||||
/* set the algorithm reference */
|
/* set the algorithm reference */
|
||||||
alg_ref = gemsafe_flags2algref(&se_env);
|
alg_ref = gemsafe_flags2algref(card, &se_env);
|
||||||
if (alg_ref) {
|
if (alg_ref) {
|
||||||
se_env.algorithm_ref = alg_ref;
|
se_env.algorithm_ref = alg_ref;
|
||||||
se_env.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
se_env.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||||
|
@ -417,11 +415,16 @@ static int gemsafe_compute_signature(struct sc_card *card, const u8 * data,
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0xAC);
|
/* the Portuguese eID card requires a two-phase exchange */
|
||||||
apdu.cla |= 0x80;
|
if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
|
||||||
apdu.resp = rbuf;
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x90, 0xA0);
|
||||||
apdu.resplen = sizeof(rbuf);
|
} else {
|
||||||
apdu.le = 256;
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0xAC);
|
||||||
|
apdu.cla |= 0x80;
|
||||||
|
apdu.resp = rbuf;
|
||||||
|
apdu.resplen = sizeof(rbuf);
|
||||||
|
apdu.le = 256;
|
||||||
|
}
|
||||||
/* we sign a digestInfo object => tag 0x90 */
|
/* we sign a digestInfo object => tag 0x90 */
|
||||||
sbuf[0] = 0x90;
|
sbuf[0] = 0x90;
|
||||||
sbuf[1] = (u8)data_len;
|
sbuf[1] = (u8)data_len;
|
||||||
|
@ -429,11 +432,21 @@ static int gemsafe_compute_signature(struct sc_card *card, const u8 * data,
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.lc = data_len + 2;
|
apdu.lc = data_len + 2;
|
||||||
apdu.datalen = data_len + 2;
|
apdu.datalen = data_len + 2;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
|
||||||
|
/* finalize the exchange */
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, 0x9E, 0x9A);
|
||||||
|
apdu.le = 128; /* 1024 bit keys */
|
||||||
|
apdu.resp = rbuf;
|
||||||
|
apdu.resplen = sizeof(rbuf);
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
if(apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
|
}
|
||||||
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
|
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
|
||||||
|
|
||||||
memcpy(out, apdu.resp, len);
|
memcpy(out, apdu.resp, len);
|
||||||
|
@ -459,7 +472,6 @@ static int gemsafe_decipher(struct sc_card *card, const u8 * crgram,
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
apdu.le = crgram_len;
|
apdu.le = crgram_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
apdu.data = crgram;
|
apdu.data = crgram;
|
||||||
apdu.lc = crgram_len;
|
apdu.lc = crgram_len;
|
||||||
|
@ -475,6 +487,25 @@ static int gemsafe_decipher(struct sc_card *card, const u8 * crgram,
|
||||||
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gemsafe_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
||||||
|
{
|
||||||
|
int prev_cla, r;
|
||||||
|
|
||||||
|
prev_cla = card->cla;
|
||||||
|
if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
|
||||||
|
/* Warning: this depends on iso7816_get_challenge not
|
||||||
|
* changing the value of the card's CLA
|
||||||
|
*/
|
||||||
|
card->cla = 0x80;
|
||||||
|
}
|
||||||
|
r = iso_ops->get_challenge(card, rnd, len);
|
||||||
|
/* Restore the CLA value if needed */
|
||||||
|
if(card->cla != prev_cla)
|
||||||
|
card->cla = prev_cla;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int gemsafe_build_pin_apdu(struct sc_card *card,
|
static int gemsafe_build_pin_apdu(struct sc_card *card,
|
||||||
struct sc_apdu *apdu,
|
struct sc_apdu *apdu,
|
||||||
struct sc_pin_cmd_data *data)
|
struct sc_pin_cmd_data *data)
|
||||||
|
@ -549,7 +580,6 @@ static int gemsafe_build_pin_apdu(struct sc_card *card,
|
||||||
apdu->datalen = len;
|
apdu->datalen = len;
|
||||||
apdu->data = sbuf;
|
apdu->data = sbuf;
|
||||||
apdu->resplen = 0;
|
apdu->resplen = 0;
|
||||||
apdu->sensitive = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -586,7 +616,7 @@ static int gemsafe_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
||||||
/* Call the reader driver to collect
|
/* Call the reader driver to collect
|
||||||
* the PIN and pass on the APDU to the card */
|
* the PIN and pass on the APDU to the card */
|
||||||
if (data->pin1.offset == 0) {
|
if (data->pin1.offset == 0) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Card driver didn't set PIN offset");
|
"Card driver didn't set PIN offset");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -598,7 +628,7 @@ static int gemsafe_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
||||||
data);
|
data);
|
||||||
/* sw1/sw2 filled in by reader driver */
|
/* sw1/sw2 filled in by reader driver */
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Card reader driver does not support "
|
"Card reader driver does not support "
|
||||||
"PIN entry through reader key pad");
|
"PIN entry through reader key pad");
|
||||||
r = SC_ERROR_NOT_SUPPORTED;
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
|
@ -625,7 +655,7 @@ static struct sc_card_driver *sc_get_driver(void)
|
||||||
iso_ops = iso_drv->ops;
|
iso_ops = iso_drv->ops;
|
||||||
/* use the standard iso operations as default */
|
/* use the standard iso operations as default */
|
||||||
gemsafe_ops = *iso_drv->ops;
|
gemsafe_ops = *iso_drv->ops;
|
||||||
/* gemsafe specfic functions */
|
/* gemsafe specific functions */
|
||||||
gemsafe_ops.match_card = gemsafe_match_card;
|
gemsafe_ops.match_card = gemsafe_match_card;
|
||||||
gemsafe_ops.init = gemsafe_init;
|
gemsafe_ops.init = gemsafe_init;
|
||||||
gemsafe_ops.finish = gemsafe_finish;
|
gemsafe_ops.finish = gemsafe_finish;
|
||||||
|
@ -634,6 +664,7 @@ static struct sc_card_driver *sc_get_driver(void)
|
||||||
gemsafe_ops.set_security_env = gemsafe_set_security_env;
|
gemsafe_ops.set_security_env = gemsafe_set_security_env;
|
||||||
gemsafe_ops.decipher = gemsafe_decipher;
|
gemsafe_ops.decipher = gemsafe_decipher;
|
||||||
gemsafe_ops.compute_signature = gemsafe_compute_signature;
|
gemsafe_ops.compute_signature = gemsafe_compute_signature;
|
||||||
|
gemsafe_ops.get_challenge = gemsafe_get_challenge;
|
||||||
gemsafe_ops.process_fci = gemsafe_process_fci;
|
gemsafe_ops.process_fci = gemsafe_process_fci;
|
||||||
gemsafe_ops.pin_cmd = gemsafe_pin_cmd;
|
gemsafe_ops.pin_cmd = gemsafe_pin_cmd;
|
||||||
|
|
||||||
|
|
|
@ -232,23 +232,23 @@ gpk_check_sw(sc_card_t *card, u8 sw1, u8 sw2)
|
||||||
unsigned short int sw = (sw1 << 8) | sw2;
|
unsigned short int sw = (sw1 << 8) | sw2;
|
||||||
|
|
||||||
if ((sw & 0xFFF0) == 0x63C0) {
|
if ((sw & 0xFFF0) == 0x63C0) {
|
||||||
sc_error(card->ctx, "wrong PIN, %u tries left\n", sw&0xf);
|
sc_debug(card->ctx, "wrong PIN, %u tries left\n", sw&0xf);
|
||||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (sw) {
|
switch (sw) {
|
||||||
case 0x6400:
|
case 0x6400:
|
||||||
sc_error(card->ctx, "wrong crypto context\n");
|
sc_debug(card->ctx, "wrong crypto context\n");
|
||||||
return SC_ERROR_OBJECT_NOT_VALID; /* XXX ??? */
|
return SC_ERROR_OBJECT_NOT_VALID; /* XXX ??? */
|
||||||
|
|
||||||
/* The following are handled by iso7816_check_sw
|
/* The following are handled by iso7816_check_sw
|
||||||
* but all return SC_ERROR_UNKNOWN_DATA_RECEIVED
|
* but all return SC_ERROR_UNKNOWN_DATA_RECEIVED
|
||||||
* XXX: fix in the iso driver? */
|
* XXX: fix in the iso driver? */
|
||||||
case 0x6983:
|
case 0x6983:
|
||||||
sc_error(card->ctx, "PIN is blocked\n");
|
sc_debug(card->ctx, "PIN is blocked\n");
|
||||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||||
case 0x6581:
|
case 0x6581:
|
||||||
sc_error(card->ctx, "out of space on card or file\n");
|
sc_debug(card->ctx, "out of space on card or file\n");
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
case 0x6981:
|
case 0x6981:
|
||||||
return SC_ERROR_FILE_NOT_FOUND;
|
return SC_ERROR_FILE_NOT_FOUND;
|
||||||
|
@ -577,9 +577,7 @@ gpk_select_id(sc_card_t *card, int kind, unsigned int fid,
|
||||||
fbuf[0] = fid >> 8;
|
fbuf[0] = fid >> 8;
|
||||||
fbuf[1] = fid & 0xff;
|
fbuf[1] = fid & 0xff;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = gpk_select(card, kind, fbuf, 2, file);
|
r = gpk_select(card, kind, fbuf, 2, file);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
/* Fix up the path cache.
|
/* Fix up the path cache.
|
||||||
* NB we never cache the ID of an EF, just the DF path */
|
* NB we never cache the ID of an EF, just the DF path */
|
||||||
|
@ -724,7 +722,7 @@ gpk_read_binary(sc_card_t *card, unsigned int offset,
|
||||||
struct gpk_private_data *priv = DRVDATA(card);
|
struct gpk_private_data *priv = DRVDATA(card);
|
||||||
|
|
||||||
if (offset & priv->offset_mask) {
|
if (offset & priv->offset_mask) {
|
||||||
sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
|
sc_debug(card->ctx, "Invalid file offset (not a multiple of %d)",
|
||||||
priv->offset_mask + 1);
|
priv->offset_mask + 1);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -739,7 +737,7 @@ gpk_write_binary(sc_card_t *card, unsigned int offset,
|
||||||
struct gpk_private_data *priv = DRVDATA(card);
|
struct gpk_private_data *priv = DRVDATA(card);
|
||||||
|
|
||||||
if (offset & priv->offset_mask) {
|
if (offset & priv->offset_mask) {
|
||||||
sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
|
sc_debug(card->ctx, "Invalid file offset (not a multiple of %d)",
|
||||||
priv->offset_mask + 1);
|
priv->offset_mask + 1);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -754,7 +752,7 @@ gpk_update_binary(sc_card_t *card, unsigned int offset,
|
||||||
struct gpk_private_data *priv = DRVDATA(card);
|
struct gpk_private_data *priv = DRVDATA(card);
|
||||||
|
|
||||||
if (offset & priv->offset_mask) {
|
if (offset & priv->offset_mask) {
|
||||||
sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
|
sc_debug(card->ctx, "Invalid file offset (not a multiple of %d)",
|
||||||
priv->offset_mask + 1);
|
priv->offset_mask + 1);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -996,7 +994,6 @@ gpk_select_key(sc_card_t *card, int key_sfi, const u8 *buf, size_t buflen)
|
||||||
apdu.resp = resp;
|
apdu.resp = resp;
|
||||||
apdu.resplen = sizeof(resp);
|
apdu.resplen = sizeof(resp);
|
||||||
apdu.le = 12;
|
apdu.le = 12;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
@ -1046,7 +1043,7 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
||||||
algorithm = env->algorithm;
|
algorithm = env->algorithm;
|
||||||
if (algorithm != SC_ALGORITHM_RSA) {
|
if (algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Algorithm not supported.\n");
|
sc_debug(card->ctx, "Algorithm not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
priv->sec_algorithm = algorithm;
|
priv->sec_algorithm = algorithm;
|
||||||
|
@ -1054,7 +1051,7 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
/* If there's a key reference, it must be 0 */
|
/* If there's a key reference, it must be 0 */
|
||||||
if ((env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
if ((env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
||||||
&& (env->key_ref_len != 1 || env->key_ref[0] != 0)) {
|
&& (env->key_ref_len != 1 || env->key_ref[0] != 0)) {
|
||||||
sc_error(card->ctx, "Unknown key referenced.\n");
|
sc_debug(card->ctx, "Unknown key referenced.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,7 +1064,7 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
else if (env->flags & SC_ALGORITHM_RSA_PAD_ISO9796)
|
else if (env->flags & SC_ALGORITHM_RSA_PAD_ISO9796)
|
||||||
priv->sec_padding = 2;
|
priv->sec_padding = 2;
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "Padding algorithm not supported.\n");
|
sc_debug(card->ctx, "Padding algorithm not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,7 +1087,7 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
context = GPK_SIGN_RSA_MD5;
|
context = GPK_SIGN_RSA_MD5;
|
||||||
priv->sec_hash_len = 16;
|
priv->sec_hash_len = 16;
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "Unsupported signature algorithm");
|
sc_debug(card->ctx, "Unsupported signature algorithm");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1098,20 +1095,20 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
context = GPK_UNWRAP_RSA;
|
context = GPK_UNWRAP_RSA;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Crypto operation not supported.\n");
|
sc_debug(card->ctx, "Crypto operation not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the file ID */
|
/* Get the file ID */
|
||||||
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
|
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
|
||||||
if (env->file_ref.len != 2) {
|
if (env->file_ref.len != 2) {
|
||||||
sc_error(card->ctx, "File reference: invalid length.\n");
|
sc_debug(card->ctx, "File reference: invalid length.\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
file_id = (env->file_ref.value[0] << 8)
|
file_id = (env->file_ref.value[0] << 8)
|
||||||
| env->file_ref.value[1];
|
| env->file_ref.value[1];
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "File reference missing.\n");
|
sc_debug(card->ctx, "File reference missing.\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,11 +1122,11 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
SC_RECORD_BY_REC_NR);
|
SC_RECORD_BY_REC_NR);
|
||||||
SC_TEST_RET(card->ctx, r, "Failed to read PK sysrec");
|
SC_TEST_RET(card->ctx, r, "Failed to read PK sysrec");
|
||||||
if (r != 7 || sysrec[0] != 0) {
|
if (r != 7 || sysrec[0] != 0) {
|
||||||
sc_error(card->ctx, "First record of file is not the sysrec");
|
sc_debug(card->ctx, "First record of file is not the sysrec");
|
||||||
return SC_ERROR_OBJECT_NOT_VALID;
|
return SC_ERROR_OBJECT_NOT_VALID;
|
||||||
}
|
}
|
||||||
if (sysrec[5] != 0x00) {
|
if (sysrec[5] != 0x00) {
|
||||||
sc_error(card->ctx, "Public key is not an RSA key");
|
sc_debug(card->ctx, "Public key is not an RSA key");
|
||||||
return SC_ERROR_OBJECT_NOT_VALID;
|
return SC_ERROR_OBJECT_NOT_VALID;
|
||||||
}
|
}
|
||||||
switch (sysrec[1]) {
|
switch (sysrec[1]) {
|
||||||
|
@ -1137,7 +1134,7 @@ gpk_set_security_env(sc_card_t *card,
|
||||||
case 0x10: priv->sec_mod_len = 768 / 8; break;
|
case 0x10: priv->sec_mod_len = 768 / 8; break;
|
||||||
case 0x11: priv->sec_mod_len = 1024 / 8; break;
|
case 0x11: priv->sec_mod_len = 1024 / 8; break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported modulus length");
|
sc_debug(card->ctx, "Unsupported modulus length");
|
||||||
return SC_ERROR_OBJECT_NOT_VALID;
|
return SC_ERROR_OBJECT_NOT_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,7 +1266,7 @@ gpk_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (data_len > priv->sec_mod_len) {
|
if (data_len > priv->sec_mod_len) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Data length (%u) does not match key modulus %u.\n",
|
"Data length (%u) does not match key modulus %u.\n",
|
||||||
data_len, priv->sec_mod_len);
|
data_len, priv->sec_mod_len);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
|
@ -1330,7 +1327,7 @@ gpk_decipher(sc_card_t *card, const u8 *in, size_t inlen,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (inlen != priv->sec_mod_len) {
|
if (inlen != priv->sec_mod_len) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Data length (%u) does not match key modulus %u.\n",
|
"Data length (%u) does not match key modulus %u.\n",
|
||||||
inlen, priv->sec_mod_len);
|
inlen, priv->sec_mod_len);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
@ -1349,7 +1346,6 @@ gpk_decipher(sc_card_t *card, const u8 *in, size_t inlen,
|
||||||
apdu.le = 256; /* give me all you got :) */
|
apdu.le = 256; /* give me all you got :) */
|
||||||
apdu.resp = buffer;
|
apdu.resp = buffer;
|
||||||
apdu.resplen = sizeof(buffer);
|
apdu.resplen = sizeof(buffer);
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
@ -1517,7 +1513,7 @@ gpk_generate_key(sc_card_t *card, struct sc_cardctl_gpk_genkey *args)
|
||||||
if (card->ctx->debug)
|
if (card->ctx->debug)
|
||||||
sc_debug(card->ctx, "gpk_generate_key(%u)\n", args->privlen);
|
sc_debug(card->ctx, "gpk_generate_key(%u)\n", args->privlen);
|
||||||
if (args->privlen != 512 && args->privlen != 1024) {
|
if (args->privlen != 512 && args->privlen != 1024) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Key generation not supported for key length %d",
|
"Key generation not supported for key length %d",
|
||||||
args->privlen);
|
args->privlen);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
@ -1584,12 +1580,11 @@ gpk_pkfile_load(sc_card_t *card, struct sc_cardctl_gpk_pkload *args)
|
||||||
apdu.p1 = args->file->id & 0x1F;
|
apdu.p1 = args->file->id & 0x1F;
|
||||||
apdu.p2 = args->len;
|
apdu.p2 = args->len;
|
||||||
apdu.lc = args->datalen;
|
apdu.lc = args->datalen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
/* encrypt the private key material */
|
/* encrypt the private key material */
|
||||||
assert(args->datalen <= sizeof(temp));
|
assert(args->datalen <= sizeof(temp));
|
||||||
if (!priv->key_set) {
|
if (!priv->key_set) {
|
||||||
sc_error(card->ctx, "No secure messaging key set!\n");
|
sc_debug(card->ctx, "No secure messaging key set!\n");
|
||||||
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1694,7 +1689,7 @@ static int gpk_get_info(sc_card_t *card, int p1, int p2, u8 *buf,
|
||||||
apdu.resplen = buflen;
|
apdu.resplen = buflen;
|
||||||
|
|
||||||
if ((r = sc_transmit_apdu(card, &apdu)) < 0) {
|
if ((r = sc_transmit_apdu(card, &apdu)) < 0) {
|
||||||
sc_error(card->ctx, "APDU transmit failed: %s",
|
sc_debug(card->ctx, "APDU transmit failed: %s",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
return r;
|
return r;
|
||||||
|
@ -1838,7 +1833,6 @@ gpk_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, struct sc_pin_cmd_data *dat
|
||||||
apdu->lc = 8;
|
apdu->lc = 8;
|
||||||
apdu->datalen = 8;
|
apdu->datalen = 8;
|
||||||
apdu->data = sbuf;
|
apdu->data = sbuf;
|
||||||
apdu->sensitive = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,543 @@
|
||||||
|
/*
|
||||||
|
* Driver for IAS based cards, e.g. Portugal's eID card.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Joao Poupino <joao.poupino@ist.utl.pt>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Partially based on the ISO7816 driver.
|
||||||
|
*
|
||||||
|
* Thanks to Andre Cruz, Jorge Ferreira and Paulo F. Andrade
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "cardctl.h"
|
||||||
|
#include "asn1.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Portugal eID uses 1024 bit keys */
|
||||||
|
#define PTEID_RSA_KEYSIZE 128
|
||||||
|
|
||||||
|
#define DRVDATA(card) ((struct ias_priv_data *) ((card)->drv_data))
|
||||||
|
|
||||||
|
static struct sc_card_operations ias_ops;
|
||||||
|
static struct sc_card_operations *iso_ops = NULL;
|
||||||
|
|
||||||
|
static struct sc_card_driver ias_drv = {
|
||||||
|
"IAS",
|
||||||
|
"ias",
|
||||||
|
&ias_ops,
|
||||||
|
NULL, 0, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Known ATRs */
|
||||||
|
static struct sc_atr_table ias_atrs[] = {
|
||||||
|
/* Portugal eID cards */
|
||||||
|
{"3B:65:00:00:D0:00:54:01:31", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
|
||||||
|
{"3B:65:00:00:D0:00:54:01:32", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
|
||||||
|
{"3B:95:95:40:FF:D0:00:54:01:31", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
|
||||||
|
{"3B:95:95:40:FF:D0:00:54:01:32", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
|
||||||
|
{NULL, NULL, NULL, 0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Known AIDs */
|
||||||
|
static const u8 ias_aid_pteid[] = {0x60, 0x46, 0x32, 0xFF, 0x00, 0x01, 0x02};
|
||||||
|
|
||||||
|
static int ias_select_applet(sc_card_t *card, const u8 *aid, size_t aid_len)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
sc_path_t tpath;
|
||||||
|
|
||||||
|
tpath.type = SC_PATH_TYPE_DF_NAME;
|
||||||
|
tpath.len = aid_len;
|
||||||
|
memcpy(tpath.value, aid, aid_len);
|
||||||
|
r = iso_ops->select_file(card, &tpath, NULL);
|
||||||
|
if (r != SC_SUCCESS) {
|
||||||
|
sc_debug(card->ctx, "unable to select applet");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_init(sc_card_t *card)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
assert(card != NULL);
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
card->name = "IAS";
|
||||||
|
card->cla = 0x00;
|
||||||
|
|
||||||
|
/* Card version detection */
|
||||||
|
if (card->type == SC_CARD_TYPE_IAS_PTEID) {
|
||||||
|
int r = ias_select_applet(card, ias_aid_pteid, sizeof(ias_aid_pteid));
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
return r;
|
||||||
|
/* Add other cards if necessary */
|
||||||
|
} else {
|
||||||
|
return SC_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set card capabilities */
|
||||||
|
card->caps |= SC_CARD_CAP_RNG;
|
||||||
|
|
||||||
|
/* Set the supported algorithms */
|
||||||
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
|
||||||
|
SC_ALGORITHM_RSA_HASH_NONE;
|
||||||
|
|
||||||
|
/* Only 1024 bit key sizes were tested */
|
||||||
|
_sc_card_add_rsa_alg(card, 1024, flags, 0);
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_match_card(sc_card_t *card)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = _sc_match_atr(card, ias_atrs, &card->type);
|
||||||
|
if (i < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_build_pin_apdu(sc_card_t *card,
|
||||||
|
sc_apdu_t *apdu,
|
||||||
|
struct sc_pin_cmd_data *data)
|
||||||
|
{
|
||||||
|
static u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
int r, len, pad, use_pin_pad, ins, p1;
|
||||||
|
|
||||||
|
r = len = pad = use_pin_pad = ins = p1 = 0;
|
||||||
|
assert(card != NULL);
|
||||||
|
|
||||||
|
switch (data->pin_type) {
|
||||||
|
case SC_AC_CHV:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->flags & SC_PIN_CMD_USE_PINPAD)
|
||||||
|
use_pin_pad = 1;
|
||||||
|
/* "needs-padding" necessary for the PTEID card,
|
||||||
|
* but not defined in the pin structure
|
||||||
|
*/
|
||||||
|
if ((data->flags & SC_PIN_CMD_NEED_PADDING) ||
|
||||||
|
card->type == SC_CARD_TYPE_IAS_PTEID)
|
||||||
|
pad = 1;
|
||||||
|
|
||||||
|
data->pin1.offset = 5;
|
||||||
|
|
||||||
|
switch (data->cmd) {
|
||||||
|
case SC_PIN_CMD_VERIFY:
|
||||||
|
ins = 0x20;
|
||||||
|
if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||||
|
return r;
|
||||||
|
len = r;
|
||||||
|
break;
|
||||||
|
case SC_PIN_CMD_CHANGE:
|
||||||
|
ins = 0x24;
|
||||||
|
if ((data->flags & SC_PIN_CMD_IMPLICIT_CHANGE) == 0 &&
|
||||||
|
(data->pin1.len != 0 || use_pin_pad)) {
|
||||||
|
if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||||
|
return r;
|
||||||
|
len += r;
|
||||||
|
} else {
|
||||||
|
/* implicit test */
|
||||||
|
p1 = 1;
|
||||||
|
}
|
||||||
|
data->pin2.offset = data->pin1.offset + len;
|
||||||
|
if ( (r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
|
||||||
|
return r;
|
||||||
|
len += r;
|
||||||
|
break;
|
||||||
|
case SC_PIN_CMD_UNBLOCK:
|
||||||
|
ins = 0x2C;
|
||||||
|
if (data->pin1.len != 0 || use_pin_pad) {
|
||||||
|
if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
|
||||||
|
return r;
|
||||||
|
len += r;
|
||||||
|
} else {
|
||||||
|
p1 |= 0x02;
|
||||||
|
}
|
||||||
|
if (data->pin2.len != 0 || use_pin_pad) {
|
||||||
|
data->pin2.offset = data->pin1.offset + len;
|
||||||
|
if ( (r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
|
||||||
|
return r;
|
||||||
|
len += r;
|
||||||
|
} else {
|
||||||
|
p1 |= 0x01;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, p1, data->pin_reference);
|
||||||
|
apdu->lc = len;
|
||||||
|
apdu->datalen = len;
|
||||||
|
apdu->data = sbuf;
|
||||||
|
apdu->resplen = 0;
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
|
int *tries_left)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
sc_apdu_t local_apdu;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
|
/* Check if a PIN change operation is being requested,
|
||||||
|
* as it requires sending two separate APDUs
|
||||||
|
*/
|
||||||
|
if (data->cmd == SC_PIN_CMD_CHANGE) {
|
||||||
|
/* Build a SC_PIN_CMD_VERIFY APDU */
|
||||||
|
data->cmd = SC_PIN_CMD_VERIFY;
|
||||||
|
r = ias_build_pin_apdu(card, &local_apdu, data);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
data->apdu = &local_apdu;
|
||||||
|
r = iso_ops->pin_cmd(card, data, tries_left);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
/* Continue processing */
|
||||||
|
data->cmd = SC_PIN_CMD_CHANGE;
|
||||||
|
/* The IAS spec mandates an implicit change PIN operation */
|
||||||
|
data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = ias_build_pin_apdu(card, &local_apdu, data);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
data->apdu = &local_apdu;
|
||||||
|
|
||||||
|
return iso_ops->pin_cmd(card, data, tries_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_set_security_env(sc_card_t *card,
|
||||||
|
const sc_security_env_t *env, int se_num)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
sc_apdu_t apdu;
|
||||||
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
|
||||||
|
sc_debug(card->ctx, "ias_set_security_env, keyRef = 0x%0x, algo = 0x%0x\n",
|
||||||
|
*env->key_ref, env->algorithm_flags);
|
||||||
|
|
||||||
|
assert(card != NULL && env != NULL);
|
||||||
|
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
|
||||||
|
switch (env->operation) {
|
||||||
|
case SC_SEC_OPERATION_DECIPHER:
|
||||||
|
apdu.p2 = 0xB8; /* confidentiality template */
|
||||||
|
sbuf[0] = 0x95; /* tag for usage qualifier byte */
|
||||||
|
sbuf[1] = 0x01; /* tag length */
|
||||||
|
sbuf[2] = 0x40; /* data decryption */
|
||||||
|
sbuf[3] = 0x84; /* tag for private key reference */
|
||||||
|
sbuf[4] = 0x01; /* tag length */
|
||||||
|
sbuf[5] = *env->key_ref; /* key reference */
|
||||||
|
sbuf[6] = 0x80; /* tag for algorithm reference */
|
||||||
|
sbuf[7] = 0x01; /* tag length */
|
||||||
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||||
|
sbuf[8] = 0x1A; /* RSA PKCS#1 with no data formatting */
|
||||||
|
else {
|
||||||
|
sc_debug(card->ctx, "Set Sec Env: unsupported algo 0X%0X\n",
|
||||||
|
env->algorithm_flags);
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
apdu.lc = 9;
|
||||||
|
apdu.datalen = 9;
|
||||||
|
break;
|
||||||
|
case SC_SEC_OPERATION_SIGN:
|
||||||
|
apdu.p2 = 0xA4; /* authentication template */
|
||||||
|
sbuf[0] = 0x95; /* tag for usage qualifier byte */
|
||||||
|
sbuf[1] = 0x01; /* tag length */
|
||||||
|
sbuf[2] = 0x40; /* internal authentication */
|
||||||
|
sbuf[3] = 0x84; /* tag for private key reference */
|
||||||
|
sbuf[4] = 0x01; /* tag length */
|
||||||
|
sbuf[5] = *env->key_ref; /* key reference */
|
||||||
|
sbuf[6] = 0x80; /* tag for algorithm reference */
|
||||||
|
sbuf[7] = 0x01; /* tag length */
|
||||||
|
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||||
|
sbuf[8] = 0x02; /* RSA PKCS#1 with no data formatting */
|
||||||
|
else {
|
||||||
|
sc_debug(card->ctx, "Set Sec Env: unsupported algo 0X%0X\n",
|
||||||
|
env->algorithm_flags);
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
apdu.lc = 9;
|
||||||
|
apdu.datalen = 9;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
apdu.le = 0;
|
||||||
|
apdu.data = sbuf;
|
||||||
|
apdu.resplen = 0;
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "Set Security Env APDU transmit failed");
|
||||||
|
|
||||||
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
SC_TEST_RET(card->ctx, r, "Card's Set Security Env command returned error");
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_compute_signature(sc_card_t *card, const u8 * data,
|
||||||
|
size_t data_len, u8 * out, size_t outlen)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
size_t len = 0;
|
||||||
|
sc_apdu_t apdu;
|
||||||
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(ctx, 1);
|
||||||
|
|
||||||
|
if (data_len > 64) {
|
||||||
|
sc_debug(ctx, "error: input data too long: %lu bytes\n", data_len);
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the data */
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x88, 0x02, 0x00);
|
||||||
|
memcpy(sbuf, data, data_len);
|
||||||
|
apdu.data = sbuf;
|
||||||
|
apdu.lc = data_len;
|
||||||
|
apdu.datalen = data_len;
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
|
/* Get the result */
|
||||||
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
len = card->type == SC_CARD_TYPE_IAS_PTEID ? PTEID_RSA_KEYSIZE : outlen;
|
||||||
|
r = iso_ops->get_response(card, &len, out);
|
||||||
|
if (r == 0)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, len);
|
||||||
|
else
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ias_select_file(sc_card_t *card, const sc_path_t *in_path,
|
||||||
|
sc_file_t **file_out)
|
||||||
|
{
|
||||||
|
int r, pathlen, stripped_len, offset;
|
||||||
|
u8 buf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
u8 pathbuf[SC_MAX_PATH_SIZE], *path;
|
||||||
|
sc_context_t *ctx;
|
||||||
|
sc_apdu_t apdu;
|
||||||
|
sc_file_t *file;
|
||||||
|
|
||||||
|
r = pathlen = stripped_len = offset = 0;
|
||||||
|
path = pathbuf;
|
||||||
|
file = NULL;
|
||||||
|
|
||||||
|
assert(card != NULL && in_path != NULL);
|
||||||
|
ctx = card->ctx;
|
||||||
|
|
||||||
|
if (in_path->len > SC_MAX_PATH_SIZE)
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
memcpy(path, in_path->value, in_path->len);
|
||||||
|
pathlen = in_path->len;
|
||||||
|
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
|
||||||
|
apdu.p2 = 0; /* First record, return FCI */
|
||||||
|
|
||||||
|
switch (in_path->type) {
|
||||||
|
case SC_PATH_TYPE_FILE_ID:
|
||||||
|
apdu.p1 = 2;
|
||||||
|
if (pathlen != 2)
|
||||||
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
break;
|
||||||
|
case SC_PATH_TYPE_DF_NAME:
|
||||||
|
apdu.p1 = 4;
|
||||||
|
break;
|
||||||
|
case SC_PATH_TYPE_PATH:
|
||||||
|
apdu.p1 = 9;
|
||||||
|
/* Strip the MF */
|
||||||
|
if (pathlen >= 2 && memcmp(path, "\x3f\x00", 2) == 0) {
|
||||||
|
if (pathlen == 2) { /* Only 3f00 provided */
|
||||||
|
apdu.p1 = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path += 2;
|
||||||
|
pathlen -= 2;
|
||||||
|
}
|
||||||
|
/* Optimization based on the normal Portuguese eID usage pattern:
|
||||||
|
* paths with len >= 4 shall be stripped - this avoids unnecessary
|
||||||
|
* "file not found" errors. Other cards may benefit from this also.
|
||||||
|
*
|
||||||
|
* This works perfectly for the Portuguese eID card, but if you
|
||||||
|
* are adapting this driver to another card, "false positives" may
|
||||||
|
* occur depending, of course, on the file structure of the card.
|
||||||
|
*
|
||||||
|
* Please have this in mind if adapting this driver to another card.
|
||||||
|
*/
|
||||||
|
if (pathlen >= 4) {
|
||||||
|
stripped_len = pathlen - 2;
|
||||||
|
path += stripped_len;
|
||||||
|
pathlen = 2;
|
||||||
|
} else if (pathlen == 2) {
|
||||||
|
apdu.p1 = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SC_PATH_TYPE_FROM_CURRENT:
|
||||||
|
apdu.p1 = 9;
|
||||||
|
break;
|
||||||
|
case SC_PATH_TYPE_PARENT:
|
||||||
|
apdu.p1 = 3;
|
||||||
|
apdu.p2 = 0x0C;
|
||||||
|
pathlen = 0;
|
||||||
|
apdu.cse = SC_APDU_CASE_2_SHORT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
apdu.lc = pathlen;
|
||||||
|
apdu.data = path;
|
||||||
|
apdu.datalen = pathlen;
|
||||||
|
|
||||||
|
if (file_out != NULL) {
|
||||||
|
apdu.resp = buf;
|
||||||
|
apdu.resplen = sizeof(buf);
|
||||||
|
apdu.le = 256;
|
||||||
|
} else {
|
||||||
|
apdu.p2 = 0x0C;
|
||||||
|
apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
if (file_out == NULL) {
|
||||||
|
if (apdu.sw1 == 0x61)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, 0);
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A "file not found" error was received, this can mean two things:
|
||||||
|
* 1) the file does not exist
|
||||||
|
* 2) the current DF may be incorrect due to the optimization applied
|
||||||
|
* earlier. If the path was previously stripped, select the first DF
|
||||||
|
* and try to re-select the path with the full value.
|
||||||
|
*/
|
||||||
|
if (stripped_len > 0 && apdu.sw1 == 0x6A && apdu.sw2 == 0x82) {
|
||||||
|
sc_file_t *file = NULL;
|
||||||
|
sc_path_t tpath;
|
||||||
|
|
||||||
|
/* Restore original path value */
|
||||||
|
path -= stripped_len;
|
||||||
|
pathlen += stripped_len;
|
||||||
|
|
||||||
|
memset(&tpath, 0, sizeof(sc_path_t));
|
||||||
|
tpath.type = SC_PATH_TYPE_PATH;
|
||||||
|
tpath.len = 2;
|
||||||
|
if(path[0] == 0x3f && path[1] == 0x00)
|
||||||
|
offset = 2;
|
||||||
|
else
|
||||||
|
offset = 0;
|
||||||
|
tpath.value[0] = path[offset];
|
||||||
|
tpath.value[1] = path[offset + 1];
|
||||||
|
|
||||||
|
/* Go up in the hierarchy to the correct DF */
|
||||||
|
r = ias_select_file(card, &tpath, &file);
|
||||||
|
SC_TEST_RET(card->ctx, r, "Error selecting parent.");
|
||||||
|
if(file->type != SC_FILE_TYPE_DF)
|
||||||
|
return SC_ERROR_FILE_NOT_FOUND;
|
||||||
|
|
||||||
|
/* We're now in the right place, reconstruct the APDU and retry */
|
||||||
|
path += offset + 2;
|
||||||
|
pathlen -= offset + 2;
|
||||||
|
apdu.lc = pathlen;
|
||||||
|
apdu.data = path;
|
||||||
|
apdu.datalen = pathlen;
|
||||||
|
|
||||||
|
if (file_out != NULL)
|
||||||
|
apdu.resplen = sizeof(buf);
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
if (file_out == NULL) {
|
||||||
|
if (apdu.sw1 == 0x61)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, 0);
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
if (r)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
|
|
||||||
|
if (apdu.resplen < 2)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
|
switch (apdu.resp[0]) {
|
||||||
|
case 0x6F:
|
||||||
|
file = sc_file_new();
|
||||||
|
if (file == NULL)
|
||||||
|
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
|
||||||
|
file->path = *in_path;
|
||||||
|
if (card->ops->process_fci == NULL) {
|
||||||
|
sc_file_free(file);
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
if ((size_t)apdu.resp[1] + 2 <= apdu.resplen)
|
||||||
|
card->ops->process_fci(card, file, apdu.resp+2, apdu.resp[1]);
|
||||||
|
*file_out = file;
|
||||||
|
break;
|
||||||
|
case 0x00: /* proprietary coding */
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
|
default:
|
||||||
|
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sc_card_driver *sc_get_driver(void)
|
||||||
|
{
|
||||||
|
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||||
|
|
||||||
|
if (iso_ops == NULL)
|
||||||
|
iso_ops = iso_drv->ops;
|
||||||
|
/* Use the standard iso operations as default */
|
||||||
|
ias_ops = *iso_drv->ops;
|
||||||
|
/* IAS specific functions */
|
||||||
|
ias_ops.select_file = ias_select_file;
|
||||||
|
ias_ops.match_card = ias_match_card;
|
||||||
|
ias_ops.init = ias_init;
|
||||||
|
ias_ops.set_security_env = ias_set_security_env;
|
||||||
|
ias_ops.compute_signature = ias_compute_signature;
|
||||||
|
ias_ops.pin_cmd = ias_pin_cmd;
|
||||||
|
|
||||||
|
return &ias_drv;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sc_card_driver *sc_get_ias_driver(void)
|
||||||
|
{
|
||||||
|
return sc_get_driver();
|
||||||
|
}
|
|
@ -49,11 +49,6 @@ static struct sc_atr_table incrypto34_atrs[] = {
|
||||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int incrypto34_finish(struct sc_card *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int incrypto34_match_card(struct sc_card *card)
|
static int incrypto34_match_card(struct sc_card *card)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -154,13 +149,13 @@ static int incrypto34_check_sw(sc_card_t *card, unsigned int sw1, unsigned int s
|
||||||
for (i = 0; i < err_count; i++) {
|
for (i = 0; i < err_count; i++) {
|
||||||
if (incrypto34_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
if (incrypto34_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
||||||
if ( incrypto34_errors[i].errorstr )
|
if ( incrypto34_errors[i].errorstr )
|
||||||
sc_error(card->ctx, "%s\n",
|
sc_debug(card->ctx, "%s\n",
|
||||||
incrypto34_errors[i].errorstr);
|
incrypto34_errors[i].errorstr);
|
||||||
return incrypto34_errors[i].errorno;
|
return incrypto34_errors[i].errorno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
sc_debug(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
||||||
return SC_ERROR_CARD_CMD_FAILED;
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +387,7 @@ static int incrypto34_create_file(sc_card_t *card, sc_file_t *file)
|
||||||
byte = acl_to_byte(
|
byte = acl_to_byte(
|
||||||
sc_file_get_acl_entry(file, idx[i]));
|
sc_file_get_acl_entry(file, idx[i]));
|
||||||
if (byte < 0) {
|
if (byte < 0) {
|
||||||
sc_error(card->ctx, "Invalid ACL\n");
|
sc_debug(card->ctx, "Invalid ACL\n");
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -452,7 +447,7 @@ static int incrypto34_set_security_env(sc_card_t *card,
|
||||||
|
|
||||||
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|
||||||
|| env->key_ref_len != 1) {
|
|| env->key_ref_len != 1) {
|
||||||
sc_error(card->ctx, "No or invalid key reference\n");
|
sc_debug(card->ctx, "No or invalid key reference\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
key_id = env->key_ref[0];
|
key_id = env->key_ref[0];
|
||||||
|
@ -516,7 +511,6 @@ static int do_compute_signature(sc_card_t *card,
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.lc = datalen;
|
apdu.lc = datalen;
|
||||||
apdu.datalen = datalen;
|
apdu.datalen = datalen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
|
@ -553,9 +547,7 @@ incrypto34_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
|
||||||
*/
|
*/
|
||||||
if (ctx->debug >= 3)
|
if (ctx->debug >= 3)
|
||||||
sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
|
sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = do_compute_signature(card, data, datalen, out, outlen);
|
r = do_compute_signature(card, data, datalen, out, outlen);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (r >= SC_SUCCESS)
|
if (r >= SC_SUCCESS)
|
||||||
SC_FUNC_RETURN(ctx, 4, r);
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
if (ctx->debug >= 3)
|
if (ctx->debug >= 3)
|
||||||
|
@ -574,9 +566,7 @@ incrypto34_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
|
||||||
}
|
}
|
||||||
memcpy(buf, p, tmp_len);
|
memcpy(buf, p, tmp_len);
|
||||||
}
|
}
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = do_compute_signature(card, buf, tmp_len, out, outlen);
|
r = do_compute_signature(card, buf, tmp_len, out, outlen);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (r >= SC_SUCCESS)
|
if (r >= SC_SUCCESS)
|
||||||
SC_FUNC_RETURN(ctx, 4, r);
|
SC_FUNC_RETURN(ctx, 4, r);
|
||||||
if (ctx->debug >= 3)
|
if (ctx->debug >= 3)
|
||||||
|
@ -624,7 +614,7 @@ incrypto34_lifecycle_get(sc_card_t *card, int *mode)
|
||||||
*mode = SC_CARDCTRL_LIFECYCLE_OTHER;
|
*mode = SC_CARDCTRL_LIFECYCLE_OTHER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
|
sc_debug(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +904,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
incrypto34_ops = *iso_ops;
|
incrypto34_ops = *iso_ops;
|
||||||
incrypto34_ops.match_card = incrypto34_match_card;
|
incrypto34_ops.match_card = incrypto34_match_card;
|
||||||
incrypto34_ops.init = incrypto34_init;
|
incrypto34_ops.init = incrypto34_init;
|
||||||
incrypto34_ops.finish = incrypto34_finish;
|
|
||||||
incrypto34_ops.select_file = incrypto34_select_file;
|
incrypto34_ops.select_file = incrypto34_select_file;
|
||||||
incrypto34_ops.create_file = incrypto34_create_file;
|
incrypto34_ops.create_file = incrypto34_create_file;
|
||||||
incrypto34_ops.set_security_env = incrypto34_set_security_env;
|
incrypto34_ops.set_security_env = incrypto34_set_security_env;
|
||||||
|
|
|
@ -328,9 +328,7 @@ static int jcop_read_binary(sc_card_t *card, unsigned int idx,
|
||||||
if (idx + count > 128) {
|
if (idx + count > 128) {
|
||||||
count=128-idx;
|
count=128-idx;
|
||||||
}
|
}
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = iso_ops->select_file(card, &drvdata->aid, &tfile);
|
r = iso_ops->select_file(card, &drvdata->aid, &tfile);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r < 0) { /* no pkcs15 app, so return empty DIR. */
|
if (r < 0) { /* no pkcs15 app, so return empty DIR. */
|
||||||
memset(buf, 0, count);
|
memset(buf, 0, count);
|
||||||
} else {
|
} else {
|
||||||
|
@ -356,9 +354,7 @@ static int jcop_list_files(sc_card_t *card, u8 *buf, size_t buflen) {
|
||||||
if (buflen < 4)
|
if (buflen < 4)
|
||||||
return 2;
|
return 2;
|
||||||
/* AppDF only exists if applet is selectable */
|
/* AppDF only exists if applet is selectable */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = iso_ops->select_file(card, &drvdata->aid, &tfile);
|
r = iso_ops->select_file(card, &drvdata->aid, &tfile);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return 2;
|
return 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -650,11 +646,11 @@ static int jcop_set_security_env(sc_card_t *card,
|
||||||
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
||||||
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||||
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Only RSA algorithm supported.\n");
|
sc_debug(card->ctx, "Only RSA algorithm supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)){
|
if (!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)){
|
||||||
sc_error(card->ctx, "Card requires RSA padding\n");
|
sc_debug(card->ctx, "Card requires RSA padding\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
tmp.algorithm_ref = 0x02;
|
tmp.algorithm_ref = 0x02;
|
||||||
|
@ -755,7 +751,6 @@ static int jcop_compute_signature(sc_card_t *card,
|
||||||
}
|
}
|
||||||
|
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
@ -793,7 +788,6 @@ static int jcop_decipher(sc_card_t *card,
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf); /* FIXME */
|
apdu.resplen = sizeof(rbuf); /* FIXME */
|
||||||
apdu.le = crgram_len;
|
apdu.le = crgram_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
if (crgram_len == 256) {
|
if (crgram_len == 256) {
|
||||||
apdu.p2 = crgram[0];
|
apdu.p2 = crgram[0];
|
||||||
|
|
|
@ -758,9 +758,7 @@ select_part(sc_card_t * card, u8 kind, unsigned short int fid,
|
||||||
|
|
||||||
fbuf[0] = fid >> 8;
|
fbuf[0] = fid >> 8;
|
||||||
fbuf[1] = fid & 0xff;
|
fbuf[1] = fid & 0xff;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = do_select(card, kind, fbuf, 2, file);
|
r = do_select(card, kind, fbuf, 2, file);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1313,8 +1311,6 @@ static int mcrd_decipher(sc_card_t * card,
|
||||||
apdu.datalen = crgram_len;
|
apdu.datalen = crgram_len;
|
||||||
apdu.lc = apdu.datalen;
|
apdu.lc = apdu.datalen;
|
||||||
|
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
|
|
|
@ -40,11 +40,6 @@ static struct sc_card_driver miocos_drv = {
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int miocos_finish(sc_card_t *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int miocos_match_card(sc_card_t *card)
|
static int miocos_match_card(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -141,7 +136,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
*p++ = 0x43;
|
*p++ = 0x43;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid EF structure\n");
|
sc_debug(card->ctx, "Invalid EF structure\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
ops = ef_ops;
|
ops = ef_ops;
|
||||||
|
@ -151,7 +146,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
ops = key_ops;
|
ops = key_ops;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unknown file type\n");
|
sc_debug(card->ctx, "Unknown file type\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (file->type == SC_FILE_TYPE_DF) {
|
if (file->type == SC_FILE_TYPE_DF) {
|
||||||
|
@ -172,7 +167,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
else {
|
else {
|
||||||
int byte = acl_to_byte(sc_file_get_acl_entry(file, ops[i]));
|
int byte = acl_to_byte(sc_file_get_acl_entry(file, ops[i]));
|
||||||
if (byte < 0) {
|
if (byte < 0) {
|
||||||
sc_error(card->ctx, "Invalid ACL\n");
|
sc_debug(card->ctx, "Invalid ACL\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
nibble = byte;
|
nibble = byte;
|
||||||
|
@ -239,7 +234,7 @@ static int miocos_set_security_env(sc_card_t *card,
|
||||||
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
||||||
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||||
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Only RSA algorithm supported.\n");
|
sc_debug(card->ctx, "Only RSA algorithm supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
tmp.algorithm_ref = 0x00;
|
tmp.algorithm_ref = 0x00;
|
||||||
|
@ -418,7 +413,7 @@ static int miocos_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
r = sc_select_file(card, path, NULL);
|
r = sc_select_file(card, path, NULL);
|
||||||
|
@ -456,7 +451,7 @@ static int miocos_create_ac(sc_card_t *card,
|
||||||
sendsize = 20;
|
sendsize = 20;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "AC type %d not supported\n", ac->type);
|
sc_debug(card->ctx, "AC type %d not supported\n", ac->type);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x1E, miocos_type,
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x1E, miocos_type,
|
||||||
|
@ -476,7 +471,7 @@ static int miocos_card_ctl(sc_card_t *card, unsigned long cmd,
|
||||||
case SC_CARDCTL_MIOCOS_CREATE_AC:
|
case SC_CARDCTL_MIOCOS_CREATE_AC:
|
||||||
return miocos_create_ac(card, (struct sc_cardctl_miocos_ac_info *) arg);
|
return miocos_create_ac(card, (struct sc_cardctl_miocos_ac_info *) arg);
|
||||||
}
|
}
|
||||||
sc_error(card->ctx, "card_ctl command 0x%X not supported\n", cmd);
|
sc_debug(card->ctx, "card_ctl command 0x%X not supported\n", cmd);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +483,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
miocos_ops = *iso_drv->ops;
|
miocos_ops = *iso_drv->ops;
|
||||||
miocos_ops.match_card = miocos_match_card;
|
miocos_ops.match_card = miocos_match_card;
|
||||||
miocos_ops.init = miocos_init;
|
miocos_ops.init = miocos_init;
|
||||||
miocos_ops.finish = miocos_finish;
|
|
||||||
if (iso_ops == NULL)
|
if (iso_ops == NULL)
|
||||||
iso_ops = iso_drv->ops;
|
iso_ops = iso_drv->ops;
|
||||||
miocos_ops.create_file = miocos_create_file;
|
miocos_ops.create_file = miocos_create_file;
|
||||||
|
|
|
@ -75,9 +75,7 @@ static int muscle_match_card(sc_card_t *card)
|
||||||
* however it's not always properly nulled out... */
|
* however it's not always properly nulled out... */
|
||||||
card->ops->logout = NULL;
|
card->ops->logout = NULL;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
i = msc_select_applet(card, muscleAppletId, 5);
|
i = msc_select_applet(card, muscleAppletId, 5);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
/* Mark the card for muscle_init */
|
/* Mark the card for muscle_init */
|
||||||
card->drv_data = (void*)0xFFFFFFFF;
|
card->drv_data = (void*)0xFFFFFFFF;
|
||||||
return i;
|
return i;
|
||||||
|
@ -282,14 +280,12 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
|
||||||
}
|
}
|
||||||
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
||||||
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4))) {
|
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4))) {
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
}
|
}
|
||||||
r = msc_delete_object(card, id, 1);
|
r = msc_delete_object(card, id, 1);
|
||||||
/* Check if its the root... this file generally is virtual
|
/* Check if its the root... this file generally is virtual
|
||||||
* So don't return an error if it fails */
|
* So don't return an error if it fails */
|
||||||
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
|
||||||
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4)))
|
|| (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4)))
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
|
@ -560,7 +556,7 @@ static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd,
|
||||||
case SC_AC_AUT:
|
case SC_AC_AUT:
|
||||||
case SC_AC_NONE:
|
case SC_AC_NONE:
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported authentication method\n");
|
sc_debug(card->ctx, "Unsupported authentication method\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
case SC_PIN_CMD_CHANGE:
|
case SC_PIN_CMD_CHANGE:
|
||||||
|
@ -576,7 +572,7 @@ static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd,
|
||||||
case SC_AC_AUT:
|
case SC_AC_AUT:
|
||||||
case SC_AC_NONE:
|
case SC_AC_NONE:
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported authentication method\n");
|
sc_debug(card->ctx, "Unsupported authentication method\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
case SC_PIN_CMD_UNBLOCK:
|
case SC_PIN_CMD_UNBLOCK:
|
||||||
|
@ -592,11 +588,11 @@ static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd,
|
||||||
case SC_AC_AUT:
|
case SC_AC_AUT:
|
||||||
case SC_AC_NONE:
|
case SC_AC_NONE:
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported authentication method\n");
|
sc_debug(card->ctx, "Unsupported authentication method\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported command\n");
|
sc_debug(card->ctx, "Unsupported command\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -673,34 +669,34 @@ static int muscle_set_security_env(sc_card_t *card,
|
||||||
|
|
||||||
if (env->operation != SC_SEC_OPERATION_SIGN &&
|
if (env->operation != SC_SEC_OPERATION_SIGN &&
|
||||||
env->operation != SC_SEC_OPERATION_DECIPHER) {
|
env->operation != SC_SEC_OPERATION_DECIPHER) {
|
||||||
sc_error(card->ctx, "Invalid crypto operation supplied.\n");
|
sc_debug(card->ctx, "Invalid crypto operation supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (env->algorithm != SC_ALGORITHM_RSA) {
|
if (env->algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Invalid crypto algorithm supplied.\n");
|
sc_debug(card->ctx, "Invalid crypto algorithm supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/* ADJUST FOR PKCS1 padding support for decryption only */
|
/* ADJUST FOR PKCS1 padding support for decryption only */
|
||||||
if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
|
if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
|
||||||
(env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
|
(env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
|
||||||
sc_error(card->ctx, "Card supports only raw RSA.\n");
|
sc_debug(card->ctx, "Card supports only raw RSA.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
||||||
if (env->key_ref_len != 1 ||
|
if (env->key_ref_len != 1 ||
|
||||||
(env->key_ref[0] > 0x0F)) {
|
(env->key_ref[0] > 0x0F)) {
|
||||||
sc_error(card->ctx, "Invalid key reference supplied.\n");
|
sc_debug(card->ctx, "Invalid key reference supplied.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
priv->rsa_key_ref = env->key_ref[0];
|
priv->rsa_key_ref = env->key_ref[0];
|
||||||
}
|
}
|
||||||
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
|
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
|
||||||
sc_error(card->ctx, "Algorithm reference not supported.\n");
|
sc_debug(card->ctx, "Algorithm reference not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/* if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
|
/* if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
|
||||||
if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
|
if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
|
||||||
sc_error(card->ctx, "File reference is not 0012.\n");
|
sc_debug(card->ctx, "File reference is not 0012.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
} */
|
} */
|
||||||
priv->env = *env;
|
priv->env = *env;
|
||||||
|
@ -731,7 +727,7 @@ static int muscle_decipher(sc_card_t * card,
|
||||||
key_id = priv->rsa_key_ref * 2; /* Private key */
|
key_id = priv->rsa_key_ref * 2; /* Private key */
|
||||||
|
|
||||||
if (out_len < crgram_len) {
|
if (out_len < crgram_len) {
|
||||||
sc_error(card->ctx, "Output buffer too small");
|
sc_debug(card->ctx, "Output buffer too small");
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,7 +753,7 @@ static int muscle_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
key_id = priv->rsa_key_ref * 2; /* Private key */
|
key_id = priv->rsa_key_ref * 2; /* Private key */
|
||||||
|
|
||||||
if (outlen < data_len) {
|
if (outlen < data_len) {
|
||||||
sc_error(card->ctx, "Output buffer too small");
|
sc_debug(card->ctx, "Output buffer too small");
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,19 +25,19 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define LOAD_KEY_MODULUS 0x80
|
#define LOAD_KEY_MODULUS 0x80
|
||||||
#define LOAD_KEY_PUBLIC_EXPONENT 0x81
|
#define LOAD_KEY_PUBLIC_EXPONENT 0x81
|
||||||
#define LOAD_KEY_PRIME_P 0x83
|
#define LOAD_KEY_PRIME_P 0x83
|
||||||
#define LOAD_KEY_PRIME_Q 0x84
|
#define LOAD_KEY_PRIME_Q 0x84
|
||||||
#define LOAD_KEY_DP1 0x85
|
#define LOAD_KEY_DP1 0x85
|
||||||
#define LOAD_KEY_DQ1 0x86
|
#define LOAD_KEY_DQ1 0x86
|
||||||
#define LOAD_KEY_INVQ 0x87
|
#define LOAD_KEY_INVQ 0x87
|
||||||
|
|
||||||
static struct sc_card_operations myeid_ops;
|
static struct sc_card_operations myeid_ops;
|
||||||
static struct sc_card_driver myeid_drv = {
|
static struct sc_card_driver myeid_drv = {
|
||||||
"MyEID cards with PKCS#15 applet",
|
"MyEID cards with PKCS#15 applet",
|
||||||
"myeid",
|
"myeid",
|
||||||
&myeid_ops
|
&myeid_ops
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *myeid_atrs[] = {
|
static const char *myeid_atrs[] = {
|
||||||
|
@ -46,12 +46,6 @@ static const char *myeid_atrs[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int myeid_finish(struct sc_card *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int myeid_match_card(struct sc_card *card)
|
static int myeid_match_card(struct sc_card *card)
|
||||||
{
|
{
|
||||||
int i, match = -1;
|
int i, match = -1;
|
||||||
|
@ -89,7 +83,7 @@ static int myeid_init(struct sc_card *card)
|
||||||
/* State that we have an RNG */
|
/* State that we have an RNG */
|
||||||
card->caps |= SC_CARD_CAP_RNG;
|
card->caps |= SC_CARD_CAP_RNG;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +98,9 @@ static int acl_to_byte(const struct sc_acl_entry *e)
|
||||||
case SC_AC_TERM:
|
case SC_AC_TERM:
|
||||||
case SC_AC_AUT:
|
case SC_AC_AUT:
|
||||||
if (e->key_ref == SC_AC_KEY_REF_NONE)
|
if (e->key_ref == SC_AC_KEY_REF_NONE)
|
||||||
return 0x00;
|
return 0x00;
|
||||||
if (e->key_ref < 1 || e->key_ref > 14)
|
if (e->key_ref < 1 || e->key_ref > 14)
|
||||||
return 0x00;
|
return 0x00;
|
||||||
return e->key_ref;
|
return e->key_ref;
|
||||||
case SC_AC_NEVER:
|
case SC_AC_NEVER:
|
||||||
return 0x0F;
|
return 0x0F;
|
||||||
|
@ -179,26 +173,26 @@ static int myeid_select_file(struct sc_card *card, const struct sc_path *in_path
|
||||||
struct sc_file **file)
|
struct sc_file **file)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
r = iso_ops->select_file(card, in_path, file);
|
r = iso_ops->select_file(card, in_path, file);
|
||||||
|
|
||||||
if (r == 0 && file != NULL) {
|
if (r == 0 && file != NULL) {
|
||||||
parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
|
parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
|
||||||
}
|
}
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_read_binary(struct sc_card *card, unsigned int idx,
|
static int myeid_read_binary(struct sc_card *card, unsigned int idx,
|
||||||
u8 * buf, size_t count, unsigned long flags)
|
u8 * buf, size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->read_binary(card, idx, buf, count, flags));
|
SC_FUNC_RETURN(card->ctx, 1, iso_ops->read_binary(card, idx, buf, count, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct sc_apdu apdu;
|
struct sc_apdu apdu;
|
||||||
int r,i;
|
int r;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
|
@ -222,10 +216,10 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
||||||
const u8 *tag = NULL;
|
const u8 *tag = NULL;
|
||||||
int r ;
|
int r ;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
r = iso_ops->process_fci(card, file, buf, buflen);
|
r = iso_ops->process_fci(card, file, buf, buflen);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
|
|
||||||
if(file->type == SC_FILE_EF_UNKNOWN)
|
if(file->type == SC_FILE_EF_UNKNOWN)
|
||||||
{
|
{
|
||||||
|
@ -241,17 +235,17 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
||||||
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
u8 *out, size_t *outlen)
|
u8 *out, size_t *outlen)
|
||||||
{
|
{
|
||||||
const sc_acl_entry_t *read, *update, *delete;
|
const sc_acl_entry_t *read, *update, *delete;
|
||||||
u8 buf[40];
|
u8 buf[40];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
/* PrivateKey
|
/* PrivateKey
|
||||||
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
|
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
|
||||||
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
|
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
|
||||||
|
@ -290,38 +284,38 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
buf[17] = file->sec_attr[2];
|
buf[17] = file->sec_attr[2];
|
||||||
|
|
||||||
sc_debug(card->ctx, "id (%X), sec_attr %X %X %X\n", file->id,
|
sc_debug(card->ctx, "id (%X), sec_attr %X %X %X\n", file->id,
|
||||||
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE);
|
delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE);
|
||||||
|
|
||||||
switch (file->type) {
|
switch (file->type) {
|
||||||
case SC_FILE_TYPE_WORKING_EF:
|
case SC_FILE_TYPE_WORKING_EF:
|
||||||
|
|
||||||
read = sc_file_get_acl_entry(file, SC_AC_OP_READ);
|
read = sc_file_get_acl_entry(file, SC_AC_OP_READ);
|
||||||
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
||||||
|
|
||||||
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
||||||
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
||||||
break;
|
break;
|
||||||
case SC_FILE_TYPE_INTERNAL_EF:
|
case SC_FILE_TYPE_INTERNAL_EF:
|
||||||
|
|
||||||
read = sc_file_get_acl_entry(file, SC_AC_OP_CRYPTO);
|
read = sc_file_get_acl_entry(file, SC_AC_OP_CRYPTO);
|
||||||
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE);
|
||||||
|
|
||||||
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update);
|
||||||
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
buf[16] = (acl_to_byte(delete)<< 4) | 0x0F;
|
||||||
break;
|
break;
|
||||||
case SC_FILE_TYPE_DF:
|
case SC_FILE_TYPE_DF:
|
||||||
|
|
||||||
update = sc_file_get_acl_entry(file, SC_AC_OP_CREATE);
|
update = sc_file_get_acl_entry(file, SC_AC_OP_CREATE);
|
||||||
|
|
||||||
buf[15] = (acl_to_byte(update) << 4) | acl_to_byte(update);
|
buf[15] = (acl_to_byte(update) << 4) | acl_to_byte(update);
|
||||||
buf[16] = (acl_to_byte(delete) << 4) | 0x0F;
|
buf[16] = (acl_to_byte(delete) << 4) | 0x0F;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,22 +346,22 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||||
{
|
{
|
||||||
buf[25] = 0x84;
|
buf[25] = 0x84;
|
||||||
buf[26] = (u8)file->namelen;
|
buf[26] = (u8)file->namelen;
|
||||||
|
|
||||||
for(i=0;i < (int)file->namelen;i++)
|
for(i=0;i < (int)file->namelen;i++)
|
||||||
buf[i + 26] = file->name[i];
|
buf[i + 26] = file->name[i];
|
||||||
|
|
||||||
buf[1] = 0x19 + file->namelen + 2;
|
buf[1] = 0x19 + file->namelen + 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unknown file type\n");
|
sc_debug(card->ctx, "Unknown file type\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
*outlen = buf[1]+2;
|
*outlen = buf[1]+2;
|
||||||
memcpy(out, buf, *outlen);
|
memcpy(out, buf, *outlen);
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
|
@ -378,7 +372,7 @@ static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
r = encode_file_structure(card, file, sbuf, &buflen);
|
r = encode_file_structure(card, file, sbuf, &buflen);
|
||||||
if (r)
|
if (r)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
|
@ -392,9 +386,9 @@ static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x6A && apdu.sw2 == 0x89)
|
if (apdu.sw1 == 0x6A && apdu.sw2 == 0x89)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_ALREADY_EXISTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_ALREADY_EXISTS);
|
||||||
|
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
SC_TEST_RET(card->ctx, r, "Card returned error");
|
SC_FUNC_RETURN(card->ctx, r, "Card returned error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no record oriented file services */
|
/* no record oriented file services */
|
||||||
|
@ -402,37 +396,37 @@ static int myeid_read_record_unsupp(struct sc_card *card, unsigned int rec_nr,
|
||||||
u8 *buf, size_t count, unsigned long flags)
|
u8 *buf, size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_wrupd_record_unsupp(struct sc_card *card, unsigned int rec_nr,
|
static int myeid_wrupd_record_unsupp(struct sc_card *card, unsigned int rec_nr,
|
||||||
const u8 *buf, size_t count, unsigned long flags)
|
const u8 *buf, size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_append_record_unsupp(struct sc_card *card, const u8 *buf,
|
static int myeid_append_record_unsupp(struct sc_card *card, const u8 *buf,
|
||||||
size_t count, unsigned long flags)
|
size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int myeid_write_binary(struct sc_card *card, unsigned int idx,
|
static int myeid_write_binary(struct sc_card *card, unsigned int idx,
|
||||||
const u8 *buf, size_t count, unsigned long flags)
|
const u8 *buf, size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->write_binary(card, idx, buf, count, flags));
|
SC_FUNC_RETURN(card->ctx, 1, iso_ops->write_binary(card, idx, buf, count, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int myeid_update_binary(struct sc_card *card, unsigned int idx,
|
static int myeid_update_binary(struct sc_card *card, unsigned int idx,
|
||||||
const u8 *buf, size_t count, unsigned long flags)
|
const u8 *buf, size_t count, unsigned long flags)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->update_binary(card, idx, buf, count, flags));
|
SC_FUNC_RETURN(card->ctx, 1, iso_ops->update_binary(card, idx, buf, count, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
||||||
|
@ -443,7 +437,7 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2)
|
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
r = sc_select_file(card, path, NULL);
|
r = sc_select_file(card, path, NULL);
|
||||||
|
@ -455,7 +449,7 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
SC_FUNC_RETURN(card->ctx, 1, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
|
@ -481,7 +475,7 @@ static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, iso_ops->pin_cmd(card, data, tries_left));
|
SC_FUNC_RETURN(card->ctx, 1, iso_ops->pin_cmd(card, data, tries_left));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env,
|
static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env,
|
||||||
int se_num)
|
int se_num)
|
||||||
|
@ -492,16 +486,16 @@ static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env
|
||||||
int r, locked = 0;
|
int r, locked = 0;
|
||||||
|
|
||||||
assert(card != NULL && env != NULL);
|
assert(card != NULL && env != NULL);
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
|
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "asymmetric keyref not supported.\n");
|
sc_debug(card->ctx, "asymmetric keyref not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (se_num > 0)
|
if (se_num > 0)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "restore security environment not supported.\n");
|
sc_debug(card->ctx, "restore security environment not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,14 +569,14 @@ static int myeid_set_security_env2(sc_card_t *card, const sc_security_env_t *env
|
||||||
err:
|
err:
|
||||||
if (locked)
|
if (locked)
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_set_security_env(struct sc_card *card,
|
static int myeid_set_security_env(struct sc_card *card,
|
||||||
const struct sc_security_env *env, int se_num)
|
const struct sc_security_env *env, int se_num)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
||||||
{
|
{
|
||||||
sc_security_env_t tmp;
|
sc_security_env_t tmp;
|
||||||
|
@ -592,7 +586,7 @@ static int myeid_set_security_env(struct sc_card *card,
|
||||||
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||||
if (tmp.algorithm != SC_ALGORITHM_RSA)
|
if (tmp.algorithm != SC_ALGORITHM_RSA)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "Only RSA algorithm supported.\n");
|
sc_debug(card->ctx, "Only RSA algorithm supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +611,7 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
||||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
assert(card != NULL && data != NULL && out != NULL);
|
assert(card != NULL && data != NULL && out != NULL);
|
||||||
if (datalen > 256)
|
if (datalen > 256)
|
||||||
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
@ -644,7 +638,6 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
||||||
}
|
}
|
||||||
|
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
||||||
|
@ -668,7 +661,7 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
||||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
assert(card != NULL && crgram != NULL && out != NULL);
|
assert(card != NULL && crgram != NULL && out != NULL);
|
||||||
SC_FUNC_CALLED(card->ctx, 2);
|
SC_FUNC_CALLED(card->ctx, 2);
|
||||||
if (crgram_len > 256)
|
if (crgram_len > 256)
|
||||||
|
@ -684,7 +677,6 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
apdu.le = crgram_len;
|
apdu.le = crgram_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
if (crgram_len == 256)
|
if (crgram_len == 256)
|
||||||
{
apdu.le = 0;
|
{
apdu.le = 0;
|
||||||
|
@ -713,7 +705,6 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
apdu.le = crgram_len;
|
apdu.le = crgram_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
/* padding indicator byte,
|
/* padding indicator byte,
|
||||||
* 0x82 = Second half of 2048 bit cryptogram */
|
* 0x82 = Second half of 2048 bit cryptogram */
|
||||||
sbuf[0] = 0x82;
|
sbuf[0] = 0x82;
|
||||||
|
@ -813,7 +804,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
|
||||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
int r, len;
|
int r, len;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
len = 0;
|
len = 0;
|
||||||
if(value_len == 0 || value == NULL)
|
if(value_len == 0 || value == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -884,9 +875,9 @@ static int myeid_generate_store_key(struct sc_card *card,
|
||||||
{
|
{
|
||||||
struct sc_apdu apdu;
|
struct sc_apdu apdu;
|
||||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
int r=0,len;
|
int r=0,len;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
/* Setup key-generation paramters */
|
/* Setup key-generation paramters */
|
||||||
if (data->op_type == OP_TYPE_GENERATE)
|
if (data->op_type == OP_TYPE_GENERATE)
|
||||||
{
|
{
|
||||||
|
@ -929,10 +920,10 @@ static int myeid_generate_store_key(struct sc_card *card,
|
||||||
data->mod, data->mod_len)) >= 0 &&
|
data->mod, data->mod_len)) >= 0 &&
|
||||||
(r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT,
|
(r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT,
|
||||||
data->pubexp, data->pubexp_len)) >= 0)
|
data->pubexp, data->pubexp_len)) >= 0)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_activate_card(struct sc_card *card)
|
static int myeid_activate_card(struct sc_card *card)
|
||||||
|
@ -941,7 +932,7 @@ static int myeid_activate_card(struct sc_card *card)
|
||||||
u8 sbuf[] ="\xA0\x00\x00\x00\x63\x50\x4B\x43\x53\x2D\x31\x35";
|
u8 sbuf[] ="\xA0\x00\x00\x00\x63\x50\x4B\x43\x53\x2D\x31\x35";
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x44, 0x04, 0x00);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x44, 0x04, 0x00);
|
||||||
apdu.cla = 0x00;
|
apdu.cla = 0x00;
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
|
@ -963,7 +954,7 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0);
|
||||||
apdu.resp = rbuf;
|
apdu.resp = rbuf;
|
||||||
apdu.resplen = sizeof(rbuf);
|
apdu.resplen = sizeof(rbuf);
|
||||||
|
@ -988,27 +979,27 @@ static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
/* copy and return serial number */
|
/* copy and return serial number */
|
||||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||||
{
|
{
|
||||||
int r = SC_ERROR_NOT_SUPPORTED;
|
int r = SC_ERROR_NOT_SUPPORTED;
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
|
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case SC_CARDCTL_MYEID_PUTDATA:
|
case SC_CARDCTL_MYEID_PUTDATA:
|
||||||
r = myeid_putdata(card,
|
r = myeid_putdata(card,
|
||||||
(struct sc_cardctl_myeid_data_obj*) ptr);
|
(struct sc_cardctl_myeid_data_obj*) ptr);
|
||||||
break;
|
break;
|
||||||
case SC_CARDCTL_MYEID_GETDATA:
|
case SC_CARDCTL_MYEID_GETDATA:
|
||||||
r = myeid_getdata(card,
|
r = myeid_getdata(card,
|
||||||
(struct sc_cardctl_myeid_data_obj*) ptr);
|
(struct sc_cardctl_myeid_data_obj*) ptr);
|
||||||
break;
|
break;
|
||||||
case SC_CARDCTL_MYEID_GENERATE_KEY:
|
case SC_CARDCTL_MYEID_GENERATE_KEY:
|
||||||
r = myeid_generate_store_key(card,
|
r = myeid_generate_store_key(card,
|
||||||
(struct sc_cardctl_myeid_gen_store_key_info *) ptr);
|
(struct sc_cardctl_myeid_gen_store_key_info *) ptr);
|
||||||
break;
|
break;
|
||||||
case SC_CARDCTL_MYEID_ACTIVATE_CARD:
|
case SC_CARDCTL_MYEID_ACTIVATE_CARD:
|
||||||
r = myeid_activate_card(card);
|
r = myeid_activate_card(card);
|
||||||
break;
|
break;
|
||||||
|
@ -1017,9 +1008,9 @@ static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||||
break;
|
break;
|
||||||
case SC_CARDCTL_LIFECYCLE_SET:
|
case SC_CARDCTL_LIFECYCLE_SET:
|
||||||
case SC_CARDCTL_LIFECYCLE_GET:
|
case SC_CARDCTL_LIFECYCLE_GET:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "The PINs are "global" in a PKCS#15 sense, meaning that they remain valid
|
/* "The PINs are "global" in a PKCS#15 sense, meaning that they remain valid
|
||||||
|
@ -1029,8 +1020,8 @@ static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
|
||||||
*/
|
*/
|
||||||
static int myeid_logout(struct sc_card *card)
|
static int myeid_logout(struct sc_card *card)
|
||||||
{
|
{
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, 0);
|
SC_FUNC_RETURN(card->ctx, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sc_card_driver * sc_get_driver(void)
|
static struct sc_card_driver * sc_get_driver(void)
|
||||||
|
@ -1040,7 +1031,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
myeid_ops = *iso_drv->ops;
|
myeid_ops = *iso_drv->ops;
|
||||||
myeid_ops.match_card = myeid_match_card;
|
myeid_ops.match_card = myeid_match_card;
|
||||||
myeid_ops.init = myeid_init;
|
myeid_ops.init = myeid_init;
|
||||||
myeid_ops.finish = myeid_finish;
|
|
||||||
if (iso_ops == NULL)
|
if (iso_ops == NULL)
|
||||||
iso_ops = iso_drv->ops;
|
iso_ops = iso_drv->ops;
|
||||||
myeid_ops.read_binary = myeid_read_binary;
|
myeid_ops.read_binary = myeid_read_binary;
|
||||||
|
@ -1060,7 +1050,7 @@ static struct sc_card_driver * sc_get_driver(void)
|
||||||
myeid_ops.logout = myeid_logout;
|
myeid_ops.logout = myeid_logout;
|
||||||
myeid_ops.process_fci = myeid_process_fci;
|
myeid_ops.process_fci = myeid_process_fci;
|
||||||
myeid_ops.card_ctl = myeid_card_ctl;
|
myeid_ops.card_ctl = myeid_card_ctl;
|
||||||
myeid_ops.pin_cmd = myeid_pin_cmd;
|
myeid_ops.pin_cmd = myeid_pin_cmd;
|
||||||
return &myeid_drv;
|
return &myeid_drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ auth_init(struct sc_card *card)
|
||||||
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
||||||
|
|
||||||
if (auth_select_aid(card)) {
|
if (auth_select_aid(card)) {
|
||||||
sc_error(card->ctx, "Failed to initialize %s\n", card->name);
|
sc_debug(card->ctx, "Failed to initialize %s\n", card->name);
|
||||||
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_CARD, "Failed to initialize");
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_CARD, "Failed to initialize");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ auth_process_fci(struct sc_card *card, struct sc_file *file,
|
||||||
else if (file->size==2048)
|
else if (file->size==2048)
|
||||||
file->size = PUBKEY_2048_ASN1_SIZE;
|
file->size = PUBKEY_2048_ASN1_SIZE;
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "Not supported public key size: %i\n", file->size);
|
sc_debug(card->ctx, "Not supported public key size: %i\n", file->size);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -621,7 +621,7 @@ auth_delete_file(struct sc_card *card, const struct sc_path *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path->len < 2) {
|
if (path->len < 2) {
|
||||||
sc_error(card->ctx, "Invalid path length\n");
|
sc_debug(card->ctx, "Invalid path length\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +782,7 @@ encode_file_structure_V5(struct sc_card *card, const struct sc_file *file,
|
||||||
rv = SC_ERROR_INVALID_ARGUMENTS;
|
rv = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (rv) {
|
if (rv) {
|
||||||
sc_error(card->ctx, "Invalid EF structure %i/%i\n",
|
sc_debug(card->ctx, "Invalid EF structure %i/%i\n",
|
||||||
file->type, file->ef_structure);
|
file->type, file->ef_structure);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
@ -810,7 +810,7 @@ encode_file_structure_V5(struct sc_card *card, const struct sc_file *file,
|
||||||
else if (file->size == PUBKEY_2048_ASN1_SIZE || file->size == 2048)
|
else if (file->size == PUBKEY_2048_ASN1_SIZE || file->size == 2048)
|
||||||
size = 2048;
|
size = 2048;
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "incorrect RSA size %X\n", file->size);
|
sc_debug(card->ctx, "incorrect RSA size %X\n", file->size);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,7 +823,7 @@ encode_file_structure_V5(struct sc_card *card, const struct sc_file *file,
|
||||||
else if (file->size == 24 || file->size == 192)
|
else if (file->size == 24 || file->size == 192)
|
||||||
size = 192;
|
size = 192;
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "incorrect DES size %X\n", file->size);
|
sc_debug(card->ctx, "incorrect DES size %X\n", file->size);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCORRECT_PARAMETERS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -936,7 +936,7 @@ auth_create_file(struct sc_card *card, struct sc_file *file)
|
||||||
path.len -= 2;
|
path.len -= 2;
|
||||||
|
|
||||||
if (auth_select_file(card, &path, NULL)) {
|
if (auth_select_file(card, &path, NULL)) {
|
||||||
sc_error(card->ctx, "Cannot select parent DF.\n");
|
sc_debug(card->ctx, "Cannot select parent DF.\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1021,7 @@ auth_set_security_env(struct sc_card *card,
|
||||||
apdu.datalen = 3;
|
apdu.datalen = 3;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "Invalid crypto operation: %X\n", env->operation);
|
sc_debug(card->ctx, "Invalid crypto operation: %X\n", env->operation);
|
||||||
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Invalid crypto operation");
|
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Invalid crypto operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,7 +1033,7 @@ auth_set_security_env(struct sc_card *card,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pads & (~supported_pads)) {
|
if (pads & (~supported_pads)) {
|
||||||
sc_error(card->ctx, "No support for PAD %X\n",pads);
|
sc_debug(card->ctx, "No support for PAD %X\n",pads);
|
||||||
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "No padding support.");
|
SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "No padding support.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,7 +1054,7 @@ auth_set_security_env(struct sc_card *card,
|
||||||
apdu.data = rsa_sbuf;
|
apdu.data = rsa_sbuf;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sc_error(card->ctx, "Invalid crypto operation: %X\n", env->operation);
|
sc_debug(card->ctx, "Invalid crypto operation: %X\n", env->operation);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,7 +1095,7 @@ auth_compute_signature(struct sc_card *card, const unsigned char *in, size_t ile
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
else if (ilen > 96) {
|
else if (ilen > 96) {
|
||||||
sc_error(card->ctx, "Illegal input length %d\n", ilen);
|
sc_debug(card->ctx, "Illegal input length %d\n", ilen);
|
||||||
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Illegal input length");
|
SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Illegal input length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,7 +1113,7 @@ auth_compute_signature(struct sc_card *card, const unsigned char *in, size_t ile
|
||||||
SC_TEST_RET(card->ctx, rv, "Compute signature failed");
|
SC_TEST_RET(card->ctx, rv, "Compute signature failed");
|
||||||
|
|
||||||
if (apdu.resplen > olen) {
|
if (apdu.resplen > olen) {
|
||||||
sc_error(card->ctx, "Compute signature failed: invalide response length %i\n",
|
sc_debug(card->ctx, "Compute signature failed: invalide response length %i\n",
|
||||||
apdu.resplen);
|
apdu.resplen);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_CARD_CMD_FAILED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_CARD_CMD_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -1342,7 +1342,7 @@ auth_update_component(struct sc_card *card, struct auth_update_component_info *a
|
||||||
EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, args->data, NULL);
|
EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, args->data, NULL);
|
||||||
rv = EVP_EncryptUpdate(&ctx, out, &outl, in, 8);
|
rv = EVP_EncryptUpdate(&ctx, out, &outl, in, 8);
|
||||||
if (!EVP_CIPHER_CTX_cleanup(&ctx) || rv == 0) {
|
if (!EVP_CIPHER_CTX_cleanup(&ctx) || rv == 0) {
|
||||||
sc_error(card->ctx, "OpenSSL encryption error.");
|
sc_debug(card->ctx, "OpenSSL encryption error.");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1359,6 @@ auth_update_component(struct sc_card *card, struct auth_update_component_info *a
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.datalen = len;
|
apdu.datalen = len;
|
||||||
apdu.lc = len;
|
apdu.lc = len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
if (args->len == 0x100) {
|
if (args->len == 0x100) {
|
||||||
sbuf[0] = args->type;
|
sbuf[0] = args->type;
|
||||||
sbuf[1] = 0x20;
|
sbuf[1] = 0x20;
|
||||||
|
@ -1617,9 +1616,7 @@ auth_is_verified(struct sc_card *card, int pin_reference, int *tries_left)
|
||||||
apdu.sw2 = 0x83;
|
apdu.sw2 = 0x83;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -1719,7 +1716,6 @@ auth_create_reference_data (struct sc_card *card,
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.datalen = len;
|
apdu.datalen = len;
|
||||||
apdu.lc = len;
|
apdu.lc = len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
rv = sc_transmit_apdu(card, &apdu);
|
rv = sc_transmit_apdu(card, &apdu);
|
||||||
sc_mem_clear(sbuf, sizeof(sbuf));
|
sc_mem_clear(sbuf, sizeof(sbuf));
|
||||||
|
|
|
@ -235,9 +235,7 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
|
||||||
if (blob->info == NULL)
|
if (blob->info == NULL)
|
||||||
return blob->status;
|
return blob->status;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = blob->info->get_fn(card, blob->id, buffer, sizeof(buffer));
|
r = blob->info->get_fn(card, blob->id, buffer, sizeof(buffer));
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
blob->status = r;
|
blob->status = r;
|
||||||
|
@ -308,7 +306,7 @@ pgp_enumerate_blob(sc_card_t *card, struct blob *blob)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
eoc: sc_error(card->ctx, "Unexpected end of contents\n");
|
eoc: sc_debug(card->ctx, "Unexpected end of contents\n");
|
||||||
return SC_ERROR_OBJECT_NOT_VALID;
|
return SC_ERROR_OBJECT_NOT_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +554,7 @@ pgp_set_security_env(sc_card_t *card,
|
||||||
case SC_SEC_OPERATION_SIGN:
|
case SC_SEC_OPERATION_SIGN:
|
||||||
if (env->key_ref[0] != 0x00
|
if (env->key_ref[0] != 0x00
|
||||||
&& env->key_ref[0] != 0x02) {
|
&& env->key_ref[0] != 0x02) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Key reference not compatible with "
|
"Key reference not compatible with "
|
||||||
"requested usage\n");
|
"requested usage\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
@ -564,7 +562,7 @@ pgp_set_security_env(sc_card_t *card,
|
||||||
break;
|
break;
|
||||||
case SC_SEC_OPERATION_DECIPHER:
|
case SC_SEC_OPERATION_DECIPHER:
|
||||||
if (env->key_ref[0] != 0x01) {
|
if (env->key_ref[0] != 0x01) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Key reference not compatible with "
|
"Key reference not compatible with "
|
||||||
"requested usage\n");
|
"requested usage\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
@ -602,11 +600,11 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
|
||||||
0x88, 0, 0);
|
0x88, 0, 0);
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Invalid key reference (decipher only key)\n");
|
"Invalid key reference (decipher only key)\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid key reference 0x%02x\n",
|
sc_debug(card->ctx, "Invalid key reference 0x%02x\n",
|
||||||
env->key_ref[0]);
|
env->key_ref[0]);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -658,12 +656,12 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
|
||||||
break;
|
break;
|
||||||
case 0x00: /* signature key */
|
case 0x00: /* signature key */
|
||||||
case 0x02: /* authentication key */
|
case 0x02: /* authentication key */
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Invalid key reference (signature only key)\n");
|
"Invalid key reference (signature only key)\n");
|
||||||
free(temp);
|
free(temp);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Invalid key reference 0x%02x\n",
|
sc_debug(card->ctx, "Invalid key reference 0x%02x\n",
|
||||||
env->key_ref[0]);
|
env->key_ref[0]);
|
||||||
free(temp);
|
free(temp);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
|
@ -581,7 +581,6 @@ static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file)
|
||||||
static int piv_get_data(sc_card_t * card, int enumtag,
|
static int piv_get_data(sc_card_t * card, int enumtag,
|
||||||
u8 **buf, size_t *buf_len)
|
u8 **buf, size_t *buf_len)
|
||||||
{
|
{
|
||||||
piv_private_data_t * priv = PIV_DATA(card);
|
|
||||||
u8 *p;
|
u8 *p;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
u8 tagbuf[8];
|
u8 tagbuf[8];
|
||||||
|
@ -853,7 +852,7 @@ static int piv_cache_internal_data(sc_card_t *card, int enumtag)
|
||||||
priv->obj_cache[enumtag].internal_obj_data = newBuf;
|
priv->obj_cache[enumtag].internal_obj_data = newBuf;
|
||||||
priv->obj_cache[enumtag].internal_obj_len = len;
|
priv->obj_cache[enumtag].internal_obj_len = len;
|
||||||
#else
|
#else
|
||||||
sc_error(card->ctx,"PIV compression not supported, no zlib");
|
sc_debug(card->ctx,"PIV compression not supported, no zlib");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
@ -1690,9 +1689,7 @@ static int piv_select_file(sc_card_t *card, const sc_path_t *in_path,
|
||||||
|
|
||||||
if (file_out) {
|
if (file_out) {
|
||||||
/* we need to read it now, to get length into cache */
|
/* we need to read it now, to get length into cache */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = piv_get_cached_data(card, i, &rbuf, &rbuflen);
|
r = piv_get_cached_data(card, i, &rbuf, &rbuflen);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_NOT_FOUND);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_NOT_FOUND);
|
||||||
|
@ -1749,7 +1746,6 @@ sc_debug(card->ctx,"DEE freeing #%d, %p:%d %p:%d", i,
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
/* TODO temp see piv_init */
|
/* TODO temp see piv_init */
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1764,9 +1760,7 @@ static int piv_match_card(sc_card_t *card)
|
||||||
card->ops->logout = NULL;
|
card->ops->logout = NULL;
|
||||||
|
|
||||||
/* Detect by selecting applet */
|
/* Detect by selecting applet */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
i = !(piv_find_aid(card, &aidfile));
|
i = !(piv_find_aid(card, &aidfile));
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
return i; /* never match */
|
return i; /* never match */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1799,7 +1793,7 @@ static int piv_init(sc_card_t *card)
|
||||||
|
|
||||||
r = piv_find_aid(card, priv->aid_file);
|
r = piv_find_aid(card, priv->aid_file);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "Failed to initialize %s\n", card->name);
|
sc_debug(card->ctx, "Failed to initialize %s\n", card->name);
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
priv->enumtag = piv_aids[r].enumtag;
|
priv->enumtag = piv_aids[r].enumtag;
|
||||||
|
@ -1815,7 +1809,6 @@ static int piv_init(sc_card_t *card)
|
||||||
|
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
r = 0;
|
r = 0;
|
||||||
sc_ctx_suppress_errors_on(card->ctx); /*TODO temp to suppresss all error */
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, r);
|
SC_FUNC_RETURN(card->ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,6 @@ static int rtecp_verify(sc_card_t *card, unsigned int type, int ref_qualifier,
|
||||||
apdu.lc = data_len;
|
apdu.lc = data_len;
|
||||||
apdu.data = data;
|
apdu.data = data;
|
||||||
apdu.datalen = data_len;
|
apdu.datalen = data_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (send_logout++ == 0 && apdu.sw1 == 0x6F && apdu.sw2 == 0x86)
|
if (send_logout++ == 0 && apdu.sw1 == 0x6F && apdu.sw2 == 0x86)
|
||||||
|
@ -411,7 +410,6 @@ static int rtecp_cipher(sc_card_t *card, const u8 *data, size_t data_len,
|
||||||
apdu.lc = data_len;
|
apdu.lc = data_len;
|
||||||
apdu.data = buf;
|
apdu.data = buf;
|
||||||
apdu.datalen = data_len;
|
apdu.datalen = data_len;
|
||||||
apdu.sensitive = 1;
|
|
||||||
apdu.resp = buf_out;
|
apdu.resp = buf_out;
|
||||||
apdu.resplen = out_len + 2;
|
apdu.resplen = out_len + 2;
|
||||||
apdu.le = out_len;
|
apdu.le = out_len;
|
||||||
|
@ -426,7 +424,7 @@ static int rtecp_cipher(sc_card_t *card, const u8 *data, size_t data_len,
|
||||||
assert(buf);
|
assert(buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
if (r)
|
if (r)
|
||||||
sc_error(card->ctx, "APDU transmit failed: %s\n", sc_strerror(r));
|
sc_debug(card->ctx, "APDU transmit failed: %s\n", sc_strerror(r));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
|
||||||
|
@ -521,7 +519,6 @@ static int rtecp_change_reference_data(sc_card_t *card, unsigned int type,
|
||||||
apdu.lc = p - buf;
|
apdu.lc = p - buf;
|
||||||
apdu.data = buf;
|
apdu.data = buf;
|
||||||
apdu.datalen = p - buf;
|
apdu.datalen = p - buf;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_mem_clear(buf, sizeof(buf));
|
sc_mem_clear(buf, sizeof(buf));
|
||||||
|
@ -662,7 +659,7 @@ static int rtecp_card_ctl(sc_card_t *card, unsigned long request, void *data)
|
||||||
if (card->ctx->debug >= 4)
|
if (card->ctx->debug >= 4)
|
||||||
sc_debug(card->ctx, "%s\n",
|
sc_debug(card->ctx, "%s\n",
|
||||||
"SC_CARDCTL_LIFECYCLE_SET not supported");
|
"SC_CARDCTL_LIFECYCLE_SET not supported");
|
||||||
/* no call sc_error (SC_FUNC_RETURN) */
|
/* no call sc_debug (SC_FUNC_RETURN) */
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
default:
|
default:
|
||||||
if (card->ctx->debug >= 3)
|
if (card->ctx->debug >= 3)
|
||||||
|
@ -788,7 +785,6 @@ struct sc_card_driver * sc_get_rtecp_driver(void)
|
||||||
|
|
||||||
rtecp_ops.match_card = rtecp_match_card;
|
rtecp_ops.match_card = rtecp_match_card;
|
||||||
rtecp_ops.init = rtecp_init;
|
rtecp_ops.init = rtecp_init;
|
||||||
rtecp_ops.finish = NULL;
|
|
||||||
/* read_binary */
|
/* read_binary */
|
||||||
rtecp_ops.write_binary = NULL;
|
rtecp_ops.write_binary = NULL;
|
||||||
/* update_binary */
|
/* update_binary */
|
||||||
|
|
|
@ -234,12 +234,12 @@ static int rutoken_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
|
||||||
for (i = 0; i < sizeof(rutoken_errors)/sizeof(rutoken_errors[0]); ++i) {
|
for (i = 0; i < sizeof(rutoken_errors)/sizeof(rutoken_errors[0]); ++i) {
|
||||||
if (rutoken_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
if (rutoken_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
||||||
if ( rutoken_errors[i].errorstr )
|
if ( rutoken_errors[i].errorstr )
|
||||||
sc_error(card->ctx, "%s\n", rutoken_errors[i].errorstr);
|
sc_debug(card->ctx, "%s\n", rutoken_errors[i].errorstr);
|
||||||
sc_debug(card->ctx, "sw1 = %x, sw2 = %x", sw1, sw2);
|
sc_debug(card->ctx, "sw1 = %x, sw2 = %x", sw1, sw2);
|
||||||
return rutoken_errors[i].errorno;
|
return rutoken_errors[i].errorno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
sc_debug(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
||||||
return SC_ERROR_CARD_CMD_FAILED;
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +603,7 @@ static int rutoken_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (!path || path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2))
|
if (!path || path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2))
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
if (path->len == sizeof(sbuf))
|
if (path->len == sizeof(sbuf))
|
||||||
|
@ -722,7 +722,7 @@ static int rutoken_reset_retry_counter(sc_card_t *card, unsigned int type,
|
||||||
if (puk && puklen)
|
if (puk && puklen)
|
||||||
{
|
{
|
||||||
ret = rutoken_verify(card, type, ref_qualifier, puk, puklen, &left);
|
ret = rutoken_verify(card, type, ref_qualifier, puk, puklen, &left);
|
||||||
sc_error(card->ctx, "Tries left: %i\n", left);
|
sc_debug(card->ctx, "Tries left: %i\n", left);
|
||||||
SC_TEST_RET(card->ctx, ret, "Invalid 'puk' pass");
|
SC_TEST_RET(card->ctx, ret, "Invalid 'puk' pass");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -770,7 +770,7 @@ static int rutoken_set_security_env(sc_card_t *card,
|
||||||
senv->algorithm = SC_ALGORITHM_GOST;
|
senv->algorithm = SC_ALGORITHM_GOST;
|
||||||
if (env->key_ref_len != 1)
|
if (env->key_ref_len != 1)
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "No or invalid key reference\n");
|
sc_debug(card->ctx, "No or invalid key reference\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
data[2] = env->key_ref[0];
|
data[2] = env->key_ref[0];
|
||||||
|
@ -1308,7 +1308,7 @@ static int cipher_ext(sc_card_t *card, const u8 *data, size_t len,
|
||||||
ret = SC_ERROR_INTERNAL;
|
ret = SC_ERROR_INTERNAL;
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
ERR_error_string(ERR_get_error(), error);
|
ERR_error_string(ERR_get_error(), error);
|
||||||
sc_error(card->ctx, error);
|
sc_debug(card->ctx, error);
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1504,7 +1504,7 @@ static int rutoken_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
|
||||||
case SC_CARDCTL_LIFECYCLE_SET:
|
case SC_CARDCTL_LIFECYCLE_SET:
|
||||||
sc_debug(card->ctx, "SC_CARDCTL_LIFECYCLE_SET not supported");
|
sc_debug(card->ctx, "SC_CARDCTL_LIFECYCLE_SET not supported");
|
||||||
sc_debug(card->ctx, "returning SC_ERROR_NOT_SUPPORTED");
|
sc_debug(card->ctx, "returning SC_ERROR_NOT_SUPPORTED");
|
||||||
/* no call sc_error (SC_FUNC_RETURN) */
|
/* no call sc_debug (SC_FUNC_RETURN) */
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,11 +70,6 @@ static struct sc_card_driver setcos_drv = {
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int setcos_finish(sc_card_t *card)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int match_hist_bytes(sc_card_t *card, const char *str, size_t len)
|
static int match_hist_bytes(sc_card_t *card, const char *str, size_t len)
|
||||||
{
|
{
|
||||||
const char *src = (const char *) card->slot->atr_info.hist_bytes;
|
const char *src = (const char *) card->slot->atr_info.hist_bytes;
|
||||||
|
@ -145,9 +140,7 @@ static int select_pkcs15_app(sc_card_t * card)
|
||||||
/* Regular PKCS#15 AID */
|
/* Regular PKCS#15 AID */
|
||||||
sc_format_path("A000000063504B43532D3135", &app);
|
sc_format_path("A000000063504B43532D3135", &app);
|
||||||
app.type = SC_PATH_TYPE_DF_NAME;
|
app.type = SC_PATH_TYPE_DF_NAME;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &app, NULL);
|
r = sc_select_file(card, &app, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +467,7 @@ static int setcos_create_file_44(sc_card_t *card, sc_file_t *file)
|
||||||
break;
|
break;
|
||||||
case SC_AC_CHV: /* pin */
|
case SC_AC_CHV: /* pin */
|
||||||
if ((bNumber & 0x7F) == 0 || (bNumber & 0x7F) > 7) {
|
if ((bNumber & 0x7F) == 0 || (bNumber & 0x7F) > 7) {
|
||||||
sc_error(card->ctx, "SetCOS 4.4 PIN refs can only be 1..7\n");
|
sc_debug(card->ctx, "SetCOS 4.4 PIN refs can only be 1..7\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
bCommands_pin[setcos_pin_index_44(pins, sizeof(pins), (int) bNumber)] |= 1 << i;
|
bCommands_pin[setcos_pin_index_44(pins, sizeof(pins), (int) bNumber)] |= 1 << i;
|
||||||
|
@ -577,11 +570,11 @@ static int setcos_set_security_env2(sc_card_t *card,
|
||||||
card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
|
card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
|
||||||
SETCOS_IS_EID_APPLET(card)) {
|
SETCOS_IS_EID_APPLET(card)) {
|
||||||
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) {
|
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) {
|
||||||
sc_error(card->ctx, "asymmetric keyref not supported.\n");
|
sc_debug(card->ctx, "asymmetric keyref not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (se_num > 0) {
|
if (se_num > 0) {
|
||||||
sc_error(card->ctx, "restore security environment not supported.\n");
|
sc_debug(card->ctx, "restore security environment not supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,7 +664,7 @@ static int setcos_set_security_env(sc_card_t *card,
|
||||||
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
|
||||||
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||||
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
if (tmp.algorithm != SC_ALGORITHM_RSA) {
|
||||||
sc_error(card->ctx, "Only RSA algorithm supported.\n");
|
sc_debug(card->ctx, "Only RSA algorithm supported.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
switch (card->type) {
|
switch (card->type) {
|
||||||
|
@ -684,7 +677,7 @@ static int setcos_set_security_env(sc_card_t *card,
|
||||||
case SC_CARD_TYPE_SETCOS_EID_V2_1:
|
case SC_CARD_TYPE_SETCOS_EID_V2_1:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Card does not support RSA.\n");
|
sc_debug(card->ctx, "Card does not support RSA.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +1115,6 @@ static struct sc_card_driver *sc_get_driver(void)
|
||||||
setcos_ops = *iso_drv->ops;
|
setcos_ops = *iso_drv->ops;
|
||||||
setcos_ops.match_card = setcos_match_card;
|
setcos_ops.match_card = setcos_match_card;
|
||||||
setcos_ops.init = setcos_init;
|
setcos_ops.init = setcos_init;
|
||||||
setcos_ops.finish = setcos_finish;
|
|
||||||
if (iso_ops == NULL)
|
if (iso_ops == NULL)
|
||||||
iso_ops = iso_drv->ops;
|
iso_ops = iso_drv->ops;
|
||||||
setcos_ops.create_file = setcos_create_file;
|
setcos_ops.create_file = setcos_create_file;
|
||||||
|
|
|
@ -1101,11 +1101,9 @@ static int starcos_set_security_env(sc_card_t *card,
|
||||||
apdu.datalen = p - sbuf;
|
apdu.datalen = p - sbuf;
|
||||||
apdu.lc = p - sbuf;
|
apdu.lc = p - sbuf;
|
||||||
apdu.le = 0;
|
apdu.le = 0;
|
||||||
/* suppress errors, as don't know whether to use
|
/* we don't know whether to use
|
||||||
* COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
|
* COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
ex_data->fix_digestInfo = 0;
|
ex_data->fix_digestInfo = 0;
|
||||||
|
@ -1183,7 +1181,6 @@ static int starcos_compute_signature(sc_card_t *card,
|
||||||
|
|
||||||
apdu.lc = 0;
|
apdu.lc = 0;
|
||||||
apdu.datalen = 0;
|
apdu.datalen = 0;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
@ -1246,7 +1243,7 @@ static int starcos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
|
||||||
return SC_NO_ERROR;
|
return SC_NO_ERROR;
|
||||||
if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
|
if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "Verification failed (remaining tries: %d)\n",
|
sc_debug(card->ctx, "Verification failed (remaining tries: %d)\n",
|
||||||
(sw2 & 0x0f));
|
(sw2 & 0x0f));
|
||||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||||
}
|
}
|
||||||
|
@ -1255,7 +1252,7 @@ static int starcos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
|
||||||
for (i = 0; i < err_count; i++)
|
for (i = 0; i < err_count; i++)
|
||||||
if (starcos_errors[i].SWs == ((sw1 << 8) | sw2))
|
if (starcos_errors[i].SWs == ((sw1 << 8) | sw2))
|
||||||
{
|
{
|
||||||
sc_error(card->ctx, "%s\n", starcos_errors[i].errorstr);
|
sc_debug(card->ctx, "%s\n", starcos_errors[i].errorstr);
|
||||||
return starcos_errors[i].errorno;
|
return starcos_errors[i].errorno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1340,9 +1337,7 @@ static int starcos_logout(sc_card_t *card)
|
||||||
apdu.datalen = 2;
|
apdu.datalen = 2;
|
||||||
apdu.resplen = 0;
|
apdu.resplen = 0;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");
|
||||||
|
|
||||||
if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
|
if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
|
||||||
|
|
|
@ -484,7 +484,7 @@ static int tcos_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
sbuf[0] = path->value[0];
|
sbuf[0] = path->value[0];
|
||||||
|
@ -575,7 +575,7 @@ static int tcos_compute_signature(sc_card_t *card, const u8 * data, size_t datal
|
||||||
|
|
||||||
if(((tcos_data *)card->drv_data)->next_sign){
|
if(((tcos_data *)card->drv_data)->next_sign){
|
||||||
if(datalen>48){
|
if(datalen>48){
|
||||||
sc_error(card->ctx, "Data to be signed is too long (TCOS supports max. 48 bytes)\n");
|
sc_debug(card->ctx, "Data to be signed is too long (TCOS supports max. 48 bytes)\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
|
||||||
|
|
|
@ -185,14 +185,10 @@ static int westcos_match_card(sc_card_t * card)
|
||||||
apdu.lc = sizeof(aid);
|
apdu.lc = sizeof(aid);
|
||||||
apdu.datalen = sizeof(aid);
|
apdu.datalen = sizeof(aid);
|
||||||
apdu.data = aid;
|
apdu.data = aid;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r)
|
if (r)
|
||||||
return 0;
|
return 0;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r)
|
if (r)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -782,7 +778,6 @@ static int westcos_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data *data,
|
||||||
apdu.datalen = len;
|
apdu.datalen = len;
|
||||||
apdu.data = buf;
|
apdu.data = buf;
|
||||||
apdu.resplen = 0;
|
apdu.resplen = 0;
|
||||||
apdu.sensitive = 1;
|
|
||||||
if (!use_pin_pad) {
|
if (!use_pin_pad) {
|
||||||
|
|
||||||
/* Transmit the APDU to the card */
|
/* Transmit the APDU to the card */
|
||||||
|
|
|
@ -90,7 +90,7 @@ static void sc_card_free(sc_card_t *card)
|
||||||
if (card->mutex != NULL) {
|
if (card->mutex != NULL) {
|
||||||
int r = sc_mutex_destroy(card->ctx, card->mutex);
|
int r = sc_mutex_destroy(card->ctx, card->mutex);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
sc_error(card->ctx, "unable to destroy mutex\n");
|
sc_debug(card->ctx, "unable to destroy mutex\n");
|
||||||
}
|
}
|
||||||
sc_mem_clear(card, sizeof(*card));
|
sc_mem_clear(card, sizeof(*card));
|
||||||
free(card);
|
free(card);
|
||||||
|
@ -172,7 +172,7 @@ int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card_out)
|
||||||
if (card->ops->init != NULL) {
|
if (card->ops->init != NULL) {
|
||||||
r = card->ops->init(card);
|
r = card->ops->init(card);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "driver '%s' init() failed: %s\n", card->driver->name,
|
sc_debug(ctx, "driver '%s' init() failed: %s\n", card->driver->name,
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card_out)
|
||||||
card->driver = drv;
|
card->driver = drv;
|
||||||
r = ops->init(card);
|
r = ops->init(card);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "driver '%s' init() failed: %s\n", drv->name,
|
sc_debug(ctx, "driver '%s' init() failed: %s\n", drv->name,
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
if (r == SC_ERROR_INVALID_CARD) {
|
if (r == SC_ERROR_INVALID_CARD) {
|
||||||
card->driver = NULL;
|
card->driver = NULL;
|
||||||
|
@ -210,7 +210,7 @@ int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card_out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (card->driver == NULL) {
|
if (card->driver == NULL) {
|
||||||
sc_error(ctx, "unable to find driver for inserted card\n");
|
sc_debug(ctx, "unable to find driver for inserted card\n");
|
||||||
r = SC_ERROR_INVALID_CARD;
|
r = SC_ERROR_INVALID_CARD;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -238,13 +238,13 @@ int sc_disconnect_card(sc_card_t *card, int action)
|
||||||
if (card->ops->finish) {
|
if (card->ops->finish) {
|
||||||
int r = card->ops->finish(card);
|
int r = card->ops->finish(card);
|
||||||
if (r)
|
if (r)
|
||||||
sc_error(card->ctx, "card driver finish() failed: %s\n",
|
sc_debug(card->ctx, "card driver finish() failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
}
|
}
|
||||||
if (card->reader->ops->disconnect) {
|
if (card->reader->ops->disconnect) {
|
||||||
int r = card->reader->ops->disconnect(card->reader, card->slot);
|
int r = card->reader->ops->disconnect(card->reader, card->slot);
|
||||||
if (r)
|
if (r)
|
||||||
sc_error(card->ctx, "disconnect() failed: %s\n",
|
sc_debug(card->ctx, "disconnect() failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
}
|
}
|
||||||
sc_card_free(card);
|
sc_card_free(card);
|
||||||
|
@ -271,7 +271,7 @@ int sc_reset(sc_card_t *card)
|
||||||
|
|
||||||
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
||||||
if (r2 != SC_SUCCESS) {
|
if (r2 != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to release lock\n");
|
sc_debug(card->ctx, "unable to release lock\n");
|
||||||
r = r != SC_SUCCESS ? r : r2;
|
r = r != SC_SUCCESS ? r : r2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +290,15 @@ int sc_lock(sc_card_t *card)
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
if (card->lock_count == 0) {
|
if (card->lock_count == 0) {
|
||||||
if (card->reader->ops->lock != NULL)
|
if (card->reader->ops->lock != NULL) {
|
||||||
r = card->reader->ops->lock(card->reader, card->slot);
|
r = card->reader->ops->lock(card->reader, card->slot);
|
||||||
|
if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) {
|
||||||
|
/* invalidate cache */
|
||||||
|
memset(&card->cache, 0, sizeof(card->cache));
|
||||||
|
card->cache_valid = 0;
|
||||||
|
r = card->reader->ops->lock(card->reader, card->slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
card->cache_valid = 1;
|
card->cache_valid = 1;
|
||||||
}
|
}
|
||||||
|
@ -299,7 +306,7 @@ int sc_lock(sc_card_t *card)
|
||||||
card->lock_count++;
|
card->lock_count++;
|
||||||
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
||||||
if (r2 != SC_SUCCESS) {
|
if (r2 != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to release lock\n");
|
sc_debug(card->ctx, "unable to release lock\n");
|
||||||
r = r != SC_SUCCESS ? r : r2;
|
r = r != SC_SUCCESS ? r : r2;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -327,7 +334,7 @@ int sc_unlock(sc_card_t *card)
|
||||||
}
|
}
|
||||||
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
r2 = sc_mutex_unlock(card->ctx, card->mutex);
|
||||||
if (r2 != SC_SUCCESS) {
|
if (r2 != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to release lock\n");
|
sc_debug(card->ctx, "unable to release lock\n");
|
||||||
r = (r == SC_SUCCESS) ? r2 : r;
|
r = (r == SC_SUCCESS) ? r2 : r;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -774,7 +781,7 @@ static int match_atr_table(sc_context_t *ctx, struct sc_atr_table *table, u8 *at
|
||||||
mbin_len = sizeof(mbin);
|
mbin_len = sizeof(mbin);
|
||||||
sc_hex_to_bin(matr, mbin, &mbin_len);
|
sc_hex_to_bin(matr, mbin, &mbin_len);
|
||||||
if (mbin_len != fix_bin_len) {
|
if (mbin_len != fix_bin_len) {
|
||||||
sc_error(ctx,"length of atr and atr mask do not match - ignored: %s - %s", tatr, matr);
|
sc_debug(ctx,"length of atr and atr mask do not match - ignored: %s - %s", tatr, matr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (s = 0; s < tbin_len; s++) {
|
for (s = 0; s < tbin_len; s++) {
|
||||||
|
|
|
@ -44,6 +44,7 @@ enum {
|
||||||
SC_CARD_TYPE_CARDOS_M4_3,
|
SC_CARD_TYPE_CARDOS_M4_3,
|
||||||
SC_CARD_TYPE_CARDOS_M4_2B, /* 4.2b is after 4.3b */
|
SC_CARD_TYPE_CARDOS_M4_2B, /* 4.2b is after 4.3b */
|
||||||
SC_CARD_TYPE_CARDOS_M4_2C,
|
SC_CARD_TYPE_CARDOS_M4_2C,
|
||||||
|
SC_CARD_TYPE_CARDOS_CIE_V1, /* Italian CIE (eID) v1 */
|
||||||
|
|
||||||
/* flex/cyberflex drivers */
|
/* flex/cyberflex drivers */
|
||||||
SC_CARD_TYPE_FLEX_BASE = 2000,
|
SC_CARD_TYPE_FLEX_BASE = 2000,
|
||||||
|
@ -150,6 +151,15 @@ enum {
|
||||||
/* MyEID cards */
|
/* MyEID cards */
|
||||||
SC_CARD_TYPE_MYEID_BASE = 20000,
|
SC_CARD_TYPE_MYEID_BASE = 20000,
|
||||||
SC_CARD_TYPE_MYEID_GENERIC,
|
SC_CARD_TYPE_MYEID_GENERIC,
|
||||||
|
|
||||||
|
/* GemsafeV1 cards */
|
||||||
|
SC_CARD_TYPE_GEMSAFEV1_BASE = 21000,
|
||||||
|
SC_CARD_TYPE_GEMSAFEV1_GENERIC,
|
||||||
|
SC_CARD_TYPE_GEMSAFEV1_PTEID,
|
||||||
|
|
||||||
|
/* IAS cards */
|
||||||
|
SC_CARD_TYPE_IAS_BASE = 22000,
|
||||||
|
SC_CARD_TYPE_IAS_PTEID,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern sc_card_driver_t *sc_get_default_driver(void);
|
extern sc_card_driver_t *sc_get_default_driver(void);
|
||||||
|
@ -180,6 +190,7 @@ extern sc_card_driver_t *sc_get_rutoken_driver(void);
|
||||||
extern sc_card_driver_t *sc_get_rtecp_driver(void);
|
extern sc_card_driver_t *sc_get_rtecp_driver(void);
|
||||||
extern sc_card_driver_t *sc_get_westcos_driver(void);
|
extern sc_card_driver_t *sc_get_westcos_driver(void);
|
||||||
extern sc_card_driver_t *sc_get_myeid_driver(void);
|
extern sc_card_driver_t *sc_get_myeid_driver(void);
|
||||||
|
extern sc_card_driver_t *sc_get_ias_driver(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ ctbcs_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
r = ctbcs_build_modify_verification_apdu(&apdu, data, slot);
|
r = ctbcs_build_modify_verification_apdu(&apdu, data, slot);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(reader->ctx, "Unknown PIN command %d", data->cmd);
|
sc_debug(reader->ctx, "Unknown PIN command %d", data->cmd);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ ctbcs_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
s = sc_mutex_destroy(reader->ctx, card->mutex);
|
s = sc_mutex_destroy(reader->ctx, card->mutex);
|
||||||
if (s != SC_SUCCESS) {
|
if (s != SC_SUCCESS) {
|
||||||
sc_error(reader->ctx, "unable to destroy mutex\n");
|
sc_debug(reader->ctx, "unable to destroy mutex\n");
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
|
|
|
@ -71,6 +71,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
||||||
{ "oberthur", (void *(*)(void)) sc_get_oberthur_driver },
|
{ "oberthur", (void *(*)(void)) sc_get_oberthur_driver },
|
||||||
#endif
|
#endif
|
||||||
{ "belpic", (void *(*)(void)) sc_get_belpic_driver },
|
{ "belpic", (void *(*)(void)) sc_get_belpic_driver },
|
||||||
|
{ "ias", (void *(*)(void)) sc_get_ias_driver },
|
||||||
{ "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
|
{ "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
|
||||||
{ "muscle", (void *(*)(void)) sc_get_muscle_driver },
|
{ "muscle", (void *(*)(void)) sc_get_muscle_driver },
|
||||||
{ "incrypto34", (void *(*)(void)) sc_get_incrypto34_driver },
|
{ "incrypto34", (void *(*)(void)) sc_get_incrypto34_driver },
|
||||||
|
@ -86,8 +87,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
||||||
{ "rutoken_ecp",(void *(*)(void)) sc_get_rtecp_driver },
|
{ "rutoken_ecp",(void *(*)(void)) sc_get_rtecp_driver },
|
||||||
{ "westcos", (void *(*)(void)) sc_get_westcos_driver },
|
{ "westcos", (void *(*)(void)) sc_get_westcos_driver },
|
||||||
{ "myeid", (void *(*)(void)) sc_get_myeid_driver },
|
{ "myeid", (void *(*)(void)) sc_get_myeid_driver },
|
||||||
/* emv is not really used, not sure if it works, but it conflicts with
|
/* emv is not really implemented */
|
||||||
muscle and rutoken driver, thus has to be after them */
|
|
||||||
{ "emv", (void *(*)(void)) sc_get_emv_driver },
|
{ "emv", (void *(*)(void)) sc_get_emv_driver },
|
||||||
/* The default driver should be last, as it handles all the
|
/* The default driver should be last, as it handles all the
|
||||||
* unrecognized cards. */
|
* unrecognized cards. */
|
||||||
|
@ -177,13 +177,9 @@ static void add_internal_drvs(struct _sc_ctx_options *opts, int type)
|
||||||
static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
||||||
{
|
{
|
||||||
ctx->debug = 0;
|
ctx->debug = 0;
|
||||||
if (ctx->debug_file && ctx->debug_file != stdout)
|
if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
|
||||||
fclose(ctx->debug_file);
|
fclose(ctx->debug_file);
|
||||||
ctx->debug_file = stdout;
|
ctx->debug_file = stderr;
|
||||||
ctx->suppress_errors = 0;
|
|
||||||
if (ctx->error_file && ctx->error_file != stderr)
|
|
||||||
fclose(ctx->error_file);
|
|
||||||
ctx->error_file = stderr;
|
|
||||||
ctx->forced_driver = NULL;
|
ctx->forced_driver = NULL;
|
||||||
add_internal_drvs(opts, 0);
|
add_internal_drvs(opts, 0);
|
||||||
add_internal_drvs(opts, 1);
|
add_internal_drvs(opts, 1);
|
||||||
|
@ -204,21 +200,14 @@ static int load_parameters(sc_context_t *ctx, scconf_block *block,
|
||||||
|
|
||||||
val = scconf_get_str(block, "debug_file", NULL);
|
val = scconf_get_str(block, "debug_file", NULL);
|
||||||
if (val) {
|
if (val) {
|
||||||
if (ctx->debug_file && ctx->debug_file != stdout)
|
if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
|
||||||
fclose(ctx->debug_file);
|
fclose(ctx->debug_file);
|
||||||
if (strcmp(val, "stdout") != 0)
|
if (!strcmp(val, "stdout"))
|
||||||
ctx->debug_file = fopen(val, "a");
|
ctx->debug_file = stdout;
|
||||||
|
else if (!strcmp(val, "stderr"))
|
||||||
|
ctx->debug_file = stderr;
|
||||||
else
|
else
|
||||||
ctx->debug_file = stdout;
|
ctx->debug_file = fopen(val, "a");
|
||||||
}
|
|
||||||
val = scconf_get_str(block, "error_file", NULL);
|
|
||||||
if (val) {
|
|
||||||
if (ctx->error_file && ctx->error_file != stderr)
|
|
||||||
fclose(ctx->error_file);
|
|
||||||
if (strcmp(val, "stderr") != 0)
|
|
||||||
ctx->error_file = fopen(val, "a");
|
|
||||||
else
|
|
||||||
ctx->error_file = stderr;
|
|
||||||
}
|
}
|
||||||
val = scconf_get_str(block, "force_card_driver", NULL);
|
val = scconf_get_str(block, "force_card_driver", NULL);
|
||||||
if (val) {
|
if (val) {
|
||||||
|
@ -340,7 +329,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll,
|
||||||
const char *(**tmodv)(void) = &modversion;
|
const char *(**tmodv)(void) = &modversion;
|
||||||
|
|
||||||
if (name == NULL) { /* should not occurr, but... */
|
if (name == NULL) { /* should not occurr, but... */
|
||||||
sc_error(ctx,"No module specified\n",name);
|
sc_debug(ctx,"No module specified\n",name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
libname = find_library(ctx, name, type);
|
libname = find_library(ctx, name, type);
|
||||||
|
@ -348,7 +337,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll,
|
||||||
return NULL;
|
return NULL;
|
||||||
handle = lt_dlopen(libname);
|
handle = lt_dlopen(libname);
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
sc_error(ctx, "Module %s: cannot load %s library: %s\n", name, libname, lt_dlerror());
|
sc_debug(ctx, "Module %s: cannot load %s library: %s\n", name, libname, lt_dlerror());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +345,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll,
|
||||||
*(void **)tmodi = lt_dlsym(handle, "sc_module_init");
|
*(void **)tmodi = lt_dlsym(handle, "sc_module_init");
|
||||||
*(void **)tmodv = lt_dlsym(handle, "sc_driver_version");
|
*(void **)tmodv = lt_dlsym(handle, "sc_driver_version");
|
||||||
if (modinit == NULL || modversion == NULL) {
|
if (modinit == NULL || modversion == NULL) {
|
||||||
sc_error(ctx, "dynamic library '%s' is not a OpenSC module\n",libname);
|
sc_debug(ctx, "dynamic library '%s' is not a OpenSC module\n",libname);
|
||||||
lt_dlclose(handle);
|
lt_dlclose(handle);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -364,7 +353,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll,
|
||||||
version = modversion();
|
version = modversion();
|
||||||
/* XXX: We really need to have ABI version for each interface */
|
/* XXX: We really need to have ABI version for each interface */
|
||||||
if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
|
if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
|
||||||
sc_error(ctx,"dynamic library '%s': invalid module version\n",libname);
|
sc_debug(ctx,"dynamic library '%s': invalid module version\n",libname);
|
||||||
lt_dlclose(handle);
|
lt_dlclose(handle);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -401,7 +390,7 @@ static int load_reader_drivers(sc_context_t *ctx,
|
||||||
*(void**)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 0);
|
*(void**)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 0);
|
||||||
/* if still null, assume driver not found */
|
/* if still null, assume driver not found */
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
sc_error(ctx, "Unable to load '%s'.\n", ent->name);
|
sc_debug(ctx, "Unable to load '%s'.\n", ent->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
driver = func();
|
driver = func();
|
||||||
|
@ -464,7 +453,7 @@ static int load_card_drivers(sc_context_t *ctx,
|
||||||
*(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 1);
|
*(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name, 1);
|
||||||
/* if still null, assume driver not found */
|
/* if still null, assume driver not found */
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
sc_error(ctx, "Unable to load '%s'.\n", ent->name);
|
sc_debug(ctx, "Unable to load '%s'.\n", ent->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +614,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
sc_debug(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
|
sc_debug(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
|
||||||
else
|
else
|
||||||
sc_error(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
|
sc_debug(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
|
||||||
scconf_free(ctx->conf);
|
scconf_free(ctx->conf);
|
||||||
ctx->conf = NULL;
|
ctx->conf = NULL;
|
||||||
return;
|
return;
|
||||||
|
@ -677,16 +666,6 @@ unsigned int sc_ctx_get_reader_count(sc_context_t *ctx)
|
||||||
return (unsigned int)ctx->reader_count;
|
return (unsigned int)ctx->reader_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc_ctx_suppress_errors_on(sc_context_t *ctx)
|
|
||||||
{
|
|
||||||
ctx->suppress_errors++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sc_ctx_suppress_errors_off(sc_context_t *ctx)
|
|
||||||
{
|
|
||||||
ctx->suppress_errors--;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
|
int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
|
||||||
{
|
{
|
||||||
sc_context_param_t ctx_param;
|
sc_context_param_t ctx_param;
|
||||||
|
@ -792,16 +771,14 @@ int sc_release_context(sc_context_t *ctx)
|
||||||
if (ctx->mutex != NULL) {
|
if (ctx->mutex != NULL) {
|
||||||
int r = sc_mutex_destroy(ctx, ctx->mutex);
|
int r = sc_mutex_destroy(ctx, ctx->mutex);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(ctx, "unable to destroy mutex\n");
|
sc_debug(ctx, "unable to destroy mutex\n");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctx->conf != NULL)
|
if (ctx->conf != NULL)
|
||||||
scconf_free(ctx->conf);
|
scconf_free(ctx->conf);
|
||||||
if (ctx->debug_file && ctx->debug_file != stdout)
|
if (ctx->debug_file && (ctx->debug_file != stdout && ctx->debug_file != stderr))
|
||||||
fclose(ctx->debug_file);
|
fclose(ctx->debug_file);
|
||||||
if (ctx->error_file && ctx->error_file != stderr)
|
|
||||||
fclose(ctx->error_file);
|
|
||||||
if (ctx->app_name != NULL)
|
if (ctx->app_name != NULL)
|
||||||
free(ctx->app_name);
|
free(ctx->app_name);
|
||||||
sc_mem_clear(ctx, sizeof(*ctx));
|
sc_mem_clear(ctx, sizeof(*ctx));
|
||||||
|
@ -902,6 +879,6 @@ int sc_make_cache_dir(sc_context_t *ctx)
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
|
|
||||||
/* for lack of a better return code */
|
/* for lack of a better return code */
|
||||||
failed: sc_error(ctx, "failed to create cache directory\n");
|
failed: sc_debug(ctx, "failed to create cache directory\n");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,9 @@ struct app_entry {
|
||||||
|
|
||||||
static const struct app_entry apps[] = {
|
static const struct app_entry apps[] = {
|
||||||
{ (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" },
|
{ (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" },
|
||||||
{ (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" },
|
{ (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" }
|
||||||
|
/* Needed for the normal PKCS#15 processing of the Portugal eID card */
|
||||||
|
/* { (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" } */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct app_entry * find_app_entry(const u8 * aid, size_t aid_len)
|
static const struct app_entry * find_app_entry(const u8 * aid, size_t aid_len)
|
||||||
|
@ -96,12 +98,12 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
||||||
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
|
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
|
||||||
return r;
|
return r;
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(card->ctx, "EF(DIR) parsing failed: %s\n",
|
sc_debug(card->ctx, "EF(DIR) parsing failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (aid_len > SC_MAX_AID_SIZE) {
|
if (aid_len > SC_MAX_AID_SIZE) {
|
||||||
sc_error(card->ctx, "AID is too long.\n");
|
sc_debug(card->ctx, "AID is too long.\n");
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
app = (sc_app_info_t *) malloc(sizeof(sc_app_info_t));
|
app = (sc_app_info_t *) malloc(sizeof(sc_app_info_t));
|
||||||
|
@ -116,7 +118,7 @@ static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen,
|
||||||
app->label = NULL;
|
app->label = NULL;
|
||||||
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) {
|
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) {
|
||||||
if (path_len > SC_MAX_PATH_SIZE) {
|
if (path_len > SC_MAX_PATH_SIZE) {
|
||||||
sc_error(card->ctx, "Application path is too long.\n");
|
sc_debug(card->ctx, "Application path is too long.\n");
|
||||||
free(app);
|
free(app);
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
|
@ -167,9 +169,7 @@ int sc_enum_apps(sc_card_t *card)
|
||||||
sc_file_free(card->ef_dir);
|
sc_file_free(card->ef_dir);
|
||||||
card->ef_dir = NULL;
|
card->ef_dir = NULL;
|
||||||
}
|
}
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, &card->ef_dir);
|
r = sc_select_file(card, &path, &card->ef_dir);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
|
if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) {
|
||||||
|
@ -198,7 +198,7 @@ int sc_enum_apps(sc_card_t *card)
|
||||||
bufsize = r;
|
bufsize = r;
|
||||||
while (bufsize > 0) {
|
while (bufsize > 0) {
|
||||||
if (card->app_count == SC_MAX_CARD_APPS) {
|
if (card->app_count == SC_MAX_CARD_APPS) {
|
||||||
sc_error(card->ctx, "Too many applications on card");
|
sc_debug(card->ctx, "Too many applications on card");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r = parse_dir_record(card, &p, &bufsize, -1);
|
r = parse_dir_record(card, &p, &bufsize, -1);
|
||||||
|
@ -214,15 +214,13 @@ int sc_enum_apps(sc_card_t *card)
|
||||||
size_t rec_size;
|
size_t rec_size;
|
||||||
|
|
||||||
for (rec_nr = 1; ; rec_nr++) {
|
for (rec_nr = 1; ; rec_nr++) {
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_read_record(card, rec_nr, buf, sizeof(buf),
|
r = sc_read_record(card, rec_nr, buf, sizeof(buf),
|
||||||
SC_RECORD_BY_REC_NR);
|
SC_RECORD_BY_REC_NR);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
||||||
break;
|
break;
|
||||||
SC_TEST_RET(card->ctx, r, "read_record() failed");
|
SC_TEST_RET(card->ctx, r, "read_record() failed");
|
||||||
if (card->app_count == SC_MAX_CARD_APPS) {
|
if (card->app_count == SC_MAX_CARD_APPS) {
|
||||||
sc_error(card->ctx, "Too many applications on card");
|
sc_debug(card->ctx, "Too many applications on card");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rec_size = r;
|
rec_size = r;
|
||||||
|
@ -285,7 +283,7 @@ static int encode_dir_record(sc_context_t *ctx, const sc_app_info_t *app,
|
||||||
(void *) &tapp.ddo_len, 1);
|
(void *) &tapp.ddo_len, 1);
|
||||||
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "sc_asn1_encode() failed: %s\n",
|
sc_debug(ctx, "sc_asn1_encode() failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -352,9 +350,7 @@ static int update_single_record(sc_card_t *card, sc_file_t *file,
|
||||||
r = sc_update_record(card, (unsigned int)app->rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
r = sc_update_record(card, (unsigned int)app->rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
||||||
else if (app->rec_nr == 0) {
|
else if (app->rec_nr == 0) {
|
||||||
/* create new record entry */
|
/* create new record entry */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_append_record(card, rec, rec_size, 0);
|
r = sc_append_record(card, rec, rec_size, 0);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r == SC_ERROR_NOT_SUPPORTED) {
|
if (r == SC_ERROR_NOT_SUPPORTED) {
|
||||||
/* if the card doesn't support APPEND RECORD we try a
|
/* if the card doesn't support APPEND RECORD we try a
|
||||||
* UPDATE RECORD on the next unused record (and hope
|
* UPDATE RECORD on the next unused record (and hope
|
||||||
|
@ -368,7 +364,7 @@ static int update_single_record(sc_card_t *card, sc_file_t *file,
|
||||||
r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "invalid record number\n");
|
sc_debug(card->ctx, "invalid record number\n");
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
free(rec);
|
free(rec);
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* emv.c: EMV functions
|
|
||||||
*
|
|
||||||
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
#include "emv.h"
|
|
||||||
|
|
||||||
/* FIXME: Implement */
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* emv.h: OpenSC EMV header file
|
|
||||||
*
|
|
||||||
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
|
||||||
*
|
|
||||||
* 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 _OPENSC_EMV_H
|
|
||||||
#define _OPENSC_EMV_H
|
|
||||||
|
|
||||||
#include <opensc/opensc.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sc_emv_card {
|
|
||||||
struct sc_card *card;
|
|
||||||
};
|
|
||||||
|
|
||||||
int sc_emv_bind(struct sc_card *card, struct sc_emv_card **emv_card);
|
|
||||||
int sc_emv_unbind(struct sc_emv_card *emv_card);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -89,7 +89,8 @@ const char *sc_strerror(int error)
|
||||||
"Wrong padding",
|
"Wrong padding",
|
||||||
"Unsupported card",
|
"Unsupported card",
|
||||||
"Unable to load external module",
|
"Unable to load external module",
|
||||||
"EF offset too large"
|
"EF offset too large",
|
||||||
|
"Not implemented"
|
||||||
};
|
};
|
||||||
const int int_base = -SC_ERROR_INTERNAL;
|
const int int_base = -SC_ERROR_INTERNAL;
|
||||||
const char *p15i_errors[] = {
|
const char *p15i_errors[] = {
|
||||||
|
|
|
@ -90,6 +90,7 @@ extern "C" {
|
||||||
#define SC_ERROR_WRONG_CARD -1413
|
#define SC_ERROR_WRONG_CARD -1413
|
||||||
#define SC_ERROR_CANNOT_LOAD_MODULE -1414
|
#define SC_ERROR_CANNOT_LOAD_MODULE -1414
|
||||||
#define SC_ERROR_OFFSET_TOO_LARGE -1415
|
#define SC_ERROR_OFFSET_TOO_LARGE -1415
|
||||||
|
#define SC_ERROR_NOT_IMPLEMENTED -1416
|
||||||
|
|
||||||
/* Relating to PKCS #15 init stuff */
|
/* Relating to PKCS #15 init stuff */
|
||||||
#define SC_ERROR_PKCS15INIT -1500
|
#define SC_ERROR_PKCS15INIT -1500
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef unsigned __int8 uint8_t;
|
||||||
|
|
||||||
#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */
|
#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */
|
||||||
#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */
|
#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */
|
||||||
|
#define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */
|
||||||
|
|
||||||
#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */
|
#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */
|
||||||
#define SCARD_RESET_CARD 0x0001 /**< Reset on close */
|
#define SCARD_RESET_CARD 0x0001 /**< Reset on close */
|
||||||
|
@ -49,6 +50,8 @@ typedef unsigned __int8 uint8_t;
|
||||||
#define SCARD_E_INVALID_HANDLE 0x80100003 /**< The supplied handle was invalid. */
|
#define SCARD_E_INVALID_HANDLE 0x80100003 /**< The supplied handle was invalid. */
|
||||||
#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout value has expired. */
|
#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout value has expired. */
|
||||||
#define SCARD_E_SHARING_VIOLATION 0x8010000B /**< The smart card cannot be accessed because of other connections outstanding. */
|
#define SCARD_E_SHARING_VIOLATION 0x8010000B /**< The smart card cannot be accessed because of other connections outstanding. */
|
||||||
|
#define SCARD_E_NO_SMARTCARD 0x8010000C /**< The operation requires a smart card, but no smart card is currently in the device. */
|
||||||
|
#define SCARD_E_PROTO_MISMATCH 0x8010000F /**< The requested protocols are incompatible with the protocol currently in use with the smart card. */
|
||||||
#define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */
|
#define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */
|
||||||
#define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */
|
#define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */
|
||||||
#define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */
|
#define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */
|
||||||
|
|
|
@ -84,22 +84,22 @@ static int iso7816_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
|
||||||
|
|
||||||
/* Handle special cases here */
|
/* Handle special cases here */
|
||||||
if (sw1 == 0x6C) {
|
if (sw1 == 0x6C) {
|
||||||
sc_error(card->ctx, "Wrong length; correct length is %d\n", sw2);
|
sc_debug(card->ctx, "Wrong length; correct length is %d\n", sw2);
|
||||||
return SC_ERROR_WRONG_LENGTH;
|
return SC_ERROR_WRONG_LENGTH;
|
||||||
}
|
}
|
||||||
if (sw1 == 0x90)
|
if (sw1 == 0x90)
|
||||||
return SC_NO_ERROR;
|
return SC_NO_ERROR;
|
||||||
if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U ) {
|
if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U ) {
|
||||||
sc_error(card->ctx, "Verification failed (remaining tries: %d)\n",
|
sc_debug(card->ctx, "Verification failed (remaining tries: %d)\n",
|
||||||
(sw2 & 0x0f));
|
(sw2 & 0x0f));
|
||||||
return SC_ERROR_PIN_CODE_INCORRECT;
|
return SC_ERROR_PIN_CODE_INCORRECT;
|
||||||
}
|
}
|
||||||
for (i = 0; i < err_count; i++)
|
for (i = 0; i < err_count; i++)
|
||||||
if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
|
||||||
sc_error(card->ctx, "%s\n", iso7816_errors[i].errorstr);
|
sc_debug(card->ctx, "%s\n", iso7816_errors[i].errorstr);
|
||||||
return iso7816_errors[i].errorno;
|
return iso7816_errors[i].errorno;
|
||||||
}
|
}
|
||||||
sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
sc_debug(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
|
||||||
return SC_ERROR_CARD_CMD_FAILED;
|
return SC_ERROR_CARD_CMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ static int iso7816_read_binary(sc_card_t *card,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (idx > 0x7fff) {
|
if (idx > 0x7fff) {
|
||||||
sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
sc_debug(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
||||||
return SC_ERROR_OFFSET_TOO_LARGE;
|
return SC_ERROR_OFFSET_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ static int iso7816_write_record(sc_card_t *card, unsigned int rec_nr,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (count > 256) {
|
if (count > 256) {
|
||||||
sc_error(card->ctx, "Trying to send too many bytes\n");
|
sc_debug(card->ctx, "Trying to send too many bytes\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD2, rec_nr, 0);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD2, rec_nr, 0);
|
||||||
|
@ -193,7 +193,7 @@ static int iso7816_append_record(sc_card_t *card,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (count > 256) {
|
if (count > 256) {
|
||||||
sc_error(card->ctx, "Trying to send too many bytes\n");
|
sc_debug(card->ctx, "Trying to send too many bytes\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE2, 0, 0);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE2, 0, 0);
|
||||||
|
@ -218,7 +218,7 @@ static int iso7816_update_record(sc_card_t *card, unsigned int rec_nr,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (count > 256) {
|
if (count > 256) {
|
||||||
sc_error(card->ctx, "Trying to send too many bytes\n");
|
sc_debug(card->ctx, "Trying to send too many bytes\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0);
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0);
|
||||||
|
@ -247,7 +247,7 @@ static int iso7816_write_binary(sc_card_t *card,
|
||||||
assert(count <= card->max_send_size);
|
assert(count <= card->max_send_size);
|
||||||
|
|
||||||
if (idx > 0x7fff) {
|
if (idx > 0x7fff) {
|
||||||
sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
sc_debug(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
||||||
return SC_ERROR_OFFSET_TOO_LARGE;
|
return SC_ERROR_OFFSET_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ static int iso7816_update_binary(sc_card_t *card,
|
||||||
assert(count <= card->max_send_size);
|
assert(count <= card->max_send_size);
|
||||||
|
|
||||||
if (idx > 0x7fff) {
|
if (idx > 0x7fff) {
|
||||||
sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
sc_debug(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
||||||
return SC_ERROR_OFFSET_TOO_LARGE;
|
return SC_ERROR_OFFSET_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +642,7 @@ static int iso7816_delete_file(sc_card_t *card, const sc_path_t *path)
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx, 1);
|
SC_FUNC_CALLED(card->ctx, 1);
|
||||||
if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
|
if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
|
||||||
sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
sc_debug(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +782,6 @@ static int iso7816_compute_signature(sc_card_t *card,
|
||||||
apdu.data = sbuf;
|
apdu.data = sbuf;
|
||||||
apdu.lc = datalen;
|
apdu.lc = datalen;
|
||||||
apdu.datalen = datalen;
|
apdu.datalen = datalen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||||
|
@ -819,7 +818,6 @@ static int iso7816_decipher(sc_card_t *card,
|
||||||
* to tell the card the we want everything available (note: we
|
* to tell the card the we want everything available (note: we
|
||||||
* always have Le <= crgram_len) */
|
* always have Le <= crgram_len) */
|
||||||
apdu.le = (outlen >= 256 && crgram_len < 256) ? 256 : outlen;
|
apdu.le = (outlen >= 256 && crgram_len < 256) ? 256 : outlen;
|
||||||
apdu.sensitive = 1;
|
|
||||||
|
|
||||||
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
|
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
|
||||||
memcpy(sbuf + 1, crgram, crgram_len);
|
memcpy(sbuf + 1, crgram, crgram_len);
|
||||||
|
@ -908,7 +906,6 @@ static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
||||||
apdu->datalen = len;
|
apdu->datalen = len;
|
||||||
apdu->data = buf;
|
apdu->data = buf;
|
||||||
apdu->resplen = 0;
|
apdu->resplen = 0;
|
||||||
apdu->sensitive = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -946,7 +943,7 @@ static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
/* Call the reader driver to collect
|
/* Call the reader driver to collect
|
||||||
* the PIN and pass on the APDU to the card */
|
* the PIN and pass on the APDU to the card */
|
||||||
if (data->pin1.offset == 0) {
|
if (data->pin1.offset == 0) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Card driver didn't set PIN offset");
|
"Card driver didn't set PIN offset");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -958,7 +955,7 @@ static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
data);
|
data);
|
||||||
/* sw1/sw2 filled in by reader driver */
|
/* sw1/sw2 filled in by reader driver */
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Card reader driver does not support "
|
"Card reader driver does not support "
|
||||||
"PIN entry through reader key pad");
|
"PIN entry through reader key pad");
|
||||||
r = SC_ERROR_NOT_SUPPORTED;
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
_sc_asn1_decode
|
_sc_asn1_decode
|
||||||
_sc_asn1_encode
|
_sc_asn1_encode
|
||||||
_sc_debug
|
_sc_debug
|
||||||
_sc_error
|
|
||||||
sc_append_file_id
|
sc_append_file_id
|
||||||
sc_append_path
|
sc_append_path
|
||||||
sc_append_path_id
|
sc_append_path_id
|
||||||
|
@ -41,8 +40,6 @@ sc_create_file
|
||||||
sc_ctx_detect_readers
|
sc_ctx_detect_readers
|
||||||
sc_ctx_get_reader
|
sc_ctx_get_reader
|
||||||
sc_ctx_get_reader_count
|
sc_ctx_get_reader_count
|
||||||
sc_ctx_suppress_errors_off
|
|
||||||
sc_ctx_suppress_errors_on
|
|
||||||
sc_decipher
|
sc_decipher
|
||||||
sc_delete_file
|
sc_delete_file
|
||||||
sc_delete_record
|
sc_delete_record
|
||||||
|
@ -159,6 +156,7 @@ sc_pkcs15_make_absolute_path
|
||||||
sc_pkcs15_parse_df
|
sc_pkcs15_parse_df
|
||||||
sc_pkcs15_parse_tokeninfo
|
sc_pkcs15_parse_tokeninfo
|
||||||
sc_pkcs15_parse_unusedspace
|
sc_pkcs15_parse_unusedspace
|
||||||
|
sc_pkcs15_pincache_clear
|
||||||
sc_pkcs15_print_id
|
sc_pkcs15_print_id
|
||||||
sc_pkcs15_read_cached_file
|
sc_pkcs15_read_cached_file
|
||||||
sc_pkcs15_read_certificate
|
sc_pkcs15_read_certificate
|
||||||
|
|
|
@ -35,16 +35,6 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Although not used, we need this for consistent exports */
|
|
||||||
void _sc_error(sc_context_t *ctx, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
sc_do_log_va(ctx, SC_LOG_TYPE_ERROR, NULL, 0, NULL, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Although not used, we need this for consistent exports */
|
/* Although not used, we need this for consistent exports */
|
||||||
void _sc_debug(sc_context_t *ctx, const char *format, ...)
|
void _sc_debug(sc_context_t *ctx, const char *format, ...)
|
||||||
{
|
{
|
||||||
|
@ -68,24 +58,12 @@ void sc_do_log_va(sc_context_t *ctx, int type, const char *file, int line, const
|
||||||
{
|
{
|
||||||
int (*display_fn)(sc_context_t *, const char *);
|
int (*display_fn)(sc_context_t *, const char *);
|
||||||
char buf[1836], *p;
|
char buf[1836], *p;
|
||||||
const char *tag = "";
|
|
||||||
int r;
|
int r;
|
||||||
size_t left;
|
size_t left;
|
||||||
|
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SC_LOG_TYPE_ERROR:
|
|
||||||
if (!ctx->suppress_errors) {
|
|
||||||
display_fn = &sc_ui_display_error;
|
|
||||||
tag = "error:";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Fall thru - suppressed errors are logged as
|
|
||||||
* debug messages */
|
|
||||||
tag = "error (suppressed):";
|
|
||||||
type = SC_LOG_TYPE_DEBUG;
|
|
||||||
|
|
||||||
case SC_LOG_TYPE_DEBUG:
|
case SC_LOG_TYPE_DEBUG:
|
||||||
if (ctx->debug == 0)
|
if (ctx->debug == 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -40,15 +40,12 @@ extern "C" {
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
|
||||||
#define sc_error(ctx, format, args...) sc_do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, format , ## args)
|
|
||||||
#define sc_debug(ctx, format, args...) sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args)
|
#define sc_debug(ctx, format, args...) sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, format , ## args)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define sc_error _sc_error
|
|
||||||
#define sc_debug _sc_debug
|
#define sc_debug _sc_debug
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void _sc_error(struct sc_context *ctx, const char *format, ...);
|
|
||||||
void _sc_debug(struct sc_context *ctx, const char *format, ...);
|
void _sc_debug(struct sc_context *ctx, const char *format, ...);
|
||||||
void sc_do_log(struct sc_context *ctx, int type, const char *file, int line, const char *func, const char *format, ...);
|
void sc_do_log(struct sc_context *ctx, int type, const char *file, int line, const char *func, const char *format, ...);
|
||||||
void sc_do_log_va(struct sc_context *ctx, int type, const char *file, int line, const char *func, const char *format, va_list args);
|
void sc_do_log_va(struct sc_context *ctx, int type, const char *file, int line, const char *func, const char *format, va_list args);
|
||||||
|
@ -62,9 +59,7 @@ void sc_hex_dump(struct sc_context *ctx, const u8 * buf, size_t len, char *out,
|
||||||
|
|
||||||
#define SC_FUNC_RETURN(ctx, level, r) do { \
|
#define SC_FUNC_RETURN(ctx, level, r) do { \
|
||||||
int _ret = r; \
|
int _ret = r; \
|
||||||
if (_ret < 0 && !ctx->suppress_errors) { \
|
if (ctx->debug >= level) { \
|
||||||
sc_do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, "returning with: %s\n", sc_strerror(_ret)); \
|
|
||||||
} else if (ctx->debug >= level) { \
|
|
||||||
sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, "returning with: %d\n", _ret); \
|
sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, "returning with: %d\n", _ret); \
|
||||||
} \
|
} \
|
||||||
return _ret; \
|
return _ret; \
|
||||||
|
@ -73,13 +68,13 @@ void sc_hex_dump(struct sc_context *ctx, const u8 * buf, size_t len, char *out,
|
||||||
#define SC_TEST_RET(ctx, r, text) do { \
|
#define SC_TEST_RET(ctx, r, text) do { \
|
||||||
int _ret = (r); \
|
int _ret = (r); \
|
||||||
if (_ret < 0) { \
|
if (_ret < 0) { \
|
||||||
sc_do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, "%s: %s\n", (text), sc_strerror(_ret)); \
|
sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, "%s: %s\n", (text), sc_strerror(_ret)); \
|
||||||
return _ret; \
|
return _ret; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define sc_perror(ctx, errno, str) { \
|
#define sc_perror(ctx, errno, str) { \
|
||||||
sc_do_log(ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, "%s: %s\n", str, sc_strerror(errno)); \
|
sc_do_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, "%s: %s\n", str, sc_strerror(errno)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -60,7 +60,7 @@ int msc_list_objects(sc_card_t* card, u8 next, mscfs_file_t* file) {
|
||||||
if(apdu.resplen == 0) /* No more left */
|
if(apdu.resplen == 0) /* No more left */
|
||||||
return 0;
|
return 0;
|
||||||
if (apdu.resplen != 14) {
|
if (apdu.resplen != 14) {
|
||||||
sc_error(card->ctx, "expected 14 bytes, got %d.\n", apdu.resplen);
|
sc_debug(card->ctx, "expected 14 bytes, got %d.\n", apdu.resplen);
|
||||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||||
}
|
}
|
||||||
memcpy(file->objectId.id, fileData, 4);
|
memcpy(file->objectId.id, fileData, 4);
|
||||||
|
@ -499,9 +499,7 @@ int msc_get_challenge(sc_card_t *card, unsigned short dataLength, unsigned short
|
||||||
r = msc_read_object(card, inputId, 2, outputData, dataLength);
|
r = msc_read_object(card, inputId, 2, outputData, dataLength);
|
||||||
if(r < 0)
|
if(r < 0)
|
||||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
msc_delete_object(card, inputId,0);
|
msc_delete_object(card, inputId,0);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,23 +827,19 @@ static int msc_compute_crypt_final_object(
|
||||||
ptr++;
|
ptr++;
|
||||||
memcpy(ptr, inputData, dataLength);
|
memcpy(ptr, inputData, dataLength);
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
|
r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
|
if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
|
||||||
r = msc_delete_object(card, outputId, 0);
|
r = msc_delete_object(card, outputId, 0);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
}
|
}
|
||||||
r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
|
r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
r = msc_update_object(card, outputId, 0, buffer + 1, dataLength + 2);
|
r = msc_update_object(card, outputId, 0, buffer + 1, dataLength + 2);
|
||||||
if(r < 0) return r;
|
if(r < 0) return r;
|
||||||
|
@ -868,10 +862,8 @@ static int msc_compute_crypt_final_object(
|
||||||
} else {
|
} else {
|
||||||
r = SC_ERROR_CARD_CMD_FAILED;
|
r = SC_ERROR_CARD_CMD_FAILED;
|
||||||
}
|
}
|
||||||
/* no error checks.. this is last ditch cleanup */
|
/* this is last ditch cleanup */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
msc_delete_object(card, outputId, 0);
|
msc_delete_object(card, outputId, 0);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||||
}
|
}
|
||||||
|
@ -996,25 +988,21 @@ int msc_import_key(sc_card_t *card,
|
||||||
CPYVAL(dq1);
|
CPYVAL(dq1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
|
if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
|
||||||
r = msc_delete_object(card, outputId, 0);
|
r = msc_delete_object(card, outputId, 0);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
}
|
}
|
||||||
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
r = msc_update_object(card, outputId, 0, buffer, bufferSize);
|
r = msc_update_object(card, outputId, 0, buffer, bufferSize);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
@ -1041,16 +1029,12 @@ int msc_import_key(sc_card_t *card,
|
||||||
sc_debug(card->ctx, "keyimport: got strange SWs: 0x%02X 0x%02X\n",
|
sc_debug(card->ctx, "keyimport: got strange SWs: 0x%02X 0x%02X\n",
|
||||||
apdu.sw1, apdu.sw2);
|
apdu.sw1, apdu.sw2);
|
||||||
}
|
}
|
||||||
/* no error checks.. this is last ditch cleanup */
|
/* this is last ditch cleanup */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
msc_delete_object(card, outputId, 0);
|
msc_delete_object(card, outputId, 0);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
SC_FUNC_RETURN(card->ctx, 0, r);
|
SC_FUNC_RETURN(card->ctx, 0, r);
|
||||||
}
|
}
|
||||||
/* no error checks.. this is last ditch cleanup */
|
/* this is last ditch cleanup */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
msc_delete_object(card, outputId, 0);
|
msc_delete_object(card, outputId, 0);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_CARD_CMD_FAILED);
|
SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_CARD_CMD_FAILED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,8 +326,9 @@ typedef struct sc_reader {
|
||||||
#define SC_PIN_CMD_CHANGE 1
|
#define SC_PIN_CMD_CHANGE 1
|
||||||
#define SC_PIN_CMD_UNBLOCK 2
|
#define SC_PIN_CMD_UNBLOCK 2
|
||||||
|
|
||||||
#define SC_PIN_CMD_USE_PINPAD 0x0001
|
#define SC_PIN_CMD_USE_PINPAD 0x0001
|
||||||
#define SC_PIN_CMD_NEED_PADDING 0x0002
|
#define SC_PIN_CMD_NEED_PADDING 0x0002
|
||||||
|
#define SC_PIN_CMD_IMPLICIT_CHANGE 0x0004
|
||||||
|
|
||||||
#define SC_PIN_ENCODING_ASCII 0
|
#define SC_PIN_ENCODING_ASCII 0
|
||||||
#define SC_PIN_ENCODING_BCD 1
|
#define SC_PIN_ENCODING_BCD 1
|
||||||
|
@ -658,8 +659,7 @@ typedef struct sc_context {
|
||||||
char *app_name;
|
char *app_name;
|
||||||
int debug;
|
int debug;
|
||||||
|
|
||||||
int suppress_errors;
|
FILE *debug_file;
|
||||||
FILE *debug_file, *error_file;
|
|
||||||
char *preferred_language;
|
char *preferred_language;
|
||||||
|
|
||||||
const struct sc_reader_driver *reader_drivers[SC_MAX_READER_DRIVERS];
|
const struct sc_reader_driver *reader_drivers[SC_MAX_READER_DRIVERS];
|
||||||
|
@ -761,18 +761,6 @@ sc_reader_t *sc_ctx_get_reader(sc_context_t *ctx, unsigned int i);
|
||||||
*/
|
*/
|
||||||
unsigned int sc_ctx_get_reader_count(sc_context_t *ctx);
|
unsigned int sc_ctx_get_reader_count(sc_context_t *ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns on error suppression
|
|
||||||
* @param ctx OpenSC context
|
|
||||||
*/
|
|
||||||
void sc_ctx_suppress_errors_on(sc_context_t *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns off error suppression
|
|
||||||
* @param ctx OpenSC context
|
|
||||||
*/
|
|
||||||
void sc_ctx_suppress_errors_off(sc_context_t *ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the use of a specified card driver
|
* Forces the use of a specified card driver
|
||||||
* @param ctx OpenSC context
|
* @param ctx OpenSC context
|
||||||
|
@ -1153,6 +1141,7 @@ int sc_base64_decode(const char *in, u8 *out, size_t outlen);
|
||||||
* @param len length of the memory buffer
|
* @param len length of the memory buffer
|
||||||
*/
|
*/
|
||||||
void sc_mem_clear(void *ptr, size_t len);
|
void sc_mem_clear(void *ptr, size_t len);
|
||||||
|
void *sc_mem_alloc_secure(size_t len);
|
||||||
|
|
||||||
int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize);
|
int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize);
|
||||||
int sc_make_cache_dir(sc_context_t *ctx);
|
int sc_make_cache_dir(sc_context_t *ctx);
|
||||||
|
|
|
@ -142,29 +142,29 @@ CERT_HANDLE_FUNCTION(default_cert_handle) {
|
||||||
int modulus_len = 0;
|
int modulus_len = 0;
|
||||||
const prdata* key = get_prkey_by_cert(items, cert);
|
const prdata* key = get_prkey_by_cert(items, cert);
|
||||||
if(!key) {
|
if(!key) {
|
||||||
sc_error(p15card->card->ctx, "Error: No key for this certificate");
|
sc_debug(p15card->card->ctx, "Error: No key for this certificate");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!d2i_X509(&cert_data, (const u8**)&data, length)) {
|
if(!d2i_X509(&cert_data, (const u8**)&data, length)) {
|
||||||
sc_error(p15card->card->ctx, "Error converting certificate");
|
sc_debug(p15card->card->ctx, "Error converting certificate");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey = X509_get_pubkey(cert_data);
|
pkey = X509_get_pubkey(cert_data);
|
||||||
|
|
||||||
if(pkey == NULL) {
|
if(pkey == NULL) {
|
||||||
sc_error(p15card->card->ctx, "Error: no public key associated with the certificate");
|
sc_debug(p15card->card->ctx, "Error: no public key associated with the certificate");
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if(! EVP_PK_RSA & (certtype = X509_certificate_type(cert_data, pkey))) {
|
if(! EVP_PK_RSA & (certtype = X509_certificate_type(cert_data, pkey))) {
|
||||||
sc_error(p15card->card->ctx, "Error: certificate is not for an RSA key");
|
sc_debug(p15card->card->ctx, "Error: certificate is not for an RSA key");
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if(pkey->pkey.rsa->n == NULL) {
|
if(pkey->pkey.rsa->n == NULL) {
|
||||||
sc_error(p15card->card->ctx, "Error: no modulus associated with the certificate");
|
sc_debug(p15card->card->ctx, "Error: no modulus associated with the certificate");
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
int modulus_length = 0, usage = 0;
|
int modulus_length = 0, usage = 0;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
sc_card_t *card = p15card->card;
|
sc_card_t *card = p15card->card;
|
||||||
sc_context_t *ctx = card->ctx;
|
|
||||||
sc_serial_number_t serial;
|
sc_serial_number_t serial;
|
||||||
sc_path_t path;
|
sc_path_t path;
|
||||||
sc_file_t *file = NULL;
|
sc_file_t *file = NULL;
|
||||||
|
@ -63,9 +62,7 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
p15card->version = buf[6];
|
p15card->version = buf[6];
|
||||||
p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED;
|
p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED;
|
||||||
sc_format_path("AAAA", &path);
|
sc_format_path("AAAA", &path);
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = sc_select_file(card, &path, &file);
|
r = sc_select_file(card, &path, &file);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
for (i = 0; i < 1; i++) {
|
for (i = 0; i < 1; i++) {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
@ -110,9 +107,7 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
sc_file_free(file);
|
sc_file_free(file);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
sc_format_path("0002", &path);
|
sc_format_path("0002", &path);
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = sc_select_file(card, &path, &file);
|
r = sc_select_file(card, &path, &file);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
struct sc_pkcs15_cert_info cert_info;
|
struct sc_pkcs15_cert_info cert_info;
|
||||||
struct sc_pkcs15_object cert_obj;
|
struct sc_pkcs15_object cert_obj;
|
||||||
|
@ -125,11 +120,9 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
cert_info.id.value[0] = 0x45;
|
cert_info.id.value[0] = 0x45;
|
||||||
cert_info.authority = 0;
|
cert_info.authority = 0;
|
||||||
cert_info.path = path;
|
cert_info.path = path;
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = sc_pkcs15_read_certificate(p15card, &cert_info,
|
r = sc_pkcs15_read_certificate(p15card, &cert_info,
|
||||||
(sc_pkcs15_cert_t
|
(sc_pkcs15_cert_t
|
||||||
**) (&cert_obj.data));
|
**) (&cert_obj.data));
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
sc_pkcs15_cert_t *cert =
|
sc_pkcs15_cert_t *cert =
|
||||||
(sc_pkcs15_cert_t *) (cert_obj.data);
|
(sc_pkcs15_cert_t *) (cert_obj.data);
|
||||||
|
@ -189,9 +182,7 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card)
|
||||||
sc_file_free(file);
|
sc_file_free(file);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
sc_format_path("0001", &path);
|
sc_format_path("0001", &path);
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
r = sc_select_file(card, &path, &file);
|
r = sc_select_file(card, &path, &file);
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
struct sc_pkcs15_prkey_info prkey_info;
|
struct sc_pkcs15_prkey_info prkey_info;
|
||||||
struct sc_pkcs15_object prkey_obj;
|
struct sc_pkcs15_object prkey_obj;
|
||||||
|
|
|
@ -231,7 +231,7 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
|
||||||
i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len,
|
i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len,
|
||||||
out, &tmp_len);
|
out, &tmp_len);
|
||||||
if (i != SC_SUCCESS) {
|
if (i != SC_SUCCESS) {
|
||||||
sc_error(ctx, "Unable to add digest info 0x%x\n",
|
sc_debug(ctx, "Unable to add digest info 0x%x\n",
|
||||||
hash_algo);
|
hash_algo);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
|
||||||
mod_len);
|
mod_len);
|
||||||
default:
|
default:
|
||||||
/* currently only pkcs1 padding is supported */
|
/* currently only pkcs1 padding is supported */
|
||||||
sc_error(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo);
|
sc_debug(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,14 +284,14 @@ int sc_get_encoding_flags(sc_context_t *ctx,
|
||||||
*pflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
*pflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
||||||
} else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
|
} else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
|
||||||
if (!(caps & SC_ALGORITHM_RSA_RAW)) {
|
if (!(caps & SC_ALGORITHM_RSA_RAW)) {
|
||||||
sc_error(ctx, "raw RSA is not supported");
|
sc_debug(ctx, "raw RSA is not supported");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
*sflags |= SC_ALGORITHM_RSA_RAW;
|
*sflags |= SC_ALGORITHM_RSA_RAW;
|
||||||
/* in case of raw RSA there is nothing to pad */
|
/* in case of raw RSA there is nothing to pad */
|
||||||
*pflags = 0;
|
*pflags = 0;
|
||||||
} else {
|
} else {
|
||||||
sc_error(ctx, "unsupported algorithm");
|
sc_debug(ctx, "unsupported algorithm");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card)
|
||||||
const char *authPRKEY = "Authentication Key";
|
const char *authPRKEY = "Authentication Key";
|
||||||
/* const char *nonrepPRKEY = "Non repudiation Key"; */
|
/* const char *nonrepPRKEY = "Non repudiation Key"; */
|
||||||
|
|
||||||
p15card->opts.use_cache = 1;
|
p15card->opts.use_file_cache = 1;
|
||||||
|
|
||||||
/* Get Serial number */
|
/* Get Serial number */
|
||||||
sc_format_path("3F0030000001", &path);
|
sc_format_path("3F0030000001", &path);
|
||||||
|
|
|
@ -345,7 +345,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
||||||
|
|
||||||
alg_info = sc_asn1_get_algorithm_info(id);
|
alg_info = sc_asn1_get_algorithm_info(id);
|
||||||
if (alg_info == NULL) {
|
if (alg_info == NULL) {
|
||||||
sc_error(ctx, "Cannot encode unknown algorithm %u.\n",
|
sc_debug(ctx, "Cannot encode unknown algorithm %u.\n",
|
||||||
id->algorithm);
|
id->algorithm);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,9 +95,7 @@ static int acos_detect_card(sc_pkcs15_card_t *p15card)
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
/* read EF_CIN_CSN file */
|
/* read EF_CIN_CSN file */
|
||||||
sc_format_path("DF71D001", &path);
|
sc_format_path("DF71D001", &path);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
r = sc_read_binary(card, 0, buf, 8, 0);
|
r = sc_read_binary(card, 0, buf, 8, 0);
|
||||||
|
@ -163,9 +161,7 @@ static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card)
|
||||||
|
|
||||||
/* read EF_CIN_CSN file */
|
/* read EF_CIN_CSN file */
|
||||||
sc_format_path("DF71D001", &path);
|
sc_format_path("DF71D001", &path);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
r = sc_read_binary(card, 0, buf, 8, 0);
|
r = sc_read_binary(card, 0, buf, 8, 0);
|
||||||
|
|
|
@ -154,7 +154,7 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card,
|
||||||
c = fwrite(buf, 1, bufsize, f);
|
c = fwrite(buf, 1, bufsize, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (c != bufsize) {
|
if (c != bufsize) {
|
||||||
sc_error(p15card->card->ctx, "fwrite() wrote only %d bytes", c);
|
sc_debug(p15card->card->ctx, "fwrite() wrote only %d bytes", c);
|
||||||
unlink(fname);
|
unlink(fname);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ static int parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, stru
|
||||||
obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS,
|
obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS,
|
||||||
&objlen);
|
&objlen);
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
sc_error(ctx, "X.509 certificate not found\n");
|
sc_debug(ctx, "X.509 certificate not found\n");
|
||||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||||
}
|
}
|
||||||
cert->data_len = objlen + (obj - buf);
|
cert->data_len = objlen + (obj - buf);
|
||||||
|
|
|
@ -65,7 +65,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
iconv_t iso_utf;
|
iconv_t iso_utf;
|
||||||
char *inptr, *outptr;
|
char *inptr, *outptr;
|
||||||
size_t inbytes, outbytes, result;
|
size_t inbytes, outbytes, result;
|
||||||
unsigned char label[64], name1[32], name2[32];
|
char label[64], name1[32], name2[32];
|
||||||
#endif
|
#endif
|
||||||
unsigned char buff[128];
|
unsigned char buff[128];
|
||||||
int r, i, flags;
|
int r, i, flags;
|
||||||
|
@ -73,6 +73,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
set_string (&p15card->label, "ID-kaart");
|
set_string (&p15card->label, "ID-kaart");
|
||||||
set_string (&p15card->manufacturer_id, "AS Sertifitseerimiskeskus");
|
set_string (&p15card->manufacturer_id, "AS Sertifitseerimiskeskus");
|
||||||
|
p15card->version = 2; /* Increases as the code changes for EstEID happen, not only in this file */
|
||||||
|
|
||||||
/* Select application directory */
|
/* Select application directory */
|
||||||
sc_format_path ("3f00eeee5044", &tmppath);
|
sc_format_path ("3f00eeee5044", &tmppath);
|
||||||
|
@ -94,7 +95,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
r = sc_read_record (card, SC_ESTEID_PD_GIVEN_NAMES1, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
|
r = sc_read_record (card, SC_ESTEID_PD_GIVEN_NAMES1, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
|
||||||
SC_TEST_RET (card->ctx, r, "read name1 failed");
|
SC_TEST_RET (card->ctx, r, "read name1 failed");
|
||||||
inptr = buff;
|
inptr = (char *) buff;
|
||||||
outptr = name1;
|
outptr = name1;
|
||||||
inbytes = r;
|
inbytes = r;
|
||||||
outbytes = 32;
|
outbytes = 32;
|
||||||
|
@ -105,7 +106,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
r = sc_read_record (card, SC_ESTEID_PD_SURNAME, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
|
r = sc_read_record (card, SC_ESTEID_PD_SURNAME, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
|
||||||
SC_TEST_RET (card->ctx, r, "read name2 failed");
|
SC_TEST_RET (card->ctx, r, "read name2 failed");
|
||||||
inptr = buff;
|
inptr = (char *) buff;
|
||||||
outptr = name2;
|
outptr = name2;
|
||||||
inbytes = r;
|
inbytes = r;
|
||||||
outbytes = 32;
|
outbytes = 32;
|
||||||
|
@ -113,7 +114,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
if (result == (size_t) -1)
|
if (result == (size_t) -1)
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
*outptr = '\0';
|
*outptr = '\0';
|
||||||
|
iconv_close(iso_utf);
|
||||||
snprintf(label, sizeof(label), "%s %s", name1, name2);
|
snprintf(label, sizeof(label), "%s %s", name1, name2);
|
||||||
set_string (&p15card->label, label);
|
set_string (&p15card->label, label);
|
||||||
#endif
|
#endif
|
||||||
|
@ -192,6 +193,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
|
||||||
pin_info.max_length = 12;
|
pin_info.max_length = 12;
|
||||||
pin_info.pad_char = '\0';
|
pin_info.pad_char = '\0';
|
||||||
pin_info.tries_left = (int)tries_left;
|
pin_info.tries_left = (int)tries_left;
|
||||||
|
pin_info.max_tries = 3;
|
||||||
|
|
||||||
strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label));
|
strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label));
|
||||||
pin_obj.flags = esteid_pin_flags[i];
|
pin_obj.flags = esteid_pin_flags[i];
|
||||||
|
|
|
@ -259,14 +259,10 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card)
|
||||||
path.value[1] = i;
|
path.value[1] = i;
|
||||||
path.len = 2;
|
path.len = 2;
|
||||||
path.type = SC_PATH_TYPE_FILE_ID;
|
path.type = SC_PATH_TYPE_FILE_ID;
|
||||||
sc_ctx_suppress_errors_on(card->ctx); /* file may not exist, and not an error */
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
continue;
|
continue;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_read_record(card, 1, sysrec, sizeof(sysrec), SC_RECORD_BY_REC_NR);
|
r = sc_read_record(card, 1, sysrec, sizeof(sysrec), SC_RECORD_BY_REC_NR);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r != 7 || sysrec[0] != 0) {
|
if (r != 7 || sysrec[0] != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +275,7 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card)
|
||||||
case 0x10: kinfo[num_keyinfo].modulus_len = 768 / 8; break;
|
case 0x10: kinfo[num_keyinfo].modulus_len = 768 / 8; break;
|
||||||
case 0x11: kinfo[num_keyinfo].modulus_len = 1024 / 8; break;
|
case 0x11: kinfo[num_keyinfo].modulus_len = 1024 / 8; break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported modulus length");
|
sc_debug(card->ctx, "Unsupported modulus length");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path,
|
||||||
sc_debug(card->ctx, "%s: Certificate object is of size: %d\n", fn_name, objlen);
|
sc_debug(card->ctx, "%s: Certificate object is of size: %d\n", fn_name, objlen);
|
||||||
|
|
||||||
if (objlen < 1 || objlen > 10240) {
|
if (objlen < 1 || objlen > 10240) {
|
||||||
sc_error(card->ctx, "%s: Invalid object size: %d\n", fn_name, objlen);
|
sc_debug(card->ctx, "%s: Invalid object size: %d\n", fn_name, objlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path,
|
||||||
offset = block*248;
|
offset = block*248;
|
||||||
r = sc_read_binary(card, offset, ibuf, 248, 0);
|
r = sc_read_binary(card, offset, ibuf, 248, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "%s: Could not read cert object\n", fn_name);
|
sc_debug(card->ctx, "%s: Could not read cert object\n", fn_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
|
||||||
df_type = SC_PKCS15_CDF;
|
df_type = SC_PKCS15_CDF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(p15card->card->ctx,
|
sc_debug(p15card->card->ctx,
|
||||||
"Unknown PKCS15 object type %d\n", type);
|
"Unknown PKCS15 object type %d\n", type);
|
||||||
free(obj);
|
free(obj);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
|
@ -242,9 +242,7 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
sc_format_path("3F002F02", &path);
|
sc_format_path("3F002F02", &path);
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, &file);
|
r = sc_select_file(card, &path, &file);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
if (r != SC_SUCCESS || file->size > 255) {
|
if (r != SC_SUCCESS || file->size > 255) {
|
||||||
/* Not EF.GDO */
|
/* Not EF.GDO */
|
||||||
|
@ -308,9 +306,7 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path);
|
sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path);
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
|
|
||||||
|
@ -398,9 +394,7 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path);
|
sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path);
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -530,7 +524,7 @@ static int loadCertificate(sc_pkcs15_card_t * p15card, int i,
|
||||||
sc_read_binary(card, 4, compCert, compLen, 0);
|
sc_read_binary(card, 4, compCert, compLen, 0);
|
||||||
|
|
||||||
if ((r = uncompress(cert, &len, compCert, compLen)) != Z_OK) {
|
if ((r = uncompress(cert, &len, compCert, compLen)) != Z_OK) {
|
||||||
sc_error(p15card->card->ctx, "Zlib error: %d", r);
|
sc_debug(p15card->card->ctx, "Zlib error: %d", r);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +590,7 @@ static int infocamere_1400_init(sc_pkcs15_card_t * p15card)
|
||||||
set_security_env = card->ops->set_security_env;
|
set_security_env = card->ops->set_security_env;
|
||||||
card->ops->set_security_env = infocamere_1400_set_sec_env;
|
card->ops->set_security_env = infocamere_1400_set_sec_env;
|
||||||
card->ops->compute_signature = do_sign;
|
card->ops->compute_signature = do_sign;
|
||||||
p15card->opts.use_cache = 1;
|
p15card->opts.use_file_cache = 1;
|
||||||
|
|
||||||
sc_format_path("30000001", &path);
|
sc_format_path("30000001", &path);
|
||||||
|
|
||||||
|
@ -614,7 +608,7 @@ static int infocamere_1400_init(sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
if ((r = loadCertificate(p15card, 0, certPath[0], certLabel[0])) !=
|
if ((r = loadCertificate(p15card, 0, certPath[0], certLabel[0])) !=
|
||||||
SC_SUCCESS) {
|
SC_SUCCESS) {
|
||||||
sc_error(p15card->card->ctx, "%s", sc_strerror(r));
|
sc_debug(p15card->card->ctx, "%s", sc_strerror(r));
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
||||||
if ((r = read_file(card, "006E007300C4", buffer, sizeof(buffer))) < 0)
|
if ((r = read_file(card, "006E007300C4", buffer, sizeof(buffer))) < 0)
|
||||||
goto failed;
|
goto failed;
|
||||||
if (r != 7) {
|
if (r != 7) {
|
||||||
sc_error(ctx,
|
sc_debug(ctx,
|
||||||
"CHV status bytes have unexpected length "
|
"CHV status bytes have unexpected length "
|
||||||
"(expected 7, got %d)\n", r);
|
"(expected 7, got %d)\n", r);
|
||||||
return SC_ERROR_OBJECT_NOT_VALID;
|
return SC_ERROR_OBJECT_NOT_VALID;
|
||||||
|
@ -229,7 +229,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed: sc_error(card->ctx, "Failed to initialize OpenPGP emulation: %s\n",
|
failed: sc_debug(card->ctx, "Failed to initialize OpenPGP emulation: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@ static const struct sc_asn1_entry c_asn1_pin[] = {
|
||||||
{ NULL, 0, 0, 0, NULL, NULL }
|
{ NULL, 0, 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void sc_pkcs15_pincache_add(struct sc_pkcs15_card *p15card, struct sc_pkcs15_pin_info *pininfo, const u8 *pin, size_t pinlen);
|
||||||
|
|
||||||
int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card,
|
int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card,
|
||||||
struct sc_pkcs15_object *obj,
|
struct sc_pkcs15_object *obj,
|
||||||
const u8 ** buf, size_t *buflen)
|
const u8 ** buf, size_t *buflen)
|
||||||
|
@ -198,15 +200,13 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
|
||||||
sc_card_t *card;
|
sc_card_t *card;
|
||||||
struct sc_pin_cmd_data data;
|
struct sc_pin_cmd_data data;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(p15card->card->ctx, 2);
|
||||||
if ((r = _validate_pin(p15card, pin, pinlen)) != SC_SUCCESS)
|
if ((r = _validate_pin(p15card, pin, pinlen)) != SC_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
card = p15card->card;
|
card = p15card->card;
|
||||||
|
|
||||||
r = sc_lock(card);
|
r = sc_lock(card);
|
||||||
if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) {
|
|
||||||
r = sc_lock(card);
|
|
||||||
}
|
|
||||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||||
/* the path in the pin object is optional */
|
/* the path in the pin object is optional */
|
||||||
if (pin->path.len > 0) {
|
if (pin->path.len > 0) {
|
||||||
|
@ -251,6 +251,8 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
||||||
|
if (r == SC_SUCCESS)
|
||||||
|
sc_pkcs15_pincache_add(p15card, pin, pincode, pinlen);
|
||||||
out:
|
out:
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
return r;
|
return r;
|
||||||
|
@ -328,6 +330,8 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
||||||
|
if (r == SC_SUCCESS)
|
||||||
|
sc_pkcs15_pincache_add(p15card, pin, newpin, newpinlen);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
|
@ -436,6 +440,8 @@ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
r = sc_pin_cmd(card, &data, &pin->tries_left);
|
||||||
|
if (r == SC_SUCCESS)
|
||||||
|
sc_pkcs15_pincache_add(p15card, pin, newpin, newpinlen);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
|
@ -446,3 +452,94 @@ void sc_pkcs15_free_pin_info(sc_pkcs15_pin_info_t *pin)
|
||||||
{
|
{
|
||||||
free(pin);
|
free(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add a PIN to the PIN cache related to the card. Some operations can trigger re-authentication later. */
|
||||||
|
static void sc_pkcs15_pincache_add(struct sc_pkcs15_card *p15card,
|
||||||
|
struct sc_pkcs15_pin_info *pininfo,
|
||||||
|
const u8 *pin, size_t pinlen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
sc_pkcs15_pincache_entry_t *entry;
|
||||||
|
sc_pkcs15_object_t *obj;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(p15card->card->ctx, 2);
|
||||||
|
|
||||||
|
if (!p15card->opts.use_pin_cache)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Is it a user consent protecting PIN ? */
|
||||||
|
if (sc_pkcs15_find_prkey_by_reference(p15card, NULL, pininfo->reference, &obj) == SC_SUCCESS) {
|
||||||
|
if (obj->user_consent) {
|
||||||
|
sc_debug(p15card->card->ctx, "Not caching userconsent related PIN");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<SC_PKCS15_MAX_PINS; i++) {
|
||||||
|
if (p15card->pin_cache[i] == NULL) {
|
||||||
|
entry = (sc_pkcs15_pincache_entry_t *) sc_mem_alloc_secure(sizeof(sc_pkcs15_pincache_entry_t));
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
memcpy(&entry->id, &pininfo->auth_id, sizeof(sc_pkcs15_id_t));
|
||||||
|
memcpy(&entry->pin, pin, pinlen);
|
||||||
|
entry->len = pinlen;
|
||||||
|
entry->counter = 0;
|
||||||
|
p15card->pin_cache[i] = entry;
|
||||||
|
return;
|
||||||
|
} else { /* Update the existing PIN */
|
||||||
|
sc_pkcs15_pincache_entry_t *entry = p15card->pin_cache[i];
|
||||||
|
if (sc_pkcs15_compare_id(&entry->id, &pininfo->auth_id)) {
|
||||||
|
memcpy(&entry->pin, pin, pinlen);
|
||||||
|
entry->len = pinlen;
|
||||||
|
entry->counter = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Validate the PIN code associated with an object */
|
||||||
|
int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs15_object_t *obj)
|
||||||
|
{
|
||||||
|
int r, i;
|
||||||
|
sc_pkcs15_object_t *pin_obj;
|
||||||
|
sc_pkcs15_pin_info_t *pin_info;
|
||||||
|
|
||||||
|
SC_FUNC_CALLED(p15card->card->ctx, 2);
|
||||||
|
|
||||||
|
if (!p15card->opts.use_pin_cache)
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
|
||||||
|
if (obj->user_consent)
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
|
||||||
|
if (p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD)
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
|
||||||
|
r = sc_pkcs15_find_pin_by_auth_id(p15card, &obj->auth_id, &pin_obj);
|
||||||
|
if (r != SC_SUCCESS) {
|
||||||
|
sc_debug(p15card->card->ctx, "Could not find pin object for auth_id %s", sc_pkcs15_print_id(&obj->auth_id));
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
|
||||||
|
for (i=0; i<SC_PKCS15_MAX_PINS && p15card->pin_cache[i] != NULL; i++) {
|
||||||
|
sc_pkcs15_pincache_entry_t *entry = p15card->pin_cache[i];
|
||||||
|
if (sc_pkcs15_compare_id(&entry->id, &obj->auth_id)) {
|
||||||
|
if (entry->counter >= p15card->opts.pin_cache_counter) {
|
||||||
|
sc_mem_clear(entry->pin, entry->len);
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
}
|
||||||
|
entry->counter++;
|
||||||
|
return sc_pkcs15_verify_pin(p15card, pin_info, entry->pin, entry->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sc_pkcs15_pincache_clear(struct sc_pkcs15_card *p15card)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i<SC_PKCS15_MAX_PINS && p15card->pin_cache[i] != NULL; i++)
|
||||||
|
sc_mem_clear(p15card->pin_cache[i]->pin, p15card->pin_cache[i]->len);
|
||||||
|
}
|
|
@ -248,9 +248,7 @@ const objdata objects[] = {
|
||||||
* but need serial number for Mac tokend
|
* but need serial number for Mac tokend
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_debug(card->ctx,"sc_card_ctl rc=%d",r);
|
sc_debug(card->ctx,"sc_card_ctl rc=%d",r);
|
||||||
p15card->serial_number = strdup("00000000");
|
p15card->serial_number = strdup("00000000");
|
||||||
|
@ -273,12 +271,10 @@ const objdata objects[] = {
|
||||||
|
|
||||||
/* We could make sure the object is on the card */
|
/* We could make sure the object is on the card */
|
||||||
/* But really don't need to do this now */
|
/* But really don't need to do this now */
|
||||||
// sc_ctx_suppress_errors_on(card->ctx);
|
/* r = sc_select_file(card, &obj_info.path, NULL);
|
||||||
// r = sc_select_file(card, &obj_info.path, NULL);
|
if (r == SC_ERROR_FILE_NOT_FOUND)
|
||||||
// sc_ctx_suppress_errors_off(card->ctx);
|
continue;
|
||||||
// if (r == SC_ERROR_FILE_NOT_FOUND)
|
*/
|
||||||
// continue;
|
|
||||||
|
|
||||||
strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||||
r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
|
r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
|
@ -330,10 +326,8 @@ const objdata objects[] = {
|
||||||
/* see if we have a cert */
|
/* see if we have a cert */
|
||||||
|
|
||||||
/* use a &file_out so card-piv will read cert if present */
|
/* use a &file_out so card-piv will read cert if present */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_pkcs15_read_file(p15card, &cert_info.path,
|
r = sc_pkcs15_read_file(p15card, &cert_info.path,
|
||||||
&cert_der.value, &cert_der.len, &file_out);
|
&cert_der.value, &cert_der.len, &file_out);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (file_out) {
|
if (file_out) {
|
||||||
sc_file_free(file_out);
|
sc_file_free(file_out);
|
||||||
file_out = NULL;
|
file_out = NULL;
|
||||||
|
@ -368,7 +362,7 @@ const objdata objects[] = {
|
||||||
|
|
||||||
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
|
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, " Failed to add cert obj r=%d",r);
|
sc_debug(card->ctx, " Failed to add cert obj r=%d",r);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,9 +435,7 @@ const objdata objects[] = {
|
||||||
/* TODO DSA */
|
/* TODO DSA */
|
||||||
pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
|
pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
|
||||||
pubkey_obj.data = &pubkey_info;
|
pubkey_obj.data = &pubkey_info;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
|
r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
pubkey_obj.data = NULL;
|
pubkey_obj.data = NULL;
|
||||||
sc_debug(card->ctx," READING PUB KEY r=%d",r);
|
sc_debug(card->ctx," READING PUB KEY r=%d",r);
|
||||||
if (r < 0 ) {
|
if (r < 0 ) {
|
||||||
|
|
|
@ -332,7 +332,7 @@ static int sc_pkcs15emu_postecert_init(sc_pkcs15_card_t * p15card)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Failed to initialize Postecert and Cnipa emulation: %s\n",
|
"Failed to initialize Postecert and Cnipa emulation: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -191,7 +191,7 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card,
|
||||||
keyinfo_gostparams->gostr3411 = gostr3410_params[1];
|
keyinfo_gostparams->gostr3411 = gostr3410_params[1];
|
||||||
keyinfo_gostparams->gost28147 = gostr3410_params[2];
|
keyinfo_gostparams->gost28147 = gostr3410_params[2];
|
||||||
} else {
|
} else {
|
||||||
sc_error(ctx, "Neither RSA or DSA or GOSTR3410 key in PrKDF entry.\n");
|
sc_debug(ctx, "Neither RSA or DSA or GOSTR3410 key in PrKDF entry.\n");
|
||||||
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INVALID_ASN1_OBJECT);
|
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INVALID_ASN1_OBJECT);
|
||||||
}
|
}
|
||||||
r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
|
r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
|
||||||
|
@ -287,7 +287,7 @@ int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "Invalid private key type: %X\n", obj->type);
|
sc_debug(ctx, "Invalid private key type: %X\n", obj->type);
|
||||||
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ sc_pkcs15_encode_prkey(sc_context_t *ctx,
|
||||||
{
|
{
|
||||||
if (key->algorithm == SC_ALGORITHM_DSA)
|
if (key->algorithm == SC_ALGORITHM_DSA)
|
||||||
return sc_pkcs15_encode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
return sc_pkcs15_encode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
||||||
sc_error(ctx, "Cannot encode private key type %u.\n",
|
sc_debug(ctx, "Cannot encode private key type %u.\n",
|
||||||
key->algorithm);
|
key->algorithm);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ sc_pkcs15_decode_prkey(sc_context_t *ctx,
|
||||||
{
|
{
|
||||||
if (key->algorithm == SC_ALGORITHM_DSA)
|
if (key->algorithm == SC_ALGORITHM_DSA)
|
||||||
return sc_pkcs15_decode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
return sc_pkcs15_decode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
||||||
sc_error(ctx, "Cannot decode private key type %u.\n",
|
sc_debug(ctx, "Cannot decode private key type %u.\n",
|
||||||
key->algorithm);
|
key->algorithm);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -390,12 +390,12 @@ sc_pkcs15_read_prkey(struct sc_pkcs15_card *p15card,
|
||||||
key.algorithm = SC_ALGORITHM_DSA;
|
key.algorithm = SC_ALGORITHM_DSA;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "Unsupported object type.\n");
|
sc_debug(ctx, "Unsupported object type.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
info = (struct sc_pkcs15_prkey_info *) obj->data;
|
info = (struct sc_pkcs15_prkey_info *) obj->data;
|
||||||
if (info->native) {
|
if (info->native) {
|
||||||
sc_error(ctx, "Private key is native, will not read.");
|
sc_debug(ctx, "Private key is native, will not read.");
|
||||||
return SC_ERROR_NOT_ALLOWED;
|
return SC_ERROR_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ sc_pkcs15_read_prkey(struct sc_pkcs15_card *p15card,
|
||||||
|
|
||||||
r = sc_pkcs15_read_file(p15card, &path, &data, &len, NULL);
|
r = sc_pkcs15_read_file(p15card, &path, &data, &len, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(ctx, "Unable to read private key file.\n");
|
sc_debug(ctx, "Unable to read private key file.\n");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ sc_pkcs15_read_prkey(struct sc_pkcs15_card *p15card,
|
||||||
data, len,
|
data, len,
|
||||||
&clear, &clear_len);
|
&clear, &clear_len);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(ctx, "Failed to unwrap privat key.");
|
sc_debug(ctx, "Failed to unwrap privat key.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -433,7 +433,7 @@ sc_pkcs15_read_prkey(struct sc_pkcs15_card *p15card,
|
||||||
|
|
||||||
r = sc_pkcs15_decode_prkey(ctx, &key, data, len);
|
r = sc_pkcs15_decode_prkey(ctx, &key, data, len);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(ctx, "Unable to decode private key");
|
sc_debug(ctx, "Unable to decode private key");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
* PKCS15 emulation layer for Portugal eID card.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Joao Poupino <joao.poupino@ist.utl.pt>
|
||||||
|
* Copyright (C) 2004, Martin Paljak <martin@paljak.pri.ee>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Based on the PKCS#15 emulation layer for EstEID card by Martin Paljak
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The card has a valid PKCS#15 file system. However, the private keys
|
||||||
|
* are missing the SC_PKCS15_CO_FLAG_PRIVATE flag and this causes problems
|
||||||
|
* with some applications (i.e. they don't work).
|
||||||
|
*
|
||||||
|
* The three main objectives of the emulation layer are:
|
||||||
|
*
|
||||||
|
* 1. Add the necessary SC_PKCS15_CO_FLAG_PRIVATE flag to private keys.
|
||||||
|
* 2. Hide "superfluous" PKCS#15 objects, e.g. PUKs (the user can't use them).
|
||||||
|
* 3. Improve usability by providing more descriptive names for the PINs, Keys, etc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "pkcs15.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <compat_strlcpy.h>
|
||||||
|
|
||||||
|
#define IAS_CARD 0
|
||||||
|
#define GEMSAFE_CARD 1
|
||||||
|
|
||||||
|
int sc_pkcs15emu_pteid_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||||
|
|
||||||
|
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
|
||||||
|
{
|
||||||
|
int r, i, type;
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t len;
|
||||||
|
sc_pkcs15_tokeninfo_t tokeninfo;
|
||||||
|
sc_path_t tmppath;
|
||||||
|
sc_card_t *card = p15card->card;
|
||||||
|
sc_context_t *ctx = card->ctx;
|
||||||
|
|
||||||
|
/* Parse the TokenInfo EF */
|
||||||
|
sc_format_path("3f004f005032", &tmppath);
|
||||||
|
r = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
|
||||||
|
if (r)
|
||||||
|
goto end;
|
||||||
|
if ( (len = p15card->file_tokeninfo->size) == 0) {
|
||||||
|
sc_debug(card->ctx, "EF(TokenInfo) is empty\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
buf = malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
r = sc_read_binary(card, 0, buf, len, 0);
|
||||||
|
if (r < 0)
|
||||||
|
goto end;
|
||||||
|
if (r <= 2) {
|
||||||
|
r = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
memset(&tokeninfo, 0, sizeof(tokeninfo));
|
||||||
|
r = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t) r);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
p15card->version = tokeninfo.version;
|
||||||
|
p15card->label = tokeninfo.label;
|
||||||
|
p15card->serial_number = tokeninfo.serial_number;
|
||||||
|
p15card->manufacturer_id = tokeninfo.manufacturer_id;
|
||||||
|
p15card->last_update = tokeninfo.last_update;
|
||||||
|
p15card->flags = tokeninfo.flags;
|
||||||
|
p15card->preferred_language = tokeninfo.preferred_language;
|
||||||
|
p15card->seInfo = tokeninfo.seInfo;
|
||||||
|
p15card->num_seInfo = tokeninfo.num_seInfo;
|
||||||
|
|
||||||
|
/* Card type detection */
|
||||||
|
if (card->type == SC_CARD_TYPE_IAS_PTEID)
|
||||||
|
type = IAS_CARD;
|
||||||
|
else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
|
||||||
|
type = GEMSAFE_CARD;
|
||||||
|
else {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
p15card->flags = SC_PKCS15_CARD_FLAG_PRN_GENERATION
|
||||||
|
| SC_PKCS15_CARD_FLAG_EID_COMPLIANT
|
||||||
|
| SC_PKCS15_CARD_FLAG_READONLY;
|
||||||
|
|
||||||
|
/* TODO: Use the cardholder's name? */
|
||||||
|
/* TODO: Use Portuguese descriptions? */
|
||||||
|
|
||||||
|
/* Add X.509 Certificates */
|
||||||
|
static const char *pteid_cert_names[4] = {
|
||||||
|
"AUTHENTICATION CERTIFICATE",
|
||||||
|
"SIGNATURE CERTIFICATE",
|
||||||
|
"SIGNATURE SUB CA",
|
||||||
|
"AUTHENTICATION SUB CA"
|
||||||
|
};
|
||||||
|
/* X.509 Certificate Paths */
|
||||||
|
static const char *pteid_cert_paths[4] = {
|
||||||
|
"3f005f00ef09", /* Authentication Certificate path */
|
||||||
|
"3f005f00ef08", /* Digital Signature Certificate path */
|
||||||
|
"3f005f00ef0f", /* Signature sub CA path */
|
||||||
|
"3f005f00ef10" /* Authentication sub CA path */
|
||||||
|
};
|
||||||
|
/* X.509 Certificate IDs */
|
||||||
|
static const int pteid_cert_ids[4] = {0x45, 0x46, 0x51, 0x52};
|
||||||
|
struct sc_pkcs15_cert_info cert_info;
|
||||||
|
struct sc_pkcs15_object cert_obj;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
memset(&cert_info, 0, sizeof(cert_info));
|
||||||
|
memset(&cert_obj, 0, sizeof(cert_obj));
|
||||||
|
|
||||||
|
cert_info.id.value[0] = pteid_cert_ids[i];
|
||||||
|
cert_info.id.len = 1;
|
||||||
|
sc_format_path(pteid_cert_paths[i], &cert_info.path);
|
||||||
|
strlcpy(cert_obj.label, pteid_cert_names[i], sizeof(cert_obj.label));
|
||||||
|
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
|
||||||
|
if (r < 0) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add PINs */
|
||||||
|
static const char *pteid_pin_names[3] = {
|
||||||
|
"Auth PIN",
|
||||||
|
"Sign PIN",
|
||||||
|
"Address PIN"
|
||||||
|
};
|
||||||
|
/* PIN References */
|
||||||
|
static const int pteid_pin_ref[2][3] = { {1, 130, 131}, {129, 130, 131} };
|
||||||
|
/* PIN Authentication IDs */
|
||||||
|
static const int pteid_pin_authid[3] = {1, 2, 3};
|
||||||
|
/* PIN Paths */
|
||||||
|
static const char *pteid_pin_paths[2][3] = { {NULL, "3f005f00", NULL},
|
||||||
|
{NULL, NULL, NULL} };
|
||||||
|
struct sc_pkcs15_pin_info pin_info;
|
||||||
|
struct sc_pkcs15_object pin_obj;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
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] = pteid_pin_authid[i];
|
||||||
|
pin_info.reference = pteid_pin_ref[type][i];
|
||||||
|
pin_info.flags = SC_PKCS15_PIN_FLAG_NEEDS_PADDING
|
||||||
|
| SC_PKCS15_PIN_FLAG_INITIALIZED
|
||||||
|
| SC_PKCS15_PIN_FLAG_CASE_SENSITIVE;
|
||||||
|
pin_info.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
|
||||||
|
pin_info.min_length = 4;
|
||||||
|
pin_info.stored_length = 8;
|
||||||
|
pin_info.max_length = 8;
|
||||||
|
pin_info.pad_char = type == IAS_CARD ? 0x2F : 0xFF;
|
||||||
|
pin_info.tries_left = -1;
|
||||||
|
if (pteid_pin_paths[type][i] != NULL)
|
||||||
|
sc_format_path(pteid_pin_paths[type][i], &pin_info.path);
|
||||||
|
strlcpy(pin_obj.label, pteid_pin_names[i], sizeof(pin_obj.label));
|
||||||
|
pin_obj.flags = 0;
|
||||||
|
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
|
||||||
|
if (r < 0) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add Private Keys */
|
||||||
|
|
||||||
|
/* Key reference */
|
||||||
|
static const int pteid_prkey_keyref[2][2] = { {1, 130}, {2, 1} };
|
||||||
|
/* RSA Private Key usage */
|
||||||
|
static int pteid_prkey_usage[2] = {
|
||||||
|
SC_PKCS15_PRKEY_USAGE_SIGN,
|
||||||
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION};
|
||||||
|
/* RSA Private Key IDs */
|
||||||
|
static const int pteid_prkey_ids[2] = {0x45, 0x46};
|
||||||
|
static const char *pteid_prkey_names[2] = {
|
||||||
|
"CITIZEN AUTHENTICATION KEY",
|
||||||
|
"CITIZEN SIGNATURE KEY"};
|
||||||
|
/* RSA Private Key Paths */
|
||||||
|
static const char *pteid_prkey_paths[2][2] = { {NULL, "3f005f00"}, {NULL, NULL} };
|
||||||
|
struct sc_pkcs15_prkey_info prkey_info;
|
||||||
|
struct sc_pkcs15_object prkey_obj;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
memset(&prkey_info, 0, sizeof(prkey_info));
|
||||||
|
memset(&prkey_obj, 0, sizeof(prkey_obj));
|
||||||
|
|
||||||
|
prkey_info.id.len = 1;
|
||||||
|
prkey_info.id.value[0] = pteid_prkey_ids[i];
|
||||||
|
prkey_info.usage = pteid_prkey_usage[i];
|
||||||
|
prkey_info.native = 1;
|
||||||
|
prkey_info.key_reference = pteid_prkey_keyref[type][i];
|
||||||
|
prkey_info.modulus_length = 1024;
|
||||||
|
if (pteid_prkey_paths[type][i] != NULL)
|
||||||
|
sc_format_path(pteid_prkey_paths[type][i], &prkey_info.path);
|
||||||
|
strlcpy(prkey_obj.label, pteid_prkey_names[i], sizeof(prkey_obj.label));
|
||||||
|
prkey_obj.auth_id.len = 1;
|
||||||
|
prkey_obj.auth_id.value[0] = i + 1;
|
||||||
|
prkey_obj.user_consent = (i == 1) ? 1 : 0;
|
||||||
|
prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
||||||
|
|
||||||
|
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||||
|
if (r < 0) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add objects */
|
||||||
|
static const char *object_ids[3] = {"1", "2", "3"};
|
||||||
|
static const char *object_oids[3] = {"-1", "-1", "-1"};
|
||||||
|
static const char *object_labels[3] = {"Citizen Data",
|
||||||
|
"Citizen Address Data",
|
||||||
|
"Citizen Notepad"};
|
||||||
|
static const char *object_authids[3] = {"3", "3", "1"};
|
||||||
|
static const char *object_paths[3] = {"3f005f00ef02",
|
||||||
|
"3f005f00ef05",
|
||||||
|
"3f005f00ef07"};
|
||||||
|
static const int object_flags[3] = {0,
|
||||||
|
SC_PKCS15_CO_FLAG_PRIVATE,
|
||||||
|
SC_PKCS15_CO_FLAG_MODIFIABLE};
|
||||||
|
struct sc_pkcs15_data_info obj_info;
|
||||||
|
struct sc_pkcs15_object obj_obj;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
memset(&obj_info, 0, sizeof(obj_info));
|
||||||
|
memset(&obj_obj, 0, sizeof(obj_obj));
|
||||||
|
|
||||||
|
sc_pkcs15_format_id(object_ids[i], &obj_info.id);
|
||||||
|
sc_format_path(object_paths[i], &obj_info.path);
|
||||||
|
r = sc_format_oid(&obj_info.app_oid, object_oids[i]);
|
||||||
|
if (r != SC_SUCCESS)
|
||||||
|
goto end;
|
||||||
|
strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
|
||||||
|
if (object_authids[i] != NULL)
|
||||||
|
sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id);
|
||||||
|
strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
|
||||||
|
obj_obj.flags = object_flags[i];
|
||||||
|
|
||||||
|
r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info);
|
||||||
|
if (r < 0)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
if (buf != NULL) {
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return SC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pteid_detect_card(sc_pkcs15_card_t *p15card)
|
||||||
|
{
|
||||||
|
if (p15card->card->type == SC_CARD_TYPE_IAS_PTEID ||
|
||||||
|
p15card->card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
|
||||||
|
return SC_SUCCESS;
|
||||||
|
return SC_ERROR_WRONG_CARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_pkcs15emu_pteid_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opts)
|
||||||
|
{
|
||||||
|
if (opts != NULL && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
|
||||||
|
return sc_pkcs15emu_pteid_init(p15card);
|
||||||
|
else {
|
||||||
|
int r = pteid_detect_card(p15card);
|
||||||
|
if (r)
|
||||||
|
return SC_ERROR_WRONG_CARD;
|
||||||
|
return sc_pkcs15emu_pteid_init(p15card);
|
||||||
|
}
|
||||||
|
}
|
|
@ -273,7 +273,7 @@ int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "Unsupported public key type: %X\n", obj->type);
|
sc_debug(ctx, "Unsupported public key type: %X\n", obj->type);
|
||||||
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
|
SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx,
|
||||||
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
|
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
|
||||||
return sc_pkcs15_encode_pubkey_gostr3410(ctx,
|
return sc_pkcs15_encode_pubkey_gostr3410(ctx,
|
||||||
&key->u.gostr3410, buf, len);
|
&key->u.gostr3410, buf, len);
|
||||||
sc_error(ctx, "Encoding of public key type %u not supported\n",
|
sc_debug(ctx, "Encoding of public key type %u not supported\n",
|
||||||
key->algorithm);
|
key->algorithm);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +501,7 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx,
|
||||||
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
|
if (key->algorithm == SC_ALGORITHM_GOSTR3410)
|
||||||
return sc_pkcs15_decode_pubkey_gostr3410(ctx,
|
return sc_pkcs15_decode_pubkey_gostr3410(ctx,
|
||||||
&key->u.gostr3410, buf, len);
|
&key->u.gostr3410, buf, len);
|
||||||
sc_error(ctx, "Decoding of public key type %u not supported\n",
|
sc_debug(ctx, "Decoding of public key type %u not supported\n",
|
||||||
key->algorithm);
|
key->algorithm);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -534,14 +534,14 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
|
||||||
algorithm = SC_ALGORITHM_GOSTR3410;
|
algorithm = SC_ALGORITHM_GOSTR3410;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(p15card->card->ctx, "Unsupported public key type.");
|
sc_debug(p15card->card->ctx, "Unsupported public key type.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
info = (const struct sc_pkcs15_pubkey_info *) obj->data;
|
info = (const struct sc_pkcs15_pubkey_info *) obj->data;
|
||||||
|
|
||||||
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len, NULL);
|
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(p15card->card->ctx, "Failed to read public key file.");
|
sc_debug(p15card->card->ctx, "Failed to read public key file.");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx,
|
||||||
struct sc_pkcs15_prkey *prvkey, struct sc_pkcs15_pubkey **out)
|
struct sc_pkcs15_prkey *prvkey, struct sc_pkcs15_pubkey **out)
|
||||||
{
|
{
|
||||||
struct sc_pkcs15_pubkey *pubkey;
|
struct sc_pkcs15_pubkey *pubkey;
|
||||||
int ii, rv = SC_SUCCESS;
|
int rv = SC_SUCCESS;
|
||||||
|
|
||||||
assert(prvkey && out);
|
assert(prvkey && out);
|
||||||
|
|
||||||
|
@ -611,7 +611,7 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx,
|
||||||
case SC_ALGORITHM_GOSTR3410:
|
case SC_ALGORITHM_GOSTR3410:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "Unsupported private key algorithm");
|
sc_debug(ctx, "Unsupported private key algorithm");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,13 +77,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
||||||
return SC_ERROR_EXTRACTABLE_KEY;
|
return SC_ERROR_EXTRACTABLE_KEY;
|
||||||
|
|
||||||
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP))) {
|
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP))) {
|
||||||
sc_error(ctx, "This key cannot be used for decryption\n");
|
sc_debug(ctx, "This key cannot be used for decryption\n");
|
||||||
return SC_ERROR_NOT_ALLOWED;
|
return SC_ERROR_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
||||||
if (alg_info == NULL) {
|
if (alg_info == NULL) {
|
||||||
sc_error(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length);
|
sc_debug(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
senv.algorithm = SC_ALGORITHM_RSA;
|
senv.algorithm = SC_ALGORITHM_RSA;
|
||||||
|
@ -121,6 +121,10 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
||||||
SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
|
SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
|
||||||
}
|
}
|
||||||
r = sc_decipher(p15card->card, in, inlen, out, outlen);
|
r = sc_decipher(p15card->card, in, inlen, out, outlen);
|
||||||
|
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||||
|
if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
|
||||||
|
r = sc_decipher(p15card->card, in, inlen, out, outlen);
|
||||||
|
}
|
||||||
sc_unlock(p15card->card);
|
sc_unlock(p15card->card);
|
||||||
SC_TEST_RET(ctx, r, "sc_decipher() failed");
|
SC_TEST_RET(ctx, r, "sc_decipher() failed");
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
||||||
in, inlen, out, outlen);
|
in, inlen, out, outlen);
|
||||||
}
|
}
|
||||||
if (modlen > tmplen) {
|
if (modlen > tmplen) {
|
||||||
sc_error(ctx, "Buffer too small, needs recompile!\n");
|
sc_debug(ctx, "Buffer too small, needs recompile!\n");
|
||||||
return SC_ERROR_NOT_ALLOWED;
|
return SC_ERROR_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen);
|
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen);
|
||||||
|
@ -180,13 +184,13 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
||||||
|
|
||||||
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
||||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) {
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) {
|
||||||
sc_error(ctx, "This key cannot be used for signing\n");
|
sc_debug(ctx, "This key cannot be used for signing\n");
|
||||||
return SC_ERROR_NOT_ALLOWED;
|
return SC_ERROR_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
||||||
if (alg_info == NULL) {
|
if (alg_info == NULL) {
|
||||||
sc_error(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length);
|
sc_debug(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
senv.algorithm = SC_ALGORITHM_RSA;
|
senv.algorithm = SC_ALGORITHM_RSA;
|
||||||
|
@ -268,6 +272,10 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen);
|
r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen);
|
||||||
|
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||||
|
if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
|
||||||
|
r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen);
|
||||||
|
}
|
||||||
sc_mem_clear(buf, sizeof(buf));
|
sc_mem_clear(buf, sizeof(buf));
|
||||||
sc_unlock(p15card->card);
|
sc_unlock(p15card->card);
|
||||||
SC_TEST_RET(ctx, r, "sc_compute_signature() failed");
|
SC_TEST_RET(ctx, r, "sc_compute_signature() failed");
|
||||||
|
|
|
@ -105,9 +105,7 @@ static int starcert_detect_card(sc_pkcs15_card_t *p15card)
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
/* read EF_Info file */
|
/* read EF_Info file */
|
||||||
sc_format_path("3F00FE13", &path);
|
sc_format_path("3F00FE13", &path);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
r = sc_read_binary(card, 0, buf, 64, 0);
|
r = sc_read_binary(card, 0, buf, 64, 0);
|
||||||
|
|
|
@ -56,6 +56,8 @@ extern int sc_pkcs15emu_tccardos_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t
|
||||||
|
|
||||||
extern int sc_pkcs15emu_entersafe_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
extern int sc_pkcs15emu_entersafe_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||||
|
|
||||||
|
extern int sc_pkcs15emu_pteid_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
const char * name;
|
const char * name;
|
||||||
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||||
|
@ -74,6 +76,7 @@ static struct {
|
||||||
{ "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex},
|
{ "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex},
|
||||||
{ "tccardos", sc_pkcs15emu_tccardos_init_ex },
|
{ "tccardos", sc_pkcs15emu_tccardos_init_ex },
|
||||||
{ "entersafe", sc_pkcs15emu_entersafe_init_ex },
|
{ "entersafe", sc_pkcs15emu_entersafe_init_ex },
|
||||||
|
{ "pteid", sc_pkcs15emu_pteid_init_ex },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,6 +93,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
|
||||||
{
|
{
|
||||||
switch (card->type) {
|
switch (card->type) {
|
||||||
case SC_CARD_TYPE_MCRD_ESTEID:
|
case SC_CARD_TYPE_MCRD_ESTEID:
|
||||||
|
case SC_CARD_TYPE_IAS_PTEID:
|
||||||
|
case SC_CARD_TYPE_GEMSAFEV1_PTEID:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -178,22 +183,13 @@ out: if (r == SC_SUCCESS) {
|
||||||
p15card->magic = SC_PKCS15_CARD_MAGIC;
|
p15card->magic = SC_PKCS15_CARD_MAGIC;
|
||||||
p15card->flags |= SC_PKCS15_CARD_FLAG_EMULATED;
|
p15card->flags |= SC_PKCS15_CARD_FLAG_EMULATED;
|
||||||
} else if (r != SC_ERROR_WRONG_CARD) {
|
} else if (r != SC_ERROR_WRONG_CARD) {
|
||||||
sc_error(ctx, "Failed to load card emulator: %s\n",
|
sc_debug(ctx, "Failed to load card emulator: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emu_detect_card(sc_card_t *card, const scconf_block *blk, int *force)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
/* TBD */
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
|
static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
|
||||||
{
|
{
|
||||||
sc_card_t *card = p15card->card;
|
sc_card_t *card = p15card->card;
|
||||||
|
@ -207,10 +203,6 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
|
||||||
|
|
||||||
driver = conf->name->data;
|
driver = conf->name->data;
|
||||||
|
|
||||||
r = emu_detect_card(card, conf, &force);
|
|
||||||
if (r < 0)
|
|
||||||
return SC_ERROR_INTERNAL;
|
|
||||||
|
|
||||||
init_func = NULL;
|
init_func = NULL;
|
||||||
init_func_ex = NULL;
|
init_func_ex = NULL;
|
||||||
|
|
||||||
|
@ -400,7 +392,7 @@ int sc_pkcs15emu_object_add(sc_pkcs15_card_t *p15card, unsigned int type,
|
||||||
data_len = sizeof(struct sc_pkcs15_data_info);
|
data_len = sizeof(struct sc_pkcs15_data_info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(p15card->card->ctx,
|
sc_debug(p15card->card->ctx,
|
||||||
"Unknown PKCS15 object type %d\n", type);
|
"Unknown PKCS15 object type %d\n", type);
|
||||||
free(obj);
|
free(obj);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
|
@ -455,14 +455,10 @@ int sc_pkcs15emu_tcos_init_ex(
|
||||||
serial[19] = '\0';
|
serial[19] = '\0';
|
||||||
p15card->serial_number = strdup(serial);
|
p15card->serial_number = strdup(serial);
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(ctx);
|
|
||||||
|
|
||||||
if(!detect_netkey(p15card)) return SC_SUCCESS;
|
if(!detect_netkey(p15card)) return SC_SUCCESS;
|
||||||
if(!detect_signtrust(p15card)) return SC_SUCCESS;
|
if(!detect_signtrust(p15card)) return SC_SUCCESS;
|
||||||
if(!detect_datev(p15card)) return SC_SUCCESS;
|
if(!detect_datev(p15card)) return SC_SUCCESS;
|
||||||
if(!detect_unicard(p15card)) return SC_SUCCESS;
|
if(!detect_unicard(p15card)) return SC_SUCCESS;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_off(ctx);
|
|
||||||
|
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ sc_pkcs15_derive_key(sc_context_t *ctx,
|
||||||
|
|
||||||
/* XXX: We might also encounter PBES2 here */
|
/* XXX: We might also encounter PBES2 here */
|
||||||
if (der_alg->algorithm != SC_ALGORITHM_PBKDF2) {
|
if (der_alg->algorithm != SC_ALGORITHM_PBKDF2) {
|
||||||
sc_error(ctx, "Unsupported key derivation algorithm.\n");
|
sc_debug(ctx, "Unsupported key derivation algorithm.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,27 +92,27 @@ sc_pkcs15_derive_key(sc_context_t *ctx,
|
||||||
iv = (u8 *) enc_alg->params;
|
iv = (u8 *) enc_alg->params;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(ctx, "Unsupported key encryption algorithm.\n");
|
sc_debug(ctx, "Unsupported key encryption algorithm.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iv) {
|
if (!iv) {
|
||||||
sc_error(ctx, "Unsupported key encryption parameters.\n");
|
sc_debug(ctx, "Unsupported key encryption parameters.\n");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
key_len = EVP_CIPHER_key_length(cipher);
|
key_len = EVP_CIPHER_key_length(cipher);
|
||||||
|
|
||||||
info = (struct sc_pbkdf2_params *) der_alg->params;
|
info = (struct sc_pbkdf2_params *) der_alg->params;
|
||||||
if (!info) {
|
if (!info) {
|
||||||
sc_error(ctx, "Key parameters missing.\n");
|
sc_debug(ctx, "Key parameters missing.\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (info->key_length && info->key_length != key_len) {
|
if (info->key_length && info->key_length != key_len) {
|
||||||
sc_error(ctx, "Incompatible key length.\n");
|
sc_debug(ctx, "Incompatible key length.\n");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (key_len > sizeof(key)) {
|
if (key_len > sizeof(key)) {
|
||||||
sc_error(ctx, "Huge key length (%u).\n", key_len);
|
sc_debug(ctx, "Huge key length (%u).\n", key_len);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ sc_pkcs15_derive_key(sc_context_t *ctx,
|
||||||
info->salt, info->salt_len,
|
info->salt, info->salt_len,
|
||||||
info->iterations, key_len, key);
|
info->iterations, key_len, key);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
sc_error(ctx, "Key derivation failed.\n");
|
sc_debug(ctx, "Key derivation failed.\n");
|
||||||
return SC_ERROR_INTERNAL; /* for lack of something better */
|
return SC_ERROR_INTERNAL; /* for lack of something better */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ sc_pkcs15_unwrap_data(sc_context_t *ctx,
|
||||||
memset(&envdata, 0, sizeof(envdata));
|
memset(&envdata, 0, sizeof(envdata));
|
||||||
r = sc_pkcs15_decode_enveloped_data(ctx, &envdata, in, in_len);
|
r = sc_pkcs15_decode_enveloped_data(ctx, &envdata, in, in_len);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(ctx, "Failed to decode EnvelopedData.\n");
|
sc_debug(ctx, "Failed to decode EnvelopedData.\n");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx,
|
||||||
|
|
||||||
r = sc_asn1_decode(ctx, asn1_tokeninfo, buf, blen, NULL, NULL);
|
r = sc_asn1_decode(ctx, asn1_tokeninfo, buf, blen, NULL, NULL);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "ASN.1 parsing of EF(TokenInfo) failed: %s\n",
|
sc_debug(ctx, "ASN.1 parsing of EF(TokenInfo) failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ int sc_pkcs15_encode_tokeninfo(sc_context_t *ctx,
|
||||||
|
|
||||||
r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
|
r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
|
sc_debug(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -223,7 +223,7 @@ static int parse_ddo(struct sc_pkcs15_card *p15card, const u8 * buf, size_t bufl
|
||||||
|
|
||||||
r = sc_asn1_decode(p15card->card->ctx, asn1_ddo, buf, buflen, NULL, NULL);
|
r = sc_asn1_decode(p15card->card->ctx, asn1_ddo, buf, buflen, NULL, NULL);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(p15card->card->ctx, "DDO parsing failed: %s\n",
|
sc_debug(p15card->card->ctx, "DDO parsing failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ static int encode_ddo(struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen)
|
||||||
|
|
||||||
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "sc_asn1_encode() failed: %s\n",
|
sc_debug(ctx, "sc_asn1_encode() failed: %s\n",
|
||||||
sc_strerror(r));
|
sc_strerror(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ int sc_pkcs15_encode_odf(sc_context_t *ctx,
|
||||||
df = df->next;
|
df = df->next;
|
||||||
};
|
};
|
||||||
if (df_count == 0) {
|
if (df_count == 0) {
|
||||||
sc_error(ctx, "No DF's found.\n");
|
sc_debug(ctx, "No DF's found.\n");
|
||||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
asn1_odf = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count + 1));
|
asn1_odf = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count + 1));
|
||||||
|
@ -384,7 +384,7 @@ int sc_pkcs15_encode_odf(sc_context_t *ctx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (type == -1) {
|
if (type == -1) {
|
||||||
sc_error(ctx, "Unsupported DF type.\n");
|
sc_debug(ctx, "Unsupported DF type.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
asn1_odf[c] = c_asn1_odf[type];
|
asn1_odf[c] = c_asn1_odf[type];
|
||||||
|
@ -416,6 +416,8 @@ struct sc_pkcs15_card * sc_pkcs15_card_new(void)
|
||||||
|
|
||||||
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
|
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (p15card == NULL)
|
if (p15card == NULL)
|
||||||
return;
|
return;
|
||||||
assert(p15card->magic == SC_PKCS15_CARD_MAGIC);
|
assert(p15card->magic == SC_PKCS15_CARD_MAGIC);
|
||||||
|
@ -446,11 +448,14 @@ void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
|
||||||
if (p15card->preferred_language != NULL)
|
if (p15card->preferred_language != NULL)
|
||||||
free(p15card->preferred_language);
|
free(p15card->preferred_language);
|
||||||
if (p15card->seInfo != NULL) {
|
if (p15card->seInfo != NULL) {
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < p15card->num_seInfo; i++)
|
for (i = 0; i < p15card->num_seInfo; i++)
|
||||||
free(p15card->seInfo[i]);
|
free(p15card->seInfo[i]);
|
||||||
free(p15card->seInfo);
|
free(p15card->seInfo);
|
||||||
}
|
}
|
||||||
|
for (i=0; i<SC_PKCS15_MAX_PINS && p15card->pin_cache[i] != NULL; i++) {
|
||||||
|
sc_mem_clear(p15card->pin_cache[i]->pin, p15card->pin_cache[i]->len);
|
||||||
|
free(p15card->pin_cache[i]);
|
||||||
|
}
|
||||||
free(p15card);
|
free(p15card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +534,7 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
if (card->app_count < 0) {
|
if (card->app_count < 0) {
|
||||||
err = sc_enum_apps(card);
|
err = sc_enum_apps(card);
|
||||||
if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) {
|
if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) {
|
||||||
sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err));
|
sc_debug(ctx, "unable to enumerate apps: %s\n", sc_strerror(err));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,7 +557,6 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if pkcs15 directory exists */
|
/* Check if pkcs15 directory exists */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
err = sc_select_file(card, &p15card->file_app->path, NULL);
|
err = sc_select_file(card, &p15card->file_app->path, NULL);
|
||||||
#if 1
|
#if 1
|
||||||
/* If the above test failed on cards without EF(DIR),
|
/* If the above test failed on cards without EF(DIR),
|
||||||
|
@ -564,18 +568,14 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
err = SC_NO_ERROR;
|
err = SC_NO_ERROR;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (p15card->file_odf == NULL) {
|
if (p15card->file_odf == NULL) {
|
||||||
/* check if an ODF is present; suppress errors as we
|
/* check if an ODF is present; we don't know yet whether we have a pkcs15 card */
|
||||||
* don't know yet whether we have a pkcs15 card */
|
|
||||||
tmppath = p15card->file_app->path;
|
tmppath = p15card->file_app->path;
|
||||||
sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2);
|
sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
err = sc_select_file(card, &tmppath, &p15card->file_odf);
|
err = sc_select_file(card, &tmppath, &p15card->file_odf);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tmppath = p15card->file_odf->path;
|
tmppath = p15card->file_odf->path;
|
||||||
|
@ -595,7 +595,7 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((len = p15card->file_odf->size) == 0) {
|
if ((len = p15card->file_odf->size) == 0) {
|
||||||
sc_error(card->ctx, "EF(ODF) is empty\n");
|
sc_debug(card->ctx, "EF(ODF) is empty\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
|
@ -611,7 +611,7 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
len = err;
|
len = err;
|
||||||
if (parse_odf(buf, len, p15card)) {
|
if (parse_odf(buf, len, p15card)) {
|
||||||
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
|
||||||
sc_error(card->ctx, "Unable to parse ODF\n");
|
sc_debug(card->ctx, "Unable to parse ODF\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -647,7 +647,7 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if ((len = p15card->file_tokeninfo->size) == 0) {
|
if ((len = p15card->file_tokeninfo->size) == 0) {
|
||||||
sc_error(card->ctx, "EF(TokenInfo) is empty\n");
|
sc_debug(card->ctx, "EF(TokenInfo) is empty\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
|
@ -692,8 +692,8 @@ int sc_pkcs15_bind(sc_card_t *card,
|
||||||
{
|
{
|
||||||
struct sc_pkcs15_card *p15card = NULL;
|
struct sc_pkcs15_card *p15card = NULL;
|
||||||
sc_context_t *ctx;
|
sc_context_t *ctx;
|
||||||
scconf_block *conf_block = NULL, **blocks;
|
scconf_block *conf_block = NULL;
|
||||||
int i, r, emu_first, enable_emu;
|
int r, emu_first, enable_emu;
|
||||||
|
|
||||||
assert(sc_card_valid(card) && p15card_out != NULL);
|
assert(sc_card_valid(card) && p15card_out != NULL);
|
||||||
ctx = card->ctx;
|
ctx = card->ctx;
|
||||||
|
@ -701,23 +701,25 @@ int sc_pkcs15_bind(sc_card_t *card,
|
||||||
p15card = sc_pkcs15_card_new();
|
p15card = sc_pkcs15_card_new();
|
||||||
if (p15card == NULL)
|
if (p15card == NULL)
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
p15card->card = card;
|
|
||||||
|
|
||||||
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
|
p15card->card = card;
|
||||||
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
|
p15card->opts.use_file_cache = 0;
|
||||||
"framework", "pkcs15");
|
p15card->opts.use_pin_cache = 1;
|
||||||
if (blocks && blocks[0] != NULL)
|
p15card->opts.pin_cache_counter = 10;
|
||||||
conf_block = blocks[0];
|
|
||||||
free(blocks);
|
conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1);
|
||||||
}
|
|
||||||
|
|
||||||
if (conf_block) {
|
if (conf_block) {
|
||||||
p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0);
|
p15card->opts.use_file_cache = scconf_get_bool(conf_block, "use_file_caching", p15card->opts.use_file_cache);
|
||||||
|
p15card->opts.use_pin_cache = scconf_get_bool(conf_block, "use_pin_caching", p15card->opts.use_pin_cache);
|
||||||
|
p15card->opts.pin_cache_counter = scconf_get_bool(conf_block, "pin_cache_counter", p15card->opts.pin_cache_counter);
|
||||||
}
|
}
|
||||||
|
sc_debug(ctx, "PKCS#15 options: use_file_cache=%d use_pin_cache=%d pin_cache_counter=%d",
|
||||||
|
p15card->opts.use_file_cache, p15card->opts.use_pin_cache, p15card->opts.pin_cache_counter);
|
||||||
|
|
||||||
r = sc_lock(card);
|
r = sc_lock(card);
|
||||||
if (r) {
|
if (r) {
|
||||||
sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(r));
|
sc_debug(ctx, "sc_lock() failed: %s\n", sc_strerror(r));
|
||||||
sc_pkcs15_card_free(p15card);
|
sc_pkcs15_card_free(p15card);
|
||||||
SC_FUNC_RETURN(ctx, 1, r);
|
SC_FUNC_RETURN(ctx, 1, r);
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1371,7 @@ int sc_pkcs15_encode_df(sc_context_t *ctx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
sc_error(ctx, "unknown DF type: %d\n", df->type);
|
sc_debug(ctx, "unknown DF type: %d\n", df->type);
|
||||||
*buf_out = NULL;
|
*buf_out = NULL;
|
||||||
*bufsize_out = 0;
|
*bufsize_out = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1426,7 +1428,7 @@ int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
sc_error(ctx, "unknown DF type: %d\n", df->type);
|
sc_debug(ctx, "unknown DF type: %d\n", df->type);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
if (df->file != NULL)
|
if (df->file != NULL)
|
||||||
|
@ -1496,7 +1498,7 @@ int sc_pkcs15_add_unusedspace(struct sc_pkcs15_card *p15card,
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
pbuf[0] = '\0';
|
pbuf[0] = '\0';
|
||||||
|
|
||||||
sc_error(p15card->card->ctx, "No offset and length present in path %s\n", pbuf);
|
sc_debug(p15card->card->ctx, "No offset and length present in path %s\n", pbuf);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1680,7 +1682,7 @@ int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = -1; /* file state: not in cache */
|
r = -1; /* file state: not in cache */
|
||||||
if (p15card->opts.use_cache) {
|
if (p15card->opts.use_file_cache) {
|
||||||
r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len);
|
r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len);
|
||||||
}
|
}
|
||||||
if (r) {
|
if (r) {
|
||||||
|
@ -1719,10 +1721,8 @@ int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card,
|
||||||
for (i=1; ; i++) {
|
for (i=1; ; i++) {
|
||||||
l = len - (head - data);
|
l = len - (head - data);
|
||||||
if (l > 256) { l = 256; }
|
if (l > 256) { l = 256; }
|
||||||
p15card->card->ctx->suppress_errors++;
|
|
||||||
r = sc_read_record(p15card->card, i, head, l,
|
r = sc_read_record(p15card->card, i, head, l,
|
||||||
SC_RECORD_BY_REC_NR);
|
SC_RECORD_BY_REC_NR);
|
||||||
p15card->card->ctx->suppress_errors--;
|
|
||||||
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
if (r == SC_ERROR_RECORD_NOT_FOUND)
|
||||||
break;
|
break;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct sc_pkcs15_pin_info {
|
||||||
u8 pad_char;
|
u8 pad_char;
|
||||||
struct sc_path path;
|
struct sc_path path;
|
||||||
int tries_left;
|
int tries_left;
|
||||||
|
int max_tries;
|
||||||
|
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
};
|
};
|
||||||
|
@ -379,6 +380,13 @@ typedef struct {
|
||||||
size_t aid_len;
|
size_t aid_len;
|
||||||
} sc_pkcs15_sec_env_info_t;
|
} sc_pkcs15_sec_env_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sc_pkcs15_id_t id;
|
||||||
|
u8 pin[SC_MAX_PIN_SIZE];
|
||||||
|
size_t len;
|
||||||
|
int counter;
|
||||||
|
} sc_pkcs15_pincache_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
@ -411,11 +419,14 @@ typedef struct sc_pkcs15_card {
|
||||||
int unusedspace_read;
|
int unusedspace_read;
|
||||||
|
|
||||||
struct sc_pkcs15_card_opts {
|
struct sc_pkcs15_card_opts {
|
||||||
int use_cache;
|
int use_file_cache;
|
||||||
|
int use_pin_cache;
|
||||||
|
int pin_cache_counter;
|
||||||
} opts;
|
} opts;
|
||||||
|
|
||||||
sc_pkcs15_sec_env_info_t **seInfo;
|
sc_pkcs15_sec_env_info_t **seInfo;
|
||||||
size_t num_seInfo;
|
size_t num_seInfo;
|
||||||
|
sc_pkcs15_pincache_entry_t *pin_cache[SC_PKCS15_MAX_PINS];
|
||||||
|
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
|
|
||||||
|
@ -565,6 +576,8 @@ int sc_pkcs15_find_pin_by_reference(struct sc_pkcs15_card *card,
|
||||||
struct sc_pkcs15_object **out);
|
struct sc_pkcs15_object **out);
|
||||||
int sc_pkcs15_find_so_pin(struct sc_pkcs15_card *card,
|
int sc_pkcs15_find_so_pin(struct sc_pkcs15_card *card,
|
||||||
struct sc_pkcs15_object **out);
|
struct sc_pkcs15_object **out);
|
||||||
|
int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs15_object_t *obj);
|
||||||
|
void sc_pkcs15_pincache_clear(struct sc_pkcs15_card *p15card);
|
||||||
|
|
||||||
int sc_pkcs15_encode_dir(struct sc_context *ctx,
|
int sc_pkcs15_encode_dir(struct sc_context *ctx,
|
||||||
struct sc_pkcs15_card *card,
|
struct sc_pkcs15_card *card,
|
||||||
|
|
|
@ -96,11 +96,11 @@ static int ctapi_reset(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
||||||
if (rv || (lr < 2)) {
|
if (rv || (lr < 2)) {
|
||||||
sc_error(reader->ctx, "Error getting status of terminal: %d, using defaults\n", rv);
|
sc_debug(reader->ctx, "Error getting status of terminal: %d, using defaults\n", rv);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
if (rbuf[lr-2] != 0x90) {
|
if (rbuf[lr-2] != 0x90) {
|
||||||
sc_error(reader->ctx, "SW1/SW2: 0x%x/0x%x\n", rbuf[lr-2], rbuf[lr-1]);
|
sc_debug(reader->ctx, "SW1/SW2: 0x%x/0x%x\n", rbuf[lr-2], rbuf[lr-1]);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -141,7 +141,7 @@ static void detect_functional_units(sc_reader_t *reader)
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
||||||
if (rv || (lr < 4) || (rbuf[lr-2] != 0x90)) {
|
if (rv || (lr < 4) || (rbuf[lr-2] != 0x90)) {
|
||||||
sc_error(reader->ctx, "Error getting status of terminal: %d, using defaults\n", rv);
|
sc_debug(reader->ctx, "Error getting status of terminal: %d, using defaults\n", rv);
|
||||||
set_default_fu(reader);
|
set_default_fu(reader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -149,13 +149,13 @@ static void detect_functional_units(sc_reader_t *reader)
|
||||||
/* Number of slots might also detected by using CTBCS_P2_STATUS_ICC.
|
/* Number of slots might also detected by using CTBCS_P2_STATUS_ICC.
|
||||||
If you think that's important please do it... ;) */
|
If you think that's important please do it... ;) */
|
||||||
set_default_fu(reader);
|
set_default_fu(reader);
|
||||||
sc_error(reader->ctx, "Invalid data object returnd on CTBCS_P2_STATUS_TFU: 0x%x\n", rbuf[0]);
|
sc_debug(reader->ctx, "Invalid data object returnd on CTBCS_P2_STATUS_TFU: 0x%x\n", rbuf[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NumUnits = rbuf[1];
|
NumUnits = rbuf[1];
|
||||||
if (NumUnits + 4 > lr) {
|
if (NumUnits + 4 > lr) {
|
||||||
set_default_fu(reader);
|
set_default_fu(reader);
|
||||||
sc_error(reader->ctx, "Invalid data returnd: %d functional units, size %d\n", NumUnits, rv);
|
sc_debug(reader->ctx, "Invalid data returnd: %d functional units, size %d\n", NumUnits, rv);
|
||||||
set_default_fu(reader);
|
set_default_fu(reader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -257,13 +257,13 @@ static int refresh_slot_attributes(sc_reader_t *reader,
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
||||||
if (rv || (lr < 3) || (rbuf[lr-2] != 0x90)) {
|
if (rv || (lr < 3) || (rbuf[lr-2] != 0x90)) {
|
||||||
sc_error(reader->ctx, "Error getting status of terminal: %d/%d/0x%x\n", rv, lr, rbuf[lr-2]);
|
sc_debug(reader->ctx, "Error getting status of terminal: %d/%d/0x%x\n", rv, lr, rbuf[lr-2]);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
if (lr < 4) {
|
if (lr < 4) {
|
||||||
/* Looks like older readers do not return data tag and length field, so assume one slot only */
|
/* Looks like older readers do not return data tag and length field, so assume one slot only */
|
||||||
if (slot->id > 0) {
|
if (slot->id > 0) {
|
||||||
sc_error(reader->ctx, "Status for slot id %d not returned, have only 1\n", slot->id);
|
sc_debug(reader->ctx, "Status for slot id %d not returned, have only 1\n", slot->id);
|
||||||
return SC_ERROR_SLOT_NOT_FOUND;
|
return SC_ERROR_SLOT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
if (rbuf[0] & CTBCS_DATA_STATUS_CARD)
|
if (rbuf[0] & CTBCS_DATA_STATUS_CARD)
|
||||||
|
@ -271,11 +271,11 @@ static int refresh_slot_attributes(sc_reader_t *reader,
|
||||||
} else {
|
} else {
|
||||||
if (rbuf[0] != CTBCS_P2_STATUS_ICC) {
|
if (rbuf[0] != CTBCS_P2_STATUS_ICC) {
|
||||||
/* Should we be more tolerant here? I do not think so... */
|
/* Should we be more tolerant here? I do not think so... */
|
||||||
sc_error(reader->ctx, "Invalid data object returnd on CTBCS_P2_STATUS_ICC: 0x%x\n", rbuf[0]);
|
sc_debug(reader->ctx, "Invalid data object returnd on CTBCS_P2_STATUS_ICC: 0x%x\n", rbuf[0]);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
if (rbuf[1] <= slot->id) {
|
if (rbuf[1] <= slot->id) {
|
||||||
sc_error(reader->ctx, "Status for slot id %d not returned, only %d\n", slot->id, rbuf[1]);
|
sc_debug(reader->ctx, "Status for slot id %d not returned, only %d\n", slot->id, rbuf[1]);
|
||||||
return SC_ERROR_SLOT_NOT_FOUND;
|
return SC_ERROR_SLOT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
if (rbuf[2+slot->id] & CTBCS_DATA_STATUS_CARD)
|
if (rbuf[2+slot->id] & CTBCS_DATA_STATUS_CARD)
|
||||||
|
@ -306,7 +306,7 @@ static int ctapi_internal_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, (unsigned short)sendsize, (u8 *) sendbuf, &lr, recvbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, (unsigned short)sendsize, (u8 *) sendbuf, &lr, recvbuf);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
sc_error(reader->ctx, "Error transmitting APDU: %d\n", rv);
|
sc_debug(reader->ctx, "Error transmitting APDU: %d\n", rv);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
*recvsize = lr;
|
*recvsize = lr;
|
||||||
|
@ -337,7 +337,7 @@ static int ctapi_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
rbuf, &rsize, apdu->control);
|
rbuf, &rsize, apdu->control);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
/* unable to transmit ... most likely a reader problem */
|
/* unable to transmit ... most likely a reader problem */
|
||||||
sc_error(reader->ctx, "unable to transmit");
|
sc_debug(reader->ctx, "unable to transmit");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (reader->ctx->debug >= 6)
|
if (reader->ctx->debug >= 6)
|
||||||
|
@ -386,7 +386,7 @@ static int ctapi_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
|
||||||
if (rv || rbuf[lr-2] != 0x90) {
|
if (rv || rbuf[lr-2] != 0x90) {
|
||||||
sc_error(reader->ctx, "Error activating card: %d\n", rv);
|
sc_debug(reader->ctx, "Error activating card: %d\n", rv);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
if (lr < 2)
|
if (lr < 2)
|
||||||
|
@ -413,7 +413,7 @@ static int ctapi_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
|
||||||
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 9, cmd, &lr, rbuf);
|
rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 9, cmd, &lr, rbuf);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
sc_error(reader->ctx, "Error negotiating PPS: %d\n", rv);
|
sc_debug(reader->ctx, "Error negotiating PPS: %d\n", rv);
|
||||||
return SC_ERROR_TRANSMIT_FAILED;
|
return SC_ERROR_TRANSMIT_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,14 +483,14 @@ static int ctapi_load_module(sc_context_t *ctx,
|
||||||
|
|
||||||
list = scconf_find_list(conf, "ports");
|
list = scconf_find_list(conf, "ports");
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
sc_error(ctx, "No ports configured.\n");
|
sc_debug(ctx, "No ports configured.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = conf->name->data;
|
val = conf->name->data;
|
||||||
dlh = lt_dlopen(val);
|
dlh = lt_dlopen(val);
|
||||||
if (!dlh) {
|
if (!dlh) {
|
||||||
sc_error(ctx, "Unable to open shared library '%s': %s\n", val, lt_dlerror());
|
sc_debug(ctx, "Unable to open shared library '%s': %s\n", val, lt_dlerror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,12 +513,12 @@ static int ctapi_load_module(sc_context_t *ctx,
|
||||||
struct ctapi_private_data *priv;
|
struct ctapi_private_data *priv;
|
||||||
|
|
||||||
if (sscanf(list->data, "%d", &port) != 1) {
|
if (sscanf(list->data, "%d", &port) != 1) {
|
||||||
sc_error(ctx, "Port '%s' is not a number.\n", list->data);
|
sc_debug(ctx, "Port '%s' is not a number.\n", list->data);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rv = funcs.CT_init((unsigned short)mod->ctn_count, (unsigned short)port);
|
rv = funcs.CT_init((unsigned short)mod->ctn_count, (unsigned short)port);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
sc_error(ctx, "CT_init() failed with %d\n", rv);
|
sc_debug(ctx, "CT_init() failed with %d\n", rv);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t));
|
reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t));
|
||||||
|
@ -550,7 +550,7 @@ static int ctapi_load_module(sc_context_t *ctx,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
symerr:
|
symerr:
|
||||||
sc_error(ctx, "Unable to resolve CT-API symbols.\n");
|
sc_debug(ctx, "Unable to resolve CT-API symbols.\n");
|
||||||
lt_dlclose(dlh);
|
lt_dlclose(dlh);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,21 +221,21 @@ openct_reader_connect(sc_reader_t *reader,
|
||||||
ct_reader_disconnect(data->h);
|
ct_reader_disconnect(data->h);
|
||||||
|
|
||||||
if (!(data->h = ct_reader_connect(data->num))) {
|
if (!(data->h = ct_reader_connect(data->num))) {
|
||||||
sc_error(reader->ctx, "ct_reader_connect socket failed\n");
|
sc_debug(reader->ctx, "ct_reader_connect socket failed\n");
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ct_card_request(data->h, slot->id, 0, NULL,
|
rc = ct_card_request(data->h, slot->id, 0, NULL,
|
||||||
slot->atr, sizeof(slot->atr));
|
slot->atr, sizeof(slot->atr));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
sc_error(reader->ctx,
|
sc_debug(reader->ctx,
|
||||||
"openct_reader_connect read failed: %s\n",
|
"openct_reader_connect read failed: %s\n",
|
||||||
ct_strerror(rc));
|
ct_strerror(rc));
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
sc_error(reader->ctx, "openct_reader_connect recved no data\n");
|
sc_debug(reader->ctx, "openct_reader_connect recved no data\n");
|
||||||
return SC_ERROR_READER;
|
return SC_ERROR_READER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ static int openct_reader_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
rbuf, &rsize, apdu->control);
|
rbuf, &rsize, apdu->control);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
/* unable to transmit ... most likely a reader problem */
|
/* unable to transmit ... most likely a reader problem */
|
||||||
sc_error(reader->ctx, "unable to transmit");
|
sc_debug(reader->ctx, "unable to transmit");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (reader->ctx->debug >= 6)
|
if (reader->ctx->debug >= 6)
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#ifdef ENABLE_PCSC
|
#ifdef ENABLE_PCSC
|
||||||
#include "ctbcs.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -39,7 +38,7 @@
|
||||||
#undef SCARD_PROTOCOL_ANY
|
#undef SCARD_PROTOCOL_ANY
|
||||||
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
|
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
|
||||||
/* Error printing */
|
/* Error printing */
|
||||||
#define PCSC_ERROR(ctx, desc, rv) sc_error(ctx, desc ": 0x%08lx\n", rv);
|
#define PCSC_ERROR(ctx, desc, rv) sc_debug(ctx, desc ": 0x%08lx\n", rv);
|
||||||
|
|
||||||
/* Utility for handling big endian IOCTL codes. */
|
/* Utility for handling big endian IOCTL codes. */
|
||||||
#define dw2i_be(a, x) ((((((a[x] << 8) + a[x+1]) << 8) + a[x+2]) << 8) + a[x+3])
|
#define dw2i_be(a, x) ((((((a[x] << 8) + a[x+1]) << 8) + a[x+2]) << 8) + a[x+3])
|
||||||
|
@ -47,9 +46,6 @@
|
||||||
#define GET_PRIV_DATA(r) ((struct pcsc_private_data *) (r)->drv_data)
|
#define GET_PRIV_DATA(r) ((struct pcsc_private_data *) (r)->drv_data)
|
||||||
#define GET_SLOT_DATA(r) ((struct pcsc_slot_data *) (r)->drv_data)
|
#define GET_SLOT_DATA(r) ((struct pcsc_slot_data *) (r)->drv_data)
|
||||||
|
|
||||||
static int part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
|
||||||
struct sc_pin_cmd_data *data);
|
|
||||||
|
|
||||||
struct pcsc_global_private_data {
|
struct pcsc_global_private_data {
|
||||||
SCARDCONTEXT pcsc_ctx;
|
SCARDCONTEXT pcsc_ctx;
|
||||||
int enable_pinpad;
|
int enable_pinpad;
|
||||||
|
@ -74,7 +70,6 @@ struct pcsc_global_private_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcsc_private_data {
|
struct pcsc_private_data {
|
||||||
char *reader_name;
|
|
||||||
struct pcsc_global_private_data *gpriv;
|
struct pcsc_global_private_data *gpriv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,9 +88,11 @@ struct pcsc_slot_data {
|
||||||
|
|
||||||
static int pcsc_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot);
|
static int pcsc_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot);
|
||||||
|
|
||||||
static int pcsc_ret_to_error(long rv)
|
static int pcsc_ret_to_error(LONG rv)
|
||||||
{
|
{
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
|
case SCARD_S_SUCCESS:
|
||||||
|
return SC_SUCCESS;
|
||||||
case SCARD_W_REMOVED_CARD:
|
case SCARD_W_REMOVED_CARD:
|
||||||
return SC_ERROR_CARD_REMOVED;
|
return SC_ERROR_CARD_REMOVED;
|
||||||
case SCARD_E_NOT_TRANSACTED:
|
case SCARD_E_NOT_TRANSACTED:
|
||||||
|
@ -113,6 +110,11 @@ static int pcsc_ret_to_error(long rv)
|
||||||
case SCARD_E_NO_SERVICE:
|
case SCARD_E_NO_SERVICE:
|
||||||
/* If the service is (auto)started, there could be readers later */
|
/* If the service is (auto)started, there could be readers later */
|
||||||
return SC_ERROR_NO_READERS_FOUND;
|
return SC_ERROR_NO_READERS_FOUND;
|
||||||
|
case SCARD_E_NO_SMARTCARD:
|
||||||
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
|
case SCARD_E_PROTO_MISMATCH: /* Should not happen */
|
||||||
|
return SC_ERROR_READER;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return SC_ERROR_UNKNOWN;
|
return SC_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +238,7 @@ static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
rbuf, &rsize, apdu->control);
|
rbuf, &rsize, apdu->control);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
/* unable to transmit ... most likely a reader problem */
|
/* unable to transmit ... most likely a reader problem */
|
||||||
sc_error(reader->ctx, "unable to transmit");
|
sc_debug(reader->ctx, "unable to transmit");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (reader->ctx->debug >= 6)
|
if (reader->ctx->debug >= 6)
|
||||||
|
@ -265,7 +267,7 @@ static int refresh_slot_attributes(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
|
||||||
SC_FUNC_CALLED(reader->ctx, 3);
|
SC_FUNC_CALLED(reader->ctx, 3);
|
||||||
if (pslot->reader_state.szReader == NULL) {
|
if (pslot->reader_state.szReader == NULL) {
|
||||||
pslot->reader_state.szReader = priv->reader_name;
|
pslot->reader_state.szReader = reader->name;
|
||||||
pslot->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
pslot->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
pslot->reader_state.dwEventState = SCARD_STATE_UNAWARE;
|
pslot->reader_state.dwEventState = SCARD_STATE_UNAWARE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -380,7 +382,7 @@ static int pcsc_wait_for_event(sc_reader_t **readers,
|
||||||
for (i = 0; i < nslots; i++) {
|
for (i = 0; i < nslots; i++) {
|
||||||
struct pcsc_private_data *priv2 = GET_PRIV_DATA(readers[i]);
|
struct pcsc_private_data *priv2 = GET_PRIV_DATA(readers[i]);
|
||||||
|
|
||||||
rgReaderStates[i].szReader = priv2->reader_name;
|
rgReaderStates[i].szReader = readers[i]->name;
|
||||||
rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
|
rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
|
rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
|
||||||
|
|
||||||
|
@ -490,11 +492,11 @@ static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot, int reset
|
||||||
|
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
||||||
return rv;
|
return pcsc_ret_to_error(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
|
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
|
||||||
return rv;
|
return pcsc_ret_to_error(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
@ -505,10 +507,6 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
int r;
|
int r;
|
||||||
u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
|
||||||
size_t rcount;
|
|
||||||
DWORD i, feature_len, display_ioctl = 0;
|
|
||||||
PCSC_TLV_STRUCTURE *pcsc_tlv;
|
|
||||||
|
|
||||||
r = refresh_slot_attributes(reader, slot);
|
r = refresh_slot_attributes(reader, slot);
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -517,7 +515,7 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
|
|
||||||
/* Always connect with whatever protocol possible */
|
/* Always connect with whatever protocol possible */
|
||||||
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, priv->reader_name,
|
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
||||||
SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
|
@ -537,94 +535,14 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
if (slot->active_protocol != protocol) {
|
if (slot->active_protocol != protocol) {
|
||||||
sc_debug(reader->ctx, "Protocol difference, forcing protocol (%d)", protocol);
|
sc_debug(reader->ctx, "Protocol difference, forcing protocol (%d)", protocol);
|
||||||
/* Reconnect with a reset. pcsc_reconnect figures out the right forced protocol */
|
/* Reconnect with a reset. pcsc_reconnect figures out the right forced protocol */
|
||||||
rv = pcsc_reconnect(reader, slot, 1);
|
r = pcsc_reconnect(reader, slot, 1);
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardReconnect (to force protocol) failed", rv);
|
sc_debug(reader->ctx, "pcsc_reconnect (to force protocol) failed", r);
|
||||||
return pcsc_ret_to_error(rv);
|
return r;
|
||||||
}
|
}
|
||||||
sc_debug(reader->ctx, "Proto after reconnect = %d", slot->active_protocol);
|
sc_debug(reader->ctx, "Proto after reconnect = %d", slot->active_protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for pinpad support */
|
|
||||||
if (priv->gpriv->SCardControl != NULL) {
|
|
||||||
sc_debug(reader->ctx, "Requesting reader features ... ");
|
|
||||||
|
|
||||||
rv = priv->gpriv->SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL,
|
|
||||||
0, feature_buf, sizeof(feature_buf), &feature_len);
|
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
|
||||||
sc_debug(reader->ctx, "SCardControl failed %08x", rv);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((feature_len % sizeof(PCSC_TLV_STRUCTURE)) != 0) {
|
|
||||||
sc_debug(reader->ctx, "Inconsistent TLV from reader!");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
char *log_disabled = "but it's disabled in configuration file";
|
|
||||||
/* get the number of elements instead of the complete size */
|
|
||||||
feature_len /= sizeof(PCSC_TLV_STRUCTURE);
|
|
||||||
|
|
||||||
pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf;
|
|
||||||
for (i = 0; i < feature_len; i++) {
|
|
||||||
if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT) {
|
|
||||||
pslot->verify_ioctl = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_START) {
|
|
||||||
pslot->verify_ioctl_start = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_FINISH) {
|
|
||||||
pslot->verify_ioctl_finish = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT) {
|
|
||||||
pslot->modify_ioctl = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_START) {
|
|
||||||
pslot->modify_ioctl_start = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_FINISH) {
|
|
||||||
pslot->modify_ioctl_finish = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) {
|
|
||||||
display_ioctl = ntohl(pcsc_tlv[i].value);
|
|
||||||
} else {
|
|
||||||
sc_debug(reader->ctx, "Reader feature %02x is not supported", pcsc_tlv[i].tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set slot capabilities based on detected IOCTLs */
|
|
||||||
if (pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish)) {
|
|
||||||
char *log_text = "Reader supports pinpad PIN verification";
|
|
||||||
if (priv->gpriv->enable_pinpad) {
|
|
||||||
sc_debug(reader->ctx, log_text);
|
|
||||||
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
|
||||||
} else {
|
|
||||||
sc_debug(reader->ctx, "%s %s", log_text, log_disabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish)) {
|
|
||||||
char *log_text = "Reader supports pinpad PIN modification";
|
|
||||||
if (priv->gpriv->enable_pinpad) {
|
|
||||||
sc_debug(reader->ctx, log_text);
|
|
||||||
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
|
||||||
} else {
|
|
||||||
sc_debug(reader->ctx, "%s %s", log_text, log_disabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display_ioctl) {
|
|
||||||
rcount = sizeof(rbuf);
|
|
||||||
r = pcsc_internal_transmit(reader, slot, NULL, 0, rbuf, &rcount, display_ioctl);
|
|
||||||
if (r == SC_SUCCESS) {
|
|
||||||
if (rcount != sizeof(PIN_PROPERTIES_STRUCTURE)) {
|
|
||||||
PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)rbuf;
|
|
||||||
if (caps->wLcdLayout > 0) {
|
|
||||||
sc_debug(reader->ctx, "Reader has a display: %04X", caps->wLcdLayout);
|
|
||||||
slot->capabilities |= SC_SLOT_CAP_DISPLAY;
|
|
||||||
} else
|
|
||||||
sc_debug(reader->ctx, "Reader does not have a display.");
|
|
||||||
} else {
|
|
||||||
sc_debug(reader->ctx, "Returned PIN properties structure has bad length (%d)", rcount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +560,8 @@ static int pcsc_disconnect(sc_reader_t * reader, sc_slot_info_t * slot)
|
||||||
|
|
||||||
static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
|
static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
{
|
{
|
||||||
long rv;
|
LONG rv;
|
||||||
|
int r;
|
||||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
|
||||||
|
@ -654,19 +573,19 @@ static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
case SCARD_E_INVALID_HANDLE:
|
case SCARD_E_INVALID_HANDLE:
|
||||||
case SCARD_E_READER_UNAVAILABLE:
|
case SCARD_E_READER_UNAVAILABLE:
|
||||||
rv = pcsc_connect(reader, slot);
|
r = pcsc_connect(reader, slot);
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardConnect failed", rv);
|
sc_debug(reader->ctx, "pcsc_connect failed", r);
|
||||||
return pcsc_ret_to_error(rv);
|
return r;
|
||||||
}
|
}
|
||||||
/* return failure so that upper layers will be notified and try to lock again */
|
/* return failure so that upper layers will be notified and try to lock again */
|
||||||
return SC_ERROR_READER_REATTACHED;
|
return SC_ERROR_READER_REATTACHED;
|
||||||
case SCARD_W_RESET_CARD:
|
case SCARD_W_RESET_CARD:
|
||||||
/* try to reconnect if the card was reset by some other application */
|
/* try to reconnect if the card was reset by some other application */
|
||||||
rv = pcsc_reconnect(reader, slot, 0);
|
r = pcsc_reconnect(reader, slot, 0);
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
sc_debug(reader->ctx, "pcsc_reconnect failed", r);
|
||||||
return pcsc_ret_to_error(rv);
|
return r;
|
||||||
}
|
}
|
||||||
/* return failure so that upper layers will be notified and try to lock again */
|
/* return failure so that upper layers will be notified and try to lock again */
|
||||||
return SC_ERROR_CARD_RESET;
|
return SC_ERROR_CARD_RESET;
|
||||||
|
@ -681,7 +600,7 @@ static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
|
|
||||||
static int pcsc_unlock(sc_reader_t *reader, sc_slot_info_t *slot)
|
static int pcsc_unlock(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
{
|
{
|
||||||
long rv;
|
LONG rv;
|
||||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
|
||||||
|
@ -703,7 +622,6 @@ static int pcsc_release(sc_reader_t *reader)
|
||||||
{
|
{
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
|
||||||
free(priv->reader_name);
|
|
||||||
free(priv);
|
free(priv);
|
||||||
if (reader->slot[0].drv_data != NULL) {
|
if (reader->slot[0].drv_data != NULL) {
|
||||||
free(reader->slot[0].drv_data);
|
free(reader->slot[0].drv_data);
|
||||||
|
@ -719,13 +637,13 @@ static int pcsc_reset(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||||
int old_locked = pslot->locked;
|
int old_locked = pslot->locked;
|
||||||
|
|
||||||
r = pcsc_reconnect(reader, slot, 1);
|
r = pcsc_reconnect(reader, slot, 1);
|
||||||
if(r != SCARD_S_SUCCESS)
|
if(r != SC_SUCCESS)
|
||||||
return pcsc_ret_to_error(r);
|
return r;
|
||||||
|
|
||||||
/* pcsc_reconnect unlocks card... try to lock it again if it was locked */
|
/* pcsc_reconnect unlocks card... try to lock it again if it was locked */
|
||||||
if(old_locked)
|
if(old_locked)
|
||||||
r = pcsc_lock(reader, slot);
|
r = pcsc_lock(reader, slot);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +674,7 @@ static int pcsc_init(sc_context_t *ctx, void **reader_data)
|
||||||
gpriv->connect_reset = 1;
|
gpriv->connect_reset = 1;
|
||||||
gpriv->connect_exclusive = 0;
|
gpriv->connect_exclusive = 0;
|
||||||
gpriv->transaction_reset = 0;
|
gpriv->transaction_reset = 0;
|
||||||
gpriv->enable_pinpad = 0;
|
gpriv->enable_pinpad = 1;
|
||||||
gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
|
gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
|
||||||
gpriv->pcsc_ctx = -1;
|
gpriv->pcsc_ctx = -1;
|
||||||
|
|
||||||
|
@ -773,6 +691,8 @@ static int pcsc_init(sc_context_t *ctx, void **reader_data)
|
||||||
gpriv->provider_library =
|
gpriv->provider_library =
|
||||||
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
|
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
|
||||||
}
|
}
|
||||||
|
sc_debug(ctx, "PC/SC options: connect_reset=%d connect_exclusive=%d transaction_reset=%d enable_pinpad=%d",
|
||||||
|
gpriv->connect_reset, gpriv->connect_exclusive, gpriv->transaction_reset, gpriv->enable_pinpad);
|
||||||
|
|
||||||
gpriv->dlhandle = lt_dlopen(gpriv->provider_library);
|
gpriv->dlhandle = lt_dlopen(gpriv->provider_library);
|
||||||
if (gpriv->dlhandle == NULL) {
|
if (gpriv->dlhandle == NULL) {
|
||||||
|
@ -862,9 +782,13 @@ static int pcsc_finish(sc_context_t *ctx, void *prv_data)
|
||||||
|
|
||||||
static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)
|
static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)
|
||||||
{
|
{
|
||||||
|
DWORD active_proto;
|
||||||
|
SCARDHANDLE card_handle;
|
||||||
|
u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
PCSC_TLV_STRUCTURE *pcsc_tlv;
|
||||||
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data;
|
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data;
|
||||||
LONG rv;
|
LONG rv;
|
||||||
DWORD reader_buf_size;
|
DWORD reader_buf_size, rcount, feature_len, display_ioctl;
|
||||||
char *reader_buf = NULL, *reader_name;
|
char *reader_buf = NULL, *reader_name;
|
||||||
const char *mszGroups = NULL;
|
const char *mszGroups = NULL;
|
||||||
int ret = SC_ERROR_INTERNAL;
|
int ret = SC_ERROR_INTERNAL;
|
||||||
|
@ -972,10 +896,6 @@ static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
priv->gpriv = gpriv;
|
priv->gpriv = gpriv;
|
||||||
if ((priv->reader_name = strdup(reader_name)) == NULL) {
|
|
||||||
ret = SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
goto err1;
|
|
||||||
}
|
|
||||||
slot = &reader->slot[0];
|
slot = &reader->slot[0];
|
||||||
memset(slot, 0, sizeof(*slot));
|
memset(slot, 0, sizeof(*slot));
|
||||||
slot->drv_data = pslot;
|
slot->drv_data = pslot;
|
||||||
|
@ -984,14 +904,103 @@ static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)
|
||||||
ret = SC_SUCCESS; /* silent ignore */
|
ret = SC_SUCCESS; /* silent ignore */
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
refresh_slot_attributes(reader, slot);
|
|
||||||
|
|
||||||
|
/* check for pinpad support */
|
||||||
|
if (gpriv->SCardControl != NULL) {
|
||||||
|
sc_debug(ctx, "Requesting reader features ... ");
|
||||||
|
#ifdef __APPLE__ /* 10.5.7 does not support 0 as protocol identifier */
|
||||||
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
||||||
|
#else
|
||||||
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, 0, &card_handle, &active_proto);
|
||||||
|
if (rv == SCARD_E_SHARING_VIOLATION) /* Assume that there is a card in the reader in shared mode */
|
||||||
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
||||||
|
#endif
|
||||||
|
if (rv == SCARD_S_SUCCESS) {
|
||||||
|
rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len);
|
||||||
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
|
sc_debug(ctx, "SCardControl failed %08x", rv);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((feature_len % sizeof(PCSC_TLV_STRUCTURE)) != 0) {
|
||||||
|
sc_debug(ctx, "Inconsistent TLV from reader!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char *log_disabled = "but it's disabled in configuration file";
|
||||||
|
/* get the number of elements instead of the complete size */
|
||||||
|
feature_len /= sizeof(PCSC_TLV_STRUCTURE);
|
||||||
|
|
||||||
|
pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf;
|
||||||
|
for (i = 0; i < feature_len; i++) {
|
||||||
|
sc_debug(ctx, "Reader feature %02x detected", pcsc_tlv[i].tag);
|
||||||
|
if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT) {
|
||||||
|
pslot->verify_ioctl = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_START) {
|
||||||
|
pslot->verify_ioctl_start = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_FINISH) {
|
||||||
|
pslot->verify_ioctl_finish = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT) {
|
||||||
|
pslot->modify_ioctl = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_START) {
|
||||||
|
pslot->modify_ioctl_start = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_FINISH) {
|
||||||
|
pslot->modify_ioctl_finish = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) {
|
||||||
|
display_ioctl = ntohl(pcsc_tlv[i].value);
|
||||||
|
} else {
|
||||||
|
sc_debug(ctx, "Reader feature %02x is not supported", pcsc_tlv[i].tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set slot capabilities based on detected IOCTLs */
|
||||||
|
if (pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish)) {
|
||||||
|
char *log_text = "Reader supports pinpad PIN verification";
|
||||||
|
if (priv->gpriv->enable_pinpad) {
|
||||||
|
sc_debug(ctx, log_text);
|
||||||
|
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||||
|
} else {
|
||||||
|
sc_debug(ctx, "%s %s", log_text, log_disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish)) {
|
||||||
|
char *log_text = "Reader supports pinpad PIN modification";
|
||||||
|
if (priv->gpriv->enable_pinpad) {
|
||||||
|
sc_debug(ctx, log_text);
|
||||||
|
slot->capabilities |= SC_SLOT_CAP_PIN_PAD;
|
||||||
|
} else {
|
||||||
|
sc_debug(ctx, "%s %s", log_text, log_disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display_ioctl) {
|
||||||
|
rcount = sizeof(rbuf);
|
||||||
|
rv = gpriv->SCardControl(card_handle, display_ioctl, NULL, 0, rbuf, sizeof(rbuf), &rcount);
|
||||||
|
if (rv == SCARD_S_SUCCESS) {
|
||||||
|
if (rcount == sizeof(PIN_PROPERTIES_STRUCTURE)) {
|
||||||
|
PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)rbuf;
|
||||||
|
if (caps->wLcdLayout > 0) {
|
||||||
|
sc_debug(ctx, "Reader has a display: %04X", caps->wLcdLayout);
|
||||||
|
slot->capabilities |= SC_SLOT_CAP_DISPLAY;
|
||||||
|
} else
|
||||||
|
sc_debug(ctx, "Reader does not have a display.");
|
||||||
|
} else {
|
||||||
|
sc_debug(ctx, "Returned PIN properties structure has bad length (%d/%d)", rcount, sizeof(PIN_PROPERTIES_STRUCTURE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gpriv->SCardDisconnect(card_handle, SCARD_LEAVE_CARD);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sc_debug(ctx, "SCardConnect failed %08x", rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh_slot_attributes(reader, slot);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
if (priv != NULL) {
|
if (priv != NULL) {
|
||||||
if (priv->reader_name)
|
|
||||||
free(priv->reader_name);
|
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
if (reader != NULL) {
|
if (reader != NULL) {
|
||||||
|
@ -1015,36 +1024,6 @@ out:
|
||||||
SC_FUNC_RETURN(ctx, 3, ret);
|
SC_FUNC_RETURN(ctx, 3, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
pcsc_pin_cmd(sc_reader_t *reader, sc_slot_info_t * slot, struct sc_pin_cmd_data *data)
|
|
||||||
{
|
|
||||||
if (slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
|
||||||
return part10_pin_cmd(reader, slot, data);
|
|
||||||
} else {
|
|
||||||
/* XXX: probably dead code */
|
|
||||||
return ctbcs_pin_cmd(reader, slot, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sc_reader_driver * sc_get_pcsc_driver(void)
|
|
||||||
{
|
|
||||||
pcsc_ops.init = pcsc_init;
|
|
||||||
pcsc_ops.finish = pcsc_finish;
|
|
||||||
pcsc_ops.detect_readers = pcsc_detect_readers;
|
|
||||||
pcsc_ops.transmit = pcsc_transmit;
|
|
||||||
pcsc_ops.detect_card_presence = pcsc_detect_card_presence;
|
|
||||||
pcsc_ops.lock = pcsc_lock;
|
|
||||||
pcsc_ops.unlock = pcsc_unlock;
|
|
||||||
pcsc_ops.release = pcsc_release;
|
|
||||||
pcsc_ops.connect = pcsc_connect;
|
|
||||||
pcsc_ops.disconnect = pcsc_disconnect;
|
|
||||||
pcsc_ops.perform_verify = pcsc_pin_cmd;
|
|
||||||
pcsc_ops.wait_for_event = pcsc_wait_for_event;
|
|
||||||
pcsc_ops.reset = pcsc_reset;
|
|
||||||
|
|
||||||
return &pcsc_drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pinpad support, based on PC/SC v2 Part 10 interface
|
* Pinpad support, based on PC/SC v2 Part 10 interface
|
||||||
* Similar to CCID in spirit.
|
* Similar to CCID in spirit.
|
||||||
|
@ -1100,7 +1079,7 @@ static int part10_build_verify_pin_block(u8 * buf, size_t * size, sc_slot_info_t
|
||||||
if (data->pin1.encoding == SC_PIN_ENCODING_GLP) {
|
if (data->pin1.encoding == SC_PIN_ENCODING_GLP) {
|
||||||
/* GLP PIN length is encoded in 4 bits and block size is always 8 bytes */
|
/* GLP PIN length is encoded in 4 bits and block size is always 8 bytes */
|
||||||
tmp |= 0x40 | 0x08;
|
tmp |= 0x40 | 0x08;
|
||||||
} else if (data->pin1.encoding == SC_PIN_ENCODING_ASCII && data->pin1.pad_length) {
|
} else if (data->pin1.encoding == SC_PIN_ENCODING_ASCII && data->flags & SC_PIN_CMD_NEED_PADDING) {
|
||||||
tmp |= data->pin1.pad_length;
|
tmp |= data->pin1.pad_length;
|
||||||
}
|
}
|
||||||
pin_verify->bmPINBlockString = tmp;
|
pin_verify->bmPINBlockString = tmp;
|
||||||
|
@ -1223,11 +1202,20 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, sc_slot_info_t
|
||||||
tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
|
tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
|
||||||
pin_modify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
|
pin_modify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */
|
||||||
|
|
||||||
pin_modify->bConfirmPIN = 0x03; /* bConfirmPIN, all */
|
/* bConfirmPIN flags
|
||||||
|
* 0x01: New Pin, Confirm Pin
|
||||||
|
* 0x03: Enter Old Pin, New Pin, Confirm Pin
|
||||||
|
*/
|
||||||
|
pin_modify->bConfirmPIN = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0x01 : 0x03;
|
||||||
pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */
|
pin_modify->bEntryValidationCondition = 0x02; /* bEntryValidationCondition, keypress only */
|
||||||
|
|
||||||
|
/* bNumberMessage flags
|
||||||
|
* 0x02: Messages seen on Pinpad display: New Pin, Confirm Pin
|
||||||
|
* 0x03: Messages seen on Pinpad display: Enter Old Pin, New Pin, Confirm Pin
|
||||||
|
* Could be 0xFF too.
|
||||||
|
*/
|
||||||
if (slot->capabilities & SC_SLOT_CAP_DISPLAY)
|
if (slot->capabilities & SC_SLOT_CAP_DISPLAY)
|
||||||
pin_modify->bNumberMessage = 0x03; /* 3 messages (because bConfirmPIN = 3), all default. Could be 0xFF too */
|
pin_modify->bNumberMessage = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0x02 : 0x03;
|
||||||
else
|
else
|
||||||
pin_modify->bNumberMessage = 0x00; /* No messages */
|
pin_modify->bNumberMessage = 0x00; /* No messages */
|
||||||
|
|
||||||
|
@ -1262,7 +1250,7 @@ static int part10_build_modify_pin_block(u8 * buf, size_t * size, sc_slot_info_t
|
||||||
|
|
||||||
/* Do the PIN command */
|
/* Do the PIN command */
|
||||||
static int
|
static int
|
||||||
part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
pcsc_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
struct sc_pin_cmd_data *data)
|
struct sc_pin_cmd_data *data)
|
||||||
{
|
{
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
@ -1282,7 +1270,7 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
|
|
||||||
/* The APDU must be provided by the card driver */
|
/* The APDU must be provided by the card driver */
|
||||||
if (!data->apdu) {
|
if (!data->apdu) {
|
||||||
sc_error(reader->ctx, "No APDU provided for PC/SC v2 pinpad verification!");
|
sc_debug(reader->ctx, "No APDU provided for PC/SC v2 pinpad verification!");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1290,7 +1278,7 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
switch (data->cmd) {
|
switch (data->cmd) {
|
||||||
case SC_PIN_CMD_VERIFY:
|
case SC_PIN_CMD_VERIFY:
|
||||||
if (!(pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish))) {
|
if (!(pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish))) {
|
||||||
sc_error(reader->ctx, "Pinpad reader does not support verification!");
|
sc_debug(reader->ctx, "Pinpad reader does not support verification!");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
r = part10_build_verify_pin_block(sbuf, &scount, slot, data);
|
r = part10_build_verify_pin_block(sbuf, &scount, slot, data);
|
||||||
|
@ -1299,14 +1287,14 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
case SC_PIN_CMD_CHANGE:
|
case SC_PIN_CMD_CHANGE:
|
||||||
case SC_PIN_CMD_UNBLOCK:
|
case SC_PIN_CMD_UNBLOCK:
|
||||||
if (!(pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish))) {
|
if (!(pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish))) {
|
||||||
sc_error(reader->ctx, "Pinpad reader does not support modification!");
|
sc_debug(reader->ctx, "Pinpad reader does not support modification!");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
r = part10_build_modify_pin_block(sbuf, &scount, slot, data);
|
r = part10_build_modify_pin_block(sbuf, &scount, slot, data);
|
||||||
ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start;
|
ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_error(reader->ctx, "Unknown PIN command %d", data->cmd);
|
sc_debug(reader->ctx, "Unknown PIN command %d", data->cmd);
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,5 +1350,25 @@ part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||||
/* PIN command completed, all is good */
|
/* PIN command completed, all is good */
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sc_reader_driver * sc_get_pcsc_driver(void)
|
||||||
|
{
|
||||||
|
pcsc_ops.init = pcsc_init;
|
||||||
|
pcsc_ops.finish = pcsc_finish;
|
||||||
|
pcsc_ops.detect_readers = pcsc_detect_readers;
|
||||||
|
pcsc_ops.transmit = pcsc_transmit;
|
||||||
|
pcsc_ops.detect_card_presence = pcsc_detect_card_presence;
|
||||||
|
pcsc_ops.lock = pcsc_lock;
|
||||||
|
pcsc_ops.unlock = pcsc_unlock;
|
||||||
|
pcsc_ops.release = pcsc_release;
|
||||||
|
pcsc_ops.connect = pcsc_connect;
|
||||||
|
pcsc_ops.disconnect = pcsc_disconnect;
|
||||||
|
pcsc_ops.perform_verify = pcsc_pin_cmd;
|
||||||
|
pcsc_ops.wait_for_event = pcsc_wait_for_event;
|
||||||
|
pcsc_ops.reset = pcsc_reset;
|
||||||
|
|
||||||
|
return &pcsc_drv;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_PCSC */
|
#endif /* HAVE_PCSC */
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include <openssl/crypto.h> /* for OPENSSL_cleanse */
|
#include <openssl/crypto.h> /* for OPENSSL_cleanse */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -660,12 +663,12 @@ int _sc_parse_atr(sc_context_t *ctx, sc_slot_info_t *slot)
|
||||||
slot->atr_info.hist_bytes = NULL;
|
slot->atr_info.hist_bytes = NULL;
|
||||||
|
|
||||||
if (atr_len == 0) {
|
if (atr_len == 0) {
|
||||||
sc_error(ctx, "empty ATR - card not present?\n");
|
sc_debug(ctx, "empty ATR - card not present?\n");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p[0] != 0x3B && p[0] != 0x3F) {
|
if (p[0] != 0x3B && p[0] != 0x3F) {
|
||||||
sc_error(ctx, "invalid sync byte in ATR: 0x%02X\n", p[0]);
|
sc_debug(ctx, "invalid sync byte in ATR: 0x%02X\n", p[0]);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
n_hist = p[1] & 0x0F;
|
n_hist = p[1] & 0x0F;
|
||||||
|
@ -715,6 +718,24 @@ int _sc_parse_atr(sc_context_t *ctx, sc_slot_info_t *slot)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *sc_mem_alloc_secure(size_t len)
|
||||||
|
{
|
||||||
|
void *pointer;
|
||||||
|
|
||||||
|
pointer = calloc(len, sizeof(unsigned char));
|
||||||
|
if (!pointer)
|
||||||
|
return NULL;
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
/* TODO Windows support and mprotect too */
|
||||||
|
/* Do not swap the memory */
|
||||||
|
if (mlock(pointer, len) == -1) {
|
||||||
|
free(pointer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
void sc_mem_clear(void *ptr, size_t len)
|
void sc_mem_clear(void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_OPENSSL
|
#ifdef ENABLE_OPENSSL
|
||||||
|
|
|
@ -192,10 +192,10 @@ int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (r == SC_ERROR_NOT_SUPPORTED)
|
if (r == SC_ERROR_NOT_SUPPORTED)
|
||||||
sc_error(card->ctx, "unsupported PIN operation (%d)",
|
sc_debug(card->ctx, "unsupported PIN operation (%d)",
|
||||||
data->cmd);
|
data->cmd);
|
||||||
} else {
|
} else {
|
||||||
sc_error(card->ctx, "Use of pin pad not supported by card driver");
|
sc_debug(card->ctx, "Use of pin pad not supported by card driver");
|
||||||
r = SC_ERROR_NOT_SUPPORTED;
|
r = SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||||
|
|
|
@ -113,9 +113,6 @@ typedef struct sc_apdu {
|
||||||
u8 *resp; /* R-APDU data buffer */
|
u8 *resp; /* R-APDU data buffer */
|
||||||
size_t resplen; /* in: size of R-APDU buffer,
|
size_t resplen; /* in: size of R-APDU buffer,
|
||||||
* out: length of data returned in R-APDU */
|
* out: length of data returned in R-APDU */
|
||||||
u8 sensitive; /* Set if either the command or
|
|
||||||
* the response contains secrets,
|
|
||||||
* e.g. a PIN. */
|
|
||||||
u8 control; /* Set if APDU should go to the reader */
|
u8 control; /* Set if APDU should go to the reader */
|
||||||
|
|
||||||
unsigned int sw1, sw2; /* Status words returned in R-APDU */
|
unsigned int sw1, sw2; /* Status words returned in R-APDU */
|
||||||
|
|
|
@ -182,7 +182,7 @@ static int sc_ui_get_func(sc_context_t *ctx, const char *name, void **ret)
|
||||||
|
|
||||||
sc_ui_lib_handle = lt_dlopen(lib_name);
|
sc_ui_lib_handle = lt_dlopen(lib_name);
|
||||||
if (!sc_ui_lib_handle) {
|
if (!sc_ui_lib_handle) {
|
||||||
sc_error(ctx,
|
sc_debug(ctx,
|
||||||
"Unable to open user interface library '%s': %s\n",
|
"Unable to open user interface library '%s': %s\n",
|
||||||
lib_name, lt_dlerror());
|
lib_name, lt_dlerror());
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
|
@ -391,10 +391,6 @@ sc_ui_display_msg(sc_context_t *ctx, int type, const char *msg)
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SC_LOG_TYPE_ERROR:
|
|
||||||
outf = ctx->error_file;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SC_LOG_TYPE_DEBUG:
|
case SC_LOG_TYPE_DEBUG:
|
||||||
outf = ctx->debug_file;
|
outf = ctx->debug_file;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -28,15 +28,8 @@
|
||||||
|
|
||||||
extern int hack_enabled;
|
extern int hack_enabled;
|
||||||
|
|
||||||
#define MAX_CACHE_PIN 32
|
|
||||||
struct pkcs15_slot_data {
|
struct pkcs15_slot_data {
|
||||||
struct sc_pkcs15_object *auth_obj;
|
struct sc_pkcs15_object *auth_obj;
|
||||||
int user_consent;
|
|
||||||
struct {
|
|
||||||
sc_path_t path;
|
|
||||||
u8 value[MAX_CACHE_PIN];
|
|
||||||
unsigned int len;
|
|
||||||
} pin[2];
|
|
||||||
};
|
};
|
||||||
#define slot_data(p) ((struct pkcs15_slot_data *) (p))
|
#define slot_data(p) ((struct pkcs15_slot_data *) (p))
|
||||||
#define slot_data_auth(p) (slot_data(p)->auth_obj)
|
#define slot_data_auth(p) (slot_data(p)->auth_obj)
|
||||||
|
@ -148,9 +141,6 @@ static CK_RV get_modulus_bits(struct sc_pkcs15_pubkey *,
|
||||||
static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);
|
static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);
|
||||||
static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
||||||
static CK_RV get_gostr3410_params(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
static CK_RV get_gostr3410_params(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
||||||
static void cache_pin(void *, int, const sc_path_t *, const void *, size_t);
|
|
||||||
static int revalidate_pin(struct pkcs15_slot_data *data,
|
|
||||||
struct sc_pkcs11_session *ses);
|
|
||||||
static int lock_card(struct pkcs15_fw_data *);
|
static int lock_card(struct pkcs15_fw_data *);
|
||||||
static int unlock_card(struct pkcs15_fw_data *);
|
static int unlock_card(struct pkcs15_fw_data *);
|
||||||
static void add_pins_to_keycache(struct sc_pkcs11_card *p11card,
|
static void add_pins_to_keycache(struct sc_pkcs11_card *p11card,
|
||||||
|
@ -674,11 +664,6 @@ pkcs15_add_object(struct sc_pkcs11_slot *slot,
|
||||||
obj->base.flags |= SC_PKCS11_OBJECT_SEEN;
|
obj->base.flags |= SC_PKCS11_OBJECT_SEEN;
|
||||||
obj->refcount++;
|
obj->refcount++;
|
||||||
|
|
||||||
if (obj->p15_object && (obj->p15_object->user_consent > 0) ) {
|
|
||||||
sc_debug(context, "User consent object detected, marking slot as user_consent!\n");
|
|
||||||
((struct pkcs15_slot_data *)slot->fw_data)->user_consent = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add related objects
|
/* Add related objects
|
||||||
* XXX prevent infinite recursion when a card specifies two certificates
|
* XXX prevent infinite recursion when a card specifies two certificates
|
||||||
* referring to each other.
|
* referring to each other.
|
||||||
|
@ -728,7 +713,6 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
||||||
slot->token_info.flags |= CKF_USER_PIN_INITIALIZED;
|
slot->token_info.flags |= CKF_USER_PIN_INITIALIZED;
|
||||||
if (card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
if (card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
||||||
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
|
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
|
||||||
sc_pkcs11_conf.cache_pins = 0;
|
|
||||||
}
|
}
|
||||||
if (card->card->caps & SC_CARD_CAP_RNG)
|
if (card->card->caps & SC_CARD_CAP_RNG)
|
||||||
slot->token_info.flags |= CKF_RNG;
|
slot->token_info.flags |= CKF_RNG;
|
||||||
|
@ -745,6 +729,14 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
||||||
snprintf(tmp, sizeof(tmp), "%s", card->label);
|
snprintf(tmp, sizeof(tmp), "%s", card->label);
|
||||||
}
|
}
|
||||||
slot->token_info.flags |= CKF_LOGIN_REQUIRED;
|
slot->token_info.flags |= CKF_LOGIN_REQUIRED;
|
||||||
|
if (pin_info->tries_left >= 0) {
|
||||||
|
if (pin_info->tries_left == 1)
|
||||||
|
slot->token_info.flags |= CKF_USER_PIN_FINAL_TRY;
|
||||||
|
else if (pin_info->tries_left == 0)
|
||||||
|
slot->token_info.flags |= CKF_USER_PIN_LOCKED;
|
||||||
|
else if (pin_info->max_tries && pin_info->tries_left && pin_info->tries_left < pin_info->max_tries)
|
||||||
|
slot->token_info.flags |= CKF_USER_PIN_COUNT_LOW;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
snprintf(tmp, sizeof(tmp), "%s", card->label);
|
snprintf(tmp, sizeof(tmp), "%s", card->label);
|
||||||
strcpy_bp(slot->token_info.label, tmp, 32);
|
strcpy_bp(slot->token_info.label, tmp, 32);
|
||||||
|
@ -757,6 +749,8 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
||||||
slot->token_info.ulMaxPinLen = 8;
|
slot->token_info.ulMaxPinLen = 8;
|
||||||
slot->token_info.ulMinPinLen = 4;
|
slot->token_info.ulMinPinLen = 4;
|
||||||
}
|
}
|
||||||
|
if (card->flags & SC_PKCS15_CARD_FLAG_EMULATED)
|
||||||
|
slot->token_info.flags |= CKF_WRITE_PROTECTED;
|
||||||
|
|
||||||
sc_debug(context, "Initialized token '%s'\n", tmp);
|
sc_debug(context, "Initialized token '%s'\n", tmp);
|
||||||
}
|
}
|
||||||
|
@ -1015,10 +1009,6 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
|
||||||
|
|
||||||
rc = sc_pkcs15_verify_pin(card, pin, pPin, ulPinLen);
|
rc = sc_pkcs15_verify_pin(card, pin, pPin, ulPinLen);
|
||||||
sc_debug(context, "PIN verification returned %d\n", rc);
|
sc_debug(context, "PIN verification returned %d\n", rc);
|
||||||
|
|
||||||
if (rc >= 0)
|
|
||||||
cache_pin(fw_token, userType, &pin->path, pPin, ulPinLen);
|
|
||||||
|
|
||||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,10 +1016,8 @@ static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
|
||||||
{
|
{
|
||||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
cache_pin(fw_token, CKU_SO, NULL, NULL, 0);
|
sc_pkcs15_pincache_clear(fw_data->p15_card);
|
||||||
cache_pin(fw_token, CKU_USER, NULL, NULL, 0);
|
|
||||||
|
|
||||||
sc_logout(fw_data->p15_card->card);
|
sc_logout(fw_data->p15_card->card);
|
||||||
|
|
||||||
if (sc_pkcs11_conf.lock_login)
|
if (sc_pkcs11_conf.lock_login)
|
||||||
|
@ -1066,9 +1054,6 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
|
||||||
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin, pOldPin, ulOldLen,
|
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin, pOldPin, ulOldLen,
|
||||||
pNewPin, ulNewLen);
|
pNewPin, ulNewLen);
|
||||||
sc_debug(context, "PIN change returned %d\n", rc);
|
sc_debug(context, "PIN change returned %d\n", rc);
|
||||||
|
|
||||||
if (rc >= 0)
|
|
||||||
cache_pin(fw_token, CKU_USER, &pin->path, pNewPin, ulNewLen);
|
|
||||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1114,9 +1099,6 @@ static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
|
||||||
pkcs15_init_slot(fw_data->p15_card, slot, auth_obj);
|
pkcs15_init_slot(fw_data->p15_card, slot, auth_obj);
|
||||||
|
|
||||||
pin_info = (sc_pkcs15_pin_info_t *) auth_obj->data;
|
pin_info = (sc_pkcs15_pin_info_t *) auth_obj->data;
|
||||||
|
|
||||||
cache_pin(slot->fw_data, CKU_USER, &pin_info->path, pPin, ulPinLen);
|
|
||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2135,6 +2117,10 @@ static CK_RV pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session,
|
||||||
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||||
*(CK_BBOOL*)attr->pValue = TRUE;
|
*(CK_BBOOL*)attr->pValue = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case CKA_ALWAYS_AUTHENTICATE:
|
||||||
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||||
|
*(CK_BBOOL*)attr->pValue = prkey->prv_p15obj->user_consent;
|
||||||
|
break;
|
||||||
case CKA_PRIVATE:
|
case CKA_PRIVATE:
|
||||||
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||||
*(CK_BBOOL*)attr->pValue = (prkey->prv_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
*(CK_BBOOL*)attr->pValue = (prkey->prv_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
||||||
|
@ -2214,7 +2200,6 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
||||||
{
|
{
|
||||||
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
||||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
||||||
struct pkcs15_slot_data *data = slot_data(ses->slot->fw_data);
|
|
||||||
int rv, flags = 0;
|
int rv, flags = 0;
|
||||||
|
|
||||||
sc_debug(context, "Initiating signing operation, mechanism 0x%x.\n",
|
sc_debug(context, "Initiating signing operation, mechanism 0x%x.\n",
|
||||||
|
@ -2286,15 +2271,6 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
||||||
pSignature,
|
pSignature,
|
||||||
*pulDataLen);
|
*pulDataLen);
|
||||||
|
|
||||||
/* Do we have to try a re-login and then try to sign again? */
|
|
||||||
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
||||||
rv = revalidate_pin(data, ses);
|
|
||||||
if (rv == 0)
|
|
||||||
rv = sc_pkcs15_compute_signature(fw_data->p15_card,
|
|
||||||
prkey->prv_p15obj, flags, pData, ulDataLen,
|
|
||||||
pSignature, *pulDataLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_unlock(ses->slot->card->card);
|
sc_unlock(ses->slot->card->card);
|
||||||
|
|
||||||
sc_debug(context, "Sign complete. Result %d.\n", rv);
|
sc_debug(context, "Sign complete. Result %d.\n", rv);
|
||||||
|
@ -2315,7 +2291,6 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
|
||||||
{
|
{
|
||||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
||||||
struct pkcs15_prkey_object *prkey;
|
struct pkcs15_prkey_object *prkey;
|
||||||
struct pkcs15_slot_data *data = slot_data(ses->slot->fw_data);
|
|
||||||
u8 decrypted[256];
|
u8 decrypted[256];
|
||||||
int buff_too_small, rv, flags = 0;
|
int buff_too_small, rv, flags = 0;
|
||||||
|
|
||||||
|
@ -2359,14 +2334,6 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
|
||||||
flags, pEncryptedData, ulEncryptedDataLen,
|
flags, pEncryptedData, ulEncryptedDataLen,
|
||||||
decrypted, sizeof(decrypted));
|
decrypted, sizeof(decrypted));
|
||||||
|
|
||||||
/* Do we have to try a re-login and then try to decrypt again? */
|
|
||||||
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
||||||
rv = revalidate_pin(data, ses);
|
|
||||||
if (rv == 0)
|
|
||||||
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj,
|
|
||||||
flags, pEncryptedData, ulEncryptedDataLen,
|
|
||||||
decrypted, sizeof(decrypted));
|
|
||||||
}
|
|
||||||
sc_unlock(ses->slot->card->card);
|
sc_unlock(ses->slot->card->card);
|
||||||
|
|
||||||
sc_debug(context, "Key unwrap/decryption complete. Result %d.\n", rv);
|
sc_debug(context, "Key unwrap/decryption complete. Result %d.\n", rv);
|
||||||
|
@ -2609,7 +2576,6 @@ static int pkcs15_dobj_get_value(struct sc_pkcs11_session *session,
|
||||||
int rv;
|
int rv;
|
||||||
struct pkcs15_fw_data *fw_data =
|
struct pkcs15_fw_data *fw_data =
|
||||||
(struct pkcs15_fw_data *) session->slot->card->fw_data;
|
(struct pkcs15_fw_data *) session->slot->card->fw_data;
|
||||||
struct pkcs15_slot_data *data = slot_data(session->slot->fw_data);
|
|
||||||
sc_card_t *card = session->slot->card->card;
|
sc_card_t *card = session->slot->card->card;
|
||||||
int reader = session->slot->card->reader;
|
int reader = session->slot->card->reader;
|
||||||
|
|
||||||
|
@ -2622,13 +2588,6 @@ static int pkcs15_dobj_get_value(struct sc_pkcs11_session *session,
|
||||||
|
|
||||||
rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data);
|
rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data);
|
||||||
|
|
||||||
/* Do we have to try a re-login and then try to sign again? */
|
|
||||||
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
||||||
rv = revalidate_pin(data, session);
|
|
||||||
if (rv == 0)
|
|
||||||
rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
return sc_to_cryptoki_error(rv, reader);
|
return sc_to_cryptoki_error(rv, reader);
|
||||||
|
@ -2727,7 +2686,6 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
||||||
struct pkcs15_data_object *obj = (struct pkcs15_data_object*) object;
|
struct pkcs15_data_object *obj = (struct pkcs15_data_object*) object;
|
||||||
struct sc_pkcs11_card *card = session->slot->card;
|
struct sc_pkcs11_card *card = session->slot->card;
|
||||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) card->fw_data;
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) card->fw_data;
|
||||||
struct pkcs15_slot_data *data = slot_data(session->slot->fw_data);
|
|
||||||
struct sc_profile *profile = NULL;
|
struct sc_profile *profile = NULL;
|
||||||
int reader = session->slot->card->reader;
|
int reader = session->slot->card->reader;
|
||||||
int rv;
|
int rv;
|
||||||
|
@ -2748,13 +2706,7 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
||||||
|
|
||||||
/* Delete object in smartcard */
|
/* Delete object in smartcard */
|
||||||
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
||||||
|
/* FIXME: PIN revalidation missing, following belongs libopensc */
|
||||||
/* Do we have to try a re-login and then try to delete again? */
|
|
||||||
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
||||||
rv = revalidate_pin(data, session);
|
|
||||||
if (rv == 0)
|
|
||||||
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
|
||||||
}
|
|
||||||
if (rv >= 0) {
|
if (rv >= 0) {
|
||||||
/* pool_find_and_delete is called, therefore correct refcont
|
/* pool_find_and_delete is called, therefore correct refcont
|
||||||
* Oppose to pkcs15_add_object */
|
* Oppose to pkcs15_add_object */
|
||||||
|
@ -2942,64 +2894,6 @@ asn1_sequence_wrapper(const u8 *data, size_t len, CK_ATTRIBUTE_PTR attr)
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cache_pin(void *p, int user, const sc_path_t *path, const void *pin, size_t len)
|
|
||||||
{
|
|
||||||
struct pkcs15_slot_data *data = (struct pkcs15_slot_data *) p;
|
|
||||||
|
|
||||||
#ifdef USE_PKCS15_INIT
|
|
||||||
if (len == 0) {
|
|
||||||
sc_keycache_forget_key(path, SC_AC_SYMBOLIC,
|
|
||||||
user? SC_PKCS15INIT_USER_PIN : SC_PKCS15INIT_SO_PIN);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((user != CKU_SO && user != CKU_USER) || !sc_pkcs11_conf.cache_pins)
|
|
||||||
return;
|
|
||||||
/* Don't cache pins related to user_consent objects/slots */
|
|
||||||
if (data->user_consent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memset(&data->pin[user], 0, sizeof(data->pin[user]));
|
|
||||||
if (len && len <= MAX_CACHE_PIN) {
|
|
||||||
memcpy(data->pin[user].value, pin, len);
|
|
||||||
data->pin[user].len = len;
|
|
||||||
if (path)
|
|
||||||
data->pin[user].path = *path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: GUI must indicate pinpad revalidation instead of a plain error.*/
|
|
||||||
static int
|
|
||||||
revalidate_pin(struct pkcs15_slot_data *data, struct sc_pkcs11_session *ses)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
u8 value[MAX_CACHE_PIN];
|
|
||||||
|
|
||||||
sc_debug(context, "PIN revalidation\n");
|
|
||||||
|
|
||||||
if (!sc_pkcs11_conf.cache_pins
|
|
||||||
&& !(ses->slot->token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH))
|
|
||||||
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
|
||||||
|
|
||||||
if (sc_pkcs11_conf.cache_pins && data->user_consent)
|
|
||||||
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
|
||||||
|
|
||||||
if (ses->slot->token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
|
|
||||||
rv = pkcs15_login(ses->slot->card, ses->slot->fw_data, CKU_USER, NULL, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(value, data->pin[CKU_USER].value, data->pin[CKU_USER].len);
|
|
||||||
rv = pkcs15_login(ses->slot->card, ses->slot->fw_data, CKU_USER,
|
|
||||||
value, data->pin[CKU_USER].len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv != CKR_OK)
|
|
||||||
sc_debug(context, "Re-login failed: 0x%0x (%d)\n", rv, rv);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
|
static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
|
||||||
{
|
{
|
||||||
CK_MECHANISM_INFO mech_info;
|
CK_MECHANISM_INFO mech_info;
|
||||||
|
@ -3141,6 +3035,7 @@ static int register_mechanisms(struct sc_pkcs11_card *p11card)
|
||||||
return rc;
|
return rc;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3172,7 +3067,8 @@ static void
|
||||||
add_pins_to_keycache(struct sc_pkcs11_card *p11card,
|
add_pins_to_keycache(struct sc_pkcs11_card *p11card,
|
||||||
struct sc_pkcs11_slot *slot)
|
struct sc_pkcs11_slot *slot)
|
||||||
{
|
{
|
||||||
#ifdef USE_PKCS15_INIT
|
#if 0
|
||||||
|
//#ifdef USE_PKCS15_INIT
|
||||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
||||||
struct sc_pkcs15_card *p15card = fw_data->p15_card;
|
struct sc_pkcs15_card *p15card = fw_data->p15_card;
|
||||||
struct pkcs15_slot_data *p15_data = slot_data(slot->fw_data);
|
struct pkcs15_slot_data *p15_data = slot_data(slot->fw_data);
|
||||||
|
|
|
@ -33,9 +33,7 @@ static CK_RV pkcs15init_bind(struct sc_pkcs11_card *p11card)
|
||||||
struct sc_profile *profile;
|
struct sc_profile *profile;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
rc = sc_pkcs15init_bind(card, "pkcs15", NULL, &profile);
|
rc = sc_pkcs15init_bind(card, "pkcs15", NULL, &profile);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
p11card->fw_data = profile;
|
p11card->fw_data = profile;
|
||||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||||
|
|
|
@ -80,10 +80,13 @@ sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *p11card,
|
||||||
unsigned int n, count = 0;
|
unsigned int n, count = 0;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
if (!pulCount)
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
for (n = 0; n < p11card->nmechanisms; n++) {
|
for (n = 0; n < p11card->nmechanisms; n++) {
|
||||||
if (!(mt = p11card->mechanisms[n]))
|
if (!(mt = p11card->mechanisms[n]))
|
||||||
continue;
|
continue;
|
||||||
if (count < *pulCount && pList)
|
if (pList && count < *pulCount)
|
||||||
pList[count] = mt->mech;
|
pList[count] = mt->mech;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ CK_RV sc_to_cryptoki_error(int rc, int reader)
|
||||||
case SC_ERROR_INVALID_DATA:
|
case SC_ERROR_INVALID_DATA:
|
||||||
case SC_ERROR_INCORRECT_PARAMETERS:
|
case SC_ERROR_INCORRECT_PARAMETERS:
|
||||||
return CKR_DATA_INVALID;
|
return CKR_DATA_INVALID;
|
||||||
|
case SC_ERROR_CARD_UNRESPONSIVE:
|
||||||
|
return CKR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
sc_debug(context, "opensc error: %s (%d)\n", sc_strerror(rc), rc);
|
sc_debug(context, "opensc error: %s (%d)\n", sc_strerror(rc), rc);
|
||||||
return CKR_GENERAL_ERROR;
|
return CKR_GENERAL_ERROR;
|
||||||
|
@ -320,8 +322,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
||||||
conf->max_virtual_slots = 16;
|
conf->max_virtual_slots = 16;
|
||||||
conf->slots_per_card = 4;
|
conf->slots_per_card = 4;
|
||||||
conf->hide_empty_tokens = 1;
|
conf->hide_empty_tokens = 1;
|
||||||
conf->lock_login = 1;
|
conf->lock_login = 0;
|
||||||
conf->cache_pins = 1;
|
|
||||||
conf->soft_keygen_allowed = 0;
|
conf->soft_keygen_allowed = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@ -337,6 +338,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
||||||
conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card);
|
conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card);
|
||||||
conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens);
|
conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens);
|
||||||
conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
|
conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
|
||||||
conf->cache_pins = scconf_get_bool(conf_block, "cache_pins", conf->cache_pins);
|
|
||||||
conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", conf->soft_keygen_allowed);
|
conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", conf->soft_keygen_allowed);
|
||||||
|
sc_debug(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d hide_empty_tokens=%d lock_login=%d",
|
||||||
|
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card, conf->hide_empty_tokens, conf->lock_login);
|
||||||
}
|
}
|
||||||
|
|
|
@ -621,7 +621,7 @@ type_spec ck_attribute_specs[] = {
|
||||||
{ CKA_EC_POINT , "CKA_EC_POINT ", print_generic, NULL },
|
{ CKA_EC_POINT , "CKA_EC_POINT ", print_generic, NULL },
|
||||||
{ CKA_SECONDARY_AUTH , "CKA_SECONDARY_AUTH ", print_generic, NULL },
|
{ CKA_SECONDARY_AUTH , "CKA_SECONDARY_AUTH ", print_generic, NULL },
|
||||||
{ CKA_AUTH_PIN_FLAGS , "CKA_AUTH_PIN_FLAGS ", print_generic, NULL },
|
{ CKA_AUTH_PIN_FLAGS , "CKA_AUTH_PIN_FLAGS ", print_generic, NULL },
|
||||||
{ CKA_ALWAYS_AUTHENTICATE, "CKA_ALWAYS_AUTHENTICATE ", print_generic, NULL },
|
{ CKA_ALWAYS_AUTHENTICATE, "CKA_ALWAYS_AUTHENTICATE ", print_boolean, NULL },
|
||||||
{ CKA_WRAP_WITH_TRUSTED , "CKA_WRAP_WITH_TRUSTED ", print_generic, NULL },
|
{ CKA_WRAP_WITH_TRUSTED , "CKA_WRAP_WITH_TRUSTED ", print_generic, NULL },
|
||||||
{ CKA_WRAP_TEMPLATE , "CKA_WRAP_TEMPLATE ", print_generic, NULL },
|
{ CKA_WRAP_TEMPLATE , "CKA_WRAP_TEMPLATE ", print_generic, NULL },
|
||||||
{ CKA_UNWRAP_TEMPLATE , "CKA_UNWRAP_TEMPLATE ", print_generic, NULL },
|
{ CKA_UNWRAP_TEMPLATE , "CKA_UNWRAP_TEMPLATE ", print_generic, NULL },
|
||||||
|
|
|
@ -188,7 +188,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (context != NULL) {
|
if (context != NULL) {
|
||||||
sc_error(context, "C_Initialize(): Cryptoki already initialized\n");
|
sc_debug(context, "C_Initialize(): Cryptoki already initialized\n");
|
||||||
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
|
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
||||||
|
|
||||||
rc = sc_context_create(&context, &ctx_opts);
|
rc = sc_context_create(&context, &ctx_opts);
|
||||||
if (rc != SC_SUCCESS) {
|
if (rc != SC_SUCCESS) {
|
||||||
rv = CKR_DEVICE_ERROR;
|
rv = CKR_GENERAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ again:
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(context, "sc_wait_for_event() returned %d\n", r);
|
sc_debug(context, "sc_wait_for_event() returned %d\n", r);
|
||||||
rv = sc_to_cryptoki_error(r, -1);
|
rv = sc_to_cryptoki_error(r, -1);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct sc_pkcs11_card;
|
||||||
|
|
||||||
/* Object Pool */
|
/* Object Pool */
|
||||||
struct sc_pkcs11_pool_item {
|
struct sc_pkcs11_pool_item {
|
||||||
int handle;
|
unsigned long int handle;
|
||||||
void *item;
|
void *item;
|
||||||
struct sc_pkcs11_pool_item *next;
|
struct sc_pkcs11_pool_item *next;
|
||||||
struct sc_pkcs11_pool_item *prev;
|
struct sc_pkcs11_pool_item *prev;
|
||||||
|
@ -92,7 +92,6 @@ struct sc_pkcs11_config {
|
||||||
unsigned int slots_per_card;
|
unsigned int slots_per_card;
|
||||||
unsigned char hide_empty_tokens;
|
unsigned char hide_empty_tokens;
|
||||||
unsigned char lock_login;
|
unsigned char lock_login;
|
||||||
unsigned char cache_pins;
|
|
||||||
unsigned char soft_keygen_allowed;
|
unsigned char soft_keygen_allowed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,7 @@ static int asepcos_cond_delete(sc_profile_t *pro, sc_card_t *card,
|
||||||
int r;
|
int r;
|
||||||
sc_file_t *tfile = NULL;
|
sc_file_t *tfile = NULL;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, path, &tfile);
|
r = sc_select_file(card, path, &tfile);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r == SC_SUCCESS) {
|
if (r == SC_SUCCESS) {
|
||||||
r = sc_pkcs15init_authenticate(pro, card, tfile, SC_AC_OP_DELETE_SELF);
|
r = sc_pkcs15init_authenticate(pro, card, tfile, SC_AC_OP_DELETE_SELF);
|
||||||
sc_file_free(tfile);
|
sc_file_free(tfile);
|
||||||
|
@ -64,9 +62,7 @@ static int asepcos_check_verify_tpin(sc_profile_t *profile, sc_card_t *card)
|
||||||
sc_path_t path;
|
sc_path_t path;
|
||||||
/* check whether the file with the transport PIN exists */
|
/* check whether the file with the transport PIN exists */
|
||||||
sc_format_path("3f000001", &path);
|
sc_format_path("3f000001", &path);
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r == SC_SUCCESS) {
|
if (r == SC_SUCCESS) {
|
||||||
/* try to verify the transport key */
|
/* try to verify the transport key */
|
||||||
u8 pbuf[64];
|
u8 pbuf[64];
|
||||||
|
@ -84,18 +80,18 @@ static int asepcos_check_verify_tpin(sc_profile_t *profile, sc_card_t *card)
|
||||||
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
||||||
sc_file_free(tfile);
|
sc_file_free(tfile);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to authenticate");
|
sc_debug(card->ctx, "unable to authenticate");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* store the transport key as a PIN */
|
/* store the transport key as a PIN */
|
||||||
r = sc_keycache_get_key(&path, SC_AC_AUT, 0, pbuf, psize);
|
r = sc_keycache_get_key(&path, SC_AC_AUT, 0, pbuf, psize);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "unable to get transport key");
|
sc_debug(card->ctx, "unable to get transport key");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r = sc_keycache_put_key(&path, SC_AC_CHV, 0, pbuf, (size_t)r);
|
r = sc_keycache_put_key(&path, SC_AC_CHV, 0, pbuf, (size_t)r);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to store transport key");
|
sc_debug(card->ctx, "unable to store transport key");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +215,7 @@ static int asepcos_pinid_to_akn(sc_card_t *card, int fileid, int *akn)
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
if (nfile->prop_attr == NULL || nfile->prop_attr_len != 11) {
|
if (nfile->prop_attr == NULL || nfile->prop_attr_len != 11) {
|
||||||
sc_error(card->ctx, "unable to determine AKN");
|
sc_debug(card->ctx, "unable to determine AKN");
|
||||||
sc_file_free(nfile);
|
sc_file_free(nfile);
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +240,7 @@ static int asepcos_do_store_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
*p++ = pinid & 0xff;
|
*p++ = pinid & 0xff;
|
||||||
/* pin length */
|
/* pin length */
|
||||||
if (pinlen < 4 || pinlen > 16) {
|
if (pinlen < 4 || pinlen > 16) {
|
||||||
sc_error(card->ctx, "invalid PIN length");
|
sc_debug(card->ctx, "invalid PIN length");
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
*p++ = 0x00;
|
*p++ = 0x00;
|
||||||
|
@ -310,7 +306,7 @@ static int asepcos_do_store_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
r = sc_create_file(card, nfile);
|
r = sc_create_file(card, nfile);
|
||||||
sc_file_free(nfile);
|
sc_file_free(nfile);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to create PIN file");
|
sc_debug(card->ctx, "unable to create PIN file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* get AKN of the newly created PIN */
|
/* get AKN of the newly created PIN */
|
||||||
|
@ -380,7 +376,7 @@ static int asepcos_create_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
r = sc_pkcs15init_authenticate(profile, card, tfile, SC_AC_OP_CREATE);
|
r = sc_pkcs15init_authenticate(profile, card, tfile, SC_AC_OP_CREATE);
|
||||||
sc_file_free(tfile);
|
sc_file_free(tfile);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to create PIN file, insufficent rights");
|
sc_debug(card->ctx, "unable to create PIN file, insufficent rights");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,13 +389,11 @@ static int asepcos_create_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
r = sc_append_file_id(&pin_path, pid & 0xff);
|
r = sc_append_file_id(&pin_path, pid & 0xff);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &pin_path, NULL);
|
r = sc_select_file(card, &pin_path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r == SC_SUCCESS)
|
if (r == SC_SUCCESS)
|
||||||
pid += 2;
|
pid += 2;
|
||||||
else if (r != SC_ERROR_FILE_NOT_FOUND) {
|
else if (r != SC_ERROR_FILE_NOT_FOUND) {
|
||||||
sc_error(card->ctx, "error selecting PIN file");
|
sc_debug(card->ctx, "error selecting PIN file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} while (r != SC_ERROR_FILE_NOT_FOUND);
|
} while (r != SC_ERROR_FILE_NOT_FOUND);
|
||||||
|
@ -452,7 +446,7 @@ static int asepcos_create_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
return r;
|
return r;
|
||||||
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_SET_SATTR, df);
|
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_SET_SATTR, df);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to change the security attributes");
|
sc_debug(card->ctx, "unable to change the security attributes");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* finally activate the application DF (fix ACLs) */
|
/* finally activate the application DF (fix ACLs) */
|
||||||
|
@ -465,7 +459,7 @@ static int asepcos_create_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
st.is_ef = 0;
|
st.is_ef = 0;
|
||||||
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_ACTIVATE_FILE, &st);
|
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_ACTIVATE_FILE, &st);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to activate DF");
|
sc_debug(card->ctx, "unable to activate DF");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,14 +491,14 @@ static int asepcos_do_authenticate(sc_profile_t *profile, sc_card_t *card,
|
||||||
sc_file_t *prkey = NULL;
|
sc_file_t *prkey = NULL;
|
||||||
r = sc_profile_get_file_by_path(profile, path, &prkey);
|
r = sc_profile_get_file_by_path(profile, path, &prkey);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to find file in profile");
|
sc_debug(card->ctx, "unable to find file in profile");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_pkcs15init_authenticate(profile, card, prkey, op);
|
r = sc_pkcs15init_authenticate(profile, card, prkey, op);
|
||||||
sc_file_free(prkey);
|
sc_file_free(prkey);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to authenticate");
|
sc_debug(card->ctx, "unable to authenticate");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
|
@ -565,7 +559,7 @@ static int asepcos_do_create_key(sc_card_t *card, size_t ksize, int fileid,
|
||||||
nfile->id = fileid & 0xffff;
|
nfile->id = fileid & 0xffff;
|
||||||
r = sc_file_set_prop_attr(nfile, buf, p - buf);
|
r = sc_file_set_prop_attr(nfile, buf, p - buf);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to set key prop. attributes");
|
sc_debug(card->ctx, "unable to set key prop. attributes");
|
||||||
sc_file_free(nfile);
|
sc_file_free(nfile);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -573,7 +567,7 @@ static int asepcos_do_create_key(sc_card_t *card, size_t ksize, int fileid,
|
||||||
r = sc_create_file(card, nfile);
|
r = sc_create_file(card, nfile);
|
||||||
sc_file_free(nfile);
|
sc_file_free(nfile);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to create key file");
|
sc_debug(card->ctx, "unable to create key file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -599,7 +593,7 @@ static int asepcos_create_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
st.akn = sc_keycache_find_named_pin(NULL, SC_PKCS15INIT_USER_PIN);
|
st.akn = sc_keycache_find_named_pin(NULL, SC_PKCS15INIT_USER_PIN);
|
||||||
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_AKN2FILEID, &st);
|
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_AKN2FILEID, &st);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to determine file id of the PIN");
|
sc_debug(card->ctx, "unable to determine file id of the PIN");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
afileid = st.fileid;
|
afileid = st.fileid;
|
||||||
|
@ -664,7 +658,7 @@ static int asepcos_create_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
|
|
||||||
r = asepcos_do_create_key(card, kinfo->modulus_length, fileid, buf, p - buf);
|
r = asepcos_do_create_key(card, kinfo->modulus_length, fileid, buf, p - buf);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to create private key file");
|
sc_debug(card->ctx, "unable to create private key file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -695,7 +689,7 @@ static int asepcos_do_store_rsa_key(sc_card_t *card, sc_profile_t *profile,
|
||||||
tpath.value[1] = kinfo->path.value[kinfo->path.len-1];
|
tpath.value[1] = kinfo->path.value[kinfo->path.len-1];
|
||||||
r = sc_select_file(card, &tpath, NULL);
|
r = sc_select_file(card, &tpath, NULL);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to select rsa key file");
|
sc_debug(card->ctx, "unable to select rsa key file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +728,7 @@ static int asepcos_do_store_rsa_key(sc_card_t *card, sc_profile_t *profile,
|
||||||
|
|
||||||
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_CHANGE_KEY, &ckdata);
|
r = sc_card_ctl(card, SC_CARDCTL_ASEPCOS_CHANGE_KEY, &ckdata);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to change key data");
|
sc_debug(card->ctx, "unable to change key data");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,7 +748,7 @@ static int asepcos_store_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data;
|
sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data;
|
||||||
|
|
||||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
sc_error(card->ctx, "only RSA is currently supported");
|
sc_debug(card->ctx, "only RSA is currently supported");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,7 +784,7 @@ static int asepcos_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
tpath.value[1] = kinfo->path.value[kinfo->path.len-1];
|
tpath.value[1] = kinfo->path.value[kinfo->path.len-1];
|
||||||
r = sc_select_file(card, &tpath, NULL);
|
r = sc_select_file(card, &tpath, NULL);
|
||||||
if (r != SC_SUCCESS) {
|
if (r != SC_SUCCESS) {
|
||||||
sc_error(card->ctx, "unable to select rsa key file");
|
sc_debug(card->ctx, "unable to select rsa key file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +803,7 @@ static int asepcos_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
|
||||||
sc_error(card->ctx, "error creating key");
|
sc_debug(card->ctx, "error creating key");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,12 +256,12 @@ cardos_store_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
int algorithm = 0, r;
|
int algorithm = 0, r;
|
||||||
|
|
||||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
sc_error(card->ctx, "CardOS supports RSA keys only.");
|
sc_debug(card->ctx, "CardOS supports RSA keys only.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cardos_key_algorithm(key_info->usage, key_info->modulus_length, &algorithm) < 0) {
|
if (cardos_key_algorithm(key_info->usage, key_info->modulus_length, &algorithm) < 0) {
|
||||||
sc_error(card->ctx, "CardOS does not support keys "
|
sc_debug(card->ctx, "CardOS does not support keys "
|
||||||
"that can both sign _and_ decrypt.");
|
"that can both sign _and_ decrypt.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ cardos_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
rsa_max_size = (card->caps & SC_CARD_CAP_RSA_2048) ? 2048 : 1024;
|
rsa_max_size = (card->caps & SC_CARD_CAP_RSA_2048) ? 2048 : 1024;
|
||||||
keybits = key_info->modulus_length & ~7UL;
|
keybits = key_info->modulus_length & ~7UL;
|
||||||
if (keybits > rsa_max_size) {
|
if (keybits > rsa_max_size) {
|
||||||
sc_error(card->ctx, "Unable to generate key, max size is %lu",
|
sc_debug(card->ctx, "Unable to generate key, max size is %lu",
|
||||||
(unsigned long) rsa_max_size);
|
(unsigned long) rsa_max_size);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -325,13 +325,13 @@ cardos_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
use_ext_rsa = 1;
|
use_ext_rsa = 1;
|
||||||
|
|
||||||
if (cardos_key_algorithm(key_info->usage, keybits, &algorithm) < 0) {
|
if (cardos_key_algorithm(key_info->usage, keybits, &algorithm) < 0) {
|
||||||
sc_error(card->ctx, "CardOS does not support keys "
|
sc_debug(card->ctx, "CardOS does not support keys "
|
||||||
"that can both sign _and_ decrypt.");
|
"that can both sign _and_ decrypt.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc_profile_get_file(profile, "tempfile", &temp) < 0) {
|
if (sc_profile_get_file(profile, "tempfile", &temp) < 0) {
|
||||||
sc_error(card->ctx, "Profile doesn't define temporary file "
|
sc_debug(card->ctx, "Profile doesn't define temporary file "
|
||||||
"for key generation.");
|
"for key generation.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ cardos_store_pin(sc_profile_t *profile, sc_card_t *card,
|
||||||
* "no padding required". */
|
* "no padding required". */
|
||||||
maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded));
|
maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded));
|
||||||
if (pin_len > maxlen) {
|
if (pin_len > maxlen) {
|
||||||
sc_error(card->ctx, "invalid pin length: %u (max %u)\n",
|
sc_debug(card->ctx, "invalid pin length: %u (max %u)\n",
|
||||||
pin_len, maxlen);
|
pin_len, maxlen);
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
@ -675,13 +675,13 @@ static int parse_ext_pubkey_file(sc_card_t *card, const u8 *data, size_t len,
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
data = sc_asn1_find_tag(card->ctx, data, len, 0x7f49, &ilen);
|
data = sc_asn1_find_tag(card->ctx, data, len, 0x7f49, &ilen);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
sc_error(card->ctx, "invalid public key data: missing tag");
|
sc_debug(card->ctx, "invalid public key data: missing tag");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = sc_asn1_find_tag(card->ctx, data, ilen, 0x81, &tlen);
|
p = sc_asn1_find_tag(card->ctx, data, ilen, 0x81, &tlen);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
sc_error(card->ctx, "invalid public key data: missing modulus");
|
sc_debug(card->ctx, "invalid public key data: missing modulus");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
pubkey->u.rsa.modulus.len = tlen;
|
pubkey->u.rsa.modulus.len = tlen;
|
||||||
|
@ -692,7 +692,7 @@ static int parse_ext_pubkey_file(sc_card_t *card, const u8 *data, size_t len,
|
||||||
|
|
||||||
p = sc_asn1_find_tag(card->ctx, data, ilen, 0x82, &tlen);
|
p = sc_asn1_find_tag(card->ctx, data, ilen, 0x82, &tlen);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
sc_error(card->ctx, "invalid public key data: missing exponent");
|
sc_debug(card->ctx, "invalid public key data: missing exponent");
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
pubkey->u.rsa.exponent.len = tlen;
|
pubkey->u.rsa.exponent.len = tlen;
|
||||||
|
|
|
@ -72,9 +72,7 @@ cflex_delete_file(sc_profile_t *profile, sc_card_t *card, sc_file_t *df)
|
||||||
path.value[1] = df->id & 0xFF;
|
path.value[1] = df->id & 0xFF;
|
||||||
path.len = 2;
|
path.len = 2;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_delete_file(card, &path);
|
r = sc_delete_file(card, &path);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +257,7 @@ cflex_create_key(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_object_t *obj
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
sc_error(card->ctx, "Cryptoflex supports only RSA keys.");
|
sc_debug(card->ctx, "Cryptoflex supports only RSA keys.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +273,7 @@ cflex_create_key(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_object_t *obj
|
||||||
case 1024: size = 326; break;
|
case 1024: size = 326; break;
|
||||||
case 2048: size = 646; break;
|
case 2048: size = 646; break;
|
||||||
default:
|
default:
|
||||||
sc_error(card->ctx, "Unsupported key size %u\n",
|
sc_debug(card->ctx, "Unsupported key size %u\n",
|
||||||
key_info->modulus_length);
|
key_info->modulus_length);
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -316,7 +314,7 @@ cflex_generate_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
sc_error(card->ctx, "Cryptoflex supports only RSA keys.");
|
sc_debug(card->ctx, "Cryptoflex supports only RSA keys.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +376,7 @@ cflex_store_key(sc_profile_t *profile, sc_card_t *card,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
sc_error(card->ctx, "Cryptoflex supports only RSA keys.");
|
sc_debug(card->ctx, "Cryptoflex supports only RSA keys.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,9 +449,7 @@ cflex_create_dummy_chvs(sc_profile_t *profile, sc_card_t *card,
|
||||||
&& !memcmp(ef.value, parent.value, ef.len))
|
&& !memcmp(ef.value, parent.value, ef.len))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &ef, NULL);
|
r = sc_select_file(card, &ef, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a valid EF(CHVx) was found, we're fine */
|
/* If a valid EF(CHVx) was found, we're fine */
|
||||||
|
@ -524,9 +520,7 @@ cflex_create_pin_file(sc_profile_t *profile, sc_card_t *card,
|
||||||
path.value[path.len++] = 0;
|
path.value[path.len++] = 0;
|
||||||
|
|
||||||
/* See if the CHV already exists */
|
/* See if the CHV already exists */
|
||||||
sc_ctx_suppress_errors_on(card->ctx);
|
|
||||||
r = sc_select_file(card, &path, NULL);
|
r = sc_select_file(card, &path, NULL);
|
||||||
sc_ctx_suppress_errors_off(card->ctx);
|
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return SC_ERROR_FILE_ALREADY_EXISTS;
|
return SC_ERROR_FILE_ALREADY_EXISTS;
|
||||||
|
|
||||||
|
@ -534,7 +528,7 @@ cflex_create_pin_file(sc_profile_t *profile, sc_card_t *card,
|
||||||
if (sc_profile_get_file_by_path(profile, &path, &file) < 0
|
if (sc_profile_get_file_by_path(profile, &path, &file) < 0
|
||||||
&& sc_profile_get_file(profile, (ref == 1)? "CHV1" : "CHV2", &file) < 0
|
&& sc_profile_get_file(profile, (ref == 1)? "CHV1" : "CHV2", &file) < 0
|
||||||
&& sc_profile_get_file(profile, "CHV", &file) < 0) {
|
&& sc_profile_get_file(profile, "CHV", &file) < 0) {
|
||||||
sc_error(card->ctx, "profile does not define pin file ACLs\n");
|
sc_debug(card->ctx, "profile does not define pin file ACLs\n");
|
||||||
return SC_ERROR_FILE_NOT_FOUND;
|
return SC_ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +553,7 @@ cflex_create_pin_file(sc_profile_t *profile, sc_card_t *card,
|
||||||
file, SC_AC_OP_UPDATE,
|
file, SC_AC_OP_UPDATE,
|
||||||
dummies);
|
dummies);
|
||||||
if (ndummies < 0) {
|
if (ndummies < 0) {
|
||||||
sc_error(card->ctx,
|
sc_debug(card->ctx,
|
||||||
"Unable to create dummy CHV file: %s",
|
"Unable to create dummy CHV file: %s",
|
||||||
sc_strerror(ndummies));
|
sc_strerror(ndummies));
|
||||||
return ndummies;
|
return ndummies;
|
||||||
|
@ -619,7 +613,7 @@ static int cflex_get_keyfiles(sc_profile_t *profile, sc_card_t *card,
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
pbuf[0] = '\0';
|
pbuf[0] = '\0';
|
||||||
|
|
||||||
sc_error(card->ctx, "Cannot find private key file info "
|
sc_debug(card->ctx, "Cannot find private key file info "
|
||||||
"in profile (path=%s).", pbuf);
|
"in profile (path=%s).", pbuf);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -629,7 +623,7 @@ static int cflex_get_keyfiles(sc_profile_t *profile, sc_card_t *card,
|
||||||
sc_append_file_id(&path, 0x1012);
|
sc_append_file_id(&path, 0x1012);
|
||||||
r = sc_profile_get_file_by_path(profile, &path, pukf);
|
r = sc_profile_get_file_by_path(profile, &path, pukf);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "Cannot find public key file info in profile.");
|
sc_debug(card->ctx, "Cannot find public key file info in profile.");
|
||||||
sc_file_free(*prkf);
|
sc_file_free(*prkf);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue