Merge branch 'master' into gnuk

Conflicts:
	src/libopensc/card-openpgp.c
	src/tools/openpgp-tool.c
This commit is contained in:
Nguyễn Hồng Quân 2015-08-31 21:55:14 +08:00
commit 70890a8f61
205 changed files with 8995 additions and 2383 deletions

1
.gitignore vendored
View File

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

69
.travis.yml Normal file
View File

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

3
CONTRIBUTING.md Normal file
View File

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

View File

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

View File

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

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

14
README.md Normal file
View File

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

View File

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

View File

@ -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' ' ')," \

View File

@ -3,20 +3,22 @@
<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>
<refname>dnie-tool</refname>
<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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -202,6 +202,10 @@ app default {
#
# flags = "rng", "0x80000000";
# Enable pkcs11 initialization.
# Default: no
# pkcs11_enable_InitToken = yes;
#
# Context: PKCS#15 emulation layer
#

View File

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

View File

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

View File

@ -1,4 +1,6 @@
#if HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_GETPASS /* empty file if getpass is available */
#include <stdio.h>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
}
memcpy(p, data, datalen);
p += datalen;
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;
@ -955,7 +1007,7 @@ static const struct sc_asn1_entry c_asn1_se_info[4] = {
};
static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen,
sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth)
sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth)
{
struct sc_pkcs15_sec_env_info **ses;
const unsigned char *ptr = obj;
@ -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);
@ -1757,7 +1813,7 @@ sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id,
unsigned char **out, size_t *size)
{
static const struct sc_asn1_entry c_asn1_object_id[2] = {
{ "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_ALLOC, NULL, NULL },
{ "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry asn1_object_id[2];
@ -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);
}

View File

@ -58,7 +58,7 @@ void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg,
int set_present);
void sc_copy_asn1_entry(const struct sc_asn1_entry *src,
struct sc_asn1_entry *dest);
/* DER tag and length parsing */
int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1,
const u8 *in, size_t len, const u8 **newp, size_t *left);
@ -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);
@ -101,7 +103,7 @@ int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out);
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
struct sc_object_id *id);
int sc_asn1_encode_object_id(u8 **buf, size_t *buflen,
int sc_asn1_encode_object_id(u8 **buf, size_t *buflen,
const struct sc_object_id *id);
/* algorithm encoding/decoding */
@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
@ -2264,22 +2264,22 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc
LOG_FUNC_CALLED(ctx);
if (!plain || !sm_apdu)
if (!plain || !sm_apdu)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
sc_log(ctx, "called; CLA:%X, INS:%X, P1:%X, P2:%X, data(%i) %p",
plain->cla, plain->ins, plain->p1, plain->p2, plain->datalen, plain->data);
*sm_apdu = NULL;
*sm_apdu = NULL;
if ((plain->cla & 0x04)
|| (plain->cla==0x00 && plain->ins==0x22)
|| (plain->cla==0x00 && plain->ins==0x2A)
|| (plain->cla==0x00 && plain->ins==0x84)
|| (plain->cla==0x00 && plain->ins==0x88)
|| (plain->cla==0x00 && plain->ins==0xA4)
|| (plain->cla==0x00 && plain->ins==0xC0)
|| (plain->cla==0x00 && plain->ins==0xCA)
|| (plain->cla==0x80 && plain->ins==0x50)
) {
|| (plain->cla==0x00 && plain->ins==0x22)
|| (plain->cla==0x00 && plain->ins==0x2A)
|| (plain->cla==0x00 && plain->ins==0x84)
|| (plain->cla==0x00 && plain->ins==0x88)
|| (plain->cla==0x00 && plain->ins==0xA4)
|| (plain->cla==0x00 && plain->ins==0xC0)
|| (plain->cla==0x00 && plain->ins==0xCA)
|| (plain->cla==0x80 && plain->ins==0x50)
) {
sc_log(ctx, "SM wrap is not applied for this APDU");
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_APPLIED);
}
@ -2290,25 +2290,31 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc
if (!card->sm_ctx.module.ops.get_apdus)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
apdu = calloc(1, sizeof(struct sc_apdu));
if (!apdu)
apdu = calloc(1, sizeof(struct sc_apdu));
if (!apdu)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy((void *)apdu, (void *)plain, sizeof(struct sc_apdu));
apdu->data = calloc (1, plain->datalen + 24);
if (!apdu->data)
apdu->data = calloc (1, plain->datalen + 24);
if (!apdu->data)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
if (plain->data && plain->datalen)
memcpy((unsigned char *) apdu->data, plain->data, plain->datalen);
apdu->resp = calloc (1, plain->resplen + 32);
if (!apdu->resp)
apdu->resp = calloc (1, plain->resplen + 32);
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
LOG_TEST_RET(ctx, rv, "Cannot make copy of 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,7 +2644,8 @@ 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");
field->on_card = 1;
if (field)
field->on_card = 1;
}
free(data);
@ -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,7 +3402,8 @@ 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");
sc_log(ctx, "encoded public key: %s", sc_dump_hex(*out, *out_len));
if (out && out_len)
sc_log(ctx, "encoded public key: %s", sc_dump_hex(*out, *out_len));
if (bn[0].data)
free(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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
@ -57,7 +61,7 @@ typedef struct muscle_private {
unsigned short verifiedPins;
mscfs_t *fs;
int rsa_key_ref;
} muscle_private_t;
static int muscle_finish(sc_card_t *card)
@ -76,13 +80,13 @@ static int muscle_match_card(sc_card_t *card)
sc_apdu_t apdu;
u8 response[64];
int r;
/* Since we send an APDU, the card's logout function may be called...
* however it's not always properly nulled out... */
card->ops->logout = NULL;
if (msc_select_applet(card, muscleAppletId, 5) == 1) {
/* Muscle applet is present, check the protocol version to be sure */
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;
apdu.le = 64;
@ -149,16 +153,16 @@ static int muscle_create_directory(sc_card_t *card, sc_file_t *file)
int r;
if(id == 0) /* No null name files */
return SC_ERROR_INVALID_ARGUMENTS;
/* No nesting directories */
if(fs->currentPath[0] != 0x3F || fs->currentPath[1] != 0x00)
return SC_ERROR_NOT_SUPPORTED;
oid[0] = ((id & 0xFF00) >> 8) & 0xFF;
oid[1] = id & 0xFF;
oid[2] = oid[3] = 0;
objectSize = file->size;
muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm);
r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm);
mscfs_clear_cache(fs);
@ -180,9 +184,9 @@ static int muscle_create_file(sc_card_t *card, sc_file_t *file)
return SC_ERROR_NOT_SUPPORTED;
if(file->id == 0) /* No null name files */
return SC_ERROR_INVALID_ARGUMENTS;
muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm);
mscfs_lookup_local(fs, file->id, &objectId);
r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm);
mscfs_clear_cache(fs);
@ -197,7 +201,7 @@ static int muscle_read_binary(sc_card_t *card, unsigned int idx, u8* buf, size_t
msc_id objectId;
u8* oid = objectId.id;
mscfs_file_t *file;
r = mscfs_check_selection(fs, -1);
if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
file = &fs->cache.array[fs->currentFileIndex];
@ -223,7 +227,7 @@ static int muscle_update_binary(sc_card_t *card, unsigned int idx, const u8* buf
r = mscfs_check_selection(fs, -1);
if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
file = &fs->cache.array[fs->currentFileIndex];
objectId = file->objectId;
/* memcpy(objectId.id, file->objectId.id, 4); */
if(!file->ef) {
@ -235,7 +239,7 @@ static int muscle_update_binary(sc_card_t *card, unsigned int idx, const u8* buf
int newFileSize = idx + count;
u8* buffer = malloc(newFileSize);
if(buffer == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
r = msc_read_object(card, objectId, 0, buffer, file->size);
/* TODO: RETREIVE ACLS */
if(r < 0) goto update_bin_free_buffer;
@ -270,7 +274,7 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
mscfs_file_t *childFile;
/* Delete children */
mscfs_check_cache(fs);
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"DELETING Children of: %02X%02X%02X%02X\n",
oid[0],oid[1],oid[2],oid[3]);
@ -278,7 +282,7 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
msc_id objectId;
childFile = &fs->cache.array[x];
objectId = childFile->objectId;
if(0 == memcmp(oid + 2, objectId.id, 2)) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"DELETING: %02X%02X%02X%02X\n",
@ -365,11 +369,11 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
int r = 0;
int objectIndex;
u8* oid;
mscfs_check_cache(fs);
r = mscfs_loadFileInfo(fs, path_in->value, path_in->len, &file_data, &objectIndex);
if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,r);
/* Check if its the right type */
if(requiredType >= 0 && requiredType != file_data->ef) {
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS);
@ -387,7 +391,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
fs->currentFile[0] = 0;
fs->currentFile[1] = 0;
}
fs->currentFileIndex = objectIndex;
if(file_out) {
sc_file_t *file;
@ -401,7 +405,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
file->type = SC_FILE_TYPE_WORKING_EF;
file->ef_structure = SC_FILE_EF_TRANSPARENT;
}
/* Setup ACLS */
if(file_data->ef) {
muscle_load_file_acls(file, file_data);
@ -409,7 +413,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f
muscle_load_dir_acls(file, file_data);
/* Setup directory acls... */
}
file->magic = SC_FILE_MAGIC;
*file_out = file;
}
@ -420,9 +424,9 @@ static int muscle_select_file(sc_card_t *card, const sc_path_t *path_in,
sc_file_t **file_out)
{
int r;
assert(card != NULL && path_in != NULL);
switch (path_in->type) {
case SC_PATH_TYPE_FILE_ID:
r = select_item(card, path_in, file_out, 1);
@ -449,7 +453,7 @@ static int _listFile(mscfs_file_t *file, int reset, void *udata)
static int muscle_init(sc_card_t *card)
{
muscle_private_t *priv;
card->name = "MuscleApplet";
card->drv_data = malloc(sizeof(muscle_private_t));
if(!card->drv_data) {
@ -467,24 +471,28 @@ static int muscle_init(sc_card_t *card)
priv->fs->listFile = _listFile;
card->cla = 0xB0;
card->flags |= SC_CARD_FLAG_RNG;
card->caps |= SC_CARD_CAP_RNG;
/* 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 */
if (1) {
unsigned long flags;
flags = SC_ALGORITHM_RSA_RAW;
flags |= SC_ALGORITHM_RSA_HASH_NONE;
flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
@ -503,7 +511,7 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
int count = 0;
mscfs_check_cache(priv->fs);
for(x = 0; x < fs->cache.size; x++) {
u8* oid= fs->cache.array[x].objectId.id;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
@ -585,7 +593,7 @@ static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd,
return SC_ERROR_NOT_SUPPORTED;
}
}
static int muscle_card_extract_key(sc_card_t *card, sc_cardctl_muscle_key_info_t *info)
@ -668,7 +676,7 @@ static int muscle_set_security_env(sc_card_t *card,
/* ADJUST FOR PKCS1 padding support for decryption only */
if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
(env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card supports only raw RSA.\n");
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card supports only raw RSA.\n");
return SC_ERROR_NOT_SUPPORTED;
}
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
@ -705,21 +713,21 @@ static int muscle_decipher(sc_card_t * card,
size_t out_len)
{
muscle_private_t* priv = MUSCLE_DATA(card);
u8 key_id;
int r;
/* saniti check */
if (priv->env.operation != SC_SEC_OPERATION_DECIPHER)
return SC_ERROR_INVALID_ARGUMENTS;
key_id = priv->rsa_key_ref * 2; /* Private key */
if (out_len < crgram_len) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Output buffer too small");
return SC_ERROR_BUFFER_TOO_SMALL;
}
r = msc_compute_crypt(card,
key_id,
0x00, /* RSA NO PADDING */
@ -738,14 +746,14 @@ static int muscle_compute_signature(sc_card_t *card, const u8 *data,
muscle_private_t* priv = MUSCLE_DATA(card);
u8 key_id;
int r;
key_id = priv->rsa_key_ref * 2; /* Private key */
if (outlen < data_len) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Output buffer too small");
return SC_ERROR_BUFFER_TOO_SMALL;
}
r = msc_compute_crypt(card,
key_id,
0x00, /* RSA NO PADDING */
@ -811,9 +819,9 @@ static struct sc_card_driver * sc_get_driver(void)
muscle_ops.match_card = muscle_match_card;
muscle_ops.init = muscle_init;
muscle_ops.finish = muscle_finish;
muscle_ops.get_challenge = muscle_get_challenge;
muscle_ops.set_security_env = muscle_set_security_env;
muscle_ops.restore_security_env = muscle_restore_security_env;
muscle_ops.compute_signature = muscle_compute_signature;

View File

@ -16,9 +16,11 @@
* 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 <string.h>
#include <stdlib.h>
@ -28,21 +30,21 @@
#include "cardctl.h"
#include "types.h"
#define LOAD_KEY_MODULUS 0x80
#define LOAD_KEY_PUBLIC_EXPONENT 0x81
#define LOAD_KEY_PRIME_P 0x83
#define LOAD_KEY_PRIME_Q 0x84
#define LOAD_KEY_DP1 0x85
#define LOAD_KEY_DQ1 0x86
#define LOAD_KEY_INVQ 0x87
#define LOAD_KEY_MODE_EC_PRIV 0x87
#define LOAD_KEY_MODE_EC_PUB 0x86
#define LOAD_KEY_MODULUS 0x80
#define LOAD_KEY_PUBLIC_EXPONENT 0x81
#define LOAD_KEY_PRIME_P 0x83
#define LOAD_KEY_PRIME_Q 0x84
#define LOAD_KEY_DP1 0x85
#define LOAD_KEY_DQ1 0x86
#define LOAD_KEY_INVQ 0x87
#define LOAD_KEY_MODE_EC_PRIV 0x87
#define LOAD_KEY_MODE_EC_PUB 0x86
#define LOAD_KEY_EC_PRIVATE 0x97
#define LOAD_KEY_EC_PUBLIC 0x96
#define LOAD_KEY_EC_PRIVATE 0x97
#define LOAD_KEY_EC_PUBLIC 0x96
#define MYEID_STATE_CREATION 0x01
#define MYEID_STATE_ACTIVATED 0x07
#define MYEID_STATE_CREATION 0x01
#define MYEID_STATE_ACTIVATED 0x07
#define MYEID_ECC_SUPPORT
@ -59,15 +61,37 @@ static struct sc_card_driver myeid_drv = {
static const char *myeid_atrs[] = {
"3B:F5:18:00:FF:81:31:FE:45:4D:79:45:49:44:65",
"3B:F5:18:00:00:81:31:FE:45:4D:79:45:49:44:9A",
"3B:85:80:01:4D:79:45:49:44:78",
"3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C",
NULL
"3B:85:80:01:4D:79:45:49:44:78",
"3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C",
NULL
};
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;
@ -95,20 +119,34 @@ static int myeid_match_card(struct sc_card *card)
static int myeid_init(struct sc_card *card)
{
unsigned long flags = 0,
ext_flags = 0;
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;
_sc_card_add_rsa_alg(card, 512, flags, 0);
_sc_card_add_rsa_alg(card, 768, flags, 0);
_sc_card_add_rsa_alg(card, 1024, flags, 0);
@ -116,14 +154,21 @@ 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;
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);
/* 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;
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 */
card->caps |= SC_CARD_CAP_RNG;
@ -241,7 +286,7 @@ static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen)
struct sc_apdu apdu;
int r;
LOG_FUNC_CALLED(card->ctx);
LOG_FUNC_CALLED(card->ctx);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, 0xA1);
apdu.resp = buf;
@ -257,7 +302,7 @@ static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen)
}
static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
const u8 *buf, size_t buflen)
const u8 *buf, size_t buflen)
{
myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data;
size_t taglen = 0;
@ -279,8 +324,8 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
}
if(file->sec_attr_len >= 3)
{
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]);
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]);
}
tag = sc_asn1_find_tag(NULL, buf, buflen, 0x8A, &taglen);
if (tag != NULL && taglen > 0)
@ -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));
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
memset(buf, 0x0, *outlen);
buf[0] = 0x62;
buf[1] = 0x17;
@ -340,17 +388,15 @@ 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];
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]);
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,14 +524,56 @@ 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)
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);
data->pin_reference, data->pin1.len, data->pin2.len);
if(data->pin1.len > 8 || data->pin2.len > 8)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_LENGTH);
@ -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,46 +668,37 @@ 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);
}
static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env,
static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env,
int se_num)
{
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);
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
{
sc_log(card->ctx, "asymmetric keyref not supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
if (se_num > 0)
if (se_num > 0)
{
sc_log(card->ctx, "restore security environment not supported.\n");
return SC_ERROR_NOT_SUPPORTED;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation)
switch (env->operation)
{
case SC_SEC_OPERATION_DECIPHER:
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n");
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n");
return SC_ERROR_NOT_SUPPORTED;
break;
case SC_SEC_OPERATION_SIGN:
@ -637,20 +710,20 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e
}
apdu.le = 0;
p = sbuf;
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT)
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT)
{
*p++ = 0x80; /* algorithm reference */
*p++ = 0x01;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
{
*p++ = 0x81;
*p++ = 0x02;
memcpy(p, env->file_ref.value, 2);
p += 2;
}
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
{
*p++ = 0x84;
*p++ = 1;
@ -661,45 +734,38 @@ 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)
if (apdu.datalen != 0)
{
r = sc_transmit_apdu(card, &apdu);
if (r)
if (r)
{
sc_log(card->ctx,
"%s: APDU transmit failed", sc_strerror(r));
goto err;
}
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r)
if (r)
{
sc_log(card->ctx,
"%s: Card returned error", sc_strerror(r));
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)
{
@ -708,8 +774,8 @@ static int myeid_set_security_env(struct sc_card *card,
tmp = *env;
tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
if (tmp.algorithm == SC_ALGORITHM_RSA)
if (tmp.algorithm == SC_ALGORITHM_RSA)
{
tmp.algorithm_ref = 0x00;
/* potential FIXME: return an error, if an unsupported
@ -719,43 +785,80 @@ static int myeid_set_security_env(struct sc_card *card,
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
tmp.algorithm_ref |= 0x10;
return myeid_set_security_env_rsa(card, &tmp, se_num);
return myeid_set_security_env_rsa(card, &tmp, se_num);
}
else if (tmp.algorithm == SC_ALGORITHM_EC)
{
else if (tmp.algorithm == SC_ALGORITHM_EC)
{
#ifdef MYEID_ECC_SUPPORT
/* TODO: Update the algorithm_ref */
tmp.algorithm_ref = 0xAA;
tmp.algorithm_flags = 0;
return myeid_set_security_env_ec(card, &tmp, se_num);
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,40 +881,107 @@ 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;
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
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);
if (crgram_len > 256)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
assert(card != NULL && crgram != NULL && out != NULL);
/* INS: 0x2A PERFORM SECURITY OPERATION
* P1: 0x80 Resp: Plain value
* P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */
sc_format_apdu(card, &apdu,
(crgram_len < 256) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT,
0x2A, 0x80, 0x86);
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);
/* INS: 0x2A PERFORM SECURITY OPERATION
* P1: 0x80 Resp: Plain value
* P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */
sc_format_apdu(card, &apdu,
(crgram_len < 256) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT,
0x2A, 0x80, 0x86);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
@ -821,17 +989,17 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
if (crgram_len == 256)
{
apdu.le = 0;
/* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */
sbuf[0] = 0x81;
memcpy(sbuf + 1, crgram, crgram_len / 2);
apdu.lc = crgram_len / 2 + 1;
apdu.le = 0;
/* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */
sbuf[0] = 0x81;
memcpy(sbuf + 1, crgram, crgram_len / 2);
apdu.lc = crgram_len / 2 + 1;
}
else
{
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
memcpy(sbuf + 1, crgram, crgram_len);
apdu.lc = crgram_len + 1;
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
memcpy(sbuf + 1, crgram, crgram_len);
apdu.lc = crgram_len + 1;
}
apdu.datalen = apdu.lc;
@ -841,43 +1009,44 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
{
if (crgram_len == 256)
{
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT,
0x2A, 0x80, 0x86);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = crgram_len;
/* padding indicator byte,
* 0x82 = Second half of 2048 bit cryptogram */
sbuf[0] = 0x82;
memcpy(sbuf + 1, crgram + crgram_len / 2, crgram_len / 2);
apdu.lc = crgram_len / 2 + 1;
apdu.datalen = apdu.lc;
apdu.data = sbuf;
if (crgram_len == 256)
{
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT,
0x2A, 0x80, 0x86);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = crgram_len;
/* padding indicator byte,
* 0x82 = Second half of 2048 bit cryptogram */
sbuf[0] = 0x82;
memcpy(sbuf + 1, crgram + crgram_len / 2, crgram_len / 2);
apdu.lc = crgram_len / 2 + 1;
apdu.datalen = apdu.lc;
apdu.data = sbuf;
r = sc_transmit_apdu(card, &apdu);
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit 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);
}
}
else
{
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
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);
}
}
else
{
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len);
LOG_FUNC_RETURN(card->ctx, len);
}
}
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
memcpy(out, apdu.resp, len);
LOG_FUNC_RETURN(card->ctx, len);
}
}
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)
{
@ -1012,7 +1181,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len)
apdu.data = sbuf;
apdu.datalen = len;
apdu.lc = len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -1045,22 +1214,22 @@ static int myeid_generate_store_key(struct sc_card *card,
memcpy(sbuf + len, data->pubexp, data->pubexp_len);
len += data->pubexp_len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
apdu.data = sbuf;
apdu.data = sbuf;
}
else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) {
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x46, 0x00, 0x00);
apdu.data = NULL;
apdu.resp = sbuf;
apdu.resplen = 0x00;
apdu.le = 0x00;
}
apdu.cla = 0x00;
apdu.datalen = len;
apdu.lc = len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
@ -1088,9 +1257,9 @@ static int myeid_generate_store_key(struct sc_card *card,
LOG_FUNC_RETURN(card->ctx, r);
}
else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) {
if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d,
if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d,
data->d_len)) >= 0 &&
(r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point,
(r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point,
data->ecpublic_point_len)) >= 0)
LOG_FUNC_RETURN(card->ctx, r);
}
@ -1230,25 +1399,25 @@ static struct sc_card_driver * sc_get_driver(void)
if (iso_ops == NULL)
iso_ops = iso_drv->ops;
myeid_ops = *iso_drv->ops;
myeid_ops.match_card = myeid_match_card;
myeid_ops.init = myeid_init;
myeid_ops.finish = myeid_finish;
myeid_ops = *iso_drv->ops;
myeid_ops.match_card = myeid_match_card;
myeid_ops.init = myeid_init;
myeid_ops.finish = myeid_finish;
/* no record oriented file services */
myeid_ops.read_record = NULL;
myeid_ops.write_record = NULL;
myeid_ops.append_record = NULL;
myeid_ops.update_record = NULL;
myeid_ops.select_file = myeid_select_file;
myeid_ops.create_file = myeid_create_file;
myeid_ops.delete_file = myeid_delete_file;
myeid_ops.list_files = myeid_list_files;
myeid_ops.set_security_env = myeid_set_security_env;
myeid_ops.compute_signature = myeid_compute_signature;
myeid_ops.decipher = myeid_decipher;
myeid_ops.process_fci = myeid_process_fci;
myeid_ops.card_ctl = myeid_card_ctl;
myeid_ops.pin_cmd = myeid_pin_cmd;
myeid_ops.read_record = NULL;
myeid_ops.write_record = NULL;
myeid_ops.append_record = NULL;
myeid_ops.update_record = NULL;
myeid_ops.select_file = myeid_select_file;
myeid_ops.create_file = myeid_create_file;
myeid_ops.delete_file = myeid_delete_file;
myeid_ops.list_files = myeid_list_files;
myeid_ops.set_security_env = myeid_set_security_env;
myeid_ops.compute_signature = myeid_compute_signature;
myeid_ops.decipher = myeid_decipher;
myeid_ops.process_fci = myeid_process_fci;
myeid_ops.card_ctl = myeid_card_ctl;
myeid_ops.pin_cmd = myeid_pin_cmd;
return &myeid_drv;
}

View File

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

View File

@ -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,7 +2082,10 @@ pgp_build_tlv(sc_context_t *ctx, unsigned int tag, u8 *data, size_t len, u8 **ou
highest_order++;
}
highest_order--;
cla = tag >> 8*highest_order;
if (highest_order >= 4)
cla = 0x00;
else
cla = tag >> 8*highest_order;
/* Restore class bits */
*out[0] |= cla;
return SC_SUCCESS;
@ -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);

View File

@ -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;
}
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
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;

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
_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;
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);
/* 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 */
r = process_fci(card->ctx, file, apdu.resp,
apdu.resplen);
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,15 +673,18 @@ 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);
/* unify path (the first FID should be MF) */
if (path[0] != 0x3f || path[1] != 0x00)
{
n_pathbuf[0] = 0x3f;
n_pathbuf[1] = 0x00;
for (i=0; i< pathlen; i++)
n_pathbuf[i+2] = pathbuf[i];
path = n_pathbuf;
pathlen += 2;
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)
{
n_pathbuf[0] = 0x3f;
n_pathbuf[1] = 0x00;
for (i=0; i< pathlen; i++)
n_pathbuf[i+2] = pathbuf[i];
path = n_pathbuf;
pathlen += 2;
}
}
/* check current working directory */
@ -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,33 +1474,65 @@ 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 */
/* set the hash value */
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A,
0x90, 0x81);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 0;
memcpy(sbuf, data, datalen);
apdu.data = sbuf;
apdu.lc = datalen;
apdu.datalen = datalen;
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 (card->type == SC_CARD_TYPE_STARCOS_V3_4) {
size_t tmp_len;
/* call COMPUTE SIGNATURE */
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A,
0x9E, 0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
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.lc = 0;
apdu.datalen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
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);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 0;
memcpy(sbuf, data, datalen);
apdu.data = sbuf;
apdu.lc = datalen;
apdu.datalen = datalen;
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));
/* call COMPUTE SIGNATURE */
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A,
0x9E, 0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
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");
}
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,14 +1549,16 @@ 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) {
u8 le = 0xff & from->le;
res = cwa_compose_tlv(card, 0x97, 1, &le, &ccbuf, &cclen);
if (res != SC_SUCCESS) {
msg = "Encode APDU compose_tlv(0x97) failed";
goto encode_end;
}
/* 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) {
msg = "Encode APDU compose_tlv(0x97) failed";
goto encode_end;
}
}
/* copy current data to apdu buffer (skip header and header padding) */
memcpy(apdubuf, ccbuf + 8, cclen - 8);
@ -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) {

View File

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

View File

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

View File

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

View File

@ -985,7 +985,8 @@ 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");
sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Create data: %s", sc_dump_hex(*out, out_len));
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 */

View File

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

View File

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

View File

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

View File

@ -31,37 +31,19 @@
static void fixup_transceive_length(const struct sc_card *card,
struct sc_apdu *apdu)
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;
}
}
@ -105,7 +87,7 @@ static const struct sc_card_error iso7816_errors[] = {
{ 0x6A87, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with P1-P2" },
{ 0x6A88, SC_ERROR_DATA_OBJECT_NOT_FOUND,"Referenced data not found" },
{ 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "File already exists"},
{ 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"},
{ 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"},
{ 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
{ 0x6D00, SC_ERROR_INS_NOT_SUPPORTED, "Instruction code not supported or invalid" },
@ -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];
/* 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);
} else {
file->size = 0;
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 */

View File

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

View File

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

View File

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

View File

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

View File

@ -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>
@ -662,8 +664,7 @@ int msc_compute_crypt_init(sc_card_t *card,
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
short receivedData = outputBuffer[0] << 8 | outputBuffer[1];
*outputDataLength = receivedData;
*outputDataLength = 0;
*outputDataLength = receivedData;
assert(receivedData <= MSC_MAX_APDU);
memcpy(outputData, outputBuffer + 2, receivedData);

View File

@ -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 {
@ -310,7 +325,7 @@ typedef struct sc_reader {
#define SC_PIN_CMD_GET_INFO 3
#define SC_PIN_CMD_USE_PINPAD 0x0001
#define SC_PIN_CMD_NEED_PADDING 0x0002
#define SC_PIN_CMD_NEED_PADDING 0x0002
#define SC_PIN_CMD_IMPLICIT_CHANGE 0x0004
#define SC_PIN_ENCODING_ASCII 0
@ -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;

View File

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

View File

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

View File

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

View File

@ -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>
@ -249,8 +251,8 @@ asn1_free_pbes2_params(void *ptr)
free(params);
}
static const struct sc_asn1_entry c_asn1_ec_params[] = {
{ "ecParameters", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
static const struct sc_asn1_entry c_asn1_ec_params[] = {
{ "ecParameters", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "namedCurve", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL},
{ "implicityCA", SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
@ -263,73 +265,71 @@ 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
/* We only want to copy the parms if they are a namedCurve
* or ecParameters nullParam aka implicityCA is not to be
* used with PKCS#11 2.20 */
sc_copy_asn1_entry(c_asn1_ec_params, asn1_ec_params);
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;
}
ecp = calloc(sizeof(struct sc_ec_parameters), 1);
if (ecp == NULL)
return SC_ERROR_OUT_OF_MEMORY;
if (r <= 1) {
ecp->der = malloc(buflen);
if (ecp->der == NULL)
ecp->der.value = malloc(buflen);
if (ecp->der.value == NULL) {
free(ecp);
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
}
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)
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

View File

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

View File

@ -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,12 +114,17 @@ 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);
fclose(f);
fclose(f);
if (got != count) {
if (data)
free(data);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,11 +383,11 @@ 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;
int key_ref = 0x03;
int key_ref = 0x03;
if (gemsafe_prkeys[i].label == NULL)
continue;
@ -403,7 +398,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
} else
pauthId = NULL;
sc_format_path(gemsafe_prkeys[i].path, &path);
/*
/*
* The key ref may be different for different sites;
* by adding flags=n where the low order 4 bits can be
* the key ref we can force it.
@ -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