Merge branch 'master' into gnuk
Conflicts: src/libopensc/card-openpgp.c src/tools/openpgp-tool.c
This commit is contained in:
commit
70890a8f61
|
@ -70,6 +70,7 @@ doc/tools/pkcs15-init
|
|||
doc/tools/pkcs15-tool
|
||||
doc/tools/sc-hsm-tool
|
||||
doc/tools/westcos-tool
|
||||
doc/tools/dnie-tool
|
||||
|
||||
etc/opensc.conf.win
|
||||
etc/opensc.conf
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
language: C
|
||||
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "UkHn7wy4im8V1nebCWbAetnDSOLRUbOlF6++ovk/7Bnso1/lnhXHelyzgRxfD/oI68wm9nnRV+RQEZ9+72Ug1CyvHxyyxxkwal/tPeHH4B/L+aGdPi0id+5OZSKIm77VP3m5s102sJMJgH7DFd03+nUd0K26p0tk8ad4j1geV4c="
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: clang
|
||||
os: osx
|
||||
- compiler: gcc
|
||||
os: osx
|
||||
- compiler: clang
|
||||
os: linux
|
||||
env: ENABLE_DOC=--enable-doc
|
||||
- compiler: gcc
|
||||
os: linux
|
||||
env: ENABLE_DOC=--enable-doc
|
||||
- compiler: gcc
|
||||
os: linux
|
||||
env: HOST=i686-w64-mingw32
|
||||
|
||||
before_install:
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then
|
||||
sudo apt-get update || true;
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then
|
||||
if [ -z "$HOST" ]; then
|
||||
sudo apt-get install libpcsclite-dev xsltproc docbook-xsl;
|
||||
else
|
||||
sudo apt-get install mingw-w64 binutils-mingw-w64-i686 gcc-mingw-w64-i686;
|
||||
fi
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- ./bootstrap
|
||||
- if [ -z "$HOST" ]; then
|
||||
./configure $ENABLE_DOC --enable-dnie-ui;
|
||||
else
|
||||
unset CC;
|
||||
unset CXX;
|
||||
./configure --host=$HOST --disable-openssl;
|
||||
fi
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "OpenSC/OpenSC"
|
||||
description: "Build submitted via Travis CI"
|
||||
notification_email: viktor.tarasov@gmail.com
|
||||
build_command: "make -j 4"
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
script:
|
||||
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then
|
||||
if [ $TRAVIS_OS_NAME == osx ]; then
|
||||
./MacOSX/build;
|
||||
else
|
||||
make;
|
||||
fi;
|
||||
fi
|
||||
- if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 -a "$TRAVIS_OS_NAME" != "osx" ]; then
|
||||
make check;
|
||||
make dist;
|
||||
fi
|
|
@ -0,0 +1,3 @@
|
|||
# Reporting Bugs
|
||||
|
||||
Please read about [reporting bugs](https://github.com/OpenSC/OpenSC/wiki/How-to-report-bugs-so-that-they-can-be-fixed) before opening an issue.
|
|
@ -70,12 +70,9 @@ fi
|
|||
test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src
|
||||
|
||||
# Build and copy OpenSC.tokend
|
||||
xcodebuild -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj
|
||||
xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${PWD}/target
|
||||
|
||||
# Prepare target root
|
||||
# Copy Tokend
|
||||
mkdir -p target/System/Library/Security/tokend
|
||||
mv OpenSC.tokend/build/OpenSC.tokend target/System/Library/Security/tokend
|
||||
# The "UnInstaller"
|
||||
mkdir -p target/usr/local/bin
|
||||
cp MacOSX/opensc-uninstall target/usr/local/bin
|
||||
|
|
|
@ -16,6 +16,7 @@ test -L /usr/lib/opensc-pkcs11.so && rm -f /usr/lib/opensc-pkcs11.so
|
|||
|
||||
# Remove installed files
|
||||
rm -rf /Library/OpenSC
|
||||
rm -rf /Library/Security/tokend/OpenSC.tokend
|
||||
rm -rf /System/Library/Security/tokend/OpenSC.tokend
|
||||
|
||||
# delete receipts on 10.6+
|
||||
|
|
64
NEWS
64
NEWS
|
@ -1,4 +1,68 @@
|
|||
NEWS for OpenSC -- History of user visible changes
|
||||
New in 0.15.0; 2015-05-11
|
||||
* new card drivers
|
||||
AzeDIT 3.5
|
||||
IsoApplet
|
||||
MaskTech
|
||||
* libopensc
|
||||
allow extended length APDUs
|
||||
accept no output for 'SELECT' MF and 'SELECT' DF_NAME APDUs
|
||||
fixed sc_driver_version check
|
||||
adjusted send/receive size accoriding to card capabilities
|
||||
in iso7816 make SELECT agnosting to sc_path_t's aid
|
||||
* asn1
|
||||
support multi-bytes tags
|
||||
* pkcs15
|
||||
reviewed support and tool functions for public key
|
||||
public certs and pubkeys with an auth_id are treated as private
|
||||
* pkcs11
|
||||
introduced default PKCS#11 provider
|
||||
fetched real value of CKA_LOCAL for pubkey
|
||||
removed inconsistent attributes
|
||||
C_Digest issues
|
||||
no check if buffer too small before update
|
||||
* added support for Travis CI
|
||||
* updated support of EC in libopensc, pkcs15 and pkcs11
|
||||
* fixed number of warnings, resource leaks, overity-scan issues
|
||||
* macosx
|
||||
target minimum OSX version to 10.7
|
||||
update the minimal building instructions.
|
||||
locate and target the latest SDK to build against.
|
||||
locate the best newest SDK present on the computer.
|
||||
* build
|
||||
disable Secure Messaging if OpenSSL is not used
|
||||
* tools
|
||||
util_get_pin helper function
|
||||
* PIV
|
||||
Add AES support for PIV General Authenticate
|
||||
fixed invalid bit when writing PIV certificate object with gzipped certificate
|
||||
fixed bad caching behavior of PIV PKCS15 emulator
|
||||
* ePass2003
|
||||
fixed failure due to re-authenticate of secure messaging when card is accessed
|
||||
by multiple PKCS11 sessions
|
||||
* MyEID
|
||||
EC support for MyEID-v4 card
|
||||
* openpgp
|
||||
extended options for openpgp-tool
|
||||
* asepcos
|
||||
fixed puk handling
|
||||
* sc-hsm
|
||||
support for Koblitz curves secp192k1 and secp256k1 (Bitcoin)
|
||||
improved error detection and reporting in sc-hsm-tool
|
||||
fixed Lc byte in VERIFY PIN block for PC/SC PIN PAD reader
|
||||
fix certificate delete bug
|
||||
* IAS/ECC
|
||||
fixed PKCS#11 compliance issues
|
||||
support for Morpho IAS Agent Card
|
||||
* cardos
|
||||
overwrite content of deleted private key
|
||||
* win32
|
||||
setup improuvement
|
||||
look & feel
|
||||
custom actions with card registration
|
||||
minidriver impouvement
|
||||
fixed errors and warnings returned by Microsoft quality tool
|
||||
pin-pad support
|
||||
|
||||
New in 0.14.0; 2014-05-31
|
||||
* new card driver DNIe
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
OpenSC documentation wiki is available online at
|
||||
https://github.com/OpenSC/OpenSC/wiki
|
||||
|
||||
Please take a look at the documentation before trying to use OpenSC.
|
||||
|
||||
Coverity Scan:
|
||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/4026/badge.svg)](https://scan.coverity.com/projects/4026)
|
||||
|
||||
Jenkins CI:
|
||||
[![Build Status](https://opensc.fr/jenkins/buildStatus/icon?job=OpenSC-master)](https://opensc.fr/jenkins/view/OpenSC-master/job/OpenSC-master/)
|
||||
|
||||
Travis CI:
|
||||
[![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC)
|
||||
|
43
configure.ac
43
configure.ac
|
@ -6,7 +6,7 @@ define([PRODUCT_NAME], [OpenSC])
|
|||
define([PRODUCT_TARNAME], [opensc])
|
||||
define([PRODUCT_BUGREPORT], [opensc-devel@lists.sourceforge.net])
|
||||
define([PACKAGE_VERSION_MAJOR], [0])
|
||||
define([PACKAGE_VERSION_MINOR], [14])
|
||||
define([PACKAGE_VERSION_MINOR], [15])
|
||||
define([PACKAGE_VERSION_FIX], [0])
|
||||
define([PACKAGE_SUFFIX], [])
|
||||
define([PACKAGE_VERSION_REVISION], [0])
|
||||
|
@ -39,8 +39,8 @@ OPENSC_VS_FF_PRODUCT_NAME="VS_FF_PRODUCT_NAME"
|
|||
# (Code changed: REVISION++)
|
||||
# (Oldest interface removed: OLDEST++)
|
||||
# (Interfaces added: CURRENT++, REVISION=0)
|
||||
OPENSC_LT_CURRENT="3"
|
||||
OPENSC_LT_OLDEST="3"
|
||||
OPENSC_LT_CURRENT="4"
|
||||
OPENSC_LT_OLDEST="4"
|
||||
OPENSC_LT_REVISION="0"
|
||||
OPENSC_LT_AGE="0"
|
||||
OPENSC_LT_AGE="$((${OPENSC_LT_CURRENT}-${OPENSC_LT_OLDEST}))"
|
||||
|
@ -52,6 +52,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|||
|
||||
AC_CANONICAL_HOST
|
||||
AC_PROG_CC
|
||||
# AC_PROG_CXX is needed to built the win32 custom action. Indeed dutil.h use [extern "C"] definition which fails on pure c compiler
|
||||
AC_PROG_CXX
|
||||
PKG_PROG_PKG_CONFIG
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
|
@ -218,6 +220,13 @@ AC_ARG_WITH(
|
|||
,
|
||||
[with_pcsc_provider="detect"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(
|
||||
[pkcs11-provider],
|
||||
[AS_HELP_STRING([--with-pkcs11-provider=PATH],[Path to the default PKCS11 provider @<:@default=OpenSC@:>@])],
|
||||
,
|
||||
[with_pkcs11_provider="detect"]
|
||||
)
|
||||
dnl ./configure check
|
||||
reader_count=""
|
||||
for rdriver in "${enable_pcsc}" "${enable_openct}" "${enable_ctapi}"; do
|
||||
|
@ -531,10 +540,13 @@ if test "${enable_pcsc}" = "yes"; then
|
|||
case "${host}" in
|
||||
*-*-darwin*)
|
||||
# Locate the latest SDK.
|
||||
SDKS_PATH="$(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs"
|
||||
SDKS_PATH="$(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs"
|
||||
if test -d $SDKS_PATH; then
|
||||
SDK_PATH="${SDK_PATH:-$SDKS_PATH/$(ls -1 ${SDKS_PATH} | sort -n -t. -k2 -r | head -1)}"
|
||||
# and set the PC/SC include path
|
||||
PCSC_CFLAGS="-I$SDK_PATH/System/Library/Frameworks/PCSC.framework/Versions/Current/Headers"
|
||||
else
|
||||
PCSC_CFLAGS="-I/System/Library/Frameworks/PCSC.framework/Headers"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
PCSC_CFLAGS="-I/usr/include/PCSC"
|
||||
|
@ -568,6 +580,24 @@ if test "${enable_pcsc}" = "yes"; then
|
|||
AC_DEFINE([ENABLE_PCSC], [1], [Define if PC/SC is to be enabled])
|
||||
fi
|
||||
|
||||
|
||||
if test "${with_pkcs11_provider}" = "detect"; then
|
||||
case "${host}" in
|
||||
*-*-darwin*)
|
||||
DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.dylib"
|
||||
;;
|
||||
*-mingw*|*-winnt*|*-cygwin*)
|
||||
DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.dll"
|
||||
;;
|
||||
*)
|
||||
DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.so"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
DEFAULT_PKCS11_PROVIDER="${with_pkcs11_provider}"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([DEFAULT_PKCS11_PROVIDER], ["${DEFAULT_PKCS11_PROVIDER}"], [Default PKCS11 provider])
|
||||
|
||||
if test "${enable_man}" = "detect"; then
|
||||
if test "${WIN32}" = "yes"; then
|
||||
enable_man="no"
|
||||
|
@ -643,6 +673,7 @@ AC_SUBST([OPENSC_LT_AGE])
|
|||
AC_SUBST([OPENSC_LT_OLDEST])
|
||||
AC_SUBST([WIN_LIBPREFIX])
|
||||
AC_SUBST([DEFAULT_PCSC_PROVIDER])
|
||||
AC_SUBST([DEFAULT_PKCS11_PROVIDER])
|
||||
AC_SUBST([OPTIONAL_ZLIB_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_ZLIB_LIBS])
|
||||
AC_SUBST([OPTIONAL_READLINE_CFLAGS])
|
||||
|
@ -708,6 +739,7 @@ AC_CONFIG_FILES([
|
|||
src/minidriver/opensc-minidriver.inf
|
||||
win32/Makefile
|
||||
win32/versioninfo.rc
|
||||
win32/versioninfo-customactions.rc
|
||||
win32/winconfig.h
|
||||
win32/OpenSC.iss
|
||||
win32/OpenSC.wxs
|
||||
|
@ -752,6 +784,7 @@ DNIe UI support: ${enable_dnie_ui}
|
|||
Debug file: ${DEBUG_FILE}
|
||||
|
||||
PC/SC default provider: ${DEFAULT_PCSC_PROVIDER}
|
||||
PKCS11 default provider: ${DEFAULT_PKCS11_PROVIDER}
|
||||
|
||||
Host: ${host}
|
||||
Compiler: ${CC}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
|
||||
EXTRA_DIST = completion-template
|
||||
|
||||
dist_noinst_DATA = $(wildcard $(srcdir)/*.xml)
|
||||
if ENABLE_DOC
|
||||
html_DATA = tools.html
|
||||
|
@ -25,8 +27,8 @@ tools.html: $(srcdir)/tools.xml $(wildcard $(srcdir)/*.1.xml) $(wildcard $(srcdi
|
|||
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $<
|
||||
|
||||
%: $(srcdir)/%.1.xml
|
||||
echo $< $@
|
||||
cat completion-template \
|
||||
@echo $< $@
|
||||
@cat completion-template \
|
||||
| sed "s,ALLOPTS,\
|
||||
$(shell sed -n 's,\s\s\s*<option>\([^<]*\)</option>.*,\1,pg' $< \
|
||||
| sort -u | grep -- '^\-' | tr '\n' ' ')," \
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
<refmeta>
|
||||
<refentrytitle>dnie-tool</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo>opensc</refmiscinfo>
|
||||
<refmiscinfo class="productname">OpenSC</refmiscinfo>
|
||||
<refmiscinfo class="manual">OpenSC Tools</refmiscinfo>
|
||||
<refmiscinfo class="source">opensc</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
|
@ -11,12 +13,12 @@
|
|||
<refpurpose>displays information about DNIe based security tokens</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Synopsis</title>
|
||||
<para>
|
||||
<command>dnie-tool</command> [OPTIONS]
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>dnie-tool</command>
|
||||
<arg choice="opt"><replaceable class="option">OPTIONS</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
@ -30,33 +32,49 @@
|
|||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--idesp, -i </option></term>
|
||||
<listitem><para>Show the DNIe IDESP value.
|
||||
</para></listitem>
|
||||
<term>
|
||||
<option>--idesp</option>,
|
||||
<option>-i</option>
|
||||
</term>
|
||||
<listitem><para>Show the DNIe IDESP value.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--data, -d </option></term>
|
||||
<term>
|
||||
<option>--data</option>,
|
||||
<option>-d</option>
|
||||
</term>
|
||||
<listitem><para>Show DNIe personal information.
|
||||
Reads and print DNIe number and User Name and SurName</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--all, -a </option></term>
|
||||
<term>
|
||||
<option>--all</option>,
|
||||
<option>-a</option>
|
||||
</term>
|
||||
<listitem><para>Displays every available information.
|
||||
This command is equivalent to -d -i -s
|
||||
</para></listitem>
|
||||
This command is equivalent to -d -i -s</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--serial, -s </option></term>
|
||||
<term>
|
||||
<option>--serial</option>,
|
||||
<option>-s</option>
|
||||
</term>
|
||||
<listitem><para>Displays DNIe Serial Number
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--version, -V </option></term>
|
||||
<term>
|
||||
<option>--version</option>,
|
||||
<option>-V</option>
|
||||
</term>
|
||||
<listitem><para>Show DNIe sw version.
|
||||
Displays sofware version for in-card DNIe OS</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--pin</option> <replaceable>pin</replaceable>, <option>-p</option> <replaceable>pin</replaceable></term>
|
||||
<term>
|
||||
<option>--pin</option> <replaceable>pin</replaceable>,
|
||||
<option>-p</option> <replaceable>pin</replaceable>
|
||||
</term>
|
||||
<listitem><para>Specify the user pin <replaceable>pin</replaceable> to use.
|
||||
If set to env:<replaceable>VARIABLE</replaceable>, the
|
||||
value of the environment variable
|
||||
|
@ -64,22 +82,34 @@
|
|||
The default is do not enter pin</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--reader</option> <replaceable>number</replaceable>, <option>-r</option> <replaceable>number</replaceable></term>
|
||||
<term>
|
||||
<option>--reader</option> <replaceable>number</replaceable>,
|
||||
<option>-r</option> <replaceable>number</replaceable>
|
||||
</term>
|
||||
<listitem><para>Specify the reader <replaceable>number</replaceable> to use.
|
||||
The default is reader 0.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--driver</option> <replaceable>driver</replaceable>, <option>-c</option> <replaceable>driver</replaceable></term>
|
||||
<term>
|
||||
<option>--driver</option> <replaceable>driver</replaceable>,
|
||||
<option>-c</option> <replaceable>driver</replaceable>
|
||||
</term>
|
||||
<listitem><para>Specify the card driver <replaceable>driver</replaceable> to use.
|
||||
Default is use driver from configuration file, or auto-detect if absent</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--wait, -w</option></term>
|
||||
<term>
|
||||
<option>--wait</option>,
|
||||
<option>-w</option>
|
||||
</term>
|
||||
<listitem><para>Causes <command>dnie-tool</command> to wait for the token to be inserted into reader.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--verbose, -v</option></term>
|
||||
<term>
|
||||
<option>--verbose</option>,
|
||||
<option>-v</option>
|
||||
</term>
|
||||
<listitem><para>Causes <command>dnie-tool</command> to be more verbose.
|
||||
Specify this flag several times
|
||||
to enable debug output in the opensc library.</para></listitem>
|
||||
|
|
|
@ -292,6 +292,14 @@
|
|||
Files are found by selecting all file identifiers in the range from <replaceable>start-fid</replaceable> to <replaceable>end-fid</replaceable> (by default from 0000 to FFFF).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>find_tags</command> [<replaceable>start-tag</replaceable> [<replaceable>end-tag</replaceable>]]
|
||||
</term>
|
||||
<listitem><para>Find all tags of data objects in the current context.
|
||||
Tags are found by using GET DATA in the range from <replaceable>start-tag</replaceable> to <replaceable>end-tag</replaceable> (by default from 0000 to FFFF).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>mkdir</command> <replaceable>file-id</replaceable> <replaceable>size</replaceable>
|
||||
|
|
|
@ -236,6 +236,13 @@
|
|||
<listitem><para>Sign some data.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--decrypt</option>,
|
||||
</term>
|
||||
<listitem><para>Decrypt some data.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--slot</option> <replaceable>id</replaceable>
|
||||
|
|
|
@ -159,6 +159,18 @@
|
|||
(see also <option>--raw</option>).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--signature-format</option>,
|
||||
<option>--f</option>
|
||||
</term>
|
||||
<listitem><para>When signing with ECDSA key this option indicates
|
||||
to <command>pkcs15-crypt</command> the signature output format.
|
||||
Possible values are 'rs'(default) -- two concatanated
|
||||
integers (PKCS#11), 'sequence' or 'openssl' -- DER encoded sequence
|
||||
of two integeres (OpenSSL).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--verbose</option>,
|
||||
|
@ -168,7 +180,6 @@
|
|||
verbose. Specify this flag several times to enable debug output
|
||||
in the OpenSC library.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
|
|
@ -185,7 +185,21 @@
|
|||
</term>
|
||||
<listitem><para>Reads the public key with id <replaceable>id</replaceable>,
|
||||
writing the output in format suitable for
|
||||
<filename>$HOME/.ssh/authorized_keys</filename>.</para></listitem>
|
||||
<filename>$HOME/.ssh/authorized_keys</filename>.</para>
|
||||
|
||||
<para>The key label, if any will be shown in the 'Comment' field.</para>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--rfc4716</option>
|
||||
</term>
|
||||
<listitem><para>When used in conjunction with option <option>--read-ssh-key</option> the
|
||||
output format of the public key follows rfc4716.</para></listitem>
|
||||
</varlistentry>
|
||||
<para></para>
|
||||
<para> The default output format is a single line (openssh).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -15,7 +15,7 @@ force:
|
|||
opensc.conf: opensc.conf.in force
|
||||
|
||||
.in:
|
||||
sed \
|
||||
@sed \
|
||||
-e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
|
||||
-e 's|@libdir[@]|$(libdir)|g' \
|
||||
-e 's|@DEFAULT_PCSC_PROVIDER[@]|$(DEFAULT_PCSC_PROVIDER)|g' \
|
||||
|
|
|
@ -202,6 +202,10 @@ app default {
|
|||
#
|
||||
# flags = "rng", "0x80000000";
|
||||
|
||||
# Enable pkcs11 initialization.
|
||||
# Default: no
|
||||
# pkcs11_enable_InitToken = yes;
|
||||
|
||||
#
|
||||
# Context: PKCS#15 emulation layer
|
||||
#
|
||||
|
@ -301,6 +305,14 @@ app default {
|
|||
# name = "Morpho YpsID S3 IAS/ECC";
|
||||
# # secure_messaging = local_morpho_YpsID_S3;
|
||||
#}
|
||||
#card_atr 3B:DF:96:00:80:31:FE:45:00:31:B8:64:04:1F:EC:C1:73:94:01:80:82:90:00:EC {
|
||||
# type = 25005;
|
||||
# driver = "iasecc";
|
||||
# name = "Morpho MI IAS/ECC v1.0.1";
|
||||
# md_read_only = false;
|
||||
# md_supports_X509_enrollment = true;
|
||||
# secure_messaging = local_morpho_mi;
|
||||
#}
|
||||
card_atr 3B:DF:18:FF:81:91:FE:1F:C3:00:31:B8:64:0C:01:EC:C1:73:94:01:80:82:90:00:B3 {
|
||||
type = 25004;
|
||||
driver = "iasecc";
|
||||
|
|
|
@ -202,6 +202,10 @@ app default {
|
|||
#
|
||||
# flags = "rng", "0x80000000";
|
||||
|
||||
# Enable pkcs11 initialization.
|
||||
# Default: no
|
||||
# pkcs11_enable_InitToken = yes;
|
||||
|
||||
#
|
||||
# Context: PKCS#15 emulation layer
|
||||
#
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if ! ( defined(HAVE_GETOPT_H) && defined(HAVE_GETOPT_LONG) && defined(HAVE_GETOPT_LONG_ONLY) )
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ main(int argc, char * argv[])
|
|||
case 'o': /* -output=FILE */
|
||||
outfilename = optarg;
|
||||
/* we allow "-" as a synonym for stdout here */
|
||||
if (! strcmp(optarg, "-"))
|
||||
if (optarg && !strcmp(optarg, "-"))
|
||||
{
|
||||
outfilename = 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETPASS /* empty file if getpass is available */
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
#include <sys/types.h>
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY /* empty file if strlcpy is available */
|
||||
#include <sys/types.h>
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
#include <windows.h>
|
||||
void *sc_dlopen(const char *filename)
|
||||
{
|
||||
return (void *)LoadLibrary(filename);
|
||||
return (void *)LoadLibraryA(filename);
|
||||
}
|
||||
|
||||
void *sc_dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
return GetProcAddress((HANDLE)handle, symbol);
|
||||
return GetProcAddress((HMODULE)handle, symbol);
|
||||
}
|
||||
|
||||
const char *sc_dlerror()
|
||||
|
@ -43,7 +43,7 @@ const char *sc_dlerror()
|
|||
|
||||
int sc_dlclose(void *handle)
|
||||
{
|
||||
return FreeLibrary((HANDLE)handle);
|
||||
return FreeLibrary((HMODULE)handle);
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
|
|
@ -41,6 +41,7 @@ libopensc_la_SOURCES = \
|
|||
card-itacns.c card-authentic.c \
|
||||
card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \
|
||||
card-dnie.c cwa14890.c cwa-dnie.c user-interface.c \
|
||||
card-isoApplet.c card-masktech.c \
|
||||
\
|
||||
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
||||
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \
|
||||
|
|
|
@ -23,7 +23,8 @@ OBJECTS = \
|
|||
card-rtecp.obj card-westcos.obj card-myeid.obj card-ias.obj \
|
||||
card-itacns.obj card-authentic.obj \
|
||||
card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \
|
||||
card-sc-hsm.obj card-dnie.obj user-interface.obj \
|
||||
card-sc-hsm.obj card-dnie.obj user-interface.obj card-isoApplet.obj \
|
||||
card-masktech.obj \
|
||||
\
|
||||
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
||||
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -203,8 +205,10 @@ int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf,
|
|||
if (nbuf == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
/* encode the APDU in the buffer */
|
||||
if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS)
|
||||
if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS) {
|
||||
free(nbuf);
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
*buf = nbuf;
|
||||
*len = nlen;
|
||||
|
||||
|
@ -577,7 +581,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu)
|
|||
* bytes using command chaining */
|
||||
size_t len = apdu->datalen;
|
||||
const u8 *buf = apdu->data;
|
||||
size_t max_send_size = card->max_send_size > 0 ? card->max_send_size : 255;
|
||||
size_t max_send_size = card->max_send_size;
|
||||
|
||||
while (len != 0) {
|
||||
size_t plen;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -65,9 +67,12 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
|
|||
if (left < 2)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
*buf = NULL;
|
||||
if (*p == 0xff || *p == 0)
|
||||
if (*p == 0xff || *p == 0) {
|
||||
/* end of data reached */
|
||||
*taglen = 0;
|
||||
*tag_out = SC_ASN1_TAG_EOC;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
/* parse tag byte(s) */
|
||||
cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED);
|
||||
tag = *p & SC_ASN1_TAG_PRIMITIVE;
|
||||
|
@ -740,23 +745,70 @@ static int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr)
|
||||
int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr)
|
||||
{
|
||||
size_t c = 0;
|
||||
size_t tag_len;
|
||||
size_t ii;
|
||||
u8 *p = out;
|
||||
u8 tag_char[4] = {0, 0, 0, 0};
|
||||
|
||||
if (outlen < 2)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
if (datalen > 127)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
*p++ = tag & 0xFF; /* FIXME: Support longer tags */
|
||||
outlen--;
|
||||
*p++ = datalen;
|
||||
outlen--;
|
||||
if (outlen < datalen)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
/* Check tag */
|
||||
if (tag == 0 || tag > 0xFFFFFFFF) {
|
||||
/* A tag of 0x00 is not valid and at most 4-byte tag names are supported. */
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
}
|
||||
for (tag_len = 0; tag; tag >>= 8) {
|
||||
/* Note: tag char will be reversed order. */
|
||||
tag_char[tag_len++] = tag & 0xFF;
|
||||
}
|
||||
|
||||
if (tag_len > 1) {
|
||||
if ((tag_char[tag_len - 1] & SC_ASN1_TAG_PRIMITIVE) != SC_ASN1_TAG_ESCAPE_MARKER) {
|
||||
/* First byte is not escape marker. */
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
}
|
||||
for (ii = 1; ii < tag_len - 1; ii++) {
|
||||
if ((tag_char[ii] & 0x80) != 0x80) {
|
||||
/* MS bit is not 'one'. */
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
if ((tag_char[0] & 0x80) != 0x00) {
|
||||
/* MS bit of the last byte is not 'zero'. */
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the number of additional bytes necessary to encode the length. */
|
||||
/* c+1 is the size of the length field. */
|
||||
if (datalen > 127) {
|
||||
c = 1;
|
||||
while (datalen >> (c << 3))
|
||||
c++;
|
||||
}
|
||||
if (outlen == 0 || out == NULL) {
|
||||
/* Caller only asks for the length that would be written. */
|
||||
return tag_len + (c+1) + datalen;
|
||||
}
|
||||
/* We will write the tag, so check the length. */
|
||||
if (outlen < tag_len + (c+1) + datalen)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
for (ii=0;ii<tag_len;ii++)
|
||||
*p++ = tag_char[tag_len - ii - 1];
|
||||
|
||||
if (c > 0) {
|
||||
*p++ = 0x80 | c;
|
||||
while (c--)
|
||||
*p++ = (datalen >> (c << 3)) & 0xFF;
|
||||
}
|
||||
else {
|
||||
*p++ = datalen & 0x7F;
|
||||
}
|
||||
if(data && datalen > 0) {
|
||||
memcpy(p, data, datalen);
|
||||
p += datalen;
|
||||
}
|
||||
if (ptr != NULL)
|
||||
*ptr = p;
|
||||
return 0;
|
||||
|
@ -1393,6 +1445,8 @@ static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1,
|
|||
left, depth,
|
||||
choice ? ", choice" : "");
|
||||
|
||||
if (!p)
|
||||
return SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
||||
if (left < 2) {
|
||||
while (asn1->name && (asn1->flags & SC_ASN1_OPTIONAL))
|
||||
asn1++;
|
||||
|
@ -1741,6 +1795,8 @@ _sc_asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1,
|
|||
int
|
||||
sc_der_copy(sc_pkcs15_der_t *dst, const sc_pkcs15_der_t *src)
|
||||
{
|
||||
if (!dst)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
if (src->len) {
|
||||
dst->value = malloc(src->len);
|
||||
|
@ -1772,3 +1828,86 @@ sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id,
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define C_ASN1_SIG_VALUE_SIZE 2
|
||||
static struct sc_asn1_entry c_asn1_sig_value[C_ASN1_SIG_VALUE_SIZE] = {
|
||||
{ "ECDSA-Sig-Value", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
#define C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE 3
|
||||
static struct sc_asn1_entry c_asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE] = {
|
||||
{ "r", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ "s", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char *in, size_t inlen,
|
||||
unsigned char **buf, size_t *buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE];
|
||||
struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE];
|
||||
unsigned char *r = in, *s = in + inlen/2;
|
||||
size_t r_len = inlen/2, s_len = inlen/2;
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value);
|
||||
sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 1);
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients);
|
||||
sc_format_asn1_entry(asn1_sig_value_coefficients + 0, r, &r_len, 1);
|
||||
sc_format_asn1_entry(asn1_sig_value_coefficients + 1, s, &s_len, 1);
|
||||
|
||||
rv = sc_asn1_encode(ctx, asn1_sig_value, buf, buflen);
|
||||
LOG_TEST_RET(ctx, rv, "ASN.1 encoding ECDSA-SIg-Value failed");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size_t inlen,
|
||||
unsigned char *buf, size_t buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE];
|
||||
struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE];
|
||||
unsigned char *r, *s;
|
||||
size_t r_len, s_len, halflen = buflen/2;
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
if (!buf || !buflen)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value);
|
||||
sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 0);
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients);
|
||||
sc_format_asn1_entry(asn1_sig_value_coefficients + 0, &r, &r_len, 0);
|
||||
sc_format_asn1_entry(asn1_sig_value_coefficients + 1, &s, &s_len, 0);
|
||||
|
||||
rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL);
|
||||
LOG_TEST_RET(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed");
|
||||
|
||||
if (halflen < r_len || halflen < s_len) {
|
||||
rv = SC_ERROR_BUFFER_TOO_SMALL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
memcpy(buf + (halflen - r_len), r, r_len);
|
||||
memcpy(buf + (buflen - s_len), s, s_len);
|
||||
|
||||
sc_log(ctx, "r(%i): %s", halflen, sc_dump_hex(buf, halflen));
|
||||
sc_log(ctx, "s(%i): %s", halflen, sc_dump_hex(buf + halflen, halflen));
|
||||
|
||||
rv = SC_SUCCESS;
|
||||
done:
|
||||
free(r);
|
||||
free(s);
|
||||
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
|
|
@ -84,8 +84,10 @@ const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf,
|
|||
/* DER encoding */
|
||||
|
||||
/* Argument 'ptr' is set to the location of the next possible ASN.1 object.
|
||||
* If NULL, no action on 'ptr' is performed. */
|
||||
int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr);
|
||||
* If NULL, no action on 'ptr' is performed.
|
||||
* If out is NULL or outlen is zero, the length that would be written is returned.
|
||||
* If data is NULL, the data field will not be written. This is helpful for constructed structures. */
|
||||
int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr);
|
||||
|
||||
/* ASN.1 printing functions */
|
||||
void sc_asn1_print_tags(const u8 * buf, size_t buflen);
|
||||
|
@ -118,6 +120,13 @@ void sc_asn1_clear_algorithm_id(struct sc_algorithm_id *);
|
|||
int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag,
|
||||
const u8 * data, size_t datalen, u8 ** out, size_t * outlen);
|
||||
|
||||
int sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx,
|
||||
unsigned char *in, size_t inlen,
|
||||
unsigned char **buf, size_t *buflen);
|
||||
int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
|
||||
unsigned char *in, size_t inlen,
|
||||
unsigned char *buf, size_t buflen);
|
||||
|
||||
#define SC_ASN1_CLASS_MASK 0x30000000
|
||||
#define SC_ASN1_UNI 0x00000000 /* Universal */
|
||||
#define SC_ASN1_APP 0x10000000 /* Application */
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -26,6 +28,8 @@
|
|||
#include "cardctl.h"
|
||||
|
||||
static struct sc_atr_table acos5_atrs[] = {
|
||||
{"3b:be:96:00:00:41:05:20:00:00:00:00:00:00:00:00:00:90:00", NULL, NULL,
|
||||
SC_CARD_TYPE_ACOS5_GENERIC, 0, NULL},
|
||||
{"3b:be:18:00:00:41:05:10:00:00:00:00:00:00:00:00:00:90:00", NULL, NULL,
|
||||
SC_CARD_TYPE_ACOS5_GENERIC, 0, NULL},
|
||||
{NULL, NULL, NULL, 0, 0, NULL}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -662,7 +664,7 @@ static int asepcos_list_files(sc_card_t *card, u8 *buf, size_t blen)
|
|||
|
||||
/* 1. get currently selected DF */
|
||||
r = asepcos_get_current_df_path(card, &bpath);
|
||||
if (rv != SC_SUCCESS)
|
||||
if (r != SC_SUCCESS)
|
||||
return r;
|
||||
/* 2. re-select DF to get the FID of the child EFs/DFs */
|
||||
r = sc_select_file(card, &bpath, &tfile);
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -650,7 +650,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path)
|
|||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
if (path->len <= 2 || path->type == SC_PATH_TYPE_DF_NAME || !path)
|
||||
if (!path || path->len <= 2 || path->type == SC_PATH_TYPE_DF_NAME)
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
|
||||
if (!card->cache.valid || !card->cache.current_df)
|
||||
|
@ -660,7 +660,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path)
|
|||
cur_path = card->cache.current_df->path;
|
||||
|
||||
if (!memcmp(cur_path.value, "\x3F\x00", 2) && memcmp(in_path.value, "\x3F\x00", 2)) {
|
||||
memcpy(in_path.value + 2, in_path.value, in_path.len);
|
||||
memmove(in_path.value + 2, in_path.value, in_path.len);
|
||||
memcpy(in_path.value, "\x3F\x00", 2);
|
||||
in_path.len += 2;
|
||||
}
|
||||
|
@ -672,7 +672,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path)
|
|||
break;
|
||||
}
|
||||
|
||||
memcpy(in_path.value, in_path.value + offs, sizeof(in_path.value) - offs);
|
||||
memmove(in_path.value, in_path.value + offs, sizeof(in_path.value) - offs);
|
||||
in_path.len -= offs;
|
||||
*path = in_path;
|
||||
|
||||
|
@ -749,7 +749,7 @@ authentic_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
rv = authentic_select_mf(card, file_out);
|
||||
LOG_TEST_RET(ctx, rv, "cannot select MF");
|
||||
|
||||
memcpy(&lpath.value[0], &lpath.value[2], lpath.len - 2);
|
||||
memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2);
|
||||
lpath.len -= 2;
|
||||
|
||||
if (!lpath.len)
|
||||
|
@ -1654,9 +1654,7 @@ authentic_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tri
|
|||
}
|
||||
|
||||
if (save_current) {
|
||||
struct sc_file *dummy_file = NULL;
|
||||
|
||||
rv = authentic_select_file(card, &save_current->path, &dummy_file);
|
||||
rv = authentic_select_file(card, &save_current->path, NULL);
|
||||
LOG_TEST_RET(ctx, rv, "Cannot return to saved PATH");
|
||||
}
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
|
@ -2112,14 +2110,16 @@ static int
|
|||
authentic_sm_acl_init (struct sc_card *card, struct sm_info *sm_info, int cmd,
|
||||
unsigned char *resp, size_t *resp_len)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
struct sm_type_params_gp *params_gp = &sm_info->session.gp.params;
|
||||
struct sc_context *ctx;
|
||||
struct sm_type_params_gp *params_gp;
|
||||
struct sc_remote_data rdata;
|
||||
int rv;
|
||||
|
||||
sc_log(ctx, "called; command 0x%X\n", cmd);
|
||||
if (!card || !sm_info || !resp || !resp_len)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
ctx = card->ctx;
|
||||
params_gp = &sm_info->session.gp.params;
|
||||
|
||||
if (!card->sm_ctx.module.ops.initialize || !card->sm_ctx.module.ops.get_apdus)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
@ -2302,13 +2302,19 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc
|
|||
memcpy((unsigned char *) apdu->data, plain->data, plain->datalen);
|
||||
|
||||
apdu->resp = calloc (1, plain->resplen + 32);
|
||||
if (!apdu->resp)
|
||||
if (!apdu->resp) {
|
||||
free(apdu);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
card->sm_ctx.info.cmd = SM_CMD_APDU_TRANSMIT;
|
||||
card->sm_ctx.info.cmd_data = (void *)apdu;
|
||||
|
||||
rv = card->sm_ctx.module.ops.get_apdus(ctx, &card->sm_ctx.info, NULL, 0, NULL);
|
||||
if (rv < 0) {
|
||||
free(apdu->resp);
|
||||
free(apdu);
|
||||
}
|
||||
LOG_TEST_RET(ctx, rv, "SM: GET_APDUS failed");
|
||||
|
||||
*sm_apdu = apdu;
|
||||
|
|
|
@ -80,7 +80,9 @@
|
|||
* language-selection functionality.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -127,6 +129,40 @@ static long t1, t2, tot_read = 0, tot_dur = 0, dur;
|
|||
#define BELPIC_PAD_CHAR 0xFF
|
||||
#define BELPIC_KEY_REF_NONREP 0x83
|
||||
|
||||
/* Data in the return value for the GET CARD DATA command:
|
||||
* All fields are one byte, except when noted otherwise.
|
||||
*
|
||||
* See §6.9 in
|
||||
* https://github.com/Fedict/eid-mw/blob/master/doc/sdk/documentation/Public_Belpic_Applet_v1%207_Ref_Manual%20-%20A01.pdf
|
||||
* for the full documentation on the GET CARD DATA command.
|
||||
*/
|
||||
// Card serial number (16 bytes)
|
||||
#define BELPIC_CARDDATA_OFF_SERIALNUM 0
|
||||
// "Component code"
|
||||
#define BELPIC_CARDDATA_OFF_COMPCODE 16
|
||||
// "OS number"
|
||||
#define BELPIC_CARDDATA_OFF_OSNUM 17
|
||||
// "OS version"
|
||||
#define BELPIC_CARDDATA_OFF_OSVER 18
|
||||
// "Softmask number"
|
||||
#define BELPIC_CARDDATA_OFF_SMNUM 19
|
||||
// "Softmask version"
|
||||
#define BELPIC_CARDDATA_OFF_SMVER 20
|
||||
// Applet version
|
||||
#define BELPIC_CARDDATA_OFF_APPLETVERS 21
|
||||
// Global OS version (2 bytes)
|
||||
#define BELPIC_CARDDATA_OFF_GL_OSVE 22
|
||||
// Applet interface version
|
||||
#define BELPIC_CARDDATA_OFF_APPINTVERS 24
|
||||
// PKCS#1 support version
|
||||
#define BELPIC_CARDDATA_OFF_PKCS1 25
|
||||
// Key exchange version
|
||||
#define BELPIC_CARDDATA_OFF_KEYX 26
|
||||
// Applet life cycle (Should always be 0F for released cards, is 07 when not issued yet)
|
||||
#define BELPIC_CARDDATA_OFF_APPLCYCLE 27
|
||||
// Full length of reply
|
||||
#define BELPIC_CARDDATA_RESP_LEN 28
|
||||
|
||||
/* Used for a trick in select file and read binary */
|
||||
static size_t next_idx = (size_t)-1;
|
||||
|
||||
|
@ -577,6 +613,42 @@ static int str2lang(sc_context_t *ctx, char *lang)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int get_carddata(sc_card_t *card, u8* carddata_loc, unsigned int carddataloc_len)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
u8 carddata_cmd[] = { 0x80, 0xE4, 0x00, 0x00, 0x1C };
|
||||
int r;
|
||||
|
||||
assert(carddataloc_len == BELPIC_CARDDATA_RESP_LEN);
|
||||
|
||||
r = sc_bytes2apdu(card->ctx, carddata_cmd, sizeof(carddata_cmd), &apdu);
|
||||
if(r) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "bytes to APDU conversion failed: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
apdu.resp = carddata_loc;
|
||||
apdu.resplen = carddataloc_len;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if(r) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData command failed: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if(r) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData: card returned %d\n", r);
|
||||
return r;
|
||||
}
|
||||
if(apdu.resplen < carddataloc_len) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData: card returned %d bytes rather than expected %d\n", apdu.resplen, carddataloc_len);
|
||||
return SC_ERROR_WRONG_LENGTH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GET_LANG_FROM_CARD
|
||||
|
||||
/* str is in lower case, the case of buf can be both, and buf is large enough */
|
||||
|
@ -843,9 +915,10 @@ static int belpic_init(sc_card_t *card)
|
|||
{
|
||||
struct belpic_priv_data *priv = NULL;
|
||||
scconf_block *conf_block;
|
||||
#ifdef BELPIC_PIN_PAD
|
||||
u8 applet_version;
|
||||
u8 carddata[BELPIC_CARDDATA_RESP_LEN];
|
||||
int key_size = 1024;
|
||||
int r;
|
||||
#endif
|
||||
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Belpic V%s", BELPIC_VERSION);
|
||||
#ifdef HAVE_GUI
|
||||
|
@ -865,7 +938,14 @@ static int belpic_init(sc_card_t *card)
|
|||
card->drv_data = priv;
|
||||
card->cla = 0x00;
|
||||
if (card->type == SC_CARD_TYPE_BELPIC_EID) {
|
||||
_sc_card_add_rsa_alg(card, 1024,
|
||||
if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) {
|
||||
return r;
|
||||
}
|
||||
applet_version = carddata[BELPIC_CARDDATA_OFF_APPLETVERS];
|
||||
if(applet_version >= 0x17) {
|
||||
key_size = 2048;
|
||||
}
|
||||
_sc_card_add_rsa_alg(card, key_size,
|
||||
SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -47,8 +49,6 @@ static struct sc_atr_table cardos_atrs[] = {
|
|||
{ "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 */
|
||||
{ "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 },
|
||||
/* Italian CNS - Prov. BZ */
|
||||
{ "3b:ff:18:00:ff:c1:0a:31:fe:55:00:6b:05:08:c8:0c:01:11:01:43:4e:53:10:31:80:05", NULL, NULL, SC_CARD_TYPE_CARDOS_M4_2, 0, NULL },
|
||||
/* Another Italian InfocamereCard */
|
||||
{ "3b:fc:98:00:ff:c1:10:31:fe:55:c8:03:49:6e:66:6f:63:61:6d:65:72:65:28", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
|
||||
{ "3b:f4:98:00:ff:c1:10:31:fe:55:4d:34:63:76:b4", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL},
|
||||
|
@ -165,6 +165,9 @@ static int cardos_have_2048bit_package(sc_card_t *card)
|
|||
static int cardos_init(sc_card_t *card)
|
||||
{
|
||||
unsigned long flags, rsa_2048 = 0;
|
||||
size_t data_field_length;
|
||||
sc_apdu_t apdu;
|
||||
u8 rbuf[2];
|
||||
|
||||
card->name = "CardOS M4";
|
||||
card->cla = 0x00;
|
||||
|
@ -195,6 +198,29 @@ static int cardos_init(sc_card_t *card)
|
|||
card->caps |= SC_CARD_CAP_APDU_EXT;
|
||||
}
|
||||
|
||||
/* probe DATA FIELD LENGTH with GET DATA */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x8D);
|
||||
apdu.le = sizeof rbuf;
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
sc_transmit_apdu(card, &apdu),
|
||||
"APDU transmit failed");
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
sc_check_sw(card, apdu.sw1, apdu.sw2),
|
||||
"GET DATA command returned error");
|
||||
if (apdu.resplen != 2)
|
||||
return SC_ERROR_WRONG_LENGTH;
|
||||
data_field_length = ((rbuf[0] << 8) | rbuf[1]);
|
||||
|
||||
/* strip the length of possible Lc and Le bytes */
|
||||
if (card->caps & SC_CARD_CAP_APDU_EXT)
|
||||
card->max_send_size = data_field_length - 6;
|
||||
else
|
||||
card->max_send_size = data_field_length - 3;
|
||||
/* strip the length of SW bytes */
|
||||
card->max_recv_size = data_field_length - 2;
|
||||
|
||||
if (rsa_2048 == 1) {
|
||||
_sc_card_add_rsa_alg(card, 1280, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 1536, flags, 0);
|
||||
|
@ -1217,35 +1243,6 @@ cardos_logout(sc_card_t *card)
|
|||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int cardos_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len)
|
||||
{
|
||||
int r;
|
||||
struct sc_apdu apdu;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA,
|
||||
(tag >> 8) & 0xff, tag & 0xff);
|
||||
apdu.lc = 0;
|
||||
apdu.datalen = 0;
|
||||
apdu.le = len;
|
||||
apdu.resp = buf;
|
||||
apdu.resplen = len;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error");
|
||||
|
||||
if (apdu.resplen > len)
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
else
|
||||
r = apdu.resplen;
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||
}
|
||||
|
||||
|
||||
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
|
||||
|
||||
static struct sc_card_driver * sc_get_driver(void)
|
||||
|
@ -1266,7 +1263,6 @@ static struct sc_card_driver * sc_get_driver(void)
|
|||
cardos_ops.card_ctl = cardos_card_ctl;
|
||||
cardos_ops.pin_cmd = cardos_pin_cmd;
|
||||
cardos_ops.logout = cardos_logout;
|
||||
cardos_ops.get_data = cardos_get_data;
|
||||
|
||||
return &cardos_drv;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ data_found:
|
|||
static int dnie_get_info(sc_card_t * card, char *data[])
|
||||
{
|
||||
sc_file_t *file = NULL;
|
||||
sc_path_t *path = NULL;
|
||||
sc_path_t path;
|
||||
u8 *buffer = NULL;
|
||||
size_t bufferlen = 0;
|
||||
char *msg = NULL;
|
||||
|
@ -309,14 +309,8 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
/* phase 1: get DNIe number, Name and GivenName */
|
||||
|
||||
/* read EF(CDF) at 3F0050156004 */
|
||||
path = (sc_path_t *) calloc(1, sizeof(sc_path_t));
|
||||
if (!path) {
|
||||
msg = "Cannot allocate path data for EF(CDF) read";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto get_info_end;
|
||||
}
|
||||
sc_format_path("3F0050156004", path);
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
sc_format_path("3F0050156004", &path);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot read EF(CDF)";
|
||||
goto get_info_end;
|
||||
|
@ -334,7 +328,7 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
}
|
||||
|
||||
/* phase 2: get IDESP */
|
||||
sc_format_path("3F000006", path);
|
||||
sc_format_path("3F000006", &path);
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
|
@ -344,9 +338,8 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
buffer=NULL;
|
||||
bufferlen=0;
|
||||
}
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot read IDESP EF";
|
||||
data[3]=NULL;
|
||||
goto get_info_ph3;
|
||||
}
|
||||
|
@ -360,7 +353,7 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
|
||||
get_info_ph3:
|
||||
/* phase 3: get DNIe software version */
|
||||
sc_format_path("3F002F03", path);
|
||||
sc_format_path("3F002F03", &path);
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
|
@ -374,7 +367,7 @@ get_info_ph3:
|
|||
* Some old DNIe cards seems not to include SW version file,
|
||||
* so let this code fail without notice
|
||||
*/
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot read DNIe Version EF";
|
||||
data[4]=NULL;
|
||||
|
@ -396,10 +389,12 @@ get_info_ph3:
|
|||
get_info_end:
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
free(buffer);
|
||||
file = NULL;
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer=NULL;
|
||||
bufferlen=0;
|
||||
}
|
||||
if (msg)
|
||||
sc_log(card->ctx,msg);
|
||||
|
@ -498,8 +493,8 @@ static inline void init_flags(struct sc_card *card)
|
|||
card->max_send_size = (255 - 12); /* manual says 255, but we need 12 extra bytes when encoding */
|
||||
card->max_recv_size = 255;
|
||||
|
||||
algoflags = SC_ALGORITHM_RSA_RAW; /* RSA support */
|
||||
algoflags |= SC_ALGORITHM_RSA_HASH_NONE;
|
||||
/* RSA Support with PKCS1.5 padding */
|
||||
algoflags = SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_PAD_PKCS1;
|
||||
_sc_card_add_rsa_alg(card, 1024, algoflags, 0);
|
||||
_sc_card_add_rsa_alg(card, 2048, algoflags, 0);
|
||||
}
|
||||
|
@ -876,7 +871,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
|
|||
apdu.lc = pathlen;
|
||||
apdu.data = path;
|
||||
apdu.datalen = pathlen;
|
||||
apdu.le = card->max_recv_size > 0 ? card->max_recv_size : 256;
|
||||
apdu.le = card->max_recv_size;
|
||||
if (p1 == 3)
|
||||
apdu.cse= SC_APDU_CASE_1;
|
||||
|
||||
|
@ -906,6 +901,8 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
|
|||
if (file == NULL)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]);
|
||||
if (*file_out != NULL)
|
||||
sc_file_free(*file_out);
|
||||
*file_out = file;
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
|
@ -1195,7 +1192,7 @@ static int dnie_set_security_env(struct sc_card *card,
|
|||
sc_log(card->ctx, "checking key references");
|
||||
if (env->key_ref_len != 1) {
|
||||
sc_log(card->ctx, "Null or invalid key ID reference");
|
||||
result = SC_ERROR_INVALID_ARGUMENTS;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
sc_log(card->ctx, "Using key reference '%s'",
|
||||
sc_dump_hex(env->key_ref, env->key_ref_len));
|
||||
|
@ -1357,8 +1354,6 @@ static int dnie_compute_signature(struct sc_card *card,
|
|||
{
|
||||
int result = SC_SUCCESS;
|
||||
struct sc_apdu apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; /* to compose digest+hash data */
|
||||
size_t sbuflen = 0;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; /* to receive sign response */
|
||||
|
||||
/* some preliminar checks */
|
||||
|
@ -1392,20 +1387,6 @@ static int dnie_compute_signature(struct sc_card *card,
|
|||
sc_log(card->ctx,
|
||||
"Compute signature len: '%d' bytes:\n%s\n============================================================",
|
||||
datalen, sc_dump_hex(data, datalen));
|
||||
if (datalen != 256) {
|
||||
sc_log(card->ctx, "Expected pkcs#1 v1.5 DigestInfo data");
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
|
||||
}
|
||||
|
||||
/* try to strip pkcs1 padding */
|
||||
sbuflen = sizeof(sbuf);
|
||||
memset(sbuf, 0, sbuflen);
|
||||
result = sc_pkcs1_strip_01_padding(card->ctx, data, datalen, sbuf, &sbuflen);
|
||||
if (result != SC_SUCCESS) {
|
||||
sc_log(card->ctx, "Provided data is not pkcs#1 padded");
|
||||
/* TODO: study what to do on plain data */
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_PADDING);
|
||||
}
|
||||
|
||||
/*INS: 0x2A PERFORM SECURITY OPERATION
|
||||
* P1: 0x9E Resp: Digital Signature
|
||||
|
@ -1414,9 +1395,9 @@ static int dnie_compute_signature(struct sc_card *card,
|
|||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.le = 256; /* signature response size */
|
||||
apdu.data = sbuf;
|
||||
apdu.lc = sbuflen; /* 15 SHA1 DigestInfo + 20 SHA1 computed Hash */
|
||||
apdu.datalen = sizeof(sbuf);
|
||||
apdu.data = data;
|
||||
apdu.lc = datalen; /* Caller determines the type of hash and its size */
|
||||
apdu.datalen = datalen;
|
||||
/* tell card to compute signature */
|
||||
result = dnie_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, result, "compute_signature() failed");
|
||||
|
@ -1747,7 +1728,7 @@ static int dnie_process_fci(struct sc_card *card,
|
|||
case 0x15: /* EF for keys: linear variable simple TLV */
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
/* pin file 3F000000 has also this EF type */
|
||||
if ( ( file->prop_attr[3] == 0x00 ) && (file->prop_attr[3] == 0x00 ) ) {
|
||||
if ( ( file->prop_attr[2] == 0x00 ) && (file->prop_attr[3] == 0x00 ) ) {
|
||||
sc_log(ctx,"Processing pin EF");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
/* Initially written by Weitao Sun (weitao@ftsafe.com) 2008 */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifdef ENABLE_OPENSSL /* empty file without openssl */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -339,7 +341,7 @@ static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
|||
blocks=(apdu->lc+2)/8+1;
|
||||
cipher_data_size=blocks*8;
|
||||
cipher_data=malloc(cipher_data_size);
|
||||
if(!cipher)
|
||||
if(!cipher_data)
|
||||
{
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifdef ENABLE_SM /* empty file without SM enabled */
|
||||
#ifdef ENABLE_OPENSSL /* empty file without openssl */
|
||||
|
||||
|
@ -209,7 +211,7 @@ des3_encrypt_ecb(const unsigned char *key, int keysize,
|
|||
|
||||
|
||||
static int
|
||||
des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
||||
des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH],
|
||||
const unsigned char *input, size_t length, unsigned char *output)
|
||||
{
|
||||
unsigned char bKey[24] = { 0 };
|
||||
|
@ -227,7 +229,7 @@ des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
|||
|
||||
|
||||
static int
|
||||
des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
||||
des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH],
|
||||
const unsigned char *input, size_t length, unsigned char *output)
|
||||
{
|
||||
unsigned char bKey[24] = { 0 };
|
||||
|
@ -244,7 +246,7 @@ des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
|||
|
||||
|
||||
static int
|
||||
des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
||||
des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH],
|
||||
const unsigned char *input, size_t length, unsigned char *output)
|
||||
{
|
||||
return openssl_enc(EVP_des_cbc(), key, iv, input, length, output);
|
||||
|
@ -252,7 +254,7 @@ des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
|||
|
||||
|
||||
static int
|
||||
des_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8],
|
||||
des_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH],
|
||||
const unsigned char *input, size_t length, unsigned char *output)
|
||||
{
|
||||
return openssl_dec(EVP_des_cbc(), key, iv, input, length, output);
|
||||
|
@ -450,7 +452,9 @@ epass2003_refresh(struct sc_card *card)
|
|||
int r = SC_SUCCESS;
|
||||
|
||||
if (g_sm) {
|
||||
card->sm_ctx.sm_mode = 0;
|
||||
r = mutual_auth(card, g_init_key_enc, g_init_key_mac);
|
||||
card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
|
||||
LOG_TEST_RET(card->ctx, r, "mutual_auth failed");
|
||||
}
|
||||
|
||||
|
@ -947,9 +951,6 @@ epass2003_init(struct sc_card *card)
|
|||
card->name = "epass2003";
|
||||
card->cla = 0x00;
|
||||
card->drv_data = NULL;
|
||||
/* VT
|
||||
card->ctx->use_sm = 1;
|
||||
*/
|
||||
|
||||
g_sm = SM_SCP01;
|
||||
/* g_sm = SM_PLAIN; */
|
||||
|
@ -1141,7 +1142,7 @@ epass2003_select_fid(struct sc_card *card, unsigned int id_hi, unsigned int id_l
|
|||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
|
||||
/* update cache */
|
||||
if (file->type == SC_FILE_TYPE_DF) {
|
||||
if (file && file->type == SC_FILE_TYPE_DF) {
|
||||
card->cache.current_path.type = SC_PATH_TYPE_PATH;
|
||||
card->cache.current_path.value[0] = 0x3f;
|
||||
card->cache.current_path.value[1] = 0x00;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
/* Initially written by David Mattes (david.mattes@boeing.com) */
|
||||
/* Portuguese eID card support by Joao Poupino (joao.poupino@ist.utl.pt) */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -369,7 +371,7 @@ static u8 gemsafe_flags2algref(struct sc_card *card, const struct sc_security_en
|
|||
} else if (env->operation == SC_SEC_OPERATION_DECIPHER) {
|
||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||
ret = (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
|
||||
card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) ? 0x02 : 0x12;
|
||||
card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) ? 0x02 : 0x12;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifdef ENABLE_OPENSSL /* empty file without openssl */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
* Thanks to Andre Cruz, Jorge Ferreira and Paulo F. Andrade
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -473,8 +475,6 @@ static int ias_select_file(sc_card_t *card, const sc_path_t *in_path,
|
|||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
if (file_out == NULL) {
|
||||
if (apdu.sw1 == 0x61)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, 0);
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ static struct sc_card_driver iasecc_drv = {
|
|||
|
||||
static struct sc_atr_table iasecc_known_atrs[] = {
|
||||
{ "3B:7F:96:00:00:00:31:B8:64:40:70:14:10:73:94:01:80:82:90:00",
|
||||
"FF:FF:FF:FF:FF:FF:FF:FE:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF",
|
||||
"FF:FF:FF:FF:FF:FF:FF:FE:FF:FF:00:00:FF:FF:FF:FF:FF:FF:FF:FF",
|
||||
"IAS/ECC Gemalto", SC_CARD_TYPE_IASECC_GEMALTO, 0, NULL },
|
||||
{ "3B:DD:18:00:81:31:FE:45:80:F9:A0:00:00:00:77:01:08:00:07:90:00:FE", NULL,
|
||||
"IAS/ECC v1.0.1 Oberthur", SC_CARD_TYPE_IASECC_OBERTHUR, 0, NULL },
|
||||
|
@ -79,6 +79,8 @@ static struct sc_atr_table iasecc_known_atrs[] = {
|
|||
"IAS/ECC v1.0.1 Sagem MDW-IAS-CARD2", SC_CARD_TYPE_IASECC_SAGEM, 0, NULL },
|
||||
{ "3B:7F:18:00:00:00:31:B8:64:50:23:EC:C1:73:94:01:80:82:90:00", NULL,
|
||||
"IAS/ECC v1.0.1 Sagem ypsID S3", SC_CARD_TYPE_IASECC_SAGEM, 0, NULL },
|
||||
{ "3B:DF:96:00:80:31:FE:45:00:31:B8:64:04:1F:EC:C1:73:94:01:80:82:90:00:EC", NULL,
|
||||
"IAS/ECC Morpho MinInt - Agent Card", SC_CARD_TYPE_IASECC_MI, 0, NULL },
|
||||
{ "3B:DF:18:FF:81:91:FE:1F:C3:00:31:B8:64:0C:01:EC:C1:73:94:01:80:82:90:00:B3", NULL,
|
||||
"IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL },
|
||||
{ "3B:DC:18:FF:81:91:FE:1F:C3:80:73:C8:21:13:66:02:04:03:55:00:02:34", NULL,
|
||||
|
@ -98,6 +100,10 @@ static struct sc_aid OberthurIASECC_AID = {
|
|||
{0xA0,0x00,0x00,0x00,0x77,0x01,0x08,0x00,0x07,0x00,0x00,0xFE,0x00,0x00,0x01,0x00}, 16
|
||||
};
|
||||
|
||||
static struct sc_aid MIIASECC_AID = {
|
||||
{ 0x4D, 0x49, 0x4F, 0x4D, 0x43, 0x54}, 6
|
||||
};
|
||||
|
||||
struct iasecc_pin_status {
|
||||
unsigned char sha1[SHA_DIGEST_LENGTH];
|
||||
unsigned char reference;
|
||||
|
@ -414,7 +420,8 @@ iasecc_init_gemalto(struct sc_card *card)
|
|||
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
||||
|
||||
sc_format_path("3F00", &path);
|
||||
sc_select_file(card, &path, NULL);
|
||||
rv = sc_select_file(card, &path, NULL);
|
||||
/* Result ignored*/
|
||||
|
||||
rv = iasecc_parse_ef_atr(card);
|
||||
sc_log(ctx, "rv %i", rv);
|
||||
|
@ -565,6 +572,54 @@ iasecc_init_amos(struct sc_card *card)
|
|||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
iasecc_mi_match(struct sc_card *card)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
if (!card->ef_atr)
|
||||
card->ef_atr = calloc(1, sizeof(struct sc_ef_atr));
|
||||
if (!card->ef_atr)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
memcpy(card->ef_atr->aid.value, MIIASECC_AID.value, MIIASECC_AID.len);
|
||||
card->ef_atr->aid.len = MIIASECC_AID.len;
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
iasecc_init_mi(struct sc_card *card)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
unsigned int flags;
|
||||
unsigned char resp[0x100];
|
||||
size_t resp_len;
|
||||
int rv = 0;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
flags = IASECC_CARD_DEFAULT_FLAGS;
|
||||
|
||||
_sc_card_add_rsa_alg(card, 1024, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card, 2048, flags, 0x10001);
|
||||
|
||||
card->caps = SC_CARD_CAP_RNG;
|
||||
card->caps |= SC_CARD_CAP_APDU_EXT;
|
||||
card->caps |= SC_CARD_CAP_USE_FCI_AC;
|
||||
|
||||
resp_len = sizeof(resp);
|
||||
rv = iasecc_select_aid(card, &MIIASECC_AID, resp, &resp_len);
|
||||
LOG_TEST_RET(ctx, rv, "Could not select MI's AID");
|
||||
|
||||
rv = iasecc_mi_match(card);
|
||||
LOG_TEST_RET(ctx, rv, "Could not match MI's AID");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
iasecc_init(struct sc_card *card)
|
||||
{
|
||||
|
@ -588,6 +643,8 @@ iasecc_init(struct sc_card *card)
|
|||
rv = iasecc_init_sagem(card);
|
||||
else if (card->type == SC_CARD_TYPE_IASECC_AMOS)
|
||||
rv = iasecc_init_amos(card);
|
||||
else if (card->type == SC_CARD_TYPE_IASECC_MI)
|
||||
rv = iasecc_init_mi(card);
|
||||
else
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT);
|
||||
|
||||
|
@ -812,7 +869,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
LOG_TEST_RET(ctx, rv, "MF selection error");
|
||||
|
||||
if (lpath.len >= 2 && lpath.value[0] == 0x3F && lpath.value[1] == 0x00) {
|
||||
memcpy(&lpath.value[0], &lpath.value[2], lpath.len - 2);
|
||||
memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2);
|
||||
lpath.len -= 2;
|
||||
}
|
||||
}
|
||||
|
@ -878,7 +935,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
if (card->type != SC_CARD_TYPE_IASECC_GEMALTO
|
||||
&& card->type != SC_CARD_TYPE_IASECC_OBERTHUR
|
||||
&& card->type != SC_CARD_TYPE_IASECC_SAGEM
|
||||
&& card->type != SC_CARD_TYPE_IASECC_AMOS)
|
||||
&& card->type != SC_CARD_TYPE_IASECC_AMOS
|
||||
&& card->type != SC_CARD_TYPE_IASECC_MI)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported card");
|
||||
|
||||
if (lpath.type == SC_PATH_TYPE_FILE_ID) {
|
||||
|
@ -889,6 +947,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
}
|
||||
if (card->type == SC_CARD_TYPE_IASECC_AMOS)
|
||||
apdu.p2 = 0x04;
|
||||
if (card->type == SC_CARD_TYPE_IASECC_MI)
|
||||
apdu.p2 = 0x04;
|
||||
}
|
||||
else if (lpath.type == SC_PATH_TYPE_FROM_CURRENT) {
|
||||
apdu.p1 = 0x09;
|
||||
|
@ -896,6 +956,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
apdu.p2 = 0x04;
|
||||
if (card->type == SC_CARD_TYPE_IASECC_AMOS)
|
||||
apdu.p2 = 0x04;
|
||||
if (card->type == SC_CARD_TYPE_IASECC_MI)
|
||||
apdu.p2 = 0x04;
|
||||
}
|
||||
else if (lpath.type == SC_PATH_TYPE_PARENT) {
|
||||
apdu.p1 = 0x03;
|
||||
|
@ -1439,12 +1501,18 @@ iasecc_se_cache_info(struct sc_card *card, struct iasecc_se_info *se)
|
|||
|
||||
if (card->cache.valid && card->cache.current_df) {
|
||||
sc_file_dup(&se_info->df, card->cache.current_df);
|
||||
if (se_info->df == NULL)
|
||||
if (se_info->df == NULL) {
|
||||
free(se_info);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate current DF file");
|
||||
}
|
||||
}
|
||||
|
||||
rv = iasecc_docp_copy(ctx, &se->docp, &se_info->docp);
|
||||
if (rv < 0) {
|
||||
free(se_info->df);
|
||||
free(se_info);
|
||||
LOG_TEST_RET(ctx, rv, "Cannot make copy of DOCP");
|
||||
}
|
||||
|
||||
if (!prv->se_info) {
|
||||
prv->se_info = se_info;
|
||||
|
@ -1740,13 +1808,14 @@ iasecc_chv_verify_pinpad(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd,
|
|||
LOG_FUNC_RETURN(ctx, SC_ERROR_READER);
|
||||
}
|
||||
|
||||
if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) {
|
||||
sc_log(ctx, "Different values for PIN min and max lengths is not actually compatible with PinPAD.");
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,
|
||||
"Different values for PIN min and max lengths is not actually compatible with PinPAD.");
|
||||
}
|
||||
|
||||
pin_cmd->pin1.len = pin_cmd->pin1.min_length;
|
||||
/* When PIN stored length available
|
||||
* P10 verify data contains full template of 'VERIFY PIN' APDU.
|
||||
* Without PIN stored length
|
||||
* pin-pad has to set the Lc and fill PIN data itself.
|
||||
* Not all pin-pads support this case
|
||||
*/
|
||||
pin_cmd->pin1.len = pin_cmd->pin1.stored_length;
|
||||
pin_cmd->pin1.length_offset = 5;
|
||||
|
||||
memset(buffer, 0xFF, sizeof(buffer));
|
||||
pin_cmd->pin1.data = buffer;
|
||||
|
@ -1976,25 +2045,29 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le
|
|||
rv = iasecc_pin_get_policy(card, &pin_cmd);
|
||||
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");
|
||||
|
||||
if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD.");
|
||||
/* Some pin-pads do not support mode with Lc=0.
|
||||
* Give them a chance to work with some cards.
|
||||
*/
|
||||
if ((pin_cmd.pin1.min_length == pin_cmd.pin1.stored_length) && (pin_cmd.pin1.max_length == pin_cmd.pin1.min_length))
|
||||
pin_cmd.pin1.len = pin_cmd.pin1.stored_length;
|
||||
else
|
||||
pin_cmd.pin1.len = 0;
|
||||
|
||||
if (pin_cmd.pin1.min_length < 4)
|
||||
pin_cmd.pin1.min_length = 4;
|
||||
pin_cmd.pin1.len = pin_cmd.pin1.min_length;
|
||||
pin_cmd.pin1.length_offset = 5;
|
||||
pin_cmd.pin1.data = pin1_data;
|
||||
|
||||
memcpy(&pin_cmd.pin2, &pin_cmd.pin1, sizeof(pin_cmd.pin1));
|
||||
pin_cmd.pin2.data = pin2_data;
|
||||
|
||||
sc_log(ctx, "PIN1 max/min: %i/%i", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length);
|
||||
sc_log(ctx, "PIN2 max/min: %i/%i", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length);
|
||||
sc_log(ctx, "PIN1 max/min/stored: %i/%i/%i", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length, pin_cmd.pin1.stored_length);
|
||||
sc_log(ctx, "PIN2 max/min/stored: %i/%i/%i", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length, pin_cmd.pin2.stored_length);
|
||||
rv = iso_ops->pin_cmd(card, &pin_cmd, tries_left);
|
||||
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int
|
||||
iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference)
|
||||
{
|
||||
|
@ -2022,16 +2095,17 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference)
|
|||
rv = iasecc_pin_get_policy(card, &pin_cmd);
|
||||
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");
|
||||
|
||||
if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD.");
|
||||
if ((pin_cmd.pin1.min_length == pin_cmd.pin1.stored_length) && (pin_cmd.pin1.max_length == pin_cmd.pin1.min_length))
|
||||
pin_cmd.pin1.len = pin_cmd.pin1.stored_length;
|
||||
else
|
||||
pin_cmd.pin1.len = 0;
|
||||
|
||||
if (pin_cmd.pin1.min_length < 4)
|
||||
pin_cmd.pin1.min_length = 4;
|
||||
pin_cmd.pin1.len = pin_cmd.pin1.min_length;
|
||||
pin_cmd.pin1.length_offset = 5;
|
||||
pin_cmd.pin1.data = pin_data;
|
||||
|
||||
memcpy(&pin_cmd.pin2, &pin_cmd.pin1, sizeof(pin_cmd.pin1));
|
||||
memset(&pin_cmd.pin1, 0, sizeof(pin_cmd.pin1));
|
||||
pin_cmd.flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
|
||||
|
||||
sc_log(ctx, "PIN1(max:%i,min:%i)", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length);
|
||||
sc_log(ctx, "PIN2(max:%i,min:%i)", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length);
|
||||
|
@ -2039,6 +2113,7 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference)
|
|||
rv = iso_ops->pin_cmd(card, &pin_cmd, NULL);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
|
@ -2091,6 +2166,7 @@ iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data)
|
|||
if (sdo.docp.acls_contact.size == 0)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Extremely strange ... there is no ACLs");
|
||||
|
||||
sc_log(ctx, "iasecc_pin_get_policy() sdo.docp.size.size %i %02X:%02X", sdo.docp.size.size, *(sdo.docp.size.value + 0), *(sdo.docp.size.value + 1));
|
||||
for (ii=0; ii<sizeof(sdo.docp.scbs); ii++) {
|
||||
struct iasecc_se_info se;
|
||||
unsigned char scb = sdo.docp.scbs[ii];
|
||||
|
@ -2147,6 +2223,10 @@ iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data)
|
|||
data->pin1.max_tries = *sdo.docp.tries_maximum.value;
|
||||
if (sdo.docp.tries_remaining.value)
|
||||
data->pin1.tries_left = *sdo.docp.tries_remaining.value;
|
||||
if (sdo.docp.size.value) {
|
||||
for (ii=0; ii<sdo.docp.size.size; ii++)
|
||||
data->pin1.stored_length = ((data->pin1.stored_length) << 8) + *(sdo.docp.size.value + ii);
|
||||
}
|
||||
|
||||
data->pin1.encoding = SC_PIN_ENCODING_ASCII;
|
||||
data->pin1.offset = 5;
|
||||
|
@ -2219,12 +2299,14 @@ iasecc_keyset_change(struct sc_card *card, struct sc_pin_cmd_data *data, int *tr
|
|||
|
||||
update.fields[0].parent_tag = IASECC_SDO_KEYSET_TAG;
|
||||
update.fields[0].tag = IASECC_SDO_KEYSET_TAG_MAC;
|
||||
update.fields[0].value = data->pin2.data;
|
||||
/* FIXME is it safe to modify the const value here? */
|
||||
update.fields[0].value = (unsigned char *) data->pin2.data;
|
||||
update.fields[0].size = 16;
|
||||
|
||||
update.fields[1].parent_tag = IASECC_SDO_KEYSET_TAG;
|
||||
update.fields[1].tag = IASECC_SDO_KEYSET_TAG_ENC;
|
||||
update.fields[1].value = data->pin2.data + 16;
|
||||
/* FIXME is it safe to modify the const value here? */
|
||||
update.fields[1].value = (unsigned char *) data->pin2.data + 16;
|
||||
update.fields[1].size = 16;
|
||||
|
||||
rv = iasecc_sm_sdo_update(card, (scb & IASECC_SCB_METHOD_MASK_REF), &update);
|
||||
|
@ -2331,6 +2413,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_
|
|||
unsigned char se_num = scb & IASECC_SCB_METHOD_MASK_REF;
|
||||
|
||||
if (scb & IASECC_SCB_METHOD_USER_AUTH) {
|
||||
sc_log(ctx, "Verify PIN in SE %X", se_num);
|
||||
rv = iasecc_pin_verify(card, SC_AC_SEN, se_num, data->pin1.data, data->pin1.len, tries_left);
|
||||
LOG_TEST_RET(ctx, rv, "iasecc_pin_reset() verify PUK error");
|
||||
|
||||
|
@ -2341,9 +2424,6 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_
|
|||
if (scb & IASECC_SCB_METHOD_SM) {
|
||||
rv = iasecc_sm_pin_reset(card, se_num, data);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
|
||||
if (!need_all)
|
||||
break;
|
||||
}
|
||||
|
||||
if (scb & IASECC_SCB_METHOD_EXT_AUTH) {
|
||||
|
@ -2355,6 +2435,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_
|
|||
iasecc_sdo_free_fields(card, &sdo);
|
||||
|
||||
if (data->pin2.len) {
|
||||
sc_log(ctx, "Reset PIN %X and set new value", reference);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2C, 0x02, reference);
|
||||
apdu.data = data->pin2.data;
|
||||
apdu.datalen = data->pin2.len;
|
||||
|
@ -2366,6 +2447,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_
|
|||
LOG_TEST_RET(ctx, rv, "PIN cmd failed");
|
||||
}
|
||||
else if (data->pin2.data) {
|
||||
sc_log(ctx, "Reset PIN %X and set new value", reference);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2C, 3, reference);
|
||||
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -2374,8 +2456,13 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_
|
|||
LOG_TEST_RET(ctx, rv, "PIN cmd failed");
|
||||
}
|
||||
else {
|
||||
sc_log(ctx, "Reset PIN %X and set new value with PIN-PAD", reference);
|
||||
#if 0
|
||||
rv = iasecc_chv_set_pinpad(card, reference);
|
||||
sc_log(ctx, "Set CHV with PIN pad returned %i", rv);
|
||||
LOG_TEST_RET(ctx, rv, "Reset PIN failed");
|
||||
#else
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Reset retry counter with PIN PAD not supported ");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (save_current) {
|
||||
|
@ -2393,7 +2480,6 @@ static int
|
|||
iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
struct sc_apdu apdu;
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
@ -2404,29 +2490,24 @@ iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_le
|
|||
switch (data->cmd) {
|
||||
case SC_PIN_CMD_VERIFY:
|
||||
rv = iasecc_pin_verify(card, data->pin_type, data->pin_reference, data->pin1.data, data->pin1.len, tries_left);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
if (data->pin_type == SC_AC_AUT)
|
||||
rv = iasecc_keyset_change(card, data, tries_left);
|
||||
else
|
||||
rv = iasecc_pin_change(card, data, tries_left);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
break;
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
rv = iasecc_pin_reset(card, data, tries_left);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
break;
|
||||
case SC_PIN_CMD_GET_INFO:
|
||||
rv = iasecc_pin_get_policy(card, data);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
break;
|
||||
default:
|
||||
sc_log(ctx, "Other pin commands not supported yet: 0x%X", data->cmd);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non-supported PIN command");
|
||||
rv = SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(ctx, rv, "APDU transmit failed");
|
||||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(ctx, rv, "PIN cmd failed");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
||||
|
@ -2563,6 +2644,7 @@ iasecc_sdo_create(struct sc_card *card, struct iasecc_sdo *sdo)
|
|||
rv = iasecc_sdo_put_data(card, &update);
|
||||
LOG_TEST_RET(ctx, rv, "failed to update 'Compulsory usage' data");
|
||||
|
||||
if (field)
|
||||
field->on_card = 1;
|
||||
}
|
||||
|
||||
|
@ -3250,14 +3332,19 @@ static int
|
|||
iasecc_compute_signature(struct sc_card *card,
|
||||
const unsigned char *in, size_t in_len, unsigned char *out, size_t out_len)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
struct iasecc_private_data *prv = (struct iasecc_private_data *) card->drv_data;
|
||||
struct sc_security_env *env = &prv->security_env;
|
||||
struct sc_context *ctx;
|
||||
struct iasecc_private_data *prv;
|
||||
struct sc_security_env *env;
|
||||
|
||||
if (!card || !in || !out)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
ctx = card->ctx;
|
||||
prv = (struct iasecc_private_data *) card->drv_data;
|
||||
env = &prv->security_env;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_log(ctx, "inlen %i, outlen %i", in_len, out_len);
|
||||
if (!card || !in || !out)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid compute signature arguments");
|
||||
|
||||
if (env->operation == SC_SEC_OPERATION_SIGN)
|
||||
return iasecc_compute_signature_dst(card, in, in_len, out, out_len);
|
||||
|
@ -3315,6 +3402,7 @@ iasecc_read_public_key(struct sc_card *card, unsigned type,
|
|||
rv = sc_pkcs15_encode_pubkey_rsa(ctx, &rsa_key, out, out_len);
|
||||
LOG_TEST_RET(ctx, rv, "failed to read public key: cannot encode RSA public key");
|
||||
|
||||
if (out && out_len)
|
||||
sc_log(ctx, "encoded public key: %s", sc_dump_hex(*out, *out_len));
|
||||
|
||||
if (bn[0].data)
|
||||
|
@ -3324,7 +3412,7 @@ iasecc_read_public_key(struct sc_card *card, unsigned type,
|
|||
|
||||
iasecc_sdo_free_fields(card, &sdo);
|
||||
|
||||
SC_FUNC_RETURN(ctx, SC_SUCCESS, rv);
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -722,7 +724,7 @@ incrypto34_generate_key(sc_card_t *card,
|
|||
apdu.ins = 0x46;
|
||||
apdu.p1 = 0x00;
|
||||
apdu.p2 = args->key_id;/* doc is not clear, it just says "ID" */
|
||||
apdu.p2 = 0x00;
|
||||
apdu.le = 0x00;
|
||||
apdu.data= data;
|
||||
apdu.datalen = apdu.lc = sizeof(data);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -479,6 +479,65 @@ static int itacns_select_file(sc_card_t *card,
|
|||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||
}
|
||||
|
||||
static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||
{
|
||||
sc_path_t path;
|
||||
sc_file_t *file;
|
||||
size_t len;
|
||||
int r;
|
||||
u8 rbuf[256];
|
||||
|
||||
if (!serial) return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
/* see if we have cached serial number */
|
||||
if (card->serialnr.len) {
|
||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Reading EF_IDCarta.\n");
|
||||
|
||||
sc_format_path("3F0010001003", &path);
|
||||
|
||||
r = sc_select_file(card, &path, &file);
|
||||
if (r != SC_SUCCESS) {
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
len = file->size;
|
||||
|
||||
//Returned file->size should be 16.
|
||||
//We choose to not consider it as critical, because some cards
|
||||
//do not return FCI/FCP templates that include the file size.
|
||||
//Notify abnormal lenght anyway.
|
||||
if (len != 16) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Unexpected file length of EF_IDCarta (%lu)\n",
|
||||
(unsigned long) len);
|
||||
}
|
||||
|
||||
r = sc_read_binary(card, 0, rbuf, 256, 0);
|
||||
if ( r != 16 ) {
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
|
||||
/* cache serial number */
|
||||
memcpy(card->serialnr.value, rbuf, 16);
|
||||
card->serialnr.len = 16;
|
||||
/* copy and return serial number */
|
||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
itacns_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SC_CARDCTL_GET_SERIALNR:
|
||||
return itacns_get_serialnr(card, ptr);
|
||||
}
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static struct sc_card_driver * sc_get_driver(void)
|
||||
{
|
||||
|
@ -494,6 +553,7 @@ static struct sc_card_driver * sc_get_driver(void)
|
|||
itacns_ops.read_binary = itacns_read_binary;
|
||||
itacns_ops.list_files = itacns_list_files;
|
||||
itacns_ops.select_file = itacns_select_file;
|
||||
itacns_ops.card_ctl = itacns_card_ctl;
|
||||
return &itacns_drv;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* card-masktech.c: Support for Masktech smart cards using the MTCOS operating system.
|
||||
*
|
||||
* Copyright (C) 2011-2015 MaskTech GmbH Fischerstrasse 19, 87435 Kempten, Germany
|
||||
* Copyright (C) 2011 Andrey Uvarov (X-Infotech) <andrejs.uvarovs@x-infotech.com>
|
||||
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "cardctl.h"
|
||||
#include "iso7816.h"
|
||||
|
||||
static struct sc_atr_table masktech_atrs[] = {
|
||||
{"3B:89:80:01:4D:54:43:4F:53:70:02:02:05:3B", NULL, NULL,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
|
||||
{"3B:88:80:01:00:00:00:00:77:81:81:00:7E", NULL, NULL,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
|
||||
{"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:02:05:41", NULL, NULL,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
|
||||
{"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:01:02:45", NULL, NULL,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
|
||||
{NULL, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static struct sc_card_operations *iso_ops;
|
||||
static struct sc_card_operations masktech_ops;
|
||||
static struct sc_card_driver masktech_drv = {
|
||||
"MaskTech Smart Card",
|
||||
"MaskTech",
|
||||
&masktech_ops,
|
||||
masktech_atrs, 0, NULL
|
||||
};
|
||||
|
||||
struct masktech_private_data {
|
||||
/* save the key reference set at set_masktech_set_security_env to recover it as the signature step */
|
||||
int rsa_key_ref;
|
||||
|
||||
};
|
||||
|
||||
static int masktech_match_card(sc_card_t * card)
|
||||
{
|
||||
/* check if the ATR is in the known ATR */
|
||||
if (_sc_match_atr(card, masktech_atrs, &card->type) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int masktech_init(sc_card_t * card)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct masktech_private_data *data;
|
||||
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_init()\n");
|
||||
|
||||
/* private data kept during the live of the driver */
|
||||
if (!(data = (struct masktech_private_data *) malloc(sizeof(*data))))
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
card->drv_data = data;
|
||||
|
||||
/* supported RSA keys and how padding is done */
|
||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
|
||||
_sc_card_add_rsa_alg(card, 1024, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 2048, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 3072, flags, 0);
|
||||
card->caps |= SC_CARD_CAP_APDU_EXT;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int masktech_finish(sc_card_t *card)
|
||||
{
|
||||
/* free the private data */
|
||||
if (card->drv_data) {
|
||||
free(card->drv_data);
|
||||
card->drv_data = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int masktech_set_security_env(sc_card_t *card,
|
||||
const sc_security_env_t *env,
|
||||
int se_num)
|
||||
{
|
||||
struct masktech_private_data *private_data;
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_set_security_env(), keyRef = 0x%0x, algo = 0x%0x\n",
|
||||
*env->key_ref, env->algorithm_flags);
|
||||
|
||||
private_data = (struct masktech_private_data *) card->drv_data;
|
||||
if (!private_data)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
/* save the key reference */
|
||||
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
||||
if (env->key_ref_len != 1) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid key reference supplied.\n");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
private_data->rsa_key_ref = env->key_ref[0];
|
||||
}
|
||||
|
||||
return iso_ops->set_security_env(card, env, se_num);
|
||||
}
|
||||
|
||||
static int masktech_compute_signature(sc_card_t *card,
|
||||
const u8 * data,
|
||||
size_t datalen,
|
||||
u8 * out,
|
||||
size_t outlen)
|
||||
{
|
||||
|
||||
struct masktech_private_data *private_data;
|
||||
u8 sha256hash[32];
|
||||
static const u8 hdr_sha256[] = {
|
||||
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
||||
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
assert(card != NULL && data != NULL && out != NULL);
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_compute_signature()\n");
|
||||
|
||||
/* retrieve the key reference */
|
||||
private_data = (struct masktech_private_data *) card->drv_data;
|
||||
if (!private_data)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
if (private_data->rsa_key_ref == 0x88)
|
||||
{
|
||||
/* for this key reference, the card supports only SHA256 hash and the hash is computed using a digest info */
|
||||
/* check that it is a SHA256 with digest info*/
|
||||
if ((datalen != sizeof(hdr_sha256) + 32) || (memcmp(hdr_sha256, data, sizeof(hdr_sha256)) != 0))
|
||||
{
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "It is not a SHA256 with digestinfo\n");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
/* extract the SHA-256 hash */
|
||||
memcpy(sha256hash, (u8 *)(data+(datalen-32)), 32);//only last 32 byte => sha256
|
||||
/* default ISO 7816 functions */
|
||||
return iso_ops->compute_signature(card, sha256hash, 32, out, outlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default ISO 7816 functions */
|
||||
return iso_ops->compute_signature(card, data, datalen, out, outlen);
|
||||
}
|
||||
}
|
||||
|
||||
static int masktech_decipher(sc_card_t *card,
|
||||
const u8 * crgram,
|
||||
size_t crgram_len,
|
||||
u8 * out,
|
||||
size_t outlen)
|
||||
{
|
||||
int r;
|
||||
sc_apdu_t apdu;
|
||||
u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE];
|
||||
|
||||
assert(card != NULL && crgram != NULL && out != NULL);
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_decipher()\n");
|
||||
|
||||
if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) {
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86);
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
/* the card doesn't support anything else here (+1 / -1 is not working) */
|
||||
apdu.le = 65536;
|
||||
|
||||
apdu.data = crgram;
|
||||
apdu.lc = crgram_len;
|
||||
apdu.datalen = crgram_len;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
|
||||
|
||||
memcpy(out, apdu.resp, len);
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
|
||||
}
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
|
||||
/* unblock pin cmd */
|
||||
static int masktech_pin_unblock(sc_card_t *card,
|
||||
struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
int rv = 0;
|
||||
struct sc_pin_cmd_data verify_data;
|
||||
struct sc_pin_cmd_data reset_data;
|
||||
|
||||
/* Build a SC_PIN_CMD_VERIFY APDU on PUK */
|
||||
memset(&verify_data, 0, sizeof(verify_data));
|
||||
verify_data.cmd = SC_PIN_CMD_VERIFY;
|
||||
verify_data.pin_type = 1;
|
||||
verify_data.pin_reference = 0x83;
|
||||
verify_data.pin1 = data->pin1;
|
||||
verify_data.flags = data->flags;
|
||||
verify_data.pin1.prompt = data->pin1.prompt;
|
||||
|
||||
rv = iso_ops->pin_cmd(card, &verify_data, tries_left);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - verify unblock PIN");
|
||||
|
||||
/* Build a SC_PIN_CMD_UNBLOCK APDU */
|
||||
memset(&reset_data, 0, sizeof(reset_data));
|
||||
reset_data.cmd = SC_PIN_CMD_UNBLOCK;
|
||||
reset_data.pin_type = 1;
|
||||
reset_data.pin_reference = 0x91;
|
||||
/* pin1 is set to null on purpose and flag set to implicit change
|
||||
=> if there is a pinpad reader, do not ask for pin1 */
|
||||
reset_data.pin2 = data->pin2;
|
||||
reset_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE;
|
||||
reset_data.pin2.prompt = data->pin2.prompt;
|
||||
|
||||
rv = iso_ops->pin_cmd(card, &reset_data, tries_left);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - reset unblock PIN");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int masktech_pin_change(sc_card_t *card,
|
||||
struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
int rv = 0;
|
||||
struct sc_pin_cmd_data verify_data;
|
||||
struct sc_pin_cmd_data change_data;
|
||||
|
||||
/* Build a SC_PIN_CMD_VERIFY APDU */
|
||||
memset(&verify_data, 0, sizeof(verify_data));
|
||||
verify_data.cmd = SC_PIN_CMD_VERIFY;
|
||||
verify_data.pin_type = 1;
|
||||
verify_data.pin_reference = data->pin_reference;
|
||||
verify_data.pin1 = data->pin1;
|
||||
verify_data.flags = data->flags;
|
||||
verify_data.pin1.prompt = data->pin1.prompt;
|
||||
|
||||
rv = iso_ops->pin_cmd(card, &verify_data, tries_left);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - verify change PIN");
|
||||
|
||||
/* Build a SC_PIN_CMD_CHANGE APDU */
|
||||
memset(&change_data, 0, sizeof(change_data));
|
||||
change_data.cmd = SC_PIN_CMD_CHANGE;
|
||||
change_data.pin_type = 1;
|
||||
change_data.pin_reference = data->pin_reference;
|
||||
/* pin1 is set to null on purpose and flag set to implicit change
|
||||
=> if there is a pinpad reader, do not ask for pin1 */
|
||||
change_data.pin2 = data->pin2;
|
||||
change_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE;
|
||||
change_data.pin2.prompt = data->pin2.prompt;
|
||||
|
||||
rv = iso_ops->pin_cmd(card, &change_data, tries_left);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - chnage PIN");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int masktech_pin_cmd(sc_card_t *card,
|
||||
struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
int rv;
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
||||
switch(data->cmd)
|
||||
{
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
rv = masktech_pin_unblock(card, data, tries_left);
|
||||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
rv = masktech_pin_change(card, data, tries_left);
|
||||
break;
|
||||
default:
|
||||
rv = iso_ops->pin_cmd(card, data, tries_left);
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int masktech_get_serialnr(sc_card_t * card, sc_serial_number_t * serial)
|
||||
{
|
||||
struct sc_apdu apdu;
|
||||
unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE-2];
|
||||
int rv;
|
||||
|
||||
if (!serial)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* Get smart card serial number */
|
||||
card->cla = 0x80;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x08, 0x00, 0x00);
|
||||
apdu.resplen = sizeof(apdu_resp);
|
||||
apdu.resp = apdu_resp;
|
||||
|
||||
rv = sc_transmit_apdu(card, &apdu);
|
||||
card->cla = 0x00;
|
||||
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed");
|
||||
|
||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
if (SC_MAX_SERIALNR < apdu.resplen)
|
||||
{
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL);
|
||||
}
|
||||
/* cache serial number */
|
||||
card->serialnr.len = apdu.resplen;
|
||||
memcpy(card->serialnr.value, apdu.resp, card->serialnr.len);
|
||||
|
||||
/* copy and return serial number */
|
||||
if (serial)
|
||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static int masktech_card_ctl(sc_card_t * card, unsigned long cmd, void *ptr)
|
||||
{
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_card_ctl()\n");
|
||||
switch (cmd) {
|
||||
case SC_CARDCTL_GET_SERIALNR:
|
||||
return masktech_get_serialnr(card, (sc_serial_number_t *) ptr);
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static struct sc_card_driver *sc_get_driver(void)
|
||||
{
|
||||
|
||||
if (iso_ops == NULL)
|
||||
iso_ops = sc_get_iso7816_driver()->ops;
|
||||
|
||||
masktech_ops = *iso_ops;
|
||||
|
||||
masktech_ops.match_card = masktech_match_card;
|
||||
masktech_ops.init = masktech_init;
|
||||
masktech_ops.finish = masktech_finish;
|
||||
masktech_ops.set_security_env = masktech_set_security_env;
|
||||
masktech_ops.compute_signature = masktech_compute_signature;
|
||||
masktech_ops.decipher = masktech_decipher;
|
||||
masktech_ops.pin_cmd = masktech_pin_cmd;
|
||||
masktech_ops.card_ctl = masktech_card_ctl;
|
||||
return &masktech_drv;
|
||||
}
|
||||
|
||||
struct sc_card_driver *sc_get_masktech_driver(void)
|
||||
{
|
||||
return sc_get_driver();
|
||||
}
|
|
@ -22,7 +22,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -379,13 +381,13 @@ static int mcrd_init(sc_card_t * card)
|
|||
priv->curpathlen = 1;
|
||||
|
||||
sc_format_path ("3f00", &tmppath);
|
||||
sc_select_file (card, &tmppath, NULL);
|
||||
r = sc_select_file (card, &tmppath, NULL);
|
||||
|
||||
/* Not needed for the fixed EstEID profile */
|
||||
if (!is_esteid_card(card))
|
||||
load_special_files(card);
|
||||
|
||||
return SC_SUCCESS;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int mcrd_finish(sc_card_t * card)
|
||||
|
@ -419,6 +421,8 @@ static int load_special_files(sc_card_t * card)
|
|||
if (dfi && dfi->rule_file)
|
||||
return 0; /* yes. */
|
||||
clear_special_files(dfi);
|
||||
if (!dfi)
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL);
|
||||
|
||||
/* Read rule file. Note that we bypass our cache here. */
|
||||
r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL);
|
||||
|
@ -1188,7 +1192,9 @@ static int mcrd_set_security_env(sc_card_t * card,
|
|||
|
||||
/* Make sure we always start from MF */
|
||||
sc_format_path ("3f00", &tmppath);
|
||||
sc_select_file (card, &tmppath, NULL);
|
||||
r = sc_select_file (card, &tmppath, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* We now know that cache is not valid */
|
||||
select_esteid_df(card);
|
||||
switch (env->operation) {
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -41,6 +43,8 @@ static struct sc_card_driver muscle_drv = {
|
|||
};
|
||||
|
||||
static struct sc_atr_table muscle_atrs[] = {
|
||||
/* Tyfone JCOP 242R2 cards */
|
||||
{ "3b:6d:00:00:ff:54:79:66:6f:6e:65:20:32:34:32:52:32", NULL, NULL, SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU, 0, NULL },
|
||||
/* Aladdin eToken PRO USB 72K Java */
|
||||
{ "3b:d5:18:00:81:31:3a:7d:80:73:c8:21:10:30", NULL, NULL, SC_CARD_TYPE_MUSCLE_ETOKEN_72K, 0, NULL },
|
||||
/* JCOP31 v2.4.1 contact interface */
|
||||
|
@ -81,7 +85,7 @@ static int muscle_match_card(sc_card_t *card)
|
|||
* however it's not always properly nulled out... */
|
||||
card->ops->logout = NULL;
|
||||
|
||||
if (msc_select_applet(card, muscleAppletId, 5) == 1) {
|
||||
if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) {
|
||||
/* Muscle applet is present, check the protocol version to be sure */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x3C, 0x00, 0x00);
|
||||
apdu.cla = 0xB0;
|
||||
|
@ -473,12 +477,16 @@ static int muscle_init(sc_card_t *card)
|
|||
|
||||
/* Card type detection */
|
||||
_sc_match_atr(card, muscle_atrs, &card->type);
|
||||
|
||||
if(card->type == SC_CARD_TYPE_MUSCLE_ETOKEN_72K) {
|
||||
card->caps |= SC_CARD_CAP_APDU_EXT;
|
||||
}
|
||||
if(card->type == SC_CARD_TYPE_MUSCLE_JCOP241) {
|
||||
card->caps |= SC_CARD_CAP_APDU_EXT;
|
||||
}
|
||||
if(card->type == SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU) {
|
||||
/* Tyfone JCOP v242R2 card that doesn't support extended APDUs */
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Card type detection */
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -66,8 +68,30 @@ static const char *myeid_atrs[] = {
|
|||
|
||||
typedef struct myeid_private_data {
|
||||
int card_state;
|
||||
|
||||
unsigned short change_counter;
|
||||
/* the driver sets sec_env pointer in myeid_set_security_env and
|
||||
it is used immediately in myeid_decipher to differentiate between RSA decryption and
|
||||
ECDH key agreement. Note that this pointer is usually not valid
|
||||
after this pair of calls and must not be used elsewhere. */
|
||||
const struct sc_security_env* sec_env;
|
||||
} myeid_private_data_t;
|
||||
|
||||
static struct myeid_supported_ec_curves {
|
||||
char *curve_name;
|
||||
struct sc_object_id curve_oid;
|
||||
size_t size;
|
||||
} ec_curves[] = {
|
||||
{"secp192r1", {{1, 2, 840, 10045, 3, 1, 1, -1}},192},
|
||||
/* {"secp224r1", {{1, 3, 132, 0, 33, -1}}, 224}, */
|
||||
{"secp256r1", {{1, 2, 840, 10045, 3, 1, 7, -1}},256},
|
||||
/* {"secp384r1", {{1, 3, 132, 0, 34, -1}}, 384}, */
|
||||
/* {"secp521r1", {{1, 3, 132, 0, 35, -1}}, 521}, */
|
||||
{NULL, {{-1}}, 0},
|
||||
};
|
||||
|
||||
static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen);
|
||||
|
||||
static int myeid_match_card(struct sc_card *card)
|
||||
{
|
||||
int i, match = -1;
|
||||
|
@ -98,14 +122,28 @@ static int myeid_init(struct sc_card *card)
|
|||
unsigned long flags = 0,
|
||||
ext_flags = 0;
|
||||
myeid_private_data_t *priv;
|
||||
u8 appletInfo[20];
|
||||
size_t appletInfoLen;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
priv = calloc(1, sizeof(myeid_private_data_t));
|
||||
if (!priv)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
priv->card_state = SC_FILE_STATUS_CREATION;
|
||||
card->drv_data = priv;
|
||||
|
||||
/* find out MyEID version */
|
||||
|
||||
appletInfoLen = 20;
|
||||
|
||||
r = myeid_get_info(card, appletInfo, appletInfoLen);
|
||||
|
||||
LOG_TEST_RET(card->ctx, r, "Failed to get MyEID applet information.");
|
||||
|
||||
priv->change_counter = appletInfo[19] | appletInfo[18] << 8;
|
||||
|
||||
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
|
||||
|
||||
|
@ -116,12 +154,19 @@ static int myeid_init(struct sc_card *card)
|
|||
_sc_card_add_rsa_alg(card, 2048, flags, 0);
|
||||
|
||||
#ifdef MYEID_ECC_SUPPORT
|
||||
flags |= SC_ALGORITHM_ECDSA_RAW;
|
||||
|
||||
/* show ECC algorithms if the applet version of the inserted card supports them */
|
||||
if ((card->version.fw_major == 3 && card->version.fw_minor > 5) ||
|
||||
card->version.fw_major >= 4) {
|
||||
int i;
|
||||
|
||||
flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
flags |= SC_ALGORITHM_ECDSA_HASH_NONE | SC_ALGORITHM_ECDSA_HASH_SHA1;
|
||||
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
|
||||
|
||||
_sc_card_add_ec_alg(card, 192, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 224, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 256, flags, ext_flags);
|
||||
for (i=0; ec_curves[i].curve_name != NULL; i++)
|
||||
_sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].curve_oid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* State that we have an RNG */
|
||||
|
@ -302,17 +347,20 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
}
|
||||
|
||||
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
||||
u8 *out, size_t *outlen)
|
||||
u8 *buf, size_t *outlen)
|
||||
{
|
||||
const sc_acl_entry_t *read, *update, *delete, *generate;
|
||||
u8 buf[40];
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
if (!buf || !outlen || *outlen < 45)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
|
||||
|
||||
/* PrivateKey
|
||||
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
|
||||
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
|
||||
memset(buf, 0x0, sizeof(buf));
|
||||
memset(buf, 0x0, *outlen);
|
||||
|
||||
buf[0] = 0x62;
|
||||
buf[1] = 0x17;
|
||||
|
@ -340,8 +388,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
buf[16] = 0xFF;
|
||||
buf[17] = 0xFF;
|
||||
|
||||
if (file->sec_attr_len == 3 && file->sec_attr)
|
||||
{
|
||||
if (file->sec_attr_len == 3 && file->sec_attr) {
|
||||
buf[15] = file->sec_attr[0];
|
||||
buf[16] = file->sec_attr[1];
|
||||
buf[17] = file->sec_attr[2];
|
||||
|
@ -349,8 +396,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
sc_log(card->ctx, "id (%X), sec_attr %X %X %X", file->id,
|
||||
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);
|
||||
|
||||
switch (file->type) {
|
||||
|
@ -412,10 +458,10 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
buf[25] = 0x84;
|
||||
buf[26] = (u8)file->namelen;
|
||||
|
||||
for(i=0;i < (int)file->namelen;i++)
|
||||
buf[i + 26] = file->name[i];
|
||||
for(i=0;i < file->namelen;i++)
|
||||
buf[i + 27] = file->name[i];
|
||||
|
||||
buf[1] = 0x19 + file->namelen + 2;
|
||||
buf[1] = 27 + file->namelen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -424,16 +470,15 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
}
|
||||
|
||||
*outlen = buf[1]+2;
|
||||
memcpy(out, buf, *outlen);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, 0);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int myeid_create_file(struct sc_card *card, struct sc_file *file)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
u8 sbuf[32];
|
||||
size_t buflen;
|
||||
u8 sbuf[45];
|
||||
size_t buflen = sizeof sbuf;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
@ -479,12 +524,54 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path)
|
|||
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
|
||||
static int myeid_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
|
||||
if (r == SC_ERROR_PIN_CODE_INCORRECT) {
|
||||
data->pin1.tries_left = apdu.sw2 & 0xF;
|
||||
r = SC_SUCCESS;
|
||||
} else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
|
||||
data->pin1.tries_left = 0;
|
||||
r = SC_SUCCESS;
|
||||
}
|
||||
LOG_TEST_RET(card->ctx, r, "Check SW error");
|
||||
|
||||
if (r == SC_SUCCESS)
|
||||
{
|
||||
data->pin1.pad_length = data->pin2.pad_length = 8;
|
||||
data->pin1.pad_char = data->pin2.pad_char = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
if (tries_left != NULL) {
|
||||
*tries_left = data->pin1.tries_left;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
if (data->cmd == SC_PIN_CMD_GET_INFO)
|
||||
{
|
||||
return myeid_pin_info(card, data, tries_left);
|
||||
}
|
||||
|
||||
sc_log(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n",
|
||||
data->pin_reference, data->pin1.len, data->pin2.len);
|
||||
|
||||
|
@ -508,7 +595,7 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *
|
|||
sc_apdu_t apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 *p;
|
||||
int r, locked = 0;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && env != NULL);
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
@ -564,11 +651,6 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *
|
|||
apdu.datalen = r;
|
||||
apdu.data = sbuf;
|
||||
apdu.resplen = 0;
|
||||
if (se_num > 0) {
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
locked = 1;
|
||||
}
|
||||
if (apdu.datalen != 0)
|
||||
{
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -586,16 +668,7 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
if (se_num <= 0)
|
||||
return 0;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
sc_unlock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
err:
|
||||
if (locked)
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
|
@ -605,7 +678,7 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e
|
|||
sc_apdu_t apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 *p;
|
||||
int r, locked = 0;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && env != NULL);
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
@ -661,11 +734,6 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e
|
|||
apdu.datalen = r;
|
||||
apdu.data = sbuf;
|
||||
apdu.resplen = 0;
|
||||
if (se_num > 0) {
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
locked = 1;
|
||||
}
|
||||
if (apdu.datalen != 0)
|
||||
{
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -683,23 +751,21 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
if (se_num <= 0)
|
||||
return 0;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
sc_unlock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
err:
|
||||
if (locked)
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
static int myeid_set_security_env(struct sc_card *card,
|
||||
const struct sc_security_env *env, int se_num)
|
||||
{
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
struct sc_context *ctx = card->ctx;
|
||||
myeid_private_data_t* priv;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
priv = (myeid_private_data_t*) card->drv_data;
|
||||
/* store security environment to differentiate between ECDH and RSA in decipher - Hannu*/
|
||||
priv->sec_env = env;
|
||||
|
||||
if (env->flags & SC_SEC_ENV_ALG_PRESENT)
|
||||
{
|
||||
|
@ -724,38 +790,75 @@ static int myeid_set_security_env(struct sc_card *card,
|
|||
else if (tmp.algorithm == SC_ALGORITHM_EC)
|
||||
{
|
||||
#ifdef MYEID_ECC_SUPPORT
|
||||
/* TODO: Update the algorithm_ref */
|
||||
tmp.algorithm_ref = 0xAA;
|
||||
tmp.algorithm_ref = 0x04;
|
||||
tmp.algorithm_flags = 0;
|
||||
return myeid_set_security_env_ec(card, &tmp, se_num);
|
||||
#else
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Elliptic curves are not supported in this version.\n");
|
||||
sc_log(ctx, "Elliptic curves are not supported in this version.");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported algorithm.\n");
|
||||
sc_log(ctx, "Unsupported algorithm.");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
return myeid_set_security_env_rsa(card, env, se_num);
|
||||
}
|
||||
|
||||
static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
||||
size_t datalen, u8 * out, size_t outlen)
|
||||
|
||||
static int
|
||||
myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char *data, size_t datalen)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
int r;
|
||||
|
||||
assert(data && datalen);
|
||||
|
||||
if (*data != 0x30 || *(data + 1) != (datalen - 2) || *(data + 2) != 0x02)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
|
||||
buf = calloc(1, (s_len + 7)/8*2);
|
||||
if (!buf)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
buflen = (s_len + 7)/8*2;
|
||||
|
||||
r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen);
|
||||
if (r < 0)
|
||||
free(buf);
|
||||
LOG_TEST_RET(ctx, r, "Failed to cenvert Sig-Value to the raw RS format");
|
||||
|
||||
if (buflen > datalen)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
|
||||
memmove(data, buf, buflen);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
myeid_compute_signature(struct sc_card *card, const u8 * data, size_t datalen,
|
||||
u8 * out, size_t outlen)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
struct sc_apdu apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
struct myeid_private_data* priv;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && data != NULL && out != NULL);
|
||||
ctx = card->ctx;
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
priv = (myeid_private_data_t*) card->drv_data;
|
||||
sc_log(ctx, "key type %i, key length %i", priv->sec_env->algorithm, priv->sec_env->algorithm_ref);
|
||||
|
||||
if (datalen > 256)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* INS: 0x2A PERFORM SECURITY OPERATION
|
||||
* P1: 0x9E Resp: Digital Signature
|
||||
|
@ -764,15 +867,13 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
|||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.le = 256;
|
||||
if (datalen == 256)
|
||||
{
|
||||
if (datalen == 256) {
|
||||
apdu.p2 = data[0];
|
||||
memcpy(sbuf, data+1, datalen-1);
|
||||
apdu.lc = datalen - 1;
|
||||
apdu.datalen = datalen - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
memcpy(sbuf, data, datalen);
|
||||
apdu.lc = datalen;
|
||||
apdu.datalen = datalen;
|
||||
|
@ -780,31 +881,98 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data,
|
|||
|
||||
apdu.data = sbuf;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
LOG_TEST_RET(ctx, r, "APDU transmit failed");
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(ctx, r, "compute_signature failed");
|
||||
|
||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
|
||||
{
|
||||
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
|
||||
|
||||
memcpy(out, apdu.resp, len);
|
||||
LOG_FUNC_RETURN(card->ctx, len);
|
||||
if (priv->sec_env->algorithm == SC_ALGORITHM_EC) {
|
||||
r = myeid_convert_ec_signature(ctx, priv->sec_env->algorithm_ref, apdu.resp, apdu.resplen);
|
||||
LOG_TEST_RET(ctx, r, "compute_signature convert signature failed");
|
||||
apdu.resplen = r;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
if (apdu.resplen > outlen)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
|
||||
|
||||
memcpy(out, apdu.resp, apdu.resplen);
|
||||
LOG_FUNC_RETURN(ctx, apdu.resplen);
|
||||
}
|
||||
|
||||
|
||||
/* takes other party's public key as input, performs ECDH key derivation and returns the shared secret in [out]. */
|
||||
int myeid_ecdh_derive(struct sc_card *card, const u8* pubkey, size_t pubkey_len, u8* out, size_t outlen)
|
||||
{
|
||||
|
||||
/* MyEID uses GENERAL AUTHENTICATE ISO command for ECDH */
|
||||
|
||||
struct sc_apdu apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu,
|
||||
SC_APDU_CASE_4_SHORT,
|
||||
0x86, 0x00, 0x00);
|
||||
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
|
||||
/* Fill in "Data objects in dynamic authentication template (tag 0x7C) structure */
|
||||
sbuf[0] = 0x7C;
|
||||
sbuf[1] = pubkey_len + 4;
|
||||
sbuf[2] = 0x85;
|
||||
sbuf[3] = pubkey_len;
|
||||
memcpy(&sbuf[4], pubkey, pubkey_len);
|
||||
|
||||
apdu.lc = pubkey_len + 4;
|
||||
apdu.datalen = apdu.lc;
|
||||
apdu.data = sbuf;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed.");
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(card->ctx, r, "ECDH operation failed - GENERAL AUTHENTICATE returned error.");
|
||||
|
||||
if (outlen < apdu.resplen)
|
||||
{
|
||||
r = SC_ERROR_BUFFER_TOO_SMALL;
|
||||
LOG_TEST_RET(card->ctx, r, "Buffer too small to hold shared secret.");
|
||||
}
|
||||
|
||||
memcpy(out, rbuf, apdu.resplen);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
|
||||
static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
||||
size_t crgram_len, u8 * out, size_t outlen)
|
||||
{
|
||||
int r;
|
||||
myeid_private_data_t* priv;
|
||||
struct sc_apdu apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
|
||||
|
||||
assert(card != NULL && crgram != NULL && out != NULL);
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
|
||||
|
||||
priv = (myeid_private_data_t*) card->drv_data;
|
||||
|
||||
if (priv->sec_env && priv->sec_env->algorithm == SC_ALGORITHM_EC
|
||||
&& priv->sec_env->operation == SC_SEC_OPERATION_DERIVE
|
||||
&& priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW)
|
||||
{
|
||||
r = myeid_ecdh_derive(card, crgram, crgram_len, out, outlen);
|
||||
priv->sec_env = NULL; /* clear after operation */
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
if (crgram_len > 256)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
|
@ -878,6 +1046,7 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
|
|||
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
}
|
||||
|
||||
|
||||
/* Write internal data, e.g. add default pin-records to pin */
|
||||
static int myeid_putdata(struct sc_card *card, struct sc_cardctl_myeid_data_obj* data_obj)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
* best view with tabstop=4
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OPENSSL /* empty file without openssl */
|
||||
#include <stdlib.h>
|
||||
|
@ -397,7 +399,8 @@ auth_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
case 0x38:
|
||||
file->type = SC_FILE_TYPE_DF;
|
||||
file->size = attr[0];
|
||||
sc_file_set_type_attr(file,attr,attr_len);
|
||||
if (SC_SUCCESS != sc_file_set_type_attr(file,attr,attr_len))
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
break;
|
||||
default:
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
|
@ -1108,16 +1111,17 @@ auth_compute_signature(struct sc_card *card, const unsigned char *in, size_t ile
|
|||
unsigned char resp[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int rv;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "inlen %i, outlen %i\n", ilen, olen);
|
||||
if (!card || !in || !out) {
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
else if (ilen > 96) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Illegal input length %d\n", ilen);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Illegal input length");
|
||||
}
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "inlen %i, outlen %i\n", ilen, olen);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
|
||||
apdu.datalen = ilen;
|
||||
apdu.data = in;
|
||||
|
@ -2012,7 +2016,7 @@ write_publickey (struct sc_card *card, unsigned int offset,
|
|||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"write_publickey in %d bytes :\n%s", count, debug_buf);
|
||||
|
||||
if (offset > sizeof(rsa_der))
|
||||
if (1+offset > sizeof(rsa_der))
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Invalid offset value");
|
||||
|
||||
len = offset+count > sizeof(rsa_der) ? sizeof(rsa_der) - offset : count;
|
||||
|
@ -2111,7 +2115,7 @@ auth_read_binary(struct sc_card *card, unsigned int offset,
|
|||
if (auth_current_ef->magic==SC_FILE_MAGIC &&
|
||||
auth_current_ef->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) {
|
||||
int jj;
|
||||
unsigned char resp[0x100], *out = NULL;
|
||||
unsigned char resp[SC_MAX_APDU_BUFFER_SIZE], *out = NULL;
|
||||
size_t resp_len, out_len;
|
||||
struct sc_pkcs15_bignum bn[2];
|
||||
struct sc_pkcs15_pubkey_rsa key;
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
* http://www.g10code.de/docs/openpgp-card-2.0.pdf
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -359,8 +361,14 @@ pgp_init(sc_card_t *card)
|
|||
return r;
|
||||
}
|
||||
|
||||
/* defensive programming check */
|
||||
if (!file) {
|
||||
pgp_finish(card);
|
||||
return SC_ERROR_OBJECT_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* read information from AID */
|
||||
if (file && file->namelen == 16) {
|
||||
if (file->namelen == 16) {
|
||||
/* OpenPGP card spec 1.1 & 2.0, section 4.2.1 & 4.1.2.1 */
|
||||
priv->bcd_version = bebytes2ushort(file->name + 6);
|
||||
/* kludge: get card's serial number from manufacturer ID + serial number */
|
||||
|
@ -949,7 +957,7 @@ static unsigned int pgp_strip_path(sc_card_t *card, const sc_path_t *path)
|
|||
{
|
||||
unsigned int start_point = 0;
|
||||
/* start_point will move through the path string */
|
||||
if (path->value == NULL || path->len == 0)
|
||||
if (path->len == 0)
|
||||
return 0;
|
||||
|
||||
/* Ignore 3F00 (MF) at the beginning */
|
||||
|
@ -2074,6 +2082,9 @@ pgp_build_tlv(sc_context_t *ctx, unsigned int tag, u8 *data, size_t len, u8 **ou
|
|||
highest_order++;
|
||||
}
|
||||
highest_order--;
|
||||
if (highest_order >= 4)
|
||||
cla = 0x00;
|
||||
else
|
||||
cla = tag >> 8*highest_order;
|
||||
/* Restore class bits */
|
||||
*out[0] |= cla;
|
||||
|
@ -2426,7 +2437,9 @@ static int pgp_erase_card(sc_card_t *card)
|
|||
/* ABI: card ctl: perform special card-specific operations */
|
||||
static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
|
||||
{
|
||||
#ifdef ENABLE_OPENSSL
|
||||
int r;
|
||||
#endif /* ENABLE_OPENSSL */
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -439,6 +441,7 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2,
|
|||
unsigned int cla_out, tag_out;
|
||||
const u8 *body;
|
||||
size_t bodylen;
|
||||
int find_len = 0;
|
||||
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
@ -463,6 +466,11 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2,
|
|||
recvbuf ? SC_APDU_CASE_4_SHORT: SC_APDU_CASE_3_SHORT,
|
||||
ins, p1, p2);
|
||||
apdu.flags |= SC_APDU_FLAGS_CHAINING;
|
||||
/* if looking for length of object, dont try and read the rest of buffer here */
|
||||
if (rbuflen == 8 && card->reader->active_protocol == SC_PROTO_T1) {
|
||||
apdu.flags |= SC_APDU_FLAGS_NO_GET_RESP;
|
||||
find_len = 1;
|
||||
}
|
||||
|
||||
apdu.lc = sendbuflen;
|
||||
apdu.datalen = sendbuflen;
|
||||
|
@ -491,7 +499,9 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (!(find_len && apdu.sw1 == 0x61)) {
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
}
|
||||
|
||||
/* TODO: - DEE look later at tag vs size read too */
|
||||
if (r < 0) {
|
||||
|
@ -784,8 +794,6 @@ static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file)
|
|||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NO_CARD_SUPPORT);
|
||||
|
||||
card->ops->process_fci(card, aid_file, apdu.resp+2, apdu.resp[1]);
|
||||
if (aid_file->name == NULL)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NO_CARD_SUPPORT);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, i);
|
||||
}
|
||||
|
@ -1558,8 +1566,10 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
|||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
if (r != SC_SUCCESS)
|
||||
goto err;
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n");
|
||||
goto err; /* cleanup */
|
||||
}
|
||||
locked = 1;
|
||||
|
||||
p = sbuf;
|
||||
|
@ -1828,8 +1838,10 @@ static int piv_general_external_authenticate(sc_card_t *card,
|
|||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
if (r != SC_SUCCESS)
|
||||
goto err;
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n");
|
||||
goto err; /* cleanup */
|
||||
}
|
||||
locked = 1;
|
||||
|
||||
p = sbuf;
|
||||
|
@ -2143,7 +2155,9 @@ static int piv_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
|||
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"challenge len=%d",len);
|
||||
|
||||
sc_lock(card);
|
||||
r = sc_lock(card);
|
||||
if (r != SC_SUCCESS)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||
|
||||
p = sbuf;
|
||||
*p++ = 0x7c;
|
||||
|
@ -2179,9 +2193,9 @@ static int piv_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
|||
rbuf = NULL;
|
||||
}
|
||||
|
||||
sc_unlock(card);
|
||||
r = sc_unlock(card);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 0);
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2875,11 +2889,11 @@ static int piv_init(sc_card_t *card)
|
|||
_sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */
|
||||
_sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */
|
||||
|
||||
flags = SC_ALGORITHM_ECDSA_RAW;
|
||||
flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE;
|
||||
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
|
||||
|
||||
_sc_card_add_ec_alg(card, 256, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 384, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL);
|
||||
_sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL);
|
||||
|
||||
card->caps |= SC_CARD_CAP_RNG;
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -234,7 +236,6 @@ static int sc_hsm_read_binary(sc_card_t *card,
|
|||
{
|
||||
sc_context_t *ctx = card->ctx;
|
||||
sc_apdu_t apdu;
|
||||
u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 cmdbuff[4];
|
||||
int r;
|
||||
|
||||
|
@ -248,14 +249,14 @@ static int sc_hsm_read_binary(sc_card_t *card,
|
|||
cmdbuff[2] = (idx >> 8) & 0xFF;
|
||||
cmdbuff[3] = idx & 0xFF;
|
||||
|
||||
assert(count <= (card->max_recv_size > 0 ? card->max_recv_size : 256));
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xB1, 0x00, 0x00);
|
||||
assert(count <= card->max_recv_size);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00);
|
||||
apdu.data = cmdbuff;
|
||||
apdu.datalen = 4;
|
||||
apdu.lc = 4;
|
||||
apdu.le = count;
|
||||
apdu.resplen = count;
|
||||
apdu.resp = recvbuf;
|
||||
apdu.resp = buf;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(ctx, r, "APDU transmit failed");
|
||||
|
@ -265,8 +266,6 @@ static int sc_hsm_read_binary(sc_card_t *card,
|
|||
LOG_TEST_RET(ctx, r, "Check SW error");
|
||||
}
|
||||
|
||||
memcpy(buf, recvbuf, apdu.resplen);
|
||||
|
||||
LOG_FUNC_RETURN(ctx, apdu.resplen);
|
||||
}
|
||||
|
||||
|
@ -1042,6 +1041,7 @@ static int sc_hsm_init(struct sc_card *card)
|
|||
_sc_card_add_rsa_alg(card, 2048, flags, 0);
|
||||
|
||||
flags = SC_ALGORITHM_ECDSA_RAW|
|
||||
SC_ALGORITHM_ECDH_CDH_RAW|
|
||||
SC_ALGORITHM_ECDSA_HASH_NONE|
|
||||
SC_ALGORITHM_ECDSA_HASH_SHA1|
|
||||
SC_ALGORITHM_ECDSA_HASH_SHA224|
|
||||
|
@ -1053,14 +1053,15 @@ static int sc_hsm_init(struct sc_card *card)
|
|||
SC_ALGORITHM_EXT_EC_NAMEDCURVE|
|
||||
SC_ALGORITHM_EXT_EC_UNCOMPRESES|
|
||||
SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
_sc_card_add_ec_alg(card, 192, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 224, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 256, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 320, flags, ext_flags);
|
||||
_sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL);
|
||||
_sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL);
|
||||
_sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL);
|
||||
_sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL);
|
||||
|
||||
card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT;
|
||||
|
||||
card->max_send_size = 1431; // 1439 buffer size - 8 byte TLV because of odd ins in UPDATE BINARY
|
||||
card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -438,7 +440,7 @@ static int setcos_create_file_44(sc_card_t *card, sc_file_t *file)
|
|||
const int* p_idx;
|
||||
int i;
|
||||
int len = 0;
|
||||
u8 bBuf[32];
|
||||
u8 bBuf[64];
|
||||
|
||||
/* Get specific operation groups for specified file-type */
|
||||
switch (file->type){
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -32,6 +34,8 @@ static struct sc_atr_table starcos_atrs[] = {
|
|||
{ "3B:B7:94:00:c0:24:31:fe:65:53:50:4b:32:33:90:00:b4", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
|
||||
{ "3B:B7:94:00:81:31:fe:65:53:50:4b:32:33:90:00:d1", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
|
||||
{ "3b:b7:18:00:c0:3e:31:fe:65:53:50:4b:32:34:90:00:25", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
|
||||
/* STARCOS 3.4 */
|
||||
{ "3b:d8:18:ff:81:b1:fe:45:1f:03:80:64:04:1a:b4:03:81:05:61", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_4, 0, NULL },
|
||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -39,7 +43,7 @@ static struct sc_card_operations starcos_ops;
|
|||
static struct sc_card_operations *iso_ops = NULL;
|
||||
|
||||
static struct sc_card_driver starcos_drv = {
|
||||
"STARCOS SPK 2.3/2.4",
|
||||
"STARCOS SPK 2.3/2.4/3.4",
|
||||
"starcos",
|
||||
&starcos_ops,
|
||||
NULL, 0, NULL
|
||||
|
@ -70,6 +74,24 @@ typedef struct starcos_ex_data_st {
|
|||
unsigned int fix_digestInfo;
|
||||
} starcos_ex_data;
|
||||
|
||||
#define CHECK_NOT_SUPPORTED_V3_4(card) \
|
||||
do { \
|
||||
if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \
|
||||
sc_debug((card)->ctx, SC_LOG_DEBUG_NORMAL, \
|
||||
"not supported for STARCOS 3.4 cards"); \
|
||||
return SC_ERROR_NOT_SUPPORTED; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_ONLY_SUPPORTED_V3_4(card) \
|
||||
do { \
|
||||
if ((card)->type != SC_CARD_TYPE_STARCOS_V3_4) { \
|
||||
sc_debug((card)->ctx, SC_LOG_DEBUG_NORMAL, \
|
||||
"only supported for STARCOS 3.4 cards"); \
|
||||
return SC_ERROR_NOT_SUPPORTED; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/* the starcos part */
|
||||
static int starcos_match_card(sc_card_t *card)
|
||||
{
|
||||
|
@ -103,15 +125,31 @@ static int starcos_init(sc_card_t *card)
|
|||
| SC_ALGORITHM_RSA_HASH_RIPEMD160
|
||||
| SC_ALGORITHM_RSA_HASH_MD5_SHA1;
|
||||
|
||||
card->caps = SC_CARD_CAP_RNG;
|
||||
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
|
||||
card->name = "STARCOS SPK 3.4";
|
||||
flags |= SC_CARD_FLAG_RNG
|
||||
| SC_ALGORITHM_RSA_HASH_SHA224
|
||||
| SC_ALGORITHM_RSA_HASH_SHA256
|
||||
| SC_ALGORITHM_RSA_HASH_SHA384
|
||||
| SC_ALGORITHM_RSA_HASH_SHA512;
|
||||
|
||||
_sc_card_add_rsa_alg(card, 512, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card, 768, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card,1024, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card,1728, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card,1976, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card,2048, flags, 0x10001);
|
||||
} else {
|
||||
_sc_card_add_rsa_alg(card, 512, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card, 768, flags, 0x10001);
|
||||
_sc_card_add_rsa_alg(card,1024, flags, 0x10001);
|
||||
|
||||
card->caps = SC_CARD_CAP_RNG;
|
||||
|
||||
/* we need read_binary&friends with max 128 bytes per read */
|
||||
card->max_send_size = 128;
|
||||
card->max_recv_size = 128;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -215,6 +253,182 @@ static int process_fci(sc_context_t *ctx, sc_file_t *file,
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int process_fci_v3_4(sc_context_t *ctx, sc_file_t *file,
|
||||
const u8 *buf, size_t buflen)
|
||||
{
|
||||
size_t taglen, len = buflen;
|
||||
const u8 *tag = NULL, *p;
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "processing %d FCI bytes\n", buflen);
|
||||
|
||||
if (buflen < 2)
|
||||
return SC_ERROR_INTERNAL;
|
||||
if (buf[0] != 0x6f)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
len = (size_t)buf[1];
|
||||
if (buflen - 2 < len)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
|
||||
/* defaults */
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
if (len == 0) {
|
||||
SC_FUNC_RETURN(ctx, 2, SC_SUCCESS);
|
||||
}
|
||||
|
||||
p = buf + 2;
|
||||
file->ef_structure = SC_FILE_TYPE_DF;
|
||||
file->shareable = 1;
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
|
||||
if (tag != NULL && taglen > 0 && taglen <= 16) {
|
||||
memcpy(file->name, tag, taglen);
|
||||
file->namelen = taglen;
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "filename %s",
|
||||
sc_dump_hex(file->name, file->namelen));
|
||||
}
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int process_fcp_v3_4(sc_context_t *ctx, sc_file_t *file,
|
||||
const u8 *buf, size_t buflen)
|
||||
{
|
||||
size_t taglen, len = buflen;
|
||||
const u8 *tag = NULL, *p;
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "processing %d FCP bytes\n", buflen);
|
||||
|
||||
if (buflen < 2)
|
||||
return SC_ERROR_INTERNAL;
|
||||
if (buf[0] != 0x62)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
len = (size_t)buf[1];
|
||||
if (buflen - 2 < len)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
p = buf + 2;
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
|
||||
if (tag != NULL && taglen >= 2) {
|
||||
int bytes = (tag[0] << 8) + tag[1];
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
|
||||
" bytes in file: %d\n", bytes);
|
||||
file->size = bytes;
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0xc5, &taglen);
|
||||
if (tag != NULL && taglen >= 2) {
|
||||
int bytes = (tag[0] << 8) + tag[1];
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
|
||||
" bytes in file 2: %d\n", bytes);
|
||||
file->size = bytes;
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
|
||||
if (tag != NULL) {
|
||||
const char *type = "unknown";
|
||||
const char *structure = "unknown";
|
||||
|
||||
if (taglen >= 1) {
|
||||
unsigned char byte = tag[0];
|
||||
if (byte & 0x40) {
|
||||
file->shareable = 1;
|
||||
}
|
||||
if (byte == 0x38) {
|
||||
type = "DF";
|
||||
file->type = SC_FILE_TYPE_DF;
|
||||
file->shareable = 1;
|
||||
}
|
||||
switch (byte & 7) {
|
||||
case 1:
|
||||
/* transparent EF */
|
||||
type = "working EF";
|
||||
structure = "transparent";
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_TRANSPARENT;
|
||||
break;
|
||||
case 2:
|
||||
/* linear fixed EF */
|
||||
type = "working EF";
|
||||
structure = "linear fixed";
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
|
||||
break;
|
||||
case 4:
|
||||
/* linear variable EF */
|
||||
type = "working EF";
|
||||
structure = "linear variable";
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
|
||||
break;
|
||||
case 6:
|
||||
/* cyclic EF */
|
||||
type = "working EF";
|
||||
structure = "cyclic";
|
||||
file->type = SC_FILE_TYPE_WORKING_EF;
|
||||
file->ef_structure = SC_FILE_EF_CYCLIC;
|
||||
break;
|
||||
default:
|
||||
/* use defaults from above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
|
||||
" type: %s\n", type);
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
|
||||
" EF structure: %s\n", structure);
|
||||
if (taglen >= 2) {
|
||||
if (tag[1] != 0x41 || taglen != 5) {
|
||||
SC_FUNC_RETURN(ctx, 2,SC_ERROR_INVALID_DATA);
|
||||
}
|
||||
/* formatted EF */
|
||||
file->record_length = (tag[2] << 8) + tag[3];
|
||||
file->record_count = tag[4];
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
|
||||
" rec_len: %d rec_cnt: %d\n\n",
|
||||
file->record_length, file->record_count);
|
||||
}
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
|
||||
if (tag != NULL && taglen >= 2) {
|
||||
file->id = (tag[0] << 8) | tag[1];
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " file identifier: 0x%02X%02X\n",
|
||||
tag[0], tag[1]);
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
|
||||
if (tag != NULL && taglen > 0 && taglen <= 16) {
|
||||
memcpy(file->name, tag, taglen);
|
||||
file->namelen = taglen;
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " filename %s",
|
||||
sc_dump_hex(file->name, file->namelen));
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x8a, &taglen);
|
||||
if (tag != NULL && taglen == 1) {
|
||||
char* status = "unknown";
|
||||
switch (tag[0]) {
|
||||
case 1:
|
||||
status = "creation";
|
||||
file->status = SC_FILE_STATUS_CREATION;
|
||||
break;
|
||||
case 5:
|
||||
status = "operational active";
|
||||
file->status = SC_FILE_STATUS_ACTIVATED;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
status = "creation";
|
||||
file->status = SC_FILE_STATUS_INVALIDATED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " file status: %s\n", status);
|
||||
}
|
||||
|
||||
file->magic = SC_FILE_MAGIC;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int starcos_select_aid(sc_card_t *card,
|
||||
u8 aid[16], size_t len,
|
||||
sc_file_t **file_out)
|
||||
|
@ -262,12 +476,14 @@ static int starcos_select_aid(sc_card_t *card,
|
|||
|
||||
static int starcos_select_fid(sc_card_t *card,
|
||||
unsigned int id_hi, unsigned int id_lo,
|
||||
sc_file_t **file_out)
|
||||
sc_file_t **file_out, int is_file)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
u8 data[] = {id_hi & 0xff, id_lo & 0xff};
|
||||
u8 resp[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int bIsDF = 0, r;
|
||||
int isFCP = 0;
|
||||
int isMF = 0;
|
||||
|
||||
/* request FCI to distinguish between EFs and DFs */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00);
|
||||
|
@ -279,6 +495,22 @@ static int starcos_select_fid(sc_card_t *card,
|
|||
apdu.data = (u8*)data;
|
||||
apdu.datalen = 2;
|
||||
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
|
||||
if (id_hi == 0x3f && id_lo == 0x0) {
|
||||
apdu.p1 = 0x0;
|
||||
apdu.p2 = 0x0;
|
||||
isMF = 1;
|
||||
} else if (file_out || is_file) {
|
||||
// last component (i.e. file or path)
|
||||
apdu.p1 = 0x2;
|
||||
apdu.p2 = 0x4;
|
||||
} else {
|
||||
// path component
|
||||
apdu.p1 = 0x1;
|
||||
apdu.p2 = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
|
||||
|
@ -291,7 +523,17 @@ static int starcos_select_fid(sc_card_t *card,
|
|||
apdu.le = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU re-transmit failed");
|
||||
} else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)) {
|
||||
} else if (card->type == SC_CARD_TYPE_STARCOS_V3_4 && apdu.p2 == 0x4 && apdu.sw1 == 0x6a && apdu.sw2 == 0x82) {
|
||||
/* not a file, could be a path */
|
||||
bIsDF = 1;
|
||||
apdu.p1 = 0x1;
|
||||
apdu.p2 = 0x0;
|
||||
apdu.resplen = sizeof(resp);
|
||||
apdu.le = 256;
|
||||
apdu.lc = 2;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU re-transmit failed");
|
||||
} else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && !isMF)) {
|
||||
/* SELECT returned some data (possible FCI) =>
|
||||
* try a READ BINARY to see if a EF is selected */
|
||||
sc_apdu_t apdu2;
|
||||
|
@ -303,16 +545,19 @@ static int starcos_select_fid(sc_card_t *card,
|
|||
apdu2.lc = 0;
|
||||
r = sc_transmit_apdu(card, &apdu2);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86)
|
||||
if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86) {
|
||||
/* no current EF is selected => we have a DF */
|
||||
bIsDF = 1;
|
||||
} else {
|
||||
isFCP = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00))
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
|
||||
/* update cache */
|
||||
if (bIsDF) {
|
||||
if (bIsDF || isMF) {
|
||||
card->cache.current_path.type = SC_PATH_TYPE_PATH;
|
||||
card->cache.current_path.value[0] = 0x3f;
|
||||
card->cache.current_path.value[1] = 0x00;
|
||||
|
@ -342,8 +587,18 @@ static int starcos_select_fid(sc_card_t *card,
|
|||
*file_out = file;
|
||||
} else {
|
||||
/* ok, assume we have a EF */
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
|
||||
if (isFCP) {
|
||||
r = process_fcp_v3_4(card->ctx, file, apdu.resp,
|
||||
apdu.resplen);
|
||||
} else {
|
||||
r = process_fci_v3_4(card->ctx, file, apdu.resp,
|
||||
apdu.resplen);
|
||||
}
|
||||
} else {
|
||||
r = process_fci(card->ctx, file, apdu.resp,
|
||||
apdu.resplen);
|
||||
}
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_file_free(file);
|
||||
return r;
|
||||
|
@ -385,7 +640,7 @@ static int starcos_select_file(sc_card_t *card,
|
|||
/* Select with 2byte File-ID */
|
||||
if (pathlen != 2)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS);
|
||||
return starcos_select_fid(card, path[0], path[1], file_out);
|
||||
return starcos_select_fid(card, path[0], path[1], file_out, 1);
|
||||
}
|
||||
else if (in_path->type == SC_PATH_TYPE_DF_NAME)
|
||||
{ /* SELECT DF with AID */
|
||||
|
@ -418,6 +673,8 @@ static int starcos_select_file(sc_card_t *card,
|
|||
if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
if (card->type != SC_CARD_TYPE_STARCOS_V3_4 ||
|
||||
(pathlen == 0 && card->cache.current_path.type != SC_PATH_TYPE_DF_NAME)) {
|
||||
/* unify path (the first FID should be MF) */
|
||||
if (path[0] != 0x3f || path[1] != 0x00)
|
||||
{
|
||||
|
@ -428,6 +685,7 @@ static int starcos_select_file(sc_card_t *card,
|
|||
path = n_pathbuf;
|
||||
pathlen += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* check current working directory */
|
||||
if (card->cache.valid
|
||||
|
@ -440,20 +698,28 @@ static int starcos_select_file(sc_card_t *card,
|
|||
if (card->cache.current_path.value[i] == path[i]
|
||||
&& card->cache.current_path.value[i+1] == path[i+1] )
|
||||
bMatch += 2;
|
||||
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4 &&
|
||||
bMatch > 0 &&
|
||||
(size_t) bMatch < card->cache.current_path.len) {
|
||||
/* we're in the wrong folder, start traversing from root */
|
||||
bMatch = 0;
|
||||
card->cache.current_path.len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( card->cache.valid && bMatch >= 0 )
|
||||
{
|
||||
if ( pathlen - bMatch == 2 )
|
||||
/* we are in the rigth directory */
|
||||
return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out);
|
||||
return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out, 1);
|
||||
else if ( pathlen - bMatch > 2 )
|
||||
{
|
||||
/* two more steps to go */
|
||||
sc_path_t new_path;
|
||||
|
||||
/* first step: change directory */
|
||||
r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL);
|
||||
r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL, 0);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "SELECT FILE (DF-ID) failed");
|
||||
|
||||
memset(&new_path, 0, sizeof(sc_path_t));
|
||||
|
@ -493,10 +759,10 @@ static int starcos_select_file(sc_card_t *card,
|
|||
/* no usable cache */
|
||||
for ( i=0; i<pathlen-2; i+=2 )
|
||||
{
|
||||
r = starcos_select_fid(card, path[i], path[i+1], NULL);
|
||||
r = starcos_select_fid(card, path[i], path[i+1], NULL, 0);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "SELECT FILE (DF-ID) failed");
|
||||
}
|
||||
return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out);
|
||||
return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -681,6 +947,8 @@ static int starcos_create_mf(sc_card_t *card, sc_starcos_create_data *data)
|
|||
sc_apdu_t apdu;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating MF \n");
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
|
||||
apdu.cla |= 0x80;
|
||||
|
@ -710,6 +978,8 @@ static int starcos_create_df(sc_card_t *card, sc_starcos_create_data *data)
|
|||
sc_apdu_t apdu;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating DF\n");
|
||||
/* first step: REGISTER DF */
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "calling REGISTER DF\n");
|
||||
|
@ -753,6 +1023,8 @@ static int starcos_create_ef(sc_card_t *card, sc_starcos_create_data *data)
|
|||
sc_apdu_t apdu;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating EF\n");
|
||||
|
||||
sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x03,0x00);
|
||||
|
@ -784,6 +1056,8 @@ static int starcos_create_end(sc_card_t *card, sc_file_t *file)
|
|||
if (file->type != SC_FILE_TYPE_DF)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
fid[0] = (file->id >> 8) & 0xff;
|
||||
fid[1] = file->id & 0xff;
|
||||
sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00);
|
||||
|
@ -809,6 +1083,8 @@ static int starcos_create_file(sc_card_t *card, sc_file_t *file)
|
|||
int r;
|
||||
sc_starcos_create_data data;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
||||
if (file->type == SC_FILE_TYPE_DF) {
|
||||
|
@ -886,6 +1162,8 @@ static int starcos_write_key(sc_card_t *card, sc_starcos_wkey_data *data)
|
|||
size_t len = sizeof(sbuf), tlen, offset = 0;
|
||||
sc_apdu_t apdu;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
if (data->mode == 0) { /* mode == 0 => install */
|
||||
/* install key header */
|
||||
sbuf[0] = 0xc1; /* key header tag */
|
||||
|
@ -955,6 +1233,9 @@ static int starcos_gen_key(sc_card_t *card, sc_starcos_gen_key_data *data)
|
|||
sc_apdu_t apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
u8 sbuf[2], *p, *q;
|
||||
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
|
||||
/* generate key */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00,
|
||||
data->key_id);
|
||||
|
@ -1021,6 +1302,51 @@ static int starcos_set_security_env(sc_card_t *card,
|
|||
|
||||
p = sbuf;
|
||||
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
|
||||
if (operation != SC_SEC_OPERATION_SIGN) {
|
||||
/* we only support signatures for now */
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"not supported for STARCOS 3.4 cards");
|
||||
return SC_ERROR_NOT_SUPPORTED; \
|
||||
}
|
||||
|
||||
if (!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) ||
|
||||
!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || env->key_ref_len != 1) {
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6);
|
||||
/* don't know what these mean but doesn't matter as card seems to take
|
||||
* algorithm / cipher from PKCS#1 padding prefix */
|
||||
*p++ = 0x84;
|
||||
*p++ = 0x01;
|
||||
*p++ = 0x84;
|
||||
|
||||
/* algorithm / cipher selector? */
|
||||
*p++ = 0x89;
|
||||
*p++ = 0x02;
|
||||
*p++ = 0x13;
|
||||
*p++ = 0x23;
|
||||
|
||||
apdu.data = sbuf;
|
||||
apdu.datalen = p - sbuf;
|
||||
apdu.lc = p - sbuf;
|
||||
apdu.le = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
|
||||
if (env->algorithm_flags == SC_ALGORITHM_RSA_PAD_PKCS1) {
|
||||
// input data will be already padded
|
||||
ex_data->fix_digestInfo = 0;
|
||||
} else {
|
||||
ex_data->fix_digestInfo = env->algorithm_flags;
|
||||
}
|
||||
ex_data->sec_ops = SC_SEC_OPERATION_SIGN;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/* copy key reference, if present */
|
||||
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
|
||||
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
|
||||
|
@ -1148,6 +1474,37 @@ static int starcos_compute_signature(sc_card_t *card,
|
|||
if (ex_data->sec_ops == SC_SEC_OPERATION_SIGN) {
|
||||
/* compute signature with the COMPUTE SIGNATURE command */
|
||||
|
||||
if (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
|
||||
size_t tmp_len;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A,
|
||||
0x9E, 0x9A);
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.le = 0;
|
||||
if (ex_data->fix_digestInfo) {
|
||||
// need to pad data
|
||||
unsigned int flags = ex_data->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;
|
||||
if (flags == 0x00) {
|
||||
flags = SC_ALGORITHM_RSA_HASH_NONE;
|
||||
}
|
||||
tmp_len = sizeof(sbuf);
|
||||
r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf));
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_pkcs1_encode failed");
|
||||
} else {
|
||||
memcpy(sbuf, data, datalen);
|
||||
tmp_len = datalen;
|
||||
}
|
||||
|
||||
apdu.data = sbuf;
|
||||
apdu.datalen = tmp_len;
|
||||
apdu.lc = tmp_len;
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.le = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
} else {
|
||||
/* set the hash value */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A,
|
||||
0x90, 0x81);
|
||||
|
@ -1175,6 +1532,7 @@ static int starcos_compute_signature(sc_card_t *card,
|
|||
apdu.datalen = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
}
|
||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
|
||||
memcpy(out, apdu.resp, len);
|
||||
|
@ -1182,6 +1540,7 @@ static int starcos_compute_signature(sc_card_t *card,
|
|||
}
|
||||
} else if (ex_data->sec_ops == SC_SEC_OPERATION_AUTHENTICATE) {
|
||||
size_t tmp_len;
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
/* call INTERNAL AUTHENTICATE */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x10, 0x00);
|
||||
/* fix/create DigestInfo structure (if necessary) */
|
||||
|
@ -1265,6 +1624,7 @@ static int starcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
|||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
CHECK_NOT_SUPPORTED_V3_4(card);
|
||||
/* get serial number via GET CARD DATA */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00);
|
||||
apdu.cla |= 0x80;
|
||||
|
@ -1341,6 +1701,20 @@ static int starcos_logout(sc_card_t *card)
|
|||
return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
}
|
||||
|
||||
static int starcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||
int *tries_left)
|
||||
{
|
||||
int ret;
|
||||
|
||||
CHECK_ONLY_SUPPORTED_V3_4(card);
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
|
||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||
data->pin1.encoding = SC_PIN_ENCODING_GLP;
|
||||
ret = iso_ops->pin_cmd(card, data, tries_left);
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, ret);
|
||||
}
|
||||
|
||||
static struct sc_card_driver * sc_get_driver(void)
|
||||
{
|
||||
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
|
@ -1359,6 +1733,7 @@ static struct sc_card_driver * sc_get_driver(void)
|
|||
starcos_ops.compute_signature = starcos_compute_signature;
|
||||
starcos_ops.card_ctl = starcos_card_ctl;
|
||||
starcos_ops.logout = starcos_logout;
|
||||
starcos_ops.pin_cmd = starcos_pin_cmd;
|
||||
|
||||
return &starcos_drv;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
@ -161,8 +163,6 @@ static int tcos_construct_fci(const sc_file_t *file,
|
|||
/* Directory name */
|
||||
if (file->type == SC_FILE_TYPE_DF) {
|
||||
if (file->namelen) {
|
||||
if (file->namelen > 16 || !file->name)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
sc_asn1_put_tag(0x84, file->name, file->namelen,
|
||||
p, 16, &p);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
@ -1109,6 +1111,15 @@ static int westcos_sign_decipher(int mode, sc_card_t *card,
|
|||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"westcos_sign_decipher outlen=%d\n", outlen);
|
||||
|
||||
#ifndef ENABLE_OPENSSL
|
||||
r = SC_ERROR_NOT_SUPPORTED;
|
||||
#else
|
||||
if (keyfile == NULL || mem == NULL || card->drv_data == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv_data = (priv_data_t *) card->drv_data;
|
||||
|
||||
if(priv_data->flags & RSA_CRYPTO_COMPONENT)
|
||||
|
@ -1134,14 +1145,6 @@ static int westcos_sign_decipher(int mode, sc_card_t *card,
|
|||
r = apdu.resplen;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_OPENSSL
|
||||
r = SC_ERROR_NOT_SUPPORTED;
|
||||
#else
|
||||
if (keyfile == NULL || mem == NULL || priv_data == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
if ((priv_data->env.flags) & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||
pad = RSA_PKCS1_PADDING;
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -29,6 +31,7 @@
|
|||
|
||||
#include "internal.h"
|
||||
#include "asn1.h"
|
||||
#include "common/compat_strlcpy.h"
|
||||
|
||||
/*
|
||||
#define INVALIDATE_CARD_CACHE_IN_UNLOCK
|
||||
|
@ -94,15 +97,35 @@ static void sc_card_free(sc_card_t *card)
|
|||
{
|
||||
sc_free_apps(card);
|
||||
sc_free_ef_atr(card);
|
||||
|
||||
if (card->ef_dir != NULL)
|
||||
sc_file_free(card->ef_dir);
|
||||
|
||||
free(card->ops);
|
||||
if (card->algorithms != NULL)
|
||||
|
||||
if (card->algorithms != NULL) {
|
||||
int i;
|
||||
for (i=0; i<card->algorithm_count; i++) {
|
||||
struct sc_algorithm_info *info = (card->algorithms + i);
|
||||
if (info->algorithm == SC_ALGORITHM_EC) {
|
||||
struct sc_ec_parameters ep = info->u._ec.params;
|
||||
|
||||
free(ep.named_curve);
|
||||
free(ep.der.value);
|
||||
}
|
||||
}
|
||||
free(card->algorithms);
|
||||
|
||||
card->algorithms = NULL;
|
||||
card->algorithm_count = 0;
|
||||
}
|
||||
|
||||
if (card->cache.current_ef)
|
||||
sc_file_free(card->cache.current_ef);
|
||||
|
||||
if (card->cache.current_df)
|
||||
sc_file_free(card->cache.current_df);
|
||||
|
||||
if (card->mutex != NULL) {
|
||||
int r = sc_mutex_destroy(card->ctx, card->mutex);
|
||||
if (r != SC_SUCCESS)
|
||||
|
@ -169,10 +192,14 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
|
|||
}
|
||||
|
||||
if (driver != NULL) {
|
||||
/* Forced driver, or matched via ATR mapping from
|
||||
* config file */
|
||||
/* Forced driver, or matched via ATR mapping from config file */
|
||||
card->driver = driver;
|
||||
|
||||
memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations));
|
||||
if (card->ops->match_card != NULL)
|
||||
if (card->ops->match_card(card) != 1)
|
||||
sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r));
|
||||
|
||||
if (card->ops->init != NULL) {
|
||||
r = card->ops->init(card);
|
||||
if (r) {
|
||||
|
@ -191,7 +218,8 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
|
|||
if (ops == NULL || ops->match_card == NULL) {
|
||||
continue;
|
||||
}
|
||||
else if (!ctx->enable_default_driver && !strcmp("default", drv->short_name)) {
|
||||
else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER)
|
||||
&& !strcmp("default", drv->short_name)) {
|
||||
sc_log(ctx , "ignore 'default' card driver");
|
||||
continue;
|
||||
}
|
||||
|
@ -222,18 +250,27 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
|
|||
}
|
||||
if (card->name == NULL)
|
||||
card->name = card->driver->name;
|
||||
*card_out = card;
|
||||
|
||||
/* Override card limitations with reader limitations.
|
||||
* Note that zero means no limitations at all.
|
||||
*/
|
||||
if ((card->max_recv_size == 0) ||
|
||||
((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size)))
|
||||
card->max_recv_size = reader->driver->max_recv_size;
|
||||
/* initialize max_send_size/max_recv_size to a meaningfull value */
|
||||
if (card->caps & SC_CARD_CAP_APDU_EXT) {
|
||||
if (!card->max_send_size)
|
||||
card->max_send_size = 65535;
|
||||
if (!card->max_recv_size)
|
||||
card->max_recv_size = 65536;
|
||||
} else {
|
||||
if (!card->max_send_size)
|
||||
card->max_send_size = 255;
|
||||
if (!card->max_recv_size)
|
||||
card->max_recv_size = 256;
|
||||
}
|
||||
|
||||
if ((card->max_send_size == 0) ||
|
||||
((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size)))
|
||||
card->max_send_size = reader->driver->max_send_size;
|
||||
/* Override card limitations with reader limitations. */
|
||||
if (reader->max_recv_size != 0
|
||||
&& (reader->max_recv_size < card->max_recv_size))
|
||||
card->max_recv_size = reader->max_recv_size;
|
||||
if (reader->max_send_size != 0
|
||||
&& (reader->max_send_size < card->max_send_size))
|
||||
card->max_send_size = reader->max_send_size;
|
||||
|
||||
sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i",
|
||||
card->name, card->type, card->flags, card->max_send_size, card->max_recv_size);
|
||||
|
@ -246,6 +283,7 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
|
|||
goto err;
|
||||
}
|
||||
#endif
|
||||
*card_out = card;
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
err:
|
||||
|
@ -334,6 +372,10 @@ int sc_lock(sc_card_t *card)
|
|||
/* invalidate cache */
|
||||
memset(&card->cache, 0, sizeof(card->cache));
|
||||
card->cache.valid = 0;
|
||||
#ifdef ENABLE_SM
|
||||
if (card->sm_ctx.ops.open)
|
||||
card->sm_ctx.ops.open(card);
|
||||
#endif
|
||||
r = card->reader->ops->lock(card->reader);
|
||||
}
|
||||
}
|
||||
|
@ -403,10 +445,11 @@ int sc_create_file(sc_card_t *card, sc_file_t *file)
|
|||
{
|
||||
int r;
|
||||
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
||||
const sc_path_t *in_path = &file->path;
|
||||
const sc_path_t *in_path;
|
||||
|
||||
assert(card != NULL);
|
||||
assert(card != NULL && file != NULL);
|
||||
|
||||
in_path = &file->path;
|
||||
r = sc_path_print(pbuf, sizeof(pbuf), in_path);
|
||||
if (r != SC_SUCCESS)
|
||||
pbuf[0] = '\0';
|
||||
|
@ -446,7 +489,7 @@ int sc_delete_file(sc_card_t *card, const sc_path_t *path)
|
|||
int sc_read_binary(sc_card_t *card, unsigned int idx,
|
||||
unsigned char *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_le = card->max_recv_size > 0 ? card->max_recv_size : 256;
|
||||
size_t max_le = card->max_recv_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -496,7 +539,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx,
|
|||
int sc_write_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255;
|
||||
size_t max_lc = card->max_send_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -539,7 +582,7 @@ int sc_write_binary(sc_card_t *card, unsigned int idx,
|
|||
int sc_update_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255;
|
||||
size_t max_lc = card->max_send_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -800,21 +843,27 @@ int _sc_card_add_algorithm(sc_card_t *card, const sc_algorithm_info_t *info)
|
|||
}
|
||||
|
||||
int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags)
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid)
|
||||
{
|
||||
sc_algorithm_info_t info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
sc_init_oid(&info.u._ec.params.id);
|
||||
|
||||
info.algorithm = SC_ALGORITHM_EC;
|
||||
info.key_length = key_length;
|
||||
info.flags = flags;
|
||||
|
||||
info.u._ec.ext_flags = ext_flags;
|
||||
if (curve_oid)
|
||||
info.u._ec.params.id = *curve_oid;
|
||||
|
||||
return _sc_card_add_algorithm(card, &info);
|
||||
}
|
||||
|
||||
static sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
|
||||
unsigned int algorithm, unsigned int key_length)
|
||||
unsigned int algorithm, unsigned int key_length, void *param)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -825,15 +874,20 @@ static sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
|
|||
continue;
|
||||
if (info->key_length != key_length)
|
||||
continue;
|
||||
if (param) {
|
||||
if (info->algorithm == SC_ALGORITHM_EC)
|
||||
if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
|
||||
continue;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc_algorithm_info_t * sc_card_find_ec_alg(sc_card_t *card,
|
||||
unsigned int key_length)
|
||||
unsigned int key_length, struct sc_object_id *curve_name)
|
||||
{
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length);
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length, curve_name);
|
||||
}
|
||||
|
||||
int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
|
||||
|
@ -853,25 +907,27 @@ int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
|
|||
sc_algorithm_info_t * sc_card_find_rsa_alg(sc_card_t *card,
|
||||
unsigned int key_length)
|
||||
{
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_RSA, key_length);
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_RSA, key_length, NULL);
|
||||
}
|
||||
|
||||
sc_algorithm_info_t * sc_card_find_gostr3410_alg(sc_card_t *card,
|
||||
unsigned int key_length)
|
||||
{
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_GOSTR3410, key_length);
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_GOSTR3410, key_length, NULL);
|
||||
}
|
||||
|
||||
static int match_atr_table(sc_context_t *ctx, struct sc_atr_table *table, struct sc_atr *atr)
|
||||
{
|
||||
u8 *card_atr_bin = atr->value;
|
||||
size_t card_atr_bin_len = atr->len;
|
||||
u8 *card_atr_bin;
|
||||
size_t card_atr_bin_len;
|
||||
char card_atr_hex[3 * SC_MAX_ATR_SIZE];
|
||||
size_t card_atr_hex_len;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (ctx == NULL || table == NULL || atr == NULL)
|
||||
return -1;
|
||||
card_atr_bin = atr->value;
|
||||
card_atr_bin_len = atr->len;
|
||||
sc_bin_to_hex(card_atr_bin, card_atr_bin_len, card_atr_hex, sizeof(card_atr_hex), ':');
|
||||
card_atr_hex_len = strlen(card_atr_hex);
|
||||
|
||||
|
@ -1075,6 +1131,31 @@ void sc_print_cache(struct sc_card *card) {
|
|||
sc_print_path(&card->cache.current_df->path));
|
||||
}
|
||||
|
||||
int sc_copy_ec_params(struct sc_ec_parameters *dst, struct sc_ec_parameters *src)
|
||||
{
|
||||
if (!dst || !src)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
if (src->named_curve) {
|
||||
dst->named_curve = strdup(src->named_curve);
|
||||
if (!dst->named_curve)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
dst->id = src->id;
|
||||
if (src->der.value && src->der.len) {
|
||||
dst->der.value = malloc(src->der.len);
|
||||
if (!dst->der.value)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(dst->der.value, src->der.value, src->der.len);
|
||||
dst->der.len = src->der.len;
|
||||
}
|
||||
src->type = dst->type;
|
||||
src->field_length = dst->field_length;
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
scconf_block *
|
||||
sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *driver, struct sc_atr *atr)
|
||||
{
|
||||
|
@ -1119,20 +1200,20 @@ sc_card_sm_load(struct sc_card *card, const char *module_path, const char *in_mo
|
|||
|
||||
#ifdef _WIN32
|
||||
if (!module_path) {
|
||||
rc = RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
rc = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
if( rc == ERROR_SUCCESS ) {
|
||||
temp_len = PATH_MAX;
|
||||
rc = RegQueryValueEx( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
rc = RegQueryValueExA( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) )
|
||||
module_path = temp_path;
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
}
|
||||
if (!module_path) {
|
||||
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
rc = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
if( rc == ERROR_SUCCESS ) {
|
||||
temp_len = PATH_MAX;
|
||||
rc = RegQueryValueEx( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
rc = RegQueryValueExA( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
if(rc == ERROR_SUCCESS && temp_len < PATH_MAX)
|
||||
module_path = temp_path;
|
||||
RegCloseKey( hKey );
|
||||
|
@ -1255,8 +1336,8 @@ sc_card_sm_check(struct sc_card *card)
|
|||
rv = sc_card_sm_load(card, module_path, module_name);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to load SM module");
|
||||
|
||||
strncpy(card->sm_ctx.module.filename, module_name, sizeof(card->sm_ctx.module.filename));
|
||||
strncpy(card->sm_ctx.config_section, sm, sizeof(card->sm_ctx.config_section));
|
||||
strlcpy(card->sm_ctx.module.filename, module_name, sizeof(card->sm_ctx.module.filename));
|
||||
strlcpy(card->sm_ctx.config_section, sm, sizeof(card->sm_ctx.config_section));
|
||||
|
||||
/* allocate resources for the external SM module */
|
||||
sc_log(ctx, "'module_init' handler %p", card->sm_ctx.module.ops.module_init);
|
||||
|
|
|
@ -255,7 +255,14 @@ enum {
|
|||
*/
|
||||
SC_CARDCTL_DNIE_BASE = _CTL_PREFIX('D', 'N', 'I'),
|
||||
SC_CARDCTL_DNIE_GENERATE_KEY,
|
||||
SC_CARDCTL_DNIE_GET_INFO
|
||||
SC_CARDCTL_DNIE_GET_INFO,
|
||||
|
||||
/*
|
||||
* isoApplet Java Card Applet
|
||||
*/
|
||||
SC_CARDCTL_ISOAPPLET_BASE = _CTL_PREFIX('I','S','O'),
|
||||
SC_CARDCTL_ISOAPPLET_GENERATE_KEY,
|
||||
SC_CARDCTL_ISOAPPLET_IMPORT_KEY
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -832,10 +839,7 @@ typedef struct sc_rtecp_genkey_data {
|
|||
*/
|
||||
enum SC_CARDCTL_MYEID_KEY_TYPE {
|
||||
SC_CARDCTL_MYEID_KEY_RSA = 0x11,
|
||||
SC_CARDCTL_MYEID_KEY_EC = 0x21,
|
||||
/* SC_CARDCTL_MYEID_KEY_AES = 0x?, // for future use
|
||||
SC_CARDCTL_MYEID_KEY_DES = 0x?,
|
||||
SC_CARDCTL_MYEID_KEY_3DES = 0x?, */
|
||||
SC_CARDCTL_MYEID_KEY_EC = 0x22
|
||||
};
|
||||
|
||||
struct sc_cardctl_myeid_data_obj {
|
||||
|
@ -939,7 +943,7 @@ typedef struct sc_cardctl_sc_hsm_init_param {
|
|||
size_t user_pin_len; /* Length of user PIN */
|
||||
u8 user_pin_retry_counter; /* Retry counter default value */
|
||||
u8 options[2]; /* Initialization options */
|
||||
char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */
|
||||
signed char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */
|
||||
char *label; /* Token label to be set in EF.TokenInfo (2F03) */
|
||||
} sc_cardctl_sc_hsm_init_param_t;
|
||||
|
||||
|
@ -957,6 +961,59 @@ typedef struct sc_cardctl_sc_hsm_wrapped_key {
|
|||
size_t wrapped_key_length; /* Length of key blob */
|
||||
} sc_cardctl_sc_hsm_wrapped_key_t;
|
||||
|
||||
/*
|
||||
* isoApplet
|
||||
*/
|
||||
|
||||
#define SC_ISOAPPLET_ALG_REF_RSA_GEN_2048 0xF3
|
||||
#define SC_ISOAPPLET_ALG_REF_EC_GEN 0xEC
|
||||
|
||||
typedef struct sc_cardctl_isoApplet_ec_parameters {
|
||||
struct sc_lv_data prime;
|
||||
struct sc_lv_data coefficientA;
|
||||
struct sc_lv_data coefficientB;
|
||||
struct sc_lv_data basePointG;
|
||||
struct sc_lv_data order;
|
||||
struct sc_lv_data coFactor;
|
||||
} sc_cardctl_isoApplet_ec_parameters_t;
|
||||
|
||||
typedef struct sc_cardctl_isoApplet_genkey {
|
||||
u8 algorithm_ref; /* Algorithm reference sent to card */
|
||||
unsigned int priv_key_ref; /* Private key refernce sent to card */
|
||||
union {
|
||||
struct
|
||||
{
|
||||
struct sc_lv_data modulus;
|
||||
struct sc_lv_data exponent;
|
||||
} rsa;
|
||||
struct
|
||||
{
|
||||
sc_cardctl_isoApplet_ec_parameters_t params;
|
||||
struct sc_lv_data ecPointQ;
|
||||
} ec;
|
||||
} pubkey;
|
||||
} sc_cardctl_isoApplet_genkey_t;
|
||||
|
||||
typedef struct sc_cardctl_isoApplet_import_key {
|
||||
u8 algorithm_ref; /* Algorithm reference sent to card */
|
||||
unsigned int priv_key_ref; /* Private key refernce sent to card */
|
||||
union {
|
||||
struct
|
||||
{
|
||||
struct sc_lv_data p;
|
||||
struct sc_lv_data q;
|
||||
struct sc_lv_data iqmp;
|
||||
struct sc_lv_data dmp1;
|
||||
struct sc_lv_data dmq1;
|
||||
} rsa;
|
||||
struct
|
||||
{
|
||||
sc_cardctl_isoApplet_ec_parameters_t params;
|
||||
struct sc_lv_data privateD;
|
||||
} ec;
|
||||
} privkey;
|
||||
} sc_cardctl_isoApplet_import_key_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -94,6 +94,7 @@ enum {
|
|||
/* starcos driver */
|
||||
SC_CARD_TYPE_STARCOS_BASE = 7000,
|
||||
SC_CARD_TYPE_STARCOS_GENERIC,
|
||||
SC_CARD_TYPE_STARCOS_V3_4,
|
||||
|
||||
/* tcos driver */
|
||||
SC_CARD_TYPE_TCOS_BASE = 8000,
|
||||
|
@ -140,6 +141,7 @@ enum {
|
|||
SC_CARD_TYPE_MUSCLE_V2,
|
||||
SC_CARD_TYPE_MUSCLE_ETOKEN_72K,
|
||||
SC_CARD_TYPE_MUSCLE_JCOP241,
|
||||
SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU,
|
||||
|
||||
/* ACOS5 driver */
|
||||
SC_CARD_TYPE_ACOS5_BASE = 16000,
|
||||
|
@ -191,6 +193,7 @@ enum {
|
|||
SC_CARD_TYPE_IASECC_OBERTHUR,
|
||||
SC_CARD_TYPE_IASECC_SAGEM,
|
||||
SC_CARD_TYPE_IASECC_AMOS,
|
||||
SC_CARD_TYPE_IASECC_MI,
|
||||
|
||||
/* SmartCard-HSM */
|
||||
SC_CARD_TYPE_SC_HSM = 26000,
|
||||
|
@ -200,7 +203,15 @@ enum {
|
|||
SC_CARD_TYPE_DNIE_BLANK, /* ATR LC byte: 00 */
|
||||
SC_CARD_TYPE_DNIE_ADMIN, /* ATR LC byte: 01 */
|
||||
SC_CARD_TYPE_DNIE_USER, /* ATR LC byte: 03 */
|
||||
SC_CARD_TYPE_DNIE_TERMINATED /* ATR LC byte: 0F */
|
||||
SC_CARD_TYPE_DNIE_TERMINATED, /* ATR LC byte: 0F */
|
||||
|
||||
/* JavaCards with isoApplet */
|
||||
SC_CARD_TYPE_ISO_APPLET_BASE = 28000,
|
||||
SC_CARD_TYPE_ISO_APPLET_GENERIC,
|
||||
|
||||
/* Masktech cards */
|
||||
SC_CARD_TYPE_MASKTECH_BASE = 29000,
|
||||
SC_CARD_TYPE_MASKTECH_GENERIC
|
||||
};
|
||||
|
||||
extern sc_card_driver_t *sc_get_default_driver(void);
|
||||
|
@ -237,6 +248,8 @@ extern sc_card_driver_t *sc_get_authentic_driver(void);
|
|||
extern sc_card_driver_t *sc_get_iasecc_driver(void);
|
||||
extern sc_card_driver_t *sc_get_epass2003_driver(void);
|
||||
extern sc_card_driver_t *sc_get_dnie_driver(void);
|
||||
extern sc_card_driver_t *sc_get_isoApplet_driver(void);
|
||||
extern sc_card_driver_t *sc_get_masktech_driver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ZLIB /* empty file without zlib */
|
||||
#include <zlib.h>
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -45,7 +47,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d
|
|||
{
|
||||
const char *prompt;
|
||||
size_t buflen, count = 0, j = 0, len;
|
||||
static u8 buf[254];
|
||||
static u8 buf[256];
|
||||
u8 control;
|
||||
|
||||
ctbcs_init_apdu(apdu,
|
||||
|
@ -58,7 +60,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d
|
|||
prompt = data->pin1.prompt;
|
||||
if (prompt && *prompt) {
|
||||
len = strlen(prompt);
|
||||
if (count + len + 2 > buflen || len > 255)
|
||||
if (len + 2 > buflen)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
buf[count++] = CTBCS_TAG_PROMPT;
|
||||
buf[count++] = len;
|
||||
|
@ -113,7 +115,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da
|
|||
{
|
||||
const char *prompt;
|
||||
size_t buflen, count = 0, j = 0, len;
|
||||
static u8 buf[254];
|
||||
static u8 buf[256];
|
||||
u8 control;
|
||||
|
||||
ctbcs_init_apdu(apdu,
|
||||
|
@ -126,7 +128,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da
|
|||
prompt = data->pin1.prompt;
|
||||
if (prompt && *prompt) {
|
||||
len = strlen(prompt);
|
||||
if (count + len + 2 > buflen || len > 255)
|
||||
if (len + 2 > buflen)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
buf[count++] = CTBCS_TAG_PROMPT;
|
||||
buf[count++] = len;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -70,7 +72,6 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
|||
#endif
|
||||
{ "gemsafeV1", (void *(*)(void)) sc_get_gemsafeV1_driver },
|
||||
{ "miocos", (void *(*)(void)) sc_get_miocos_driver },
|
||||
{ "mcrd", (void *(*)(void)) sc_get_mcrd_driver },
|
||||
{ "asepcos", (void *(*)(void)) sc_get_asepcos_driver },
|
||||
{ "starcos", (void *(*)(void)) sc_get_starcos_driver },
|
||||
{ "tcos", (void *(*)(void)) sc_get_tcos_driver },
|
||||
|
@ -100,14 +101,17 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
|
|||
#ifdef ENABLE_OPENSSL
|
||||
{ "dnie", (void *(*)(void)) sc_get_dnie_driver },
|
||||
#endif
|
||||
{ "masktech", (void *(*)(void)) sc_get_masktech_driver },
|
||||
|
||||
/* Here should be placed drivers that need some APDU transactions to
|
||||
* recognise its cards. */
|
||||
{ "mcrd", (void *(*)(void)) sc_get_mcrd_driver },
|
||||
{ "setcos", (void *(*)(void)) sc_get_setcos_driver },
|
||||
{ "muscle", (void *(*)(void)) sc_get_muscle_driver },
|
||||
{ "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
|
||||
{ "PIV-II", (void *(*)(void)) sc_get_piv_driver },
|
||||
{ "itacns", (void *(*)(void)) sc_get_itacns_driver },
|
||||
{ "isoApplet", (void *(*)(void)) sc_get_isoApplet_driver },
|
||||
/* The default driver should be last, as it handles all the
|
||||
* unrecognized cards. */
|
||||
{ "default", (void *(*)(void)) sc_get_default_driver },
|
||||
|
@ -182,8 +186,7 @@ static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
|||
if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout))
|
||||
fclose(ctx->debug_file);
|
||||
ctx->debug_file = stderr;
|
||||
ctx->paranoid_memory = 0;
|
||||
ctx->enable_default_driver = 0;
|
||||
ctx->flags = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* Override the default debug log for OpenSC.tokend to be different from PKCS#11.
|
||||
|
@ -244,7 +247,7 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *
|
|||
if (val) {
|
||||
#ifdef _WIN32
|
||||
expanded_len = PATH_MAX;
|
||||
expanded_len = ExpandEnvironmentStrings(val, expanded_val, expanded_len);
|
||||
expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len);
|
||||
if (expanded_len > 0)
|
||||
val = expanded_val;
|
||||
#endif
|
||||
|
@ -254,11 +257,13 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *
|
|||
sc_ctx_log_to_file(ctx, val);
|
||||
}
|
||||
|
||||
ctx->paranoid_memory = scconf_get_bool (block, "paranoid-memory",
|
||||
ctx->paranoid_memory);
|
||||
if (scconf_get_bool (block, "paranoid-memory",
|
||||
ctx->flags & SC_CTX_FLAG_PARANOID_MEMORY))
|
||||
ctx->flags |= SC_CTX_FLAG_PARANOID_MEMORY;
|
||||
|
||||
ctx->enable_default_driver = scconf_get_bool (block, "enable_default_driver",
|
||||
ctx->enable_default_driver);
|
||||
if (scconf_get_bool (block, "enable_default_driver",
|
||||
ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER))
|
||||
ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;
|
||||
|
||||
val = scconf_get_str(block, "force_card_driver", NULL);
|
||||
if (val) {
|
||||
|
@ -285,15 +290,28 @@ static void load_reader_driver_options(sc_context_t *ctx)
|
|||
{
|
||||
struct sc_reader_driver *driver = ctx->reader_driver;
|
||||
scconf_block *conf_block = NULL;
|
||||
|
||||
driver->max_send_size = 0;
|
||||
driver->max_recv_size = 0;
|
||||
sc_reader_t *reader;
|
||||
int max_send_size;
|
||||
int max_recv_size;
|
||||
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", driver->short_name, 1);
|
||||
|
||||
if (conf_block != NULL) {
|
||||
driver->max_send_size = scconf_get_int(conf_block, "max_send_size", driver->max_send_size);
|
||||
driver->max_recv_size = scconf_get_int(conf_block, "max_recv_size", driver->max_recv_size);
|
||||
max_send_size = scconf_get_int(conf_block, "max_send_size", -1);
|
||||
max_recv_size = scconf_get_int(conf_block, "max_recv_size", -1);
|
||||
if (max_send_size >= 0 || max_recv_size >= 0) {
|
||||
if (list_iterator_start(&ctx->readers)) {
|
||||
reader = list_iterator_next(&ctx->readers);
|
||||
while (reader) {
|
||||
if (max_send_size >= 0)
|
||||
reader->max_send_size = max_send_size;
|
||||
if (max_recv_size >= 0)
|
||||
reader->max_recv_size = max_recv_size;
|
||||
reader = list_iterator_next(&ctx->readers);
|
||||
}
|
||||
list_iterator_stop(&ctx->readers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +569,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
|||
#ifdef _WIN32
|
||||
conf_path = getenv("OPENSC_CONF");
|
||||
if (!conf_path) {
|
||||
rc = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey);
|
||||
rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey);
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
temp_len = PATH_MAX;
|
||||
rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
|
@ -562,7 +580,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
|
|||
}
|
||||
|
||||
if (!conf_path) {
|
||||
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
rc = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey );
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
temp_len = PATH_MAX;
|
||||
rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len);
|
||||
|
@ -706,7 +724,9 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
|
|||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ctx->flags = parm->flags;
|
||||
set_defaults(ctx, &opts);
|
||||
|
||||
list_init(&ctx->readers);
|
||||
list_attributes_seeker(&ctx->readers, reader_list_seeker);
|
||||
/* set thread context and create mutex object (if specified) */
|
||||
|
@ -735,7 +755,6 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
|
|||
ctx->reader_driver = sc_get_openct_driver();
|
||||
#endif
|
||||
|
||||
load_reader_driver_options(ctx);
|
||||
r = ctx->reader_driver->ops->init(ctx);
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_release_context(ctx);
|
||||
|
@ -751,6 +770,7 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
|
|||
}
|
||||
del_drvs(&opts);
|
||||
sc_ctx_detect_readers(ctx);
|
||||
load_reader_driver_options(ctx);
|
||||
*ctx_out = ctx;
|
||||
|
||||
return SC_SUCCESS;
|
||||
|
@ -840,7 +860,7 @@ int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
|
|||
if (short_name == NULL) {
|
||||
ctx->forced_driver = NULL;
|
||||
match = 1;
|
||||
} else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) {
|
||||
} else while (i < SC_MAX_CARD_DRIVERS && ctx->card_drivers[i] != NULL) {
|
||||
struct sc_card_driver *drv = ctx->card_drivers[i];
|
||||
|
||||
if (strcmp(short_name, drv->short_name) == 0) {
|
||||
|
@ -873,7 +893,7 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
|
|||
/* If USERPROFILE isn't defined, assume it's a single-user OS
|
||||
* and put the cache dir in the Windows dir (usually C:\\WINDOWS) */
|
||||
if (homedir == NULL || homedir[0] == '\0') {
|
||||
GetWindowsDirectory(temp_path, sizeof(temp_path));
|
||||
GetWindowsDirectoryA(temp_path, sizeof(temp_path));
|
||||
homedir = temp_path;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#define MAX_RESP_BUFFER_SIZE 2048
|
||||
|
||||
/********************* Keys and certificates as published by DGP ********/
|
||||
|
||||
/**
|
||||
|
@ -209,7 +211,7 @@ int dnie_read_file(sc_card_t * card,
|
|||
const sc_path_t * path,
|
||||
sc_file_t ** file, u8 ** buffer, size_t * length)
|
||||
{
|
||||
u8 *data;
|
||||
u8 *data = NULL;
|
||||
char *msg = NULL;
|
||||
int res = SC_SUCCESS;
|
||||
size_t fsize = 0; /* file size */
|
||||
|
@ -265,8 +267,12 @@ int dnie_read_file(sc_card_t * card,
|
|||
res = SC_SUCCESS;
|
||||
goto dnie_read_file_end;
|
||||
dnie_read_file_err:
|
||||
if (*file)
|
||||
if (data)
|
||||
free(data);
|
||||
if (*file) {
|
||||
sc_file_free(*file);
|
||||
*file = NULL;
|
||||
}
|
||||
dnie_read_file_end:
|
||||
if (msg)
|
||||
sc_log(ctx, msg);
|
||||
|
@ -287,39 +293,37 @@ int dnie_read_file(sc_card_t * card,
|
|||
static int dnie_read_certificate(sc_card_t * card, char *certpath, X509 ** cert)
|
||||
{
|
||||
sc_file_t *file = NULL;
|
||||
sc_path_t *path = NULL;
|
||||
u8 *buffer = NULL;
|
||||
sc_path_t path;
|
||||
u8 *buffer = NULL, *buffer2 = NULL;
|
||||
char *msg = NULL;
|
||||
size_t bufferlen = 0;
|
||||
int res = SC_SUCCESS;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
path = (sc_path_t *) calloc(1, sizeof(sc_path_t));
|
||||
if (!path) {
|
||||
msg = "Cannot allocate path data for cert read";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto read_cert_end;
|
||||
}
|
||||
sc_format_path(certpath, path);
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
sc_format_path(certpath, &path);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot get intermediate CA cert";
|
||||
goto read_cert_end;
|
||||
}
|
||||
*cert = d2i_X509(NULL, (const unsigned char **)&buffer, bufferlen);
|
||||
buffer2 = buffer;
|
||||
*cert = d2i_X509(NULL, (const unsigned char **)&buffer2, bufferlen);
|
||||
if (*cert == NULL) { /* received data is not a certificate */
|
||||
res = SC_ERROR_OBJECT_NOT_VALID;
|
||||
msg = "Readed data is not a certificate";
|
||||
msg = "Read data is not a certificate";
|
||||
goto read_cert_end;
|
||||
}
|
||||
res = SC_SUCCESS;
|
||||
|
||||
read_cert_end:
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (msg)
|
||||
sc_log(card->ctx, msg);
|
||||
|
@ -688,16 +692,14 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
|
|||
|
||||
static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
||||
{
|
||||
u8 *buf = NULL; /* use for store partial le responses */
|
||||
u8 buf[MAX_RESP_BUFFER_SIZE]; /* use for store partial le responses */
|
||||
int res = SC_SUCCESS;
|
||||
cwa_provider_t *provider = NULL;
|
||||
if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL))
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
|
||||
buf = calloc(2048, sizeof(u8));
|
||||
if (!buf)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* check if envelope is needed */
|
||||
if (apdu->lc <= card->max_send_size) {
|
||||
|
@ -711,8 +713,10 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
if (tmp == SC_APDU_CASE_3_SHORT)
|
||||
apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||
if (apdu->resplen == 0) { /* no response buffer: create */
|
||||
apdu->resp = buf;
|
||||
apdu->resplen = 2048;
|
||||
apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE);
|
||||
if (apdu->resp == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
apdu->resplen = MAX_RESP_BUFFER_SIZE;
|
||||
apdu->le = card->max_recv_size;
|
||||
}
|
||||
}
|
||||
|
@ -724,15 +728,15 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
|
||||
size_t e_txlen = 0;
|
||||
size_t index = 0;
|
||||
sc_apdu_t *e_apdu = NULL;
|
||||
u8 *e_tx = NULL;
|
||||
sc_apdu_t e_apdu;
|
||||
u8 * e_tx = NULL;
|
||||
|
||||
/* envelope needed */
|
||||
sc_log(card->ctx, "envelope tx required: lc:%d", apdu->lc);
|
||||
|
||||
e_apdu = calloc(1, sizeof(sc_apdu_t)); /* enveloped apdu */
|
||||
e_tx = calloc(7 + apdu->datalen, sizeof(u8)); /* enveloped data */
|
||||
if (!e_apdu || !e_tx)
|
||||
|
||||
if (!e_tx)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
/* copy apdu info into enveloped data */
|
||||
|
@ -753,35 +757,47 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
index, len);
|
||||
|
||||
/* compose envelope apdu command */
|
||||
sc_format_apdu(card, e_apdu, apdu->cse, 0xC2, 0x00,
|
||||
0x00);
|
||||
e_apdu->cla = 0x90; /* propietary CLA */
|
||||
e_apdu->data = e_tx + index;
|
||||
e_apdu->lc = len;
|
||||
e_apdu->datalen = len;
|
||||
e_apdu->le = apdu->le;
|
||||
e_apdu->resp = apdu->resp;
|
||||
e_apdu->resplen = apdu->resplen;
|
||||
sc_format_apdu(card, &e_apdu, apdu->cse, 0xC2, 0x00, 0x00);
|
||||
e_apdu.cla = 0x90; /* propietary CLA */
|
||||
e_apdu.data = e_tx + index;
|
||||
e_apdu.lc = len;
|
||||
e_apdu.datalen = len;
|
||||
e_apdu.le = apdu->le;
|
||||
e_apdu.resp = apdu->resp;
|
||||
e_apdu.resplen = apdu->resplen;
|
||||
/* if SM is ON, ensure resp exists, and force getResponse() */
|
||||
if (provider->status.session.state == CWA_SM_ACTIVE) {
|
||||
/* set up proper apdu type */
|
||||
if (e_apdu->cse == SC_APDU_CASE_3_SHORT)
|
||||
e_apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||
if (e_apdu.cse == SC_APDU_CASE_3_SHORT)
|
||||
e_apdu.cse = SC_APDU_CASE_4_SHORT;
|
||||
/* if no response buffer: create */
|
||||
if (apdu->resplen == 0) {
|
||||
e_apdu->resp = buf;
|
||||
e_apdu->resplen = 2048;
|
||||
e_apdu->le = card->max_recv_size;
|
||||
e_apdu.resp = buf;
|
||||
e_apdu.resplen = 2048;
|
||||
e_apdu.le = card->max_recv_size;
|
||||
}
|
||||
}
|
||||
/* send data chunk bypassing apdu wrapping */
|
||||
res = sc_transmit_apdu(card, e_apdu);
|
||||
LOG_TEST_RET(card->ctx, res,
|
||||
"Error in envelope() send apdu");
|
||||
res = sc_transmit_apdu(card, &e_apdu);
|
||||
if (res != SC_SUCCESS) {
|
||||
if (e_tx) {
|
||||
free(e_tx);
|
||||
e_tx = NULL;
|
||||
}
|
||||
sc_log(card->ctx, "Error in envelope() send apdu");
|
||||
LOG_FUNC_RETURN(card->ctx, res);
|
||||
}
|
||||
} /* for */
|
||||
if (e_tx) {
|
||||
free(e_tx);
|
||||
e_tx = NULL;
|
||||
}
|
||||
/* last apdu sent contains response to enveloped cmd */
|
||||
apdu->resp = e_apdu->resp;
|
||||
apdu->resplen = e_apdu->resplen;
|
||||
apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE);
|
||||
if (apdu->resp == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
memcpy(apdu->resp, e_apdu.resp, e_apdu.resplen);
|
||||
apdu->resplen = e_apdu.resplen;
|
||||
res = SC_SUCCESS;
|
||||
}
|
||||
LOG_FUNC_RETURN(card->ctx, res);
|
||||
|
@ -817,6 +833,7 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
sc_context_t *ctx;
|
||||
cwa_provider_t *provider = NULL;
|
||||
int retries = 3;
|
||||
char * msg = NULL;
|
||||
|
||||
if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL))
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
@ -831,13 +848,18 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
wrapped.resp = NULL;
|
||||
wrapped.resplen = 0; /* let get_response() assign space */
|
||||
res = cwa_encode_apdu(card, provider, apdu, &wrapped);
|
||||
LOG_TEST_RET(ctx, res,
|
||||
"Error in cwa_encode_apdu process");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Error in cwa_encode_apdu process";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
}
|
||||
/* send apdu via envelope() cmd if needed */
|
||||
res = dnie_transmit_apdu_internal(card, &wrapped);
|
||||
/* check for tx errors */
|
||||
LOG_TEST_RET(ctx, res, "Error in dnie_transmit_apdu process");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Error in dnie_transmit_apdu process";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
|
||||
/* parse response and handle SM related errors */
|
||||
res=card->ops->check_sw(card,wrapped.sw1,wrapped.sw2);
|
||||
|
@ -852,7 +874,10 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
/* SM was active: force restart SM and retry */
|
||||
case CWA_SM_ACTIVE:
|
||||
res=cwa_create_secure_channel(card, provider, CWA_SM_COLD);
|
||||
LOG_TEST_RET(ctx,res,"Cannot re-enable SM");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot re-enable SM";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -862,15 +887,24 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
apdu->resp = NULL;
|
||||
apdu->resplen = 0; /* let cwa_decode_response() eval & create size */
|
||||
res = cwa_decode_response(card, provider, &wrapped, apdu);
|
||||
LOG_TEST_RET(ctx, res, "Error in cwa_decode_response process");
|
||||
if (res != SC_SUCCESS)
|
||||
msg = "Error in cwa_decode_response process";
|
||||
goto cleanup_and_return;
|
||||
} else {
|
||||
if (apdu->resp != wrapped.resp) free(apdu->resp);
|
||||
/* memcopy result to original apdu */
|
||||
memcpy(apdu, &wrapped, sizeof(sc_apdu_t));
|
||||
}
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
sc_log(ctx,"Too many retransmissions. Abort and return");
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
||||
}
|
||||
msg = "Too many retransmissions. Abort and return";
|
||||
res = SC_ERROR_INTERNAL;
|
||||
|
||||
cleanup_and_return:
|
||||
if (apdu->resp != wrapped.resp) free(wrapped.resp);
|
||||
if (msg)
|
||||
sc_log(ctx, msg);
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
|
||||
int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
||||
|
|
|
@ -43,6 +43,23 @@
|
|||
|
||||
#include "cwa14890.h"
|
||||
|
||||
/**
|
||||
* Structure used to compose BER-TLV encoded data
|
||||
* according to iso7816-4 sect 5.2.2.
|
||||
*
|
||||
* Notice that current implementation does not handle properly
|
||||
* multibyte tag id. Just asume that tag is 1-byte length
|
||||
* Also, encodings for data length longer than 0x01000000 bytes
|
||||
* are not supported (tag 0x84)
|
||||
*/
|
||||
typedef struct cwa_tlv_st {
|
||||
u8 *buf; /** local copy of TLV byte array */
|
||||
size_t buflen; /** lengt of buffer */
|
||||
unsigned int tag; /** tag ID */
|
||||
size_t len; /** length of data field */
|
||||
u8 *data; /** pointer to start of data in buf buffer */
|
||||
} cwa_tlv_t;
|
||||
|
||||
/*********************** utility functions ************************/
|
||||
|
||||
/**
|
||||
|
@ -242,13 +259,13 @@ static int cwa_compose_tlv(sc_card_t * card,
|
|||
* @return SC_SUCCESS if OK; else error code
|
||||
*/
|
||||
static int cwa_parse_tlv(sc_card_t * card,
|
||||
u8 * data, size_t datalen, cwa_tlv_t tlv_array[]
|
||||
u8 * buffer, size_t datalen,
|
||||
cwa_tlv_t tlv_array[]
|
||||
)
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t next = 0;
|
||||
sc_context_t *ctx = NULL;
|
||||
u8 *buffer = NULL;
|
||||
|
||||
/* preliminary checks */
|
||||
if (!card || !card->ctx)
|
||||
|
@ -257,14 +274,9 @@ static int cwa_parse_tlv(sc_card_t * card,
|
|||
ctx = card->ctx;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
if (!data || !tlv_array)
|
||||
if (!tlv_array)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
/* create buffer and copy data into */
|
||||
buffer = calloc(datalen, sizeof(u8));
|
||||
if (!buffer)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
memcpy(buffer, data, datalen);
|
||||
for (n = 0; n < datalen; n += next) {
|
||||
cwa_tlv_t *tlv = NULL; /* pointer to TLV structure to store info */
|
||||
size_t j = 2; /* TLV has at least two bytes */
|
||||
|
@ -1385,6 +1397,10 @@ int cwa_create_secure_channel(sc_card_t * card,
|
|||
/* arriving here means ok: cleanup */
|
||||
res = SC_SUCCESS;
|
||||
csc_end:
|
||||
if (icc_cert)
|
||||
X509_free(icc_cert);
|
||||
if (ca_cert)
|
||||
X509_free(ca_cert);
|
||||
if (icc_pubkey)
|
||||
EVP_PKEY_free(icc_pubkey);
|
||||
if (ifd_privkey)
|
||||
|
@ -1418,9 +1434,9 @@ int cwa_create_secure_channel(sc_card_t * card,
|
|||
int cwa_encode_apdu(sc_card_t * card,
|
||||
cwa_provider_t * provider, sc_apdu_t * from, sc_apdu_t * to)
|
||||
{
|
||||
u8 *apdubuf; /* to store resulting apdu */
|
||||
u8 *apdubuf = NULL; /* to store resulting apdu */
|
||||
size_t apdulen;
|
||||
u8 *ccbuf; /* where to store data to eval cryptographic checksum CC */
|
||||
u8 *ccbuf = NULL; /* where to store data to eval cryptographic checksum CC */
|
||||
size_t cclen = 0;
|
||||
u8 macbuf[8]; /* to store and compute CC */
|
||||
DES_key_schedule k1;
|
||||
|
@ -1434,10 +1450,6 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
u8 *msgbuf = NULL; /* to encrypt apdu data */
|
||||
u8 *cryptbuf = NULL;
|
||||
|
||||
/* reserve extra bytes for padding and tlv header */
|
||||
msgbuf = calloc(12 + from->lc, sizeof(u8)); /* to encrypt apdu data */
|
||||
cryptbuf = calloc(12 + from->lc, sizeof(u8));
|
||||
|
||||
/* mandatory check */
|
||||
if (!card || !card->ctx || !provider)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
@ -1450,6 +1462,10 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
|
||||
if (sm_session->state != CWA_SM_ACTIVE)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
||||
|
||||
/* reserve extra bytes for padding and tlv header */
|
||||
msgbuf = calloc(12 + from->lc, sizeof(u8)); /* to encrypt apdu data */
|
||||
cryptbuf = calloc(12 + from->lc, sizeof(u8));
|
||||
if (!msgbuf || !cryptbuf)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -1477,6 +1493,7 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
|
||||
/* reserve enougth space for apdulen+tlv bytes
|
||||
* to-be-crypted buffer and result apdu buffer */
|
||||
/* TODO DEE add 4 more bytes for testing.... */
|
||||
apdubuf =
|
||||
calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen),
|
||||
sizeof(u8));
|
||||
|
@ -1532,8 +1549,10 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
}
|
||||
|
||||
/* if le byte is declared, compose and add Le TLV */
|
||||
/* TODO: study why original driver checks for le>=256? */
|
||||
if (from->le > 0) {
|
||||
/* FIXME: For DNIe we must not send the le bytes
|
||||
when le == 256 but this goes against the standard
|
||||
and might break other cards reusing this code */
|
||||
if ((0xff & from->le) > 0) {
|
||||
u8 le = 0xff & from->le;
|
||||
res = cwa_compose_tlv(card, 0x97, 1, &le, &ccbuf, &cclen);
|
||||
if (res != SC_SUCCESS) {
|
||||
|
@ -1591,12 +1610,20 @@ int cwa_encode_apdu(sc_card_t * card,
|
|||
goto encode_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* that's all folks */
|
||||
res = SC_SUCCESS;
|
||||
goto encode_end_apdu_valid;
|
||||
|
||||
encode_end:
|
||||
encode_end:
|
||||
if (apdubuf)
|
||||
free(apdubuf);
|
||||
encode_end_apdu_valid:
|
||||
if (msg)
|
||||
sc_log(ctx, msg);
|
||||
free(msgbuf);
|
||||
free(cryptbuf);
|
||||
free(ccbuf);
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
|
||||
|
@ -1624,6 +1651,7 @@ int cwa_decode_response(sc_card_t * card,
|
|||
cwa_tlv_t *e_tlv = &tlv_array[1]; /* to store pad encoded data (Tag 0x87) */
|
||||
cwa_tlv_t *m_tlv = &tlv_array[2]; /* to store mac CC (Tag 0x8E) */
|
||||
cwa_tlv_t *s_tlv = &tlv_array[3]; /* to store sw1-sw2 status (Tag 0x99) */
|
||||
u8 *buffer = NULL; /* buffer for data. pointers to this buffer are in tlv_array */
|
||||
u8 *ccbuf = NULL; /* buffer for mac CC calculation */
|
||||
size_t cclen = 0; /* ccbuf len */
|
||||
u8 macbuf[8]; /* where to calculate mac */
|
||||
|
@ -1687,8 +1715,16 @@ int cwa_decode_response(sc_card_t * card,
|
|||
|
||||
/* parse response to find TLV's data and check results */
|
||||
memset(tlv_array, 0, 4 * sizeof(cwa_tlv_t));
|
||||
/* create buffer and copy data into */
|
||||
buffer = calloc(from->resplen, sizeof(u8));
|
||||
if (!buffer) {
|
||||
msg = "Cannot allocate space for response buffer";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto response_decode_end;
|
||||
}
|
||||
memcpy(buffer, from->resp, from->resplen);
|
||||
|
||||
res = cwa_parse_tlv(card, from->resp, from->resplen, tlv_array);
|
||||
res = cwa_parse_tlv(card, buffer, from->resplen, tlv_array);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Error in TLV parsing";
|
||||
goto response_decode_end;
|
||||
|
@ -1789,7 +1825,7 @@ int cwa_decode_response(sc_card_t * card,
|
|||
if (to->resp) { /* if response apdu provides buffer, try to use it */
|
||||
if (to->resplen < resplen) {
|
||||
msg =
|
||||
"Provided buffer has not enought size to store response";
|
||||
"Provided buffer has not enough size to store response";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto response_decode_end;
|
||||
}
|
||||
|
@ -1857,7 +1893,7 @@ int cwa_decode_response(sc_card_t * card,
|
|||
res = provider->cwa_decode_post_ops(card, provider, from, to);
|
||||
if (res != SC_SUCCESS) {
|
||||
sc_log(ctx, "Decode APDU: provider post_ops() failed");
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
goto response_decode_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1865,6 +1901,8 @@ int cwa_decode_response(sc_card_t * card,
|
|||
res = SC_SUCCESS;
|
||||
|
||||
response_decode_end:
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
if (ccbuf)
|
||||
free(ccbuf);
|
||||
if (msg) {
|
||||
|
|
|
@ -51,23 +51,6 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/des.h>
|
||||
|
||||
/**
|
||||
* Structure used to compose BER-TLV encoded data
|
||||
* according to iso7816-4 sect 5.2.2.
|
||||
*
|
||||
* Notice that current implementation does not handle properly
|
||||
* multibyte tag id. Just asume that tag is 1-byte lenght
|
||||
* Also, encodings for data lenght longer than 0x01000000 bytes
|
||||
* are not supported (tag 0x84)
|
||||
*/
|
||||
typedef struct cwa_tlv_st {
|
||||
u8 *buf; /** local copy of TLV byte array */
|
||||
size_t buflen; /** lengt of buffer */
|
||||
unsigned int tag; /** tag ID */
|
||||
size_t len; /** lenght of data field */
|
||||
u8 *data; /** pointer to start of data in buf buffer */
|
||||
} cwa_tlv_t;
|
||||
|
||||
/**
|
||||
* Structure used to handle keys and sequence counter once SM session
|
||||
* is stablished
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -36,7 +38,8 @@ struct app_entry {
|
|||
static const struct app_entry apps[] = {
|
||||
{ (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" },
|
||||
{ (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" },
|
||||
{ (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" }
|
||||
{ (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" },
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"}
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_dirrecord[] = {
|
||||
|
@ -91,7 +94,7 @@ parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen, int rec_nr)
|
|||
else
|
||||
app->label = NULL;
|
||||
|
||||
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) {
|
||||
if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT && path_len > 0) {
|
||||
/* application path present: ignore AID */
|
||||
if (path_len > SC_MAX_PATH_SIZE) {
|
||||
free(app);
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
|
@ -985,6 +985,7 @@ iasecc_sdo_encode_create(struct sc_context *ctx, struct iasecc_sdo *sdo, unsigne
|
|||
|
||||
rv = sc_asn1_encode(ctx, asn1_create_data, out, &out_len);
|
||||
LOG_TEST_RET(ctx, rv, "Encode create data error");
|
||||
if (out)
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Create data: %s", sc_dump_hex(*out, out_len));
|
||||
|
||||
LOG_FUNC_RETURN(ctx, out_len);
|
||||
|
@ -1287,4 +1288,15 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase
|
|||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* we need to define the functions below to export them */
|
||||
#include "errors.h"
|
||||
|
||||
int
|
||||
iasecc_sdo_encode_update_field()
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_OPENSSL */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "internal.h"
|
||||
#include "asn1.h"
|
||||
#include "cardctl.h"
|
||||
#include "common/compat_strlcpy.h"
|
||||
|
||||
#include "sm.h"
|
||||
#include "iasecc.h"
|
||||
|
@ -36,12 +37,15 @@
|
|||
static int
|
||||
sm_save_sc_context (struct sc_card *card, struct sm_info *sm_info)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
struct sc_card_cache *cache = &card->cache;
|
||||
struct sc_context *ctx;
|
||||
struct sc_card_cache *cache;
|
||||
|
||||
if (!card || !sm_info)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
ctx = card->ctx;
|
||||
cache = &card->cache;
|
||||
|
||||
sc_log(ctx, "SM save context: cache(valid:%i,current_df:%p)", cache->valid, cache->current_df);
|
||||
if (cache->valid && cache->current_df) {
|
||||
sm_info->current_path_df = cache->current_df->path;
|
||||
|
@ -156,7 +160,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
|
|||
if (card->sm_ctx.sm_mode == SM_MODE_NONE)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot do 'External Authentication' without SM activated ");
|
||||
|
||||
strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
|
||||
strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
|
||||
sm_info->cmd = SM_CMD_EXTERNAL_AUTH;
|
||||
sm_info->serialnr = card->serialnr;
|
||||
sm_info->card_type = card->type;
|
||||
|
@ -296,7 +300,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
|
|||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
|
||||
strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
|
||||
sm_info->cmd = cmd;
|
||||
sm_info->serialnr = card->serialnr;
|
||||
sm_info->card_type = card->type;
|
||||
|
|
|
@ -20,6 +20,13 @@ typedef unsigned __int8 uint8_t;
|
|||
#ifdef __APPLE__
|
||||
#include <wintypes.h>
|
||||
#endif
|
||||
// allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW
|
||||
#ifdef WIN32
|
||||
#ifdef UNICODE
|
||||
#define SCARD_READERSTATE SCARD_READERSTATEA
|
||||
#undef SCardGetStatusChange
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
/* mingw32 does not have winscard.h */
|
||||
|
||||
|
@ -193,6 +200,7 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\
|
|||
#define PCSCv2_PART10_PROPERTY_bMaxPINSize 7
|
||||
#define PCSCv2_PART10_PROPERTY_sFirmwareID 8
|
||||
#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9
|
||||
#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10
|
||||
|
||||
/* structures used (but not defined) in PCSC Part 10:
|
||||
* "IFDs with Secure Pin Entry Capabilities" */
|
||||
|
|
|
@ -74,7 +74,6 @@ struct sc_atr_table {
|
|||
|
||||
/* Internal use only */
|
||||
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader);
|
||||
int _sc_delete_reader(struct sc_context *ctx, struct sc_reader *reader);
|
||||
int _sc_parse_atr(struct sc_reader *reader);
|
||||
|
||||
/* Add an ATR to the card driver's struct sc_atr_table */
|
||||
|
@ -121,7 +120,8 @@ int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info
|
|||
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long exponent);
|
||||
int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags);
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid);
|
||||
|
||||
/********************************************************************/
|
||||
/* pkcs1 padding/encoding functions */
|
||||
|
|
|
@ -33,35 +33,17 @@
|
|||
static void fixup_transceive_length(const struct sc_card *card,
|
||||
struct sc_apdu *apdu)
|
||||
{
|
||||
size_t max_send_size;
|
||||
size_t max_recv_size;
|
||||
|
||||
assert(card != NULL && apdu != NULL);
|
||||
|
||||
max_send_size = card->max_send_size;
|
||||
max_recv_size = card->max_recv_size;
|
||||
|
||||
if (card->caps & SC_CARD_CAP_APDU_EXT) {
|
||||
if (!max_send_size)
|
||||
max_send_size = 65535;
|
||||
if (!max_recv_size)
|
||||
max_recv_size = 65536;
|
||||
} else {
|
||||
if (!max_send_size)
|
||||
max_send_size = 255;
|
||||
if (!max_recv_size)
|
||||
max_recv_size = 256;
|
||||
}
|
||||
|
||||
if (apdu->lc > max_send_size) {
|
||||
if (apdu->lc > card->max_send_size) {
|
||||
/* The lower layers will automatically do chaining */
|
||||
apdu->flags |= SC_APDU_FLAGS_CHAINING;
|
||||
}
|
||||
|
||||
if (apdu->le > max_recv_size) {
|
||||
if (apdu->le > card->max_recv_size) {
|
||||
/* The lower layers will automatically do a GET RESPONSE, if possible.
|
||||
* All other workarounds must be carried out by the upper layers. */
|
||||
apdu->le = max_recv_size;
|
||||
apdu->le = card->max_recv_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,6 +332,7 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
size_t taglen, len = buflen;
|
||||
int i;
|
||||
const unsigned char *tag = NULL, *p = buf;
|
||||
|
||||
sc_log(ctx, "processing FCI bytes");
|
||||
|
@ -359,17 +342,25 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
sc_log(ctx, " file identifier: 0x%02X%02X", tag[0], tag[1]);
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
|
||||
if (tag == NULL) {
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
|
||||
}
|
||||
if (tag != NULL && taglen > 0 && taglen < 3) {
|
||||
file->size = tag[0];
|
||||
if (taglen == 2)
|
||||
file->size = (file->size << 8) + tag[1];
|
||||
sc_log(ctx, " bytes in file: %d", file->size);
|
||||
} else {
|
||||
/* determine the file size */
|
||||
/* try the tag 0x80 then the tag 0x81 */
|
||||
file->size = 0;
|
||||
for (i = 0x80; i <= 0x81; i++) {
|
||||
int size = 0;
|
||||
len = buflen;
|
||||
tag = sc_asn1_find_tag(ctx, p, len, i, &taglen);
|
||||
if (tag == NULL)
|
||||
continue;
|
||||
if (taglen == 0)
|
||||
continue;
|
||||
if (sc_asn1_decode_integer(tag, taglen, &size) < 0)
|
||||
continue;
|
||||
if (size <0)
|
||||
continue;
|
||||
|
||||
file->size = size;
|
||||
sc_log(ctx, " bytes in file: %d", file->size);
|
||||
break;
|
||||
}
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
|
||||
|
@ -430,6 +421,10 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
if (tag != NULL && taglen)
|
||||
sc_file_set_sec_attr(file, tag, taglen);
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x88, &taglen);
|
||||
if (tag != NULL && taglen == 1)
|
||||
file->sid = *tag;
|
||||
|
||||
tag = sc_asn1_find_tag(ctx, p, len, 0x8A, &taglen);
|
||||
if (tag != NULL && taglen==1) {
|
||||
if (tag[0] == 0x01)
|
||||
|
@ -452,17 +447,46 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
|
|||
struct sc_apdu apdu;
|
||||
unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
|
||||
int r, pathlen;
|
||||
int r, pathlen, pathtype;
|
||||
int select_mf = 0;
|
||||
struct sc_file *file = NULL;
|
||||
|
||||
assert(card != NULL && in_path != NULL);
|
||||
ctx = card->ctx;
|
||||
memcpy(path, in_path->value, in_path->len);
|
||||
pathlen = in_path->len;
|
||||
pathtype = in_path->type;
|
||||
|
||||
if (file_out != NULL) {
|
||||
*file_out = NULL;
|
||||
}
|
||||
if (in_path->aid.len) {
|
||||
if (!pathlen) {
|
||||
memcpy(path, in_path->aid.value, in_path->aid.len);
|
||||
pathlen = in_path->aid.len;
|
||||
pathtype = SC_PATH_TYPE_DF_NAME;
|
||||
} else {
|
||||
/* First, select the application */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
|
||||
apdu.data = in_path->aid.value;
|
||||
apdu.datalen = in_path->aid.len;
|
||||
apdu.lc = in_path->aid.len;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(ctx, r, "APDU transmit failed");
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if (r)
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
|
||||
if (pathtype == SC_PATH_TYPE_PATH
|
||||
|| pathtype == SC_PATH_TYPE_DF_NAME)
|
||||
pathtype = SC_PATH_TYPE_FROM_CURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
|
||||
|
||||
switch (in_path->type) {
|
||||
switch (pathtype) {
|
||||
case SC_PATH_TYPE_FILE_ID:
|
||||
apdu.p1 = 0;
|
||||
if (pathlen != 2)
|
||||
|
@ -475,6 +499,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
|
|||
apdu.p1 = 8;
|
||||
if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
|
||||
if (pathlen == 2) { /* only 3F00 supplied */
|
||||
select_mf = 1;
|
||||
apdu.p1 = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -501,7 +526,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
|
|||
apdu.p2 = 0; /* first record, return FCI */
|
||||
apdu.resp = buf;
|
||||
apdu.resplen = sizeof(buf);
|
||||
apdu.le = card->max_recv_size > 0 && card->max_recv_size < 256 ? card->max_recv_size : 256;
|
||||
apdu.le = card->max_recv_size < 256 ? card->max_recv_size : 256;
|
||||
}
|
||||
else {
|
||||
apdu.p2 = 0x0C; /* first record, return nothing */
|
||||
|
@ -527,6 +552,19 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
|
|||
if (r)
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
|
||||
if (file_out && (apdu.resplen == 0)) {
|
||||
/* For some cards 'SELECT' MF or DF_NAME do not return FCI. */
|
||||
if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME) {
|
||||
file = sc_file_new();
|
||||
if (file == NULL)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
file->path = *in_path;
|
||||
|
||||
*file_out = file;
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (apdu.resplen < 2)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
switch (apdu.resp[0]) {
|
||||
|
@ -632,7 +670,7 @@ iso7816_construct_fci(struct sc_card *card, const sc_file_t *file,
|
|||
p, *outlen - (p - out), &p);
|
||||
}
|
||||
if (file->sec_attr_len) {
|
||||
assert(sizeof(buf) >= file->prop_attr_len);
|
||||
assert(sizeof(buf) >= file->sec_attr_len);
|
||||
memcpy(buf, file->sec_attr, file->sec_attr_len);
|
||||
sc_asn1_put_tag(0x86, buf, file->sec_attr_len,
|
||||
p, *outlen - (p - out), &p);
|
||||
|
@ -681,7 +719,7 @@ iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf)
|
|||
size_t rlen;
|
||||
|
||||
/* request at most max_recv_size bytes */
|
||||
if (card->max_recv_size > 0 && *count > card->max_recv_size)
|
||||
if (*count > card->max_recv_size)
|
||||
rlen = card->max_recv_size;
|
||||
else
|
||||
rlen = *count;
|
||||
|
@ -955,7 +993,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
|
|||
break;
|
||||
case SC_PIN_CMD_CHANGE:
|
||||
ins = 0x24;
|
||||
if (data->pin1.len != 0 || use_pin_pad) {
|
||||
if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
|
||||
if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
|
@ -972,15 +1010,14 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
|
|||
* but expect the new one to be entered on the keypad.
|
||||
*/
|
||||
if (data->pin1.len && data->pin2.len == 0) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Special case - initial pin provided - but new pin asked on keypad");
|
||||
sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad");
|
||||
data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
|
||||
};
|
||||
len += r;
|
||||
break;
|
||||
case SC_PIN_CMD_UNBLOCK:
|
||||
ins = 0x2C;
|
||||
if (data->pin1.len != 0 || use_pin_pad) {
|
||||
if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
|
||||
if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
|
||||
return r;
|
||||
len += r;
|
||||
|
@ -1073,6 +1110,38 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l
|
|||
}
|
||||
|
||||
|
||||
static int iso7816_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len)
|
||||
{
|
||||
int r, cse;
|
||||
struct sc_apdu apdu;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
||||
if (buf && len)
|
||||
cse = SC_APDU_CASE_2;
|
||||
else
|
||||
cse = SC_APDU_CASE_1;
|
||||
|
||||
sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
|
||||
apdu.le = len;
|
||||
apdu.resp = buf;
|
||||
apdu.resplen = len;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error");
|
||||
|
||||
if (apdu.resplen > len)
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
else
|
||||
r = apdu.resplen;
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
iso7816_init(struct sc_card *card)
|
||||
{
|
||||
|
@ -1120,7 +1189,7 @@ static struct sc_card_operations iso_ops = {
|
|||
iso7816_process_fci,
|
||||
iso7816_construct_fci,
|
||||
iso7816_pin_cmd,
|
||||
NULL, /* get_data */
|
||||
iso7816_get_data,
|
||||
NULL, /* put_data */
|
||||
NULL, /* delete_record */
|
||||
NULL /* read_public_key */
|
||||
|
|
|
@ -51,6 +51,8 @@ sc_asn1_put_tag
|
|||
sc_asn1_skip_tag
|
||||
sc_asn1_verify_tag
|
||||
sc_asn1_write_element
|
||||
sc_asn1_sig_value_sequence_to_rs
|
||||
sc_asn1_sig_value_rs_to_sequence
|
||||
sc_base64_decode
|
||||
sc_base64_encode
|
||||
sc_bin_to_hex
|
||||
|
@ -75,6 +77,7 @@ sc_ctx_get_reader_by_name
|
|||
sc_ctx_get_reader_count
|
||||
sc_ctx_log_to_file
|
||||
sc_ctx_use_reader
|
||||
_sc_delete_reader
|
||||
sc_decipher
|
||||
sc_delete_file
|
||||
sc_delete_record
|
||||
|
@ -235,6 +238,7 @@ sc_pkcs15emu_add_ec_prkey
|
|||
sc_pkcs15emu_add_ec_pubkey
|
||||
sc_pkcs15emu_add_x509_cert
|
||||
sc_pkcs15emu_object_add
|
||||
sc_pkcs15_bind_internal
|
||||
sc_print_path
|
||||
sc_put_data
|
||||
sc_read_binary
|
||||
|
@ -315,6 +319,7 @@ sc_pkcs15_convert_pubkey
|
|||
sc_sm_parse_answer
|
||||
sc_sm_update_apdu_response
|
||||
sc_sm_single_transmit
|
||||
sc_sm_stop
|
||||
iasecc_sm_create_file
|
||||
iasecc_sm_delete_file
|
||||
iasecc_sm_external_authentication
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -73,9 +75,7 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin
|
|||
FILE *outf = NULL;
|
||||
int n;
|
||||
|
||||
assert(ctx != NULL);
|
||||
|
||||
if (ctx->debug < level)
|
||||
if (!ctx || ctx->debug < level)
|
||||
return;
|
||||
|
||||
p = buf;
|
||||
|
@ -167,9 +167,7 @@ void sc_hex_dump(struct sc_context *ctx, int level, const u8 * in, size_t count,
|
|||
char *p = buf;
|
||||
int lines = 0;
|
||||
|
||||
assert(ctx != NULL);
|
||||
|
||||
if (ctx->debug < level)
|
||||
if (!ctx || ctx->debug < level)
|
||||
return;
|
||||
|
||||
assert(buf != NULL && (in != NULL || count == 0));
|
||||
|
@ -235,3 +233,17 @@ sc_dump_hex(const u8 * in, size_t count)
|
|||
|
||||
return dump_buf;
|
||||
}
|
||||
|
||||
char *
|
||||
sc_dump_oid(const struct sc_object_id *oid)
|
||||
{
|
||||
static char dump_buf[SC_MAX_OBJECT_ID_OCTETS * 20];
|
||||
size_t ii;
|
||||
|
||||
memset(dump_buf, 0, sizeof(dump_buf));
|
||||
if (oid)
|
||||
for (ii=0; ii<SC_MAX_OBJECT_ID_OCTETS && oid->value[ii] != -1; ii++)
|
||||
snprintf(dump_buf + strlen(dump_buf), sizeof(dump_buf) - strlen(dump_buf), "%s%i", (ii ? "." : ""), oid->value[ii]);
|
||||
|
||||
return dump_buf;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void _sc_log(struct sc_context *ctx, const char *format, ...);
|
|||
|
||||
void sc_hex_dump(struct sc_context *ctx, int level, const u8 * buf, size_t len, char *out, size_t outlen);
|
||||
char * sc_dump_hex(const u8 * in, size_t count);
|
||||
|
||||
char * sc_dump_oid(const struct sc_object_id *oid);
|
||||
#define SC_FUNC_CALLED(ctx, level) do { \
|
||||
sc_do_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, "called\n"); \
|
||||
} while (0)
|
||||
|
@ -89,6 +89,16 @@ char * sc_dump_hex(const u8 * in, size_t count);
|
|||
} while(0)
|
||||
#define LOG_TEST_RET(ctx, r, text) SC_TEST_RET((ctx), SC_LOG_DEBUG_NORMAL, (r), (text))
|
||||
|
||||
#define SC_TEST_GOTO_ERR(ctx, level, r, text) do { \
|
||||
int _ret = (r); \
|
||||
if (_ret < 0) { \
|
||||
sc_do_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, \
|
||||
"%s: %d (%s)\n", (text), _ret, sc_strerror(_ret)); \
|
||||
goto err; \
|
||||
} \
|
||||
} while(0)
|
||||
#define LOG_TEST_GOTO_ERR(ctx, r, text) SC_TEST_GOTO_ERR((ctx), SC_LOG_DEBUG_NORMAL, (r), (text))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
|
@ -42,6 +44,8 @@ static const u8* ignoredFiles[] = {
|
|||
|
||||
mscfs_t *mscfs_new(void) {
|
||||
mscfs_t *fs = malloc(sizeof(mscfs_t));
|
||||
if (!fs)
|
||||
return NULL;
|
||||
memset(fs, 0, sizeof(mscfs_t));
|
||||
memcpy(fs->currentPath, "\x3F\x00", 2);
|
||||
return fs;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -663,7 +665,6 @@ int msc_compute_crypt_init(sc_card_t *card,
|
|||
if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
short receivedData = outputBuffer[0] << 8 | outputBuffer[1];
|
||||
*outputDataLength = receivedData;
|
||||
*outputDataLength = 0;
|
||||
|
||||
assert(receivedData <= MSC_MAX_APDU);
|
||||
memcpy(outputData, outputBuffer + 2, receivedData);
|
||||
|
|
|
@ -191,10 +191,23 @@ struct sc_pbes2_params {
|
|||
struct sc_algorithm_id key_encr_alg;
|
||||
};
|
||||
|
||||
struct sc_ec_params {
|
||||
/*
|
||||
* The ecParameters can be presented as
|
||||
* - name of curve;
|
||||
* - OID of named curve;
|
||||
* - implicit parameters.
|
||||
*
|
||||
* type - type(choice) of 'EC domain parameters' as it present in CKA_EC_PARAMS (PKCS#11).
|
||||
Recommended value '1' -- namedCurve.
|
||||
* field_length - EC key size in bits.
|
||||
*/
|
||||
struct sc_ec_parameters {
|
||||
char *named_curve;
|
||||
struct sc_object_id id;
|
||||
struct sc_lv_data der;
|
||||
|
||||
int type;
|
||||
u8 * der;
|
||||
size_t der_len;
|
||||
size_t field_length;
|
||||
};
|
||||
|
||||
typedef struct sc_algorithm_info {
|
||||
|
@ -208,6 +221,7 @@ typedef struct sc_algorithm_info {
|
|||
} _rsa;
|
||||
struct sc_ec_info {
|
||||
unsigned ext_flags;
|
||||
struct sc_ec_parameters params;
|
||||
} _ec;
|
||||
} u;
|
||||
} sc_algorithm_info_t;
|
||||
|
@ -261,8 +275,6 @@ struct sc_reader_driver {
|
|||
const char *short_name;
|
||||
struct sc_reader_operations *ops;
|
||||
|
||||
size_t max_send_size; /* Max Lc supported by the reader layer */
|
||||
size_t max_recv_size; /* Mac Le supported by the reader layer */
|
||||
void *dll;
|
||||
};
|
||||
|
||||
|
@ -272,6 +284,7 @@ struct sc_reader_driver {
|
|||
#define SC_READER_CARD_INUSE 0x00000004
|
||||
#define SC_READER_CARD_EXCLUSIVE 0x00000008
|
||||
#define SC_READER_HAS_WAITING_AREA 0x00000010
|
||||
#define SC_READER_REMOVED 0x00000020
|
||||
|
||||
/* reader capabilities */
|
||||
#define SC_READER_CAP_DISPLAY 0x00000001
|
||||
|
@ -290,6 +303,8 @@ typedef struct sc_reader {
|
|||
|
||||
unsigned long flags, capabilities;
|
||||
unsigned int supported_protocols, active_protocol;
|
||||
size_t max_send_size; /* Max Lc supported by the reader layer */
|
||||
size_t max_recv_size; /* Mac Le supported by the reader layer */
|
||||
|
||||
struct sc_atr atr;
|
||||
struct _atr_info {
|
||||
|
@ -320,14 +335,18 @@ typedef struct sc_reader {
|
|||
struct sc_pin_cmd_pin {
|
||||
const char *prompt; /* Prompt to display */
|
||||
|
||||
const u8 *data; /* PIN, if given by the appliction */
|
||||
const unsigned char *data; /* PIN, if given by the appliction */
|
||||
int len; /* set to -1 to get pin from pin pad */
|
||||
|
||||
size_t min_length; /* min/max length of PIN */
|
||||
size_t max_length;
|
||||
size_t min_length; /* min length of PIN */
|
||||
size_t max_length; /* max length of PIN */
|
||||
size_t stored_length; /* stored length of PIN */
|
||||
|
||||
unsigned int encoding; /* ASCII-numeric, BCD, etc */
|
||||
|
||||
size_t pad_length; /* filled in by the card driver */
|
||||
u8 pad_char;
|
||||
unsigned char pad_char;
|
||||
|
||||
size_t offset; /* PIN offset in the APDU */
|
||||
size_t length_offset; /* Effective PIN length offset in the APDU */
|
||||
|
||||
|
@ -349,73 +368,6 @@ struct sc_pin_cmd_data {
|
|||
struct sc_apdu *apdu; /* APDU of the PIN command */
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define PACE_PIN_ID_MRZ 0x01
|
||||
#define PACE_PIN_ID_CAN 0x02
|
||||
#define PACE_PIN_ID_PIN 0x03
|
||||
#define PACE_PIN_ID_PUK 0x04
|
||||
/**
|
||||
* Input data for EstablishPACEChannel()
|
||||
*/
|
||||
struct establish_pace_channel_input {
|
||||
/** Type of secret (CAN, MRZ, PIN or PUK). */
|
||||
unsigned char pin_id;
|
||||
|
||||
/** Length of \a chat */
|
||||
size_t chat_length;
|
||||
/** Card holder authorization template */
|
||||
const unsigned char *chat;
|
||||
|
||||
/** Length of \a pin */
|
||||
size_t pin_length;
|
||||
/** Secret */
|
||||
const unsigned char *pin;
|
||||
|
||||
/** Length of \a certificate_description */
|
||||
size_t certificate_description_length;
|
||||
/** Certificate description */
|
||||
const unsigned char *certificate_description;
|
||||
};
|
||||
|
||||
/**
|
||||
* Output data for EstablishPACEChannel()
|
||||
*/
|
||||
struct establish_pace_channel_output {
|
||||
/** PACE result (TR-03119) */
|
||||
unsigned int result;
|
||||
|
||||
/** MSE: Set AT status byte */
|
||||
unsigned char mse_set_at_sw1;
|
||||
/** MSE: Set AT status byte */
|
||||
unsigned char mse_set_at_sw2;
|
||||
|
||||
/** Length of \a ef_cardaccess */
|
||||
size_t ef_cardaccess_length;
|
||||
/** EF.CardAccess */
|
||||
unsigned char *ef_cardaccess;
|
||||
|
||||
/** Length of \a recent_car */
|
||||
size_t recent_car_length;
|
||||
/** Most recent certificate authority reference */
|
||||
unsigned char *recent_car;
|
||||
|
||||
/** Length of \a previous_car */
|
||||
size_t previous_car_length;
|
||||
/** Previous certificate authority reference */
|
||||
unsigned char *previous_car;
|
||||
|
||||
/** Length of \a id_icc */
|
||||
size_t id_icc_length;
|
||||
/** ICC identifier */
|
||||
unsigned char *id_icc;
|
||||
|
||||
/** Length of \a id_pcd */
|
||||
size_t id_pcd_length;
|
||||
/** PCD identifier */
|
||||
unsigned char *id_pcd;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct sc_reader_operations {
|
||||
/* Called during sc_establish_context(), when the driver
|
||||
* is loaded */
|
||||
|
@ -687,13 +639,25 @@ typedef struct {
|
|||
unsigned long (*thread_id)(void);
|
||||
} sc_thread_context_t;
|
||||
|
||||
/** Stop modifing or using external resources
|
||||
*
|
||||
* Currently this is used to avoid freeing duplicated external resources for a
|
||||
* process that has been forked. For example, a child process may want to leave
|
||||
* the duplicated card handles for the parent process. With this flag the child
|
||||
* process indicates that shall the reader shall ignore those resources when
|
||||
* calling sc_disconnect_card.
|
||||
*/
|
||||
#define SC_CTX_FLAG_TERMINATE 0x00000001
|
||||
#define SC_CTX_FLAG_PARANOID_MEMORY 0x00000002
|
||||
#define SC_CTX_FLAG_DEBUG_MEMORY 0x00000004
|
||||
#define SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER 0x00000008
|
||||
|
||||
typedef struct sc_context {
|
||||
scconf_context *conf;
|
||||
scconf_block *conf_blocks[3];
|
||||
char *app_name;
|
||||
int debug;
|
||||
int paranoid_memory;
|
||||
int enable_default_driver;
|
||||
unsigned long flags;
|
||||
|
||||
FILE *debug_file;
|
||||
char *debug_filename;
|
||||
|
@ -767,7 +731,7 @@ typedef struct {
|
|||
* dependend configuration data). If NULL the name "default"
|
||||
* will be used. */
|
||||
const char *app_name;
|
||||
/** flags, currently unused */
|
||||
/** context flags */
|
||||
unsigned long flags;
|
||||
/** mutex functions to use (optional) */
|
||||
sc_thread_context_t *thread_ctx;
|
||||
|
@ -851,6 +815,8 @@ sc_reader_t *sc_ctx_get_reader_by_id(sc_context_t *ctx, unsigned int id);
|
|||
*/
|
||||
unsigned int sc_ctx_get_reader_count(sc_context_t *ctx);
|
||||
|
||||
int _sc_delete_reader(sc_context_t *ctx, sc_reader_t *reader);
|
||||
|
||||
/**
|
||||
* Redirects OpenSC debug log to the specified file
|
||||
* @param ctx existing OpenSC context
|
||||
|
@ -1282,7 +1248,7 @@ void sc_print_cache(struct sc_card *card);
|
|||
struct sc_algorithm_info * sc_card_find_rsa_alg(struct sc_card *card,
|
||||
unsigned int key_length);
|
||||
struct sc_algorithm_info * sc_card_find_ec_alg(struct sc_card *card,
|
||||
unsigned int field_length);
|
||||
unsigned int field_length, struct sc_object_id *curve_oid);
|
||||
struct sc_algorithm_info * sc_card_find_gostr3410_alg(struct sc_card *card,
|
||||
unsigned int key_length);
|
||||
|
||||
|
@ -1301,6 +1267,15 @@ unsigned sc_crc32(unsigned char *value, size_t len);
|
|||
*/
|
||||
void sc_remote_data_init(struct sc_remote_data *rdata);
|
||||
|
||||
|
||||
/**
|
||||
* Copy and allocate if needed EC parameters data
|
||||
* @dst destination
|
||||
* @src source
|
||||
*/
|
||||
int sc_copy_ec_params(struct sc_ec_parameters *, struct sc_ec_parameters *);
|
||||
|
||||
|
||||
struct sc_card_error {
|
||||
unsigned int SWs;
|
||||
int errorno;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OPENSSL /* empty file without openssl */
|
||||
#include <string.h>
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -122,10 +124,6 @@ static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
|
|||
info.modulus_length = modulus_length;
|
||||
info.usage = usage;
|
||||
info.native = 1;
|
||||
info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
|
||||
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
info.key_reference = ref;
|
||||
|
||||
if (path)
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -263,16 +265,11 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp,
|
|||
int r;
|
||||
struct sc_object_id curve;
|
||||
struct sc_asn1_entry asn1_ec_params[4];
|
||||
struct sc_ec_params * ecp;
|
||||
struct sc_ec_parameters *ecp;
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params %p:%d %d", buf, buflen, depth);
|
||||
|
||||
memset(&curve, 0, sizeof(curve));
|
||||
ecp = malloc(sizeof(struct sc_ec_params));
|
||||
if (ecp == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memset(ecp,0,sizeof(struct sc_ec_params));
|
||||
|
||||
|
||||
/* We only want to copy the parms if they are a namedCurve
|
||||
* or ecParameters nullParam aka implicityCA is not to be
|
||||
|
@ -281,55 +278,58 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp,
|
|||
sc_format_asn1_entry(asn1_ec_params + 1, &curve, 0, 0);
|
||||
|
||||
/* Some signature algorithms will not have any data */
|
||||
if (buflen == 0 || buf == NULL) {
|
||||
free(ecp);
|
||||
if (buflen == 0 || buf == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sc_asn1_decode_choice(ctx, asn1_ec_params, buf, buflen, NULL, NULL);
|
||||
/* r = index into asn1_ec_params */
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params r=%d", r);
|
||||
if (r < 0) {
|
||||
free(ecp);
|
||||
/* r = index in asn1_ec_params */
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_decode_ec_params r=%d", r);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (r <= 1) {
|
||||
ecp->der = malloc(buflen);
|
||||
|
||||
if (ecp->der == NULL)
|
||||
ecp = calloc(sizeof(struct sc_ec_parameters), 1);
|
||||
if (ecp == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
ecp->der_len = buflen;
|
||||
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params paramp=%p %p:%d %d",
|
||||
ecp, ecp->der, ecp->der_len, ecp->type);
|
||||
memcpy(ecp->der, buf, buflen); /* copy der parameters */
|
||||
} else
|
||||
if (r <= 1) {
|
||||
ecp->der.value = malloc(buflen);
|
||||
if (ecp->der.value == NULL) {
|
||||
free(ecp);
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
ecp->der.len = buflen;
|
||||
memcpy(ecp->der.value, buf, buflen);
|
||||
}
|
||||
else {
|
||||
r = 0;
|
||||
}
|
||||
|
||||
ecp->type = r; /* but 0 = ecparams if any, 1=named curve */
|
||||
*paramp = ecp;
|
||||
return 0;
|
||||
return SC_SUCCESS;
|
||||
};
|
||||
|
||||
static int
|
||||
asn1_encode_ec_params(sc_context_t *ctx, void *params,
|
||||
u8 **buf, size_t *buflen, int depth)
|
||||
{
|
||||
struct sc_ec_params * ecp = (struct sc_ec_params *) params;
|
||||
struct sc_ec_parameters *ecp = (struct sc_ec_parameters *) params;
|
||||
|
||||
/* Only handle named curves. They may be absent too */
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_encode_ec_params");
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_encode_ec_params() called");
|
||||
*buf = NULL;
|
||||
*buflen = 0;
|
||||
if (ecp && ecp->type == 1 && ecp->der) { /* named curve */
|
||||
*buf = malloc(ecp->der_len);
|
||||
if (ecp && ecp->type == 1 && ecp->der.value) { /* named curve */
|
||||
*buf = malloc(ecp->der.len);
|
||||
if (*buf == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
memcpy(*buf, ecp->der, ecp->der_len);
|
||||
*buflen = ecp->der_len;
|
||||
} else
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - Not named curve");
|
||||
memcpy(*buf, ecp->der.value, ecp->der.len);
|
||||
*buflen = ecp->der.len;
|
||||
}
|
||||
else {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_ASN1, "Not named curve");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -337,10 +337,13 @@ u8 **buf, size_t *buflen, int depth)
|
|||
static void
|
||||
asn1_free_ec_params(void *params)
|
||||
{
|
||||
struct sc_ec_params * ecp = (struct sc_ec_params *) params;
|
||||
struct sc_ec_parameters *ecp = (struct sc_ec_parameters *) params;
|
||||
|
||||
if (ecp) {
|
||||
if (ecp->der)
|
||||
free(ecp->der);
|
||||
if (ecp->der.value)
|
||||
free(ecp->der.value);
|
||||
if (ecp->named_curve)
|
||||
free(ecp->named_curve);
|
||||
free(ecp);
|
||||
}
|
||||
}
|
||||
|
@ -468,52 +471,51 @@ sc_asn1_get_algorithm_info(const struct sc_algorithm_id *id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_alg_id[6] = {
|
||||
static const struct sc_asn1_entry c_asn1_alg_id[3] = {
|
||||
{ "algorithm", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
|
||||
{ "nullParam", SC_ASN1_NULL, SC_ASN1_TAG_NULL, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
sc_asn1_decode_algorithm_id(sc_context_t *ctx, const u8 *in,
|
||||
sc_asn1_decode_algorithm_id(struct sc_context *ctx, const unsigned char *in,
|
||||
size_t len, struct sc_algorithm_id *id,
|
||||
int depth)
|
||||
{
|
||||
struct sc_asn1_pkcs15_algorithm_info *alg_info;
|
||||
struct sc_asn1_pkcs15_algorithm_info *alg_info = NULL;
|
||||
struct sc_asn1_entry asn1_alg_id[3];
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
|
||||
sc_format_asn1_entry(asn1_alg_id + 0, &id->oid, NULL, 0);
|
||||
|
||||
memset(id, 0, sizeof(*id));
|
||||
r = _sc_asn1_decode(ctx, asn1_alg_id, in, len, &in, &len, 0, depth + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
LOG_TEST_RET(ctx, r, "ASN.1 parsing of algo ID failed");
|
||||
|
||||
sc_log(ctx, "decoded OID '%s'", sc_dump_oid(&(id->oid)));
|
||||
|
||||
/* See if we understand the algorithm, and if we do, check
|
||||
* whether we know how to decode any additional parameters */
|
||||
id->algorithm = (unsigned int ) -1;
|
||||
if ((alg_info = sc_asn1_get_algorithm_info(id)) != NULL) {
|
||||
alg_info = sc_asn1_get_algorithm_info(id);
|
||||
if (alg_info != NULL) {
|
||||
id->algorithm = alg_info->id;
|
||||
if (alg_info->decode) {
|
||||
/* TODO: -DEE why the test for SC_ASN1_PRESENT?
|
||||
* If it looking for SC_ASN1_NULL, thats valid for EC, in some cases
|
||||
*/
|
||||
if (asn1_alg_id[1].flags & SC_ASN1_PRESENT) {
|
||||
sc_debug( ctx,SC_LOG_DEBUG_NORMAL,"SC_ASN1_PRESENT was set, so invalid");
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
sc_log(ctx, "SC_ASN1_PRESENT was set, so invalid");
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT);
|
||||
}
|
||||
r = alg_info->decode(ctx, &id->params, in, len, depth);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
|
||||
int
|
||||
sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
||||
u8 **buf, size_t *len,
|
||||
sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len,
|
||||
const struct sc_algorithm_id *id,
|
||||
int depth)
|
||||
{
|
||||
|
@ -525,10 +527,12 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
int r;
|
||||
u8 *tmp;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_log(ctx, "type of algorithm to encode: %i", id->algorithm);
|
||||
alg_info = sc_asn1_get_algorithm_info(id);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Cannot encode unknown algorithm %u", id->algorithm);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
/* Set the oid if not yet given */
|
||||
|
@ -538,6 +542,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
id = &temp_id;
|
||||
}
|
||||
|
||||
sc_log(ctx, "encode algo %s", sc_dump_oid(&(id->oid)));
|
||||
sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
|
||||
sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1);
|
||||
|
||||
|
@ -546,8 +551,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
asn1_alg_id[1].flags |= SC_ASN1_PRESENT;
|
||||
|
||||
r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
LOG_TEST_RET(ctx, r, "ASN.1 encode of algorithm failed");
|
||||
|
||||
/* Encode any parameters */
|
||||
if (id->params && alg_info->encode) {
|
||||
|
@ -555,7 +559,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
if (r < 0) {
|
||||
if (obj)
|
||||
free(obj);
|
||||
return r;
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,7 +569,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
free(*buf);
|
||||
*buf = NULL;
|
||||
free(obj);
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
*buf = tmp;
|
||||
memcpy(*buf + *len, obj, obj_len);
|
||||
|
@ -574,7 +578,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx,
|
|||
}
|
||||
|
||||
sc_log(ctx, "return encoded algorithm ID: %s", sc_dump_hex(*buf, *len));
|
||||
return 0;
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -112,8 +114,13 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card,
|
|||
free(data);
|
||||
return SC_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
if (offset)
|
||||
fseek(f, (long)offset, SEEK_SET);
|
||||
if (offset) {
|
||||
if (0 != fseek(f, (long)offset, SEEK_SET)) {
|
||||
fclose(f);
|
||||
free(data);
|
||||
return SC_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
if (data)
|
||||
*buf = data;
|
||||
got = fread(*buf, 1, count, f);
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -60,9 +62,14 @@ sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
|
|||
}
|
||||
|
||||
sc_der_copy(&der, &info->data);
|
||||
if (!der.value)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for der value");
|
||||
|
||||
data_object = calloc(sizeof(struct sc_pkcs15_data), 1);
|
||||
if (!data_object && !der.value)
|
||||
if (!data_object) {
|
||||
free(der.value);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for data object");
|
||||
}
|
||||
|
||||
data_object->data = der.value;
|
||||
data_object->data_len = der.len;
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "libopensc/log.h"
|
||||
#include "libopensc/asn1.h"
|
||||
#include "libopensc/pkcs15.h"
|
||||
|
@ -40,11 +42,19 @@ int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len)
|
|||
{
|
||||
int rv;
|
||||
sc_file_t *file = sc_file_new();
|
||||
sc_format_path(path, &file->path);
|
||||
sc_select_file(card, &file->path, &file);
|
||||
if (file->size > *buf_len)
|
||||
sc_path_t scpath;
|
||||
sc_format_path(path, &scpath);
|
||||
rv = sc_select_file(card, &scpath, &file);
|
||||
if (rv < 0) {
|
||||
sc_file_free(file);
|
||||
return rv;
|
||||
}
|
||||
if (file->size > *buf_len) {
|
||||
sc_file_free(file);
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
rv = sc_read_binary(card, 0, buf, file->size, 0);
|
||||
sc_file_free(file);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
*buf_len = rv;
|
||||
|
@ -100,8 +110,9 @@ int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15card)
|
|||
};
|
||||
struct sc_asn1_entry asn1_odf[10];
|
||||
|
||||
sc_path_t *path_prefix = calloc(1, sizeof(sc_path_t));
|
||||
sc_format_path("3F005015", path_prefix);
|
||||
sc_path_t path_prefix;
|
||||
|
||||
sc_format_path("3F005015", &path_prefix);
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_odf, asn1_odf);
|
||||
for (i = 0; asn1_odf[i].name != NULL; i++)
|
||||
|
@ -114,7 +125,7 @@ int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15card)
|
|||
if (r < 0)
|
||||
return r;
|
||||
type = r;
|
||||
r = sc_pkcs15_make_absolute_path(path_prefix, &path);
|
||||
r = sc_pkcs15_make_absolute_path(&path_prefix, &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path);
|
||||
|
@ -131,6 +142,7 @@ static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card)
|
|||
sc_pkcs15_object_t *p15_obj;
|
||||
size_t len = sizeof(buf);
|
||||
int rv;
|
||||
struct sc_pkcs15_cert_info *p15_info = NULL;
|
||||
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
@ -220,6 +232,15 @@ static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card)
|
|||
&& (p15_obj->auth_id.len == 0)) {
|
||||
p15_obj->auth_id.value[0] = 0x01;
|
||||
p15_obj->auth_id.len = 1;
|
||||
};
|
||||
/* Set path count to -1 for public certificates, as they
|
||||
will need to be decompressed and read_binary()'d, so
|
||||
we make sure we end up reading the file->size and not the
|
||||
path->count which is the compressed size on newer
|
||||
DNIe versions */
|
||||
if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_CDF) ) {
|
||||
p15_info = (struct sc_pkcs15_cert_info *) p15_obj ->data;
|
||||
p15_info ->path.count = -1;
|
||||
}
|
||||
/* Remove found public keys as cannot be read_binary()'d */
|
||||
if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) {
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
/* Initially written by Weitao Sun (weitao@ftsafe.com) 2008*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
/* Initially written by David Mattes <david.mattes@boeing.com> */
|
||||
/* Support for multiple key containers by Lukas Wunner <lukas@wunner.de> */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -183,11 +185,9 @@ static int gemsafe_get_cert_len(sc_card_t *card)
|
|||
* (allocated EF space is much greater!)
|
||||
*/
|
||||
objlen = (((size_t) ibuf[0]) << 8) | ibuf[1];
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Stored object is of size: %d\n", objlen);
|
||||
sc_log(card->ctx, "Stored object is of size: %d", objlen);
|
||||
if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Invalid object size: %d\n", objlen);
|
||||
sc_log(card->ctx, "Invalid object size: %d", objlen);
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
@ -209,15 +209,14 @@ static int gemsafe_get_cert_len(sc_card_t *card)
|
|||
while (ibuf[ind] == 0x01) {
|
||||
if (ibuf[ind+1] == 0xFE) {
|
||||
gemsafe_prkeys[i].ref = ibuf[ind+4];
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Key container %d is allocated and uses key_ref %d\n", i+1,
|
||||
gemsafe_prkeys[i].ref);
|
||||
sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
|
||||
i+1, gemsafe_prkeys[i].ref);
|
||||
ind += 9;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
gemsafe_prkeys[i].label = NULL;
|
||||
gemsafe_cert[i].label = NULL;
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Key container %d is unallocated\n", i+1);
|
||||
sc_log(card->ctx, "Key container %d is unallocated", i+1);
|
||||
ind += 8;
|
||||
}
|
||||
i++;
|
||||
|
@ -239,8 +238,7 @@ static int gemsafe_get_cert_len(sc_card_t *card)
|
|||
r = sc_read_binary(card, iptr - ibuf, iptr,
|
||||
MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
|
||||
if (r < 0) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Could not read cert object\n");
|
||||
sc_log(card->ctx, "Could not read cert object");
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
iptr += GEMSAFE_READ_QUANTUM;
|
||||
|
@ -254,15 +252,12 @@ static int gemsafe_get_cert_len(sc_card_t *card)
|
|||
while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL)
|
||||
i++;
|
||||
if (i == gemsafe_cert_max) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Warning: Found orphaned certificate at offset %d\n", ind);
|
||||
sc_log(card->ctx, "Warning: Found orphaned certificate at offset %d", ind);
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
/* DER cert len is encoded this way */
|
||||
certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4;
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Found certificate of key container %d at offset %d, len %d\n",
|
||||
i+1, ind, certlen);
|
||||
sc_log(card->ctx, "Found certificate of key container %d at offset %d, len %d", i+1, ind, certlen);
|
||||
gemsafe_cert[i].index = ind;
|
||||
gemsafe_cert[i].count = certlen;
|
||||
ind += certlen;
|
||||
|
@ -276,8 +271,7 @@ static int gemsafe_get_cert_len(sc_card_t *card)
|
|||
*/
|
||||
for (; i < gemsafe_cert_max; i++) {
|
||||
if (gemsafe_cert[i].label) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Warning: Certificate of key container %d is missing\n", i+1);
|
||||
sc_log(card->ctx, "Warning: Certificate of key container %d is missing", i+1);
|
||||
gemsafe_prkeys[i].label = NULL;
|
||||
gemsafe_cert[i].label = NULL;
|
||||
}
|
||||
|
@ -304,7 +298,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
struct sc_apdu apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n");
|
||||
sc_log(p15card->card->ctx, "Setting pkcs15 parameters");
|
||||
|
||||
if (p15card->tokeninfo->label)
|
||||
free(p15card->tokeninfo->label);
|
||||
|
@ -330,7 +324,8 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
apdu.lc = 0;
|
||||
apdu.datalen = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
|
||||
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
|
||||
return SC_ERROR_INTERNAL;
|
||||
if (r != SC_SUCCESS)
|
||||
|
@ -350,7 +345,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
return SC_ERROR_INTERNAL;
|
||||
|
||||
/* set certs */
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n");
|
||||
sc_log(p15card->card->ctx, "Setting certificates");
|
||||
for (i = 0; i < gemsafe_cert_max; i++) {
|
||||
struct sc_pkcs15_id p15Id;
|
||||
struct sc_path path;
|
||||
|
@ -367,7 +362,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
}
|
||||
|
||||
/* set gemsafe_pin */
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n");
|
||||
sc_log(p15card->card->ctx, "Setting PIN");
|
||||
for (i=0; i < gemsafe_pin_max; i++) {
|
||||
struct sc_pkcs15_id p15Id;
|
||||
struct sc_path path;
|
||||
|
@ -388,7 +383,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
};
|
||||
|
||||
/* set private keys */
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n");
|
||||
sc_log(p15card->card->ctx, "Setting private keys");
|
||||
for (i = 0; i < gemsafe_cert_max; i++) {
|
||||
struct sc_pkcs15_id p15Id, authId, *pauthId;
|
||||
struct sc_path path;
|
||||
|
@ -423,7 +418,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
|
|||
}
|
||||
|
||||
/* select the application DF */
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n");
|
||||
sc_log(p15card->card->ctx, "Selecting application DF");
|
||||
sc_format_path(GEMSAFE_APP_PATH, &path);
|
||||
r = sc_select_file(card, &path, &file);
|
||||
if (r != SC_SUCCESS || !file)
|
||||
|
@ -511,8 +506,7 @@ sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
|
|||
df_type = SC_PKCS15_CDF;
|
||||
break;
|
||||
default:
|
||||
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"Unknown PKCS15 object type %d\n", type);
|
||||
sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type);
|
||||
free(obj);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
@ -534,6 +528,9 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
|||
sc_pkcs15_auth_info_t *info;
|
||||
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (!info)
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
info->auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
|
||||
info->auth_method = SC_AC_CHV;
|
||||
info->auth_id = *id;
|
||||
|
@ -549,9 +546,7 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
|||
if (path)
|
||||
info->path = *path;
|
||||
|
||||
return sc_pkcs15emu_add_object(p15card,
|
||||
SC_PKCS15_TYPE_AUTH_PIN,
|
||||
label, info, NULL, obj_flags);
|
||||
return sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info, NULL, obj_flags);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -563,6 +558,10 @@ sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card,
|
|||
{
|
||||
sc_pkcs15_cert_info_t *info;
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (!info)
|
||||
{
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
info->id = *id;
|
||||
info->authority = authority;
|
||||
if (path)
|
||||
|
@ -582,6 +581,10 @@ sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
|
|||
sc_pkcs15_prkey_info_t *info;
|
||||
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (!info)
|
||||
{
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
info->id = *id;
|
||||
info->modulus_length = modulus_length;
|
||||
info->usage = usage;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue