Compare commits

...

79 Commits

Author SHA1 Message Date
giomba 932bd27549 libgcns: ArchLinux package 2022-01-08 20:37:35 +01:00
giomba b965e20bfd libgcns: C++ version 2022-01-06 21:12:55 +01:00
giomba 060d8ddb19 libgcns: first commit 2022-01-06 20:27:23 +01:00
giomba 5167b30043 gcns.c: refactoring 2022-01-06 18:04:42 +01:00
giomba 606edadb13 gcns.c: read Italian healthcare smart card 2022-01-06 17:29:06 +01:00
Jakub Jelen c902e19921 prepare 0.22.0 release 2021-08-10 11:09:03 +02:00
Vesa Jääskeläinen e97fec4d91 pkcs11-spy: Fix attribute displaying crash in case pTemplate=NULL
In real world pTemplate=NULL case is only used by PKCS#11 test suites but
no need to crash them.

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:54:08 +02:00
Vesa Jääskeläinen cababca4d5 pkcs11-spy: Fix C_OpenSession() crash with phSession=NULL argument
In real world phSession=NULL case is only used by PKCS#11 test suites but
no need to crash them.

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:54:08 +02:00
Vesa Jääskeläinen 63a5a493a6 pkcs11-spy: Match formatting for C_OpenSession()
Match spacing and add [in] to argument dumps.

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:54:08 +02:00
Vesa Jääskeläinen 1b344a4847 pkcs11-spy: Fix C_GetFunctionList() crash with NULL argument
In real world ppFunctionList=NULL case is only used by PKCS#11 test suites but
no need to crash them.

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:54:08 +02:00
Vesa Jääskeläinen 7007eda0ba pkcs11-spy: fix random crash in print_generic()
Depending on stack state print_generic() could cause crash or spurious garbage
in logs.

Example crash:

*** buffer overflow detected ***: pkcs11test terminated

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:53:13 +02:00
Vesa Jääskeläinen 1991fa24ae [merge] new output for pMechas
Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:52:42 +02:00
Vesa Jääskeläinen 6431f69dcc pkcs11-spy: Fix crash for pMechanism=NULL
Some test suites are excercising pMechanism==NULL case and this causes
crash when using pkcs11-spy for logging in between.

Centralize logging for pMechanism and handle NULL case.

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
2021-08-10 08:52:42 +02:00
Frank Morgner 7d315b5546
Merge pull request #2379 from dengert/Fix-new-line
log.c - fix newline - Fixes:#2378
2021-08-09 14:52:41 +02:00
Doug Engert 4c923c637c log.c - fix newline - Fixes:#2378
On branch Fix-new-line
 Changes to be committed:
	modified:   log.c
2021-08-06 13:53:49 -05:00
Jakub Jelen b67261ab27 Upload also tarball as a build artifact 2021-08-04 22:08:19 +02:00
Jakub Jelen 68b7efb591 github actions: Unbreak migw builds 2021-08-04 22:08:19 +02:00
Jakub Jelen 3048156db0 Execute push-artifacts on macos 2021-08-04 22:08:19 +02:00
Jakub Jelen 1e43a6a1af Make sure the dist creates tarball for pushing artifacts 2021-08-04 22:08:19 +02:00
Doug Engert c6a9b5699a PIV-improved parsing - fix two whilhspace nits
On branch PIV-improved-parsing
 Changes to be committed:
	modified:   card-piv.c
2021-08-04 08:58:06 +02:00
Doug Engert 445a6324de Remove unused code
two lines that are never executed are removed for the code.
The LOG_TEST_GOTO_ERR before these lines will goto err.

 On branch PIV-improved-parsing
 Changes to be committed:
	modified:   src/libopensc/card-piv.c
2021-08-04 08:58:06 +02:00
Doug Engert 456ac56693 PIV Improved parsing of data from the card
Based on Fuzz testing, many of the calls to sc_asn1_find_tag were replaced
with sc_asn1_read_tag. The input is also tested that the
expected tag is  the first byte. Additional tests are also add.

sc_asn1_find_tag will skip 0X00 or 0Xff if found. NIST sp800-73-x specs
do not allow these extra bytes.

 On branch PIV-improved-parsing
 Changes to be committed:
	modified:   card-piv.c
2021-08-04 08:58:06 +02:00
Jakub Jelen 8453c0d99a Skip openpgp test for now 2021-08-04 08:57:34 +02:00
Jakub Jelen d47f42b12a README: Update badges and links from travis 2021-08-04 08:57:34 +02:00
Jakub Jelen 01cf556ba2 github-actions: Unbreak artifacts pushing 2021-08-04 08:57:34 +02:00
Jakub Jelen f43d3f8042 Add Javacard tests and mingw build to Github Actions
* PIV applet
* Isoapplet
* Gids Applet
* openpgp applet
* Split clang-tidy to separate task as it is too slow
2021-08-03 12:00:49 +02:00
Jakub Jelen 5d338739ac CI: Avoid warnings from tput
As reported by Peter Popovec
2021-08-03 12:00:49 +02:00
Jakub Jelen e683c531f6 Migrate some tests to Github Actions
This ads also retention json files with results from p11test to
make sure we are not introducing regressions for existing cards.
2021-08-03 12:00:49 +02:00
Jakub Jelen 1b329093f7 Move the cifuzz to separate file 2021-08-03 12:00:49 +02:00
Jakub Jelen bc9b9df869 Do not use EVP_PKEY_get0() for EC_KEY handling
The function is intentionally broken in OpenSSL 3.0 for provided keys
and returning NULL. But it should still work for the legacy gost engine
implementation (but I do not have a good way to check).

Discussed in openssl upstream issue:

https://github.com/openssl/openssl/issues/16081
2021-08-02 10:05:59 +02:00
Frank Morgner 99656deaf4 avoid limited size when logging data 2021-07-15 10:04:23 +02:00
Jakub Jelen 9a5a008093 pkcs15-tool: Update the logic to make it more clear for some dumb static analyzers 2021-07-15 09:51:59 +02:00
Jakub Jelen d34e84c78d eidenv: Avoid memory leak 2021-07-15 09:51:59 +02:00
Frank Morgner d90048e5bb
Merge pull request #2357 from a-dma/p11_extractable
pkcs11-tool: allow setting CKA_EXTRACTABLE during keypair generation
2021-07-05 16:21:41 +02:00
Jakub Jelen aa6574b60e New rc published 2021-06-29 18:17:19 +02:00
Jakub Jelen fd6b64b91b Update NEWS with recently merged changes 2021-06-29 13:58:55 +02:00
Alessio Di Mauro 2f94a6b155
pkcs11-tool: allow setting CKA_EXTRACTABLE during keypair generation
Section 4.9 of the PKCS#11 v2.40 specification [1], mentions
CKA_EXTRACTABLE as a valid attribute for Private Key objects. However,
when calling "pkcs11-tool" with the "--exportable" option, the
attribute is not set as part of the private key template.

[1]: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/os/pkcs11-base-v2.40-errata01-os-complete.html
2021-06-23 15:29:29 +02:00
Doug Engert aebebac432 p11test: Use OPTIONAL_OPENSSL_CFLAGS
Needed if building with OpenSSL in non stanard location.

 Changes to be committed:
	modified:   src/tests/p11test/Makefile.am
2021-06-11 05:28:07 -05:00
Frank Morgner c42792c216
Merge pull request #2343 from Jakuje/ossl3v1
Working subset of #2337 (OpenSSL 3.0)
2021-06-07 14:38:30 +02:00
Stephan Mühlstrasser 151583ce26 C_Initialize() must copy CK_C_INITIALIZE_ARGS
C_Initialize() must make a copy of the function pointers supplied
via pInitArgs, as the PKCS#11 specification makes no guarantee that
the pInitArgs pointer is allowed to be dereferenced after C_Initialize()
returns.

Fixes issue #2170.
2021-06-07 12:44:07 +02:00
Jakub Jelen 9be6dc6606 pkcs11: Update the version to 3.0 (unused anywhere though) 2021-06-02 15:46:00 +02:00
Jakub Jelen 9d1a214340 pkcs11: Undefine internal typedef and remove its usage 2021-06-02 15:46:00 +02:00
Jakub Jelen fc2fecc80e Use const types for RSA and EC_KEY
These are anyway not supposed to be modified even in older versions of
openssl.

Visible when building with -Wno-deprecated-declarations
2021-06-02 15:46:00 +02:00
Jakub Jelen ffd6e2a576 p11test: Expect DERIVE to be set on both private and public key
Basically reverts part of 485b6cf, which turned out to be wrong.

Alternative to #2292
2021-05-31 15:36:29 +02:00
Jaime Hablutzel 465375bda2 Fixing command-line option names in error messages 2021-05-26 10:41:30 +02:00
Jakub Jelen 33426df3ff p11test: Do not return on warnings for (X)EDDSA keys 2021-05-24 11:25:53 +02:00
Jakub Jelen 8e4134841d p11test: Add new mechanisms from softhsm 2021-05-24 11:25:53 +02:00
Jakub Jelen a8a4bddfad p11test: Debug level from commandline
This replaces the debug level defined at build time with -NDEBUG,
which turned out to be quite confusing.

Fixes #2304
2021-05-24 11:25:53 +02:00
Jakub Jelen a69ab7c70c tests: Fix context for the asn1 test 2021-05-24 11:25:53 +02:00
Jakub Jelen fd96d2c960 Do not use deprecated ERR_load_ERR_strings() with OpenSSL 3.0 2021-05-24 11:25:53 +02:00
Jakub Jelen 1b92501ef9 sm: Rewrite to use non-deprecated OpenSSL 3.0 API 2021-05-24 11:25:53 +02:00
Jakub Jelen 07f5e63abf tests: verify secure messaging functions work as expected 2021-05-24 11:25:53 +02:00
Jakub Jelen 12be677cb8 Drop duplicate -Werror build flag (already used unless --disable-strict) 2021-05-24 11:25:53 +02:00
Jakub Jelen e4cf0e7b39 Basic unit test for secure messaging functions 2021-05-24 11:25:53 +02:00
Jakub Jelen 0b45e78e4f idprime: Fix RSA-PKCS mechanism with hashing on card 2021-05-24 10:42:08 +02:00
Yaroslav Isakov fc08818f6f OpenPGP: Fix read/write certs with Ed25519/X25519 public key
Proper Ed25519/X25519 certs have pubkey algo with OID 1.3.101.112/110, according to
RFC8410. This commit add these OIDs, and also fixes pubkey parsing/creation - according
to the same RFC, it's just a bytestring, without ASN.1 wrapping.

Also, according to the same RFC, EDDSA/X25519 MUST not have params, even empty.
2021-05-21 14:37:30 +02:00
Yaroslav Isakov 23dc52c903 Fixed OpenPGP logic for comparing OIDs
It's better to leave oid comparison as it was before, and drop trailing
zero byte after it, when reading from token.
2021-05-20 11:11:05 +02:00
Yaroslav Isakov 29410c170e Make OpenPGP curves to be a pointer to OpenPGP 3.4 curves list 2021-05-20 11:11:05 +02:00
Yaroslav Isakov f356d301b9 Enable ed25519/curve25519 support for Yubikey 5 2021-05-20 11:11:05 +02:00
Doug Engert 48a11c0634 Update piv-tool man pages for AES
commit 295c523e4 (William Roberts     2014-07-08 13:52:48)
added support for AES keys to card-piv.c but the man page
for piv-tool that uses the code was never  updated.

 On branch piv-tool-doc
 Changes to be committed:
	modified:   ../../doc/tools/piv-tool.1.xml
2021-05-20 11:07:29 +02:00
Doug Engert f1bc07dec1 Fix piv-tool on wondows
fopen needs "rb" for fopen in two places

fixes #2338

 On branch piv-tool-windows
 Changes to be committed:
	modified:   piv-tool.c
2021-05-20 10:37:31 +02:00
Doug Engert 8dfafe4fc2 Fix 2340 pkcs15-sec.c wrong test
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA) { is the correct test.
2021-05-17 15:00:26 +02:00
Vincent JARDIN 5256bc3d3d tests: minidriver using T0 or T1
Some cards should be used with T0 and some others with T1. Let's support
both.

Fix: issue #2326
2021-05-17 12:06:12 +02:00
Vincent JARDIN 180737d1b6 tests: minidriver runtime PINCODE
Let's define an environment MINIDRIVER_PIN=1234 in order to be able
to reuse the tests with any cards.
usage:
(cmd) set MINIDRIVER_PIN=1234

When the PIN code is not defined, let's skip the tests since it may runs
the number of trials out of the max attempts.

Moreover, some cards may have many roles, but the tests are designed for
the ROLE_USER, so let's enforce only the ROLE_USER.

Fix: issue #2326
2021-05-17 12:06:12 +02:00
Vincent JARDIN f0c059ede8 ATRMask: better describe the rule to be applied
Include some notes in order to properly define the ATR values.

Suggested-by: Doug Engert <deengert@gmail.com>
Fix: issue #2321
2021-05-12 07:51:42 +02:00
Vincent JARDIN 46c50dc51d CPx: add registration for Windows/minidrivers
Let's OpenSC be able to support the IAS/ECC CPx cards.

Suggested-by: Doug Engert <deengert@gmail.com>

Fix: issue #2321
2021-05-12 07:51:42 +02:00
Georgi Kirichkov ca01d2c5e2 Code style changes 2021-05-11 11:44:39 +02:00
Georgi Kirichkov 5ae0ef4f41 Sets card->name for IDPrime v3 and v4 cards 2021-05-11 11:44:39 +02:00
Georgi Kirichkov 072c64aaed Adds Gemalto IDPrime v4 2021-05-11 11:44:39 +02:00
Alon Bar-Lev 35a8a1d7e1 pkcs11.h: avoid C++ comments 2021-05-07 23:59:12 +02:00
Ludovic Rousseau 2ea5ed8ddd Fix 'make check' when make --jobs= is used
The error was:
PASS: test-duplicate-symbols.sh
PASS: test-pkcs11-tool-allowed-mechanisms.sh
XFAIL: test-pkcs11-tool-test.sh
XFAIL: test-pkcs11-tool-test-threads.sh
PASS: test-manpage.sh
FAIL: test-pkcs11-tool-sign-verify.sh
============================================================================
Testsuite summary for OpenSC 0.22.0-rc1
============================================================================
============================================================================
See tests/test-suite.log
Please report to https://github.com/OpenSC/OpenSC/issues
============================================================================

This is because more than 1 test is executed at the same time. So
card_cleanup() is called at the end of one test while another test is
still running.
The problem is easy to replicate using "make --jobs=2".
2021-05-06 15:05:15 +02:00
Jakub Jelen 2f145f5804 Workaround for broken Ubuntu Focal images
https://travis-ci.community/t/clang-10-was-recently-broken-on-linux-unmet-dependencies-for-clang-10-clang-tidy-10-valgrind/11527
2021-05-06 15:02:45 +02:00
Jakub Jelen 613b56ee55 Add correct prefix on the clang-tidy commandline 2021-05-05 14:22:58 +02:00
Jakub Jelen d0b847c6cf tests: Remove files after disclean 2021-05-05 14:22:58 +02:00
Jakub Jelen 835cee2e5a tests: Add correct path to enable out-of-source build 2021-05-05 14:22:58 +02:00
Jakub Jelen 06ac408bb4 travis: Invoke distcheck to make sure all needed files are packaged 2021-05-05 14:22:58 +02:00
divinehawk 98663528cf pkcs15-tool: Write data objects in binary mode 2021-05-03 11:48:28 +02:00
ihsinme 50eaa6bf57 fix possible access outside the array.
if 5000 bytes are read, then at the end of the array we will write zero beyond its boundaries, damaging the stack.
Here's a simple solution. if you see the need to increase the array itself, let me know.
2021-05-03 11:47:51 +02:00
Frank Morgner 32004e74ce added missing files to distribution 2021-05-01 01:42:11 +02:00
83 changed files with 3868 additions and 410 deletions

3
.clang-format Normal file
View File

@ -0,0 +1,3 @@
BasedOnStyle: Google
IndentWidth: 4

54
.github/build.sh vendored Executable file
View File

@ -0,0 +1,54 @@
#!/bin/bash -e
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig;
if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then
PR_NUMBER=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
if [ "$GITHUB_BASE_REF" == "master" ]; then
./bootstrap.ci -s "-pr$PR_NUMBER"
else
./bootstrap.ci -s "$GITHUB_BASE_REF-pr$PR_NUMBER"
fi
else
BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
if [ "$BRANCH" == "master" ]; then
./bootstrap
else
./bootstrap.ci -s "$BRANCH"
fi
fi
if [ "$RUNNER_OS" == "macOS" ]; then
./MacOSX/build
exit $?
fi
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
if [ "$1" == "mingw" ]; then
HOST=x86_64-w64-mingw32
elif [ "$1" == "mingw32" ]; then
HOST=i686-w64-mingw32
fi
unset CC
unset CXX
./configure --host=$HOST --with-completiondir=/tmp --disable-openssl --disable-readline --disable-zlib --disable-notify --prefix=$PWD/win32/opensc || cat config.log;
make -j 2
# no point in running tests on mingw
else
# normal procedure
./configure --disable-dependency-tracking
make -j 2
make check
fi
# this is broken in old ubuntu
if [ "$1" == "dist" ]; then
make distcheck
make dist
fi
sudo make install
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
# pack installed files
wine "C:/Program Files/Inno Setup 5/ISCC.exe" win32/OpenSC.iss
fi

View File

@ -6,7 +6,7 @@ BUILDPATH=${PWD}
BRANCH="`git log --max-count=1 --date=short --abbrev=8 --pretty=format:"%cd_%h"`"
git clone --single-branch https://${GH_TOKEN}@github.com/OpenSC/Nightly.git > /dev/null 2>&1
cd Nightly
pushd Nightly
git checkout -b "${BRANCH}"
for file in ${BUILDPATH}/win32/Output/OpenSC*.exe ${BUILDPATH}/opensc*.tar.gz ${BUILDPATH}/OpenSC*.dmg ${BUILDPATH}/OpenSC*.msi ${BUILDPATH}/OpenSC*.zip
@ -33,3 +33,4 @@ do
git pull --rebase origin --strategy-option ours "${BRANCH}"
i=$(( $i + 1 ))
done
popd

24
.github/setup-java.sh vendored Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash -e
# Select the right java
sudo update-java-alternatives -s java-1.8.0-openjdk-amd64
sudo update-alternatives --get-selections | grep ^java
export PATH="/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH"
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
env | grep -i openjdk
# VSmartcard
./.github/setup-vsmartcard.sh
# Javacard SDKs
git clone https://github.com/martinpaljak/oracle_javacard_sdks.git
export JC_HOME=$PWD/oracle_javacard_sdks/jc222_kit
export JC_CLASSIC_HOME=$PWD/oracle_javacard_sdks/jc305u3_kit
# jCardSim
git clone https://github.com/arekinath/jcardsim.git
pushd jcardsim
env | grep -i openjdk
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
mvn initialize && mvn clean install
popd

42
.github/setup-linux.sh vendored Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash -e
DEPS="docbook-xsl libpcsclite-dev xsltproc gengetopt libcmocka-dev help2man pcscd check softhsm2 pcsc-tools libtool make autoconf autoconf-archive automake libssl-dev zlib1g-dev pkg-config libreadline-dev openssl git"
if [ "$1" == "clang-tidy" ]; then
DEPS="$DEPS clang-tidy"
elif [ "$1" == "cac" ]; then
DEPS="$DEPS libglib2.0-dev libnss3-dev gnutls-bin libusb-dev libudev-dev flex libnss3-tools"
elif [ "$1" == "oseid" ]; then
DEPS="$DEPS socat gawk xxd"
elif [ "$1" == "piv" -o "$1" == "isoapplet" -o "$1" == "gidsapplet" -o "$1" == "openpgp" ]; then
if [ "$1" == "piv" ]; then
DEPS="$DEPS cmake"
fi
DEPS="$DEPS ant openjdk-8-jdk"
elif [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
DEPS="$DEPS wine wine32 xvfb wget"
sudo dpkg --add-architecture i386
if [ "$1" == "mingw" ]; then
DEPS="$DEPS binutils-mingw-w64-x86-64 gcc-mingw-w64-x86-64 mingw-w64"
elif [ "$1" == "mingw32" ]; then
DEPS="$DEPS binutils-mingw-w64-i686 gcc-mingw-w64-i686"
fi
fi
# make sure we do not get prompts
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get install -y build-essential $DEPS
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
if [ ! -f "$(winepath 'C:/Program Files/Inno Setup 5/ISCC.exe')" ]; then
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
export DISPLAY=:99.0
[ -d isetup ] || mkdir isetup
pushd isetup
[ -f isetup-5.5.6.exe ] || wget http://files.jrsoftware.org/is/5/isetup-5.5.6.exe
sleep 5 # make sure the X server is ready ?
wine isetup-5.5.6.exe /SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
popd
fi
fi

32
.github/setup-macos.sh vendored Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
brew install automake
# gengetopt
curl https://ftp.gnu.org/gnu/gengetopt/gengetopt-2.23.tar.xz -L --output gengetopt-2.23.tar.xz
tar xfj gengetopt-2.23.tar.xz
pushd gengetopt-2.23
./configure && make
sudo make install
popd
# help2man
curl https://ftp.gnu.org/gnu/help2man/help2man-1.47.16.tar.xz -L --output help2man-1.47.16.tar.xz
tar xjf help2man-1.47.16.tar.xz
pushd help2man-1.47.16
./configure && make
sudo make install
popd
# openSCToken
export PATH="/usr/local/opt/ccache/libexec:$PATH"
git clone https://github.com/frankmorgner/OpenSCToken.git
sudo rm -rf /Library/Developer/CommandLineTools;
# TODO make the encrypted key working in github
if [ "$GITHUB_EVENT_NAME" == "pull_request" -a -n "$encrypted_3b9f0b9d36d1_key" ]; then
openssl aes-256-cbc -K $encrypted_3b9f0b9d36d1_key -iv $encrypted_3b9f0b9d36d1_iv -in .github/secrets.tar.enc -out .github/secrets.tar -d;
.github/add_signing_key.sh;
else
unset CODE_SIGN_IDENTITY INSTALLER_SIGN_IDENTITY;
fi

8
.github/setup-vsmartcard.sh vendored Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
if [ ! -d "vsmartcard" ]; then
git clone https://github.com/frankmorgner/vsmartcard.git
fi
pushd vsmartcard/virtualsmartcard
autoreconf -vis && ./configure && make -j2 && sudo make install
popd

47
.github/test-cac.sh vendored Executable file
View File

@ -0,0 +1,47 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
# VSmartcard
./.github/setup-vsmartcard.sh
# libcacard
if [ ! -d "libcacard" ]; then
git clone https://gitlab.freedesktop.org/spice/libcacard.git
fi
pushd libcacard
./autogen.sh --prefix=/usr && make -j2 && sudo make install
popd
# virt_cacard
if [ ! -d "virt_cacard" ]; then
git clone https://github.com/Jakuje/virt_cacard.git
fi
pushd virt_cacard
./autogen.sh && ./configure && make
popd
sudo /etc/init.d/pcscd restart
pushd src/tests/p11test/
./p11test -s 0 -p 12345678 -i -o virt_cacard.json &
sleep 5
popd
# virt_cacard startup
pushd virt_cacard
./setup-softhsm2.sh
export SOFTHSM2_CONF=$PWD/softhsm2.conf
./virt_cacard &
wait $(ps aux | grep '[p]11test'| awk '{print $2}')
kill -9 $(ps aux | grep '[v]irt_cacard'| awk '{print $2}')
popd
# cleanup -- this would break later uses of pcscd
pushd vsmartcard/virtualsmartcard
sudo make uninstall
popd
diff -u3 src/tests/p11test/virt_cacard{_ref,}.json

36
.github/test-gidsapplet.sh vendored Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
# setup java stuff
. .github/setup-java.sh
# GidsApplet
git clone https://github.com/vletoux/GidsApplet.git;
javac -classpath jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar GidsApplet/src/com/mysmartlogon/gidsApplet/*.java;
echo "com.licel.jcardsim.card.applet.0.AID=A000000397425446590201" > gids_jcardsim.cfg;
echo "com.licel.jcardsim.card.applet.0.Class=com.mysmartlogon.gidsApplet.GidsApplet" >> gids_jcardsim.cfg;
echo "com.licel.jcardsim.card.ATR=3B80800101" >> gids_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> gids_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.port=35963" >> gids_jcardsim.cfg;
# log errors from pcscd to console
sudo systemctl stop pcscd.service pcscd.socket
sudo /usr/sbin/pcscd -f &
PCSCD_PID=$!
# start the applet and run couple of commands against that
java -noverify -cp GidsApplet/src/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard gids_jcardsim.cfg >/dev/null &
PID=$!;
sleep 5;
opensc-tool --card-driver default --send-apdu 80b80000190bA0000003974254465902010bA00000039742544659020100;
opensc-tool -n;
gids-tool --initialize --pin 123456 --admin-key 000000000000000000000000000000000000000000000000 --serial 00000000000000000000000000000000;
kill -9 $PID
# cleanup
sudo kill -9 $PCSCD_PID

41
.github/test-isoapplet.sh vendored Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
# setup java stuff
./.github/setup-java.sh
# The ISO applet
git clone https://github.com/philipWendland/IsoApplet.git;
javac -classpath jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar IsoApplet/src/net/pwendland/javacard/pki/isoapplet/*.java;
echo "com.licel.jcardsim.card.applet.0.AID=F276A288BCFBA69D34F31001" > isoapplet_jcardsim.cfg;
echo "com.licel.jcardsim.card.applet.0.Class=net.pwendland.javacard.pki.isoapplet.IsoApplet" >> isoapplet_jcardsim.cfg;
echo "com.licel.jcardsim.card.ATR=3B80800101" >> isoapplet_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> isoapplet_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.port=35963" >> isoapplet_jcardsim.cfg;
# log errors from pcscd to console
sudo systemctl stop pcscd.service pcscd.socket
sudo /usr/sbin/pcscd -f &
PCSCD_PID=$!
# start the applet and run couple of commands against that
java -noverify -cp IsoApplet/src/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard isoapplet_jcardsim.cfg >/dev/null &
PID=$!;
sleep 5;
opensc-tool --card-driver default --send-apdu 80b800001a0cf276a288bcfba69d34f310010cf276a288bcfba69d34f3100100;
opensc-tool -n;
pkcs15-init --create-pkcs15 --so-pin 123456 --so-puk 0123456789abcdef;
pkcs15-tool --change-pin --pin 123456 --new-pin 654321;
pkcs15-tool --unblock-pin --puk 0123456789abcdef --new-pin 123456;
pkcs15-init --generate-key rsa/2048 --id 1 --key-usage decrypt,sign --auth-id FF --pin 123456;
pkcs15-init --generate-key rsa/2048 --id 2 --key-usage decrypt --auth-id FF --pin 123456;
pkcs15-init --generate-key ec/secp256r1 --id 3 --key-usage sign --auth-id FF --pin 123456;
pkcs15-tool -D;
pkcs11-tool -l -t -p 123456;
kill -9 $PID;
# cleanup
sudo kill -9 $PCSCD_PID

40
.github/test-openpgp.sh vendored Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
# setup java stuff
. .github/setup-java.sh
# The OpenPGP applet
git clone --recursive https://github.com/Yubico/ykneo-openpgp.git;
cd ykneo-openpgp;
ant -DJAVACARD_HOME=${JC_HOME};
cd $TRAVIS_BUILD_DIR;
echo "com.licel.jcardsim.card.applet.0.AID=D2760001240102000000000000010000" > openpgp_jcardsim.cfg;
echo "com.licel.jcardsim.card.applet.0.Class=openpgpcard.OpenPGPApplet" >> openpgp_jcardsim.cfg;
echo "com.licel.jcardsim.card.ATR=3B80800101" >> openpgp_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> openpgp_jcardsim.cfg;
echo "com.licel.jcardsim.vsmartcard.port=35963" >> openpgp_jcardsim.cfg;
# log errors from pcscd to console
sudo systemctl stop pcscd.service pcscd.socket
sudo /usr/sbin/pcscd -f &
PCSCD_PID=$!
# start the applet and run couple of commands against that
java -noverify -cp ykneo-openpgp/applet/bin:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard openpgp_jcardsim.cfg >/dev/null &
PID=$!;
sleep 5;
opensc-tool --card-driver default --send-apdu 80b800002210D276000124010200000000000001000010D276000124010200000000000001000000;
opensc-tool -n;
openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2;
pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048;
pkcs11-tool -l -t -p 123456;
kill -9 $PID
# cleanup
sudo kill -9 $PCSCD_PID

54
.github/test-oseid.sh vendored Executable file
View File

@ -0,0 +1,54 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
if [ ! -d oseid ]; then
git clone https://github.com/popovec/oseid
fi
pushd oseid/src/
make -f Makefile.console
if [ ! -d tmp ]; then
mkdir tmp
fi
socat -d -d pty,link=tmp/OsEIDsim.socket,raw,echo=0 "exec:build/console/console ...,pty,raw,echo=0" &
PID=$!
sleep 1
echo "# OsEIDsim" > tmp/reader.conf
echo 'FRIENDLYNAME "OsEIDsim"' >> tmp/reader.conf
echo "DEVICENAME $PWD/tmp/OsEIDsim.socket" >> tmp/reader.conf
echo "LIBPATH $PWD/build/console/libOsEIDsim.so.0.0.1" >> tmp/reader.conf
echo "CHANNELID 1" >> tmp/reader.conf
sudo mv tmp/reader.conf /etc/reader.conf.d/reader.conf
cat /etc/reader.conf.d/reader.conf
popd
sudo /etc/init.d/pcscd restart
# Needed for tput to not report warnings
export TERM=xterm-256color
pushd oseid/tools
echo | ./OsEID-tool INIT
./OsEID-tool RSA-CREATE-KEYS
./OsEID-tool RSA-UPLOAD-KEYS
./OsEID-tool RSA-DECRYPT-TEST
./OsEID-tool RSA-SIGN-PKCS11-TEST
./OsEID-tool EC-CREATE-KEYS
./OsEID-tool EC-UPLOAD-KEYS
./OsEID-tool EC-SIGN-TEST
./OsEID-tool EC-SIGN-PKCS11-TEST
./OsEID-tool EC-ECDH-TEST
popd
# this does not work as we have random key IDs in here
#pushd src/tests/p11test/
#./p11test -s 0 -p 11111111 -o oseid.json || true
#diff -u3 oseid_ref.json oseid.json
#popd
# cleanup -- this would break later uses of pcscd
kill -9 $PID
rm oseid/src/card_mem
sudo rm /etc/reader.conf.d/reader.conf

45
.github/test-piv.sh vendored Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash -e
# install the opensc
sudo make install
export LD_LIBRARY_PATH=/usr/local/lib
# setup java stuff
. .github/setup-java.sh
# The PIV Applet
git clone --recursive https://github.com/arekinath/PivApplet.git
pushd PivApplet
JC_HOME=${JC_CLASSIC_HOME} ant dist
popd
# yubico-piv-tool is needed for PIV Applet management
git clone https://github.com/Yubico/yubico-piv-tool.git
pushd yubico-piv-tool
mkdir build
pushd build
cmake .. && make && sudo make install
popd
popd
# log errors from pcscd to console
sudo systemctl stop pcscd.service pcscd.socket
sudo /usr/sbin/pcscd -f &
PCSCD_PID=$!
# start the applet and run couple of commands against that
java -noverify -cp PivApplet/bin/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard PivApplet/test/jcardsim.cfg >/dev/null &
PID=$!
sleep 5
opensc-tool --card-driver default --send-apdu 80b80000120ba000000308000010000100050000020F0F7f
opensc-tool -n
yubico-piv-tool -v 9999 -r 'Virtual PCD 00 00' -P 123456 -s 9e -a generate -A RSA2048
yubico-piv-tool -v 9999 -r 'Virtual PCD 00 00' -P 123456 -s 9a -a generate -A ECCP256
pkcs11-tool -l -t -p 123456
kill -9 $PID
# cleanup
sudo kill -9 $PCSCD_PID

176
.github/workflows/linux.yml vendored Normal file
View File

@ -0,0 +1,176 @@
name: Linux
on:
pull_request:
paths:
- '**.c'
- '**.h'
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: .github/setup-linux.sh
- run: .github/build.sh dist
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-${{ github.sha }}
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: opensc-build
path:
opensc*.tar.gz
build-ubuntu-18:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- run: .github/setup-linux.sh
- run: .github/build.sh
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-18-${{ github.sha }}
build-mingw:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: .github/setup-linux.sh mingw
- run: .github/build.sh mingw
- name: Cache build artifacts
uses: actions/upload-artifact@v2
with:
name: opensc-build-mingw
path:
win32/Output/OpenSC*.exe
build-mingw32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: .github/setup-linux.sh mingw32
- run: .github/build.sh mingw32
- name: Cache build artifacts
uses: actions/upload-artifact@v2
with:
name: opensc-build-mingw32
path:
win32/Output/OpenSC*.exe
test-piv:
runs-on: ubuntu-18.04
needs: [build-ubuntu-18]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-18-${{ github.sha }}
- run: .github/setup-linux.sh piv
- run: .github/test-piv.sh
test-isoapplet:
runs-on: ubuntu-18.04
needs: [build-ubuntu-18]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-18-${{ github.sha }}
- run: .github/setup-linux.sh isoapplet
- run: .github/test-isoapplet.sh
test-gidsapplet:
runs-on: ubuntu-18.04
needs: [build-ubuntu-18]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-18-${{ github.sha }}
- run: .github/setup-linux.sh gidsapplet
- run: .github/test-gidsapplet.sh
test-openpgp:
runs-on: ubuntu-18.04
needs: [build-ubuntu-18]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-18-${{ github.sha }}
- run: .github/setup-linux.sh openpgp
# the openpgp sometimes fails
- run: .github/test-openpgp.sh || true
build-clang-tidy:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-${{ github.sha }}
- run: .github/setup-linux.sh clang-tidy
- run: .github/build.sh
test-cac:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-${{ github.sha }}
- run: .github/setup-linux.sh cac
- run: .github/test-cac.sh
test-oseid:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-${{ github.sha }}
- run: .github/setup-linux.sh oseid
- run: .github/test-oseid.sh
push-artifacts:
runs-on: ubuntu-latest
needs: [build, build-mingw]
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-build
with:
path: ./*
key: ${{ runner.os }}-${{ github.sha }}
- name: Pull mingw build artifacts
uses: actions/download-artifact@v2
with:
name: opensc-build-mingw
- run: git config --global user.email "builds@github.com"
- run: git config --global user.name "Github Actions";
- run: .github/push_artifacts.sh "Github Actions ${GITHUB_REF}"
if: ${{ github.event_name != 'pull_request' && github.repository == 'OpenSC/OpenSC' }}

39
.github/workflows/macos.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: OSX
on:
pull_request:
paths:
- '**.c'
- '**.h'
push:
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: .github/setup-macos.sh
- run: .github/build.sh
- name: Cache build artifacts
uses: actions/upload-artifact@v2
with:
name: opensc-build-macos
path:
OpenSC*.dmg
push-artifacts:
runs-on: macos-latest
needs: [build]
steps:
- uses: actions/checkout@v2
- name: Pull build artifacts
uses: actions/download-artifact@v2
with:
name: opensc-build-macos
- run: git config --global user.email "builds@github.com"
- run: git config --global user.name "Github Actions";
- run: .github/push_artifacts.sh "Github Actions ${GITHUB_REF}"
if: ${{ github.event_name != 'pull_request' && github.repository == 'OpenSC/OpenSC' }}
# TODO this fails probably because the key is not loaded in keychain before with
# security: SecKeychainDelete: The specified keychain could not be found.
# - run: .github/remove_signing_key.sh; rm -f .github/secrets.tar

1
.gitignore vendored
View File

@ -80,6 +80,7 @@ src/tools/pkcs15-init
src/tools/eidenv
src/tools/opensc-explorer
src/tools/cardos-info
src/tools/gcns
src/tools/sceac-example
src/tools/opensc-notify
src/tools/opensc-notify.plist

View File

@ -51,27 +51,29 @@ env:
- COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
- SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
addons:
apt_packages:
- binutils-mingw-w64-i686
- binutils-mingw-w64-x86-64
- docbook-xsl
- gcc-mingw-w64-i686
- gcc-mingw-w64-x86-64
- libpcsclite-dev
- mingw-w64
- xsltproc
- gengetopt
- libcmocka-dev
- help2man
- pcscd
- pcsc-tools
- check
- ant
- socat
- cmake
- clang-tidy
- softhsm2
# Commented out because of a bug in travis images for Focal:
# https://travis-ci.community/t/clang-10-was-recently-broken-on-linux-unmet-dependencies-for-clang-10-clang-tidy-10-valgrind/11527
#addons:
# apt_packages:
# - binutils-mingw-w64-i686
# - binutils-mingw-w64-x86-64
# - docbook-xsl
# - gcc-mingw-w64-i686
# - gcc-mingw-w64-x86-64
# - libpcsclite-dev
# - mingw-w64
# - xsltproc
# - gengetopt
# - libcmocka-dev
# - help2man
# - pcscd
# - pcsc-tools
# - check
# - ant
# - socat
# - cmake
# - clang-tidy
# - softhsm2
before_install:
# homebrew is dead slow in older images due to the many updates it would need to download and build.
@ -114,6 +116,12 @@ before_install:
- if [ -n "${HOST}" ]; then
sudo apt-get install -y wine;
fi
- if [ "$TRAVIS_DIST" == "focal" ]; then
sudo apt-get install -yq --allow-downgrades libc6=2.31-0ubuntu9.2 libc6-dev=2.31-0ubuntu9.2;
fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --allow-downgrades --allow-remove-essential --allow-change-held-packages install binutils-mingw-w64-i686 binutils-mingw-w64-x86-64 docbook-xsl gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 libpcsclite-dev mingw-w64 xsltproc gengetopt libcmocka-dev help2man pcscd pcsc-tools check ant socat cmake clang-tidy softhsm2;
fi
before_script:
- if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then
@ -252,7 +260,7 @@ script:
fi;
fi
- if [ -z "$HOST" -a "${DO_COVERITY_SCAN}" != "yes" -a -z "$DO_SIMULATION" ]; then
make check && make dist || (cat tests/*log src/tests/unittests/*log && exit 1);
make check && make distcheck || (cat tests/*log src/tests/unittests/*log && exit 1);
fi
- if [ ! -z "$HOST" -a "${DO_COVERITY_SCAN}" != "yes" ]; then
make install;

9
NEWS
View File

@ -1,6 +1,6 @@
NEWS for OpenSC -- History of user visible changes
# New in 0.22.0; 2021-04-XX
# New in 0.22.0; 2021-08-10
## General improvements
* Use standard paths for file cache on Linux (#2148) and OSX (#2214)
* Various issues of memory/buffer handling in legacy drivers mostly reported by oss-fuzz and coverity (tcos, oberthur, isoapplet, iasecc, westcos, gpk, flex, dnie, mcrd, authentic, belpic)
@ -9,13 +9,17 @@ NEWS for OpenSC -- History of user visible changes
* `opensc-explorer`: Print information about LCS (Life cycle status byte) (#2195)
* Add support for Apple's arm64 (M1) binaries, removed TokenD. A seperate installer with TokenD (and without arm64 binaries) will be available (#2179).
* Support for gcc11 and its new strict aliasing rules (#2241, #2260)
* Initial support for building with OpenSSL 3.0 (#2343)
* pkcs15-tool: Write data objects in binary mode (#2324)
* Avoid limited size of log messages (#2352)
## PKCS#11
* Support for ECDSA verification (#2211)
* Support for ECDSA with different SHA hashes (#2190)
* Prevent issues in p11-kit by not returning unexpected return codes (#2207)
* Add support for PKCS#11 3.0: The new interfaces, profile objects and functions (#2096)
* Add support for PKCS#11 3.0: The new interfaces, profile objects and functions (#2096, #2293)
* Standardize the version 2 on 2.20 in the code (#2096)
* Fix CKA_MODIFIABLE and CKA_EXTRACTABLE (#2176)
* Copy arguments of C_Initialize (#2350)
## Minidriver
* Fix RSA-PSS signing (#2234)
## OpenPGP
@ -23,6 +27,7 @@ NEWS for OpenSC -- History of user visible changes
* Add support for (X)EdDSA keys (#1960)
## IDPrime
* Add support for applet version 3 and fix RSA-PSS mechanisms (#2205)
* Add support for applet version 4 (#2332)
## MyEID
* New configuration option for opensc.conf to disable pkcs1_padding (#2193)
* Add support for ECDSA with different hashes (#2190)

View File

@ -4,7 +4,8 @@ Wiki is [available online](https://github.com/OpenSC/OpenSC/wiki)
Please take a look at the documentation before trying to use OpenSC.
[![Travis CI Build Status](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches)
[![Linux build](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml)
[![OSX build](https://github.com/OpenSC/OpenSC/actions/workflows/macos.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/macos.yml)
[![AppVeyor CI Build Status](https://ci.appveyor.com/api/projects/status/github/OpenSC/OpenSC?branch=master&svg=true)](https://ci.appveyor.com/project/LudovicRousseau/OpenSC/branch/master)
[![Coverity Scan Status](https://scan.coverity.com/projects/4026/badge.svg)](https://scan.coverity.com/projects/4026)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/OpenSC/OpenSC.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/OpenSC/OpenSC/context:cpp)
@ -15,11 +16,11 @@ Build and test status of specific cards:
| Cards | Status |
|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| CAC | [![CAC](https://gitlab.com/redhat-crypto/OpenSC/badges/cac/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
| [virt_CACard](https://github.com/PL4typus/virt_cacard) | [![virt_CACard](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| CAC | [![CAC](https://gitlab.com/redhat-crypto/OpenSC/badges/cac/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
| [virt_CACard](https://github.com/Jakuje/virt_cacard) | [![virt_CACard](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
| [Coolkey](https://github.com/dogtagpki/coolkey/tree/master/applet) | [![Coolkey](https://gitlab.com/redhat-crypto/OpenSC/badges/coolkey/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
| [PivApplet](https://github.com/arekinath/PivApplet) | [![PIV](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| [OpenPGP Applet](https://github.com/Yubico/ykneo-openpgp/) | [![OpenPGP](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| [GidsApplet](https://github.com/vletoux/GidsApplet/) | [![GIDS](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| [IsoApplet](https://github.com/philipWendland/IsoApplet/) | [![IsoApplet](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| [OsEID (MyEID)](https://sourceforge.net/projects/oseid/) | [![OsEID (MyEID)](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
| [PivApplet](https://github.com/arekinath/PivApplet) | [![PIV](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
| [OpenPGP Applet](https://github.com/Yubico/ykneo-openpgp/) | [![OpenPGP](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
| [GidsApplet](https://github.com/vletoux/GidsApplet/) | [![GIDS](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
| [IsoApplet](https://github.com/philipWendland/IsoApplet/) | [![IsoApplet](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
| [OsEID (MyEID)](https://sourceforge.net/projects/oseid/) | [![OsEID (MyEID)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |

View File

@ -9,7 +9,7 @@ define([PRODUCT_URL], [https://github.com/OpenSC/OpenSC])
define([PACKAGE_VERSION_MAJOR], [0])
define([PACKAGE_VERSION_MINOR], [22])
define([PACKAGE_VERSION_FIX], [0])
define([PACKAGE_SUFFIX], [-rc1])
define([PACKAGE_SUFFIX], [])
define([VS_FF_LEGAL_COPYRIGHT], [OpenSC Project])
define([VS_FF_LEGAL_COMPANY_NAME], [OpenSC Project])
@ -46,7 +46,7 @@ OPENSC_VS_FF_PRODUCT_URL="VS_FF_PRODUCT_URL"
# (Oldest interface changed/removed: OLDEST++)
# (Interfaces added: CURRENT++, REVISION=0)
OPENSC_LT_CURRENT="8"
OPENSC_LT_OLDEST="7"
OPENSC_LT_OLDEST="8"
OPENSC_LT_REVISION="0"
OPENSC_LT_AGE="0"
OPENSC_LT_AGE="$((${OPENSC_LT_CURRENT}-${OPENSC_LT_OLDEST}))"
@ -133,7 +133,7 @@ esac
AX_CODE_COVERAGE()
AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"], [-Werror])
AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"])
AM_CONDITIONAL([HAVE_UNKNOWN_WARNING_OPTION], [test "${have_unknown_warning_option}" = "yes"])
AC_ARG_ENABLE(

View File

@ -53,15 +53,18 @@
<option>--admin</option> <replaceable>argument</replaceable>,
<option>-A</option> <replaceable>argument</replaceable>
</term>
<listitem><para>Authenticate to the card using a 2DES or 3DES key.
<listitem><para>Authenticate to the card using a 2DES, 3DES or AES key.
The <replaceable>argument</replaceable> of the form
<synopsis> {<literal>A</literal>|<literal>M</literal>}<literal>:</literal><replaceable>ref</replaceable><literal>:</literal><replaceable>alg</replaceable></synopsis>
is required, were <literal>A</literal> uses "EXTERNAL AUTHENTICATION"
and <literal>M</literal> uses "MUTUAL AUTHENTICATION".
<replaceable>ref</replaceable> is normally <literal>9B</literal>,
and <replaceable>alg</replaceable> is <literal>03</literal> for 3DES.
The key is provided by the card vendor, and the environment variable
<varname>PIV_EXT_AUTH_KEY</varname> must point to a text file containing
and <replaceable>alg</replaceable> is <literal>03</literal> for 3DES,
<literal>01</literal> for 2DES, <literal>08</literal> for AES-128,
<literal>0A</literal> for AES-192 or <literal>0C</literal> for AES-256.
The key is provided by the card vendor. The environment variable
<varname>PIV_EXT_AUTH_KEY</varname> must point to either a binary file
matching the length of the key or a text file containing
the key in the format:
<code>XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX</code>
</para></listitem>

View File

@ -43,4 +43,4 @@ TIDY_FILES = \
libpkcs11.c libscdl.c
check-local:
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi

1
src/gcns/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

12
src/gcns/CMakeLists.txt Normal file
View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.18)
project(gcns VERSION 1.0 DESCRIPTION "Italian healthcare smart card parsing utility")
add_library(gcns SHARED gcns.c gcns.cpp)
target_include_directories(gcns PUBLIC ../.. .. .)
install(TARGETS gcns LIBRARY)
install(FILES gcns.h gcns.hpp DESTINATION include)
add_executable(main main.c ../tools/util.c)
target_link_libraries(main gcns opensc bsd)

33
src/gcns/arch/PKGBUILD Normal file
View File

@ -0,0 +1,33 @@
# Maintainer: Giovan Battista Rolandi <giomba@linux.it>
pkgname=gcns
pkgver=1.0
pkgrel=1
pkgdesc='Tools for Italian healthcare smart card'
arch=('x86_64')
url='https://git.golem.linux.it/giomba/opensc'
license=('LGPL')
depends=('opensc')
source=('git+https://git.golem.linux.it/giomba/opensc#branch=golem/tessera-sanitaria')
sha256sums=('SKIP')
build() {
cd opensc
./bootstrap
./configure
make -j$(nproc)
cd src/gcns
mkdir -p build
cd build
cmake ..
make -j$(nproc)
}
package() {
cd opensc/src/gcns/build
make DESTDIR=$pkgdir install
}

91
src/gcns/gcns.c Normal file
View File

@ -0,0 +1,91 @@
/*
* gcns.c: A reader of Italian healtcare smartcards with libopensc
*
* Copyright (C) 2022 Giovan Battista Rolandi <giomba@linux.it>
* based on previous work by
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gcns.h"
#include "libopensc/asn1.h"
#include "tools/util.h"
static int opt_wait = 0;
static const char *opt_reader = NULL;
static sc_context_t *ctx = NULL;
static sc_card_t *card = NULL;
sc_context_param_t ctx_param;
int gcns_init() {
int r, err = 0;
int lcycle = SC_CARDCTRL_LIFECYCLE_ADMIN;
memset(&ctx_param, 0, sizeof(ctx_param));
ctx_param.ver = 0;
r = sc_context_create(&ctx, &ctx_param);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
return GCNS_INIT;
}
ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;
err = util_connect_card_ex(ctx, &card, opt_reader, opt_wait, 0, 0);
if (err) {
return GCNS_INIT;
}
r = sc_lock(card);
if (r == SC_SUCCESS)
r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle);
sc_unlock(card);
if (r && r != SC_ERROR_NOT_SUPPORTED) {
fprintf(stderr, "unable to change lifecycle: %s\n", sc_strerror(r));
return GCNS_INIT;
}
return GCNS_SUCCESS;
}
int gcns_close() {
if (card) {
sc_disconnect_card(card);
}
if (ctx) sc_release_context(ctx);
return GCNS_SUCCESS;
}
int gcns_read_personal_data(u8 *buffer, size_t len) {
sc_path_t path;
int r;
sc_format_path("3F0011001102", &path);
r = sc_select_file(card, &path, NULL);
if (r) {
fprintf(stderr, "no select file: 3F0011001102\n");
return GCNS_READ_PERSONAL_DATA;
}
r = sc_read_binary(card, 0, buffer, 0x180, 0);
if (r < 0) {
fprintf(stderr, "no read binary: %d\n", r);
return GCNS_READ_PERSONAL_DATA;
}
return r;
}

71
src/gcns/gcns.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "gcns.hpp"
#include <vector>
using namespace gcns;
PersonalData::PersonalData(const uint8_t* buffer, size_t len) {
std::vector<std::string> field;
// TODO check length at the beginning?
for (int i = 12; i < len;) {
if (buffer[i] == '\0') break;
std::string hexstring((const char*)&buffer[i], 2);
int len = std::stoi(hexstring, nullptr, 16);
i += 2;
std::string fieldData((const char*)&buffer[i], len);
i += len;
field.push_back(fieldData);
}
for (int i = 0; i < (int)field.size(); ++i) {
switch (i) {
case 0:
this->issue_date.year =
std::stoi(field[i].substr(4, 4), nullptr);
this->issue_date.month =
std::stoi(field[i].substr(2, 2), nullptr);
this->issue_date.day =
std::stoi(field[i].substr(0, 2), nullptr);
break;
case 1:
this->expiration_date.year =
std::stoi(field[i].substr(4, 4), nullptr);
this->expiration_date.month =
std::stoi(field[i].substr(2, 2), nullptr);
this->expiration_date.day =
std::stoi(field[i].substr(0, 2), nullptr);
break;
case 2:
this->family_name = field[i];
break;
case 3:
this->first_name = field[i];
break;
case 4:
this->birth_date.year =
std::stoi(field[i].substr(4, 4), nullptr);
this->birth_date.month =
std::stoi(field[i].substr(2, 2), nullptr);
this->birth_date.day =
std::stoi(field[i].substr(0, 2), nullptr);
break;
case 5:
this->gender = field[i] == "F" ? GENDER_FEMALE : GENDER_MALE;
break;
case 7:
this->fiscal_code = field[i];
break;
case 9:
this->birth_place = field[i];
break;
case 12:
this->residence_place = field[i];
break;
default:
break;
}
}
}

13
src/gcns/gcns.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef GCNS_H
#define GCNS_H
#define GCNS_SUCCESS 0
#define GCNS_INIT -1001
#define GCNS_READ_PERSONAL_DATA -1002
#define GCNS_CLOSE -1003
int gcns_init();
int gcns_read_personal_data(u8 *buffer, size_t len);
int gcns_close();
#endif

34
src/gcns/gcns.hpp Normal file
View File

@ -0,0 +1,34 @@
#ifndef GCNS_CPP
#define GCNS_CPP
#include <string>
namespace gcns {
enum Gender { GENDER_MALE, GENDER_FEMALE };
struct Date {
uint16_t year;
uint8_t month;
uint8_t day;
};
class PersonalData {
private:
std::string first_name;
std::string family_name;
std::string fiscal_code;
std::string birth_place;
Date birth_date;
std::string residence_place;
Gender gender;
Date issue_date;
Date expiration_date;
public:
PersonalData(const uint8_t* personal_data, size_t len);
};
} // namespace gcns
#endif

56
src/gcns/main.c Normal file
View File

@ -0,0 +1,56 @@
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#ifdef ENABLE_READLINE
#include <readline/history.h>
#include <readline/readline.h>
#endif
#if !defined(_WIN32)
#include <arpa/inet.h> /* for htons() */
#endif
#include <getopt.h>
#include "common/compat_strlcpy.h"
#include "gcns.h"
#include "libopensc/asn1.h"
#include "libopensc/cardctl.h"
#include "libopensc/cards.h"
#include "libopensc/internal.h"
#include "libopensc/iso7816.h"
#include "libopensc/log.h"
#include "libopensc/opensc.h"
#include "tools/util.h"
int main(int argc, char *argv[]) {
int r;
printf("OpenSC version: %s\n", sc_get_version());
r = gcns_init();
if (r != GCNS_SUCCESS) {
fprintf(stderr, "Init Error\n");
return GCNS_INIT;
}
u8 buffer[2048];
r = gcns_read_personal_data(buffer, 2048);
if (r < 0) {
fprintf(stderr, "Read personal data error\n");
return GCNS_READ_PERSONAL_DATA;
}
util_hex_dump_asc(stdout, buffer, r, 0);
r = gcns_close();
if (r != GCNS_SUCCESS) {
return GCNS_CLOSE;
}
return GCNS_SUCCESS;
}

View File

@ -147,4 +147,4 @@ TIDY_FILES = \
#$(SOURCES)
check-local:
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi

View File

@ -203,12 +203,16 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv,
if (start[8] >= '0' && start[8] <= '9') {
key_id = start[8] - '0';
}
if (card->type == SC_CARD_TYPE_IDPRIME_V2) {
/* The key reference starts from 0x11 and increments by the key id (ASCII) */
switch (card->type) {
case SC_CARD_TYPE_IDPRIME_V2:
new_object.key_reference = 0x11 + key_id;
} else { /* V3 */
/* The key reference starts from 0xF7 and increments by the key id (ASCII) */
break;
case SC_CARD_TYPE_IDPRIME_V3:
new_object.key_reference = 0xF7 + key_id;
break;
case SC_CARD_TYPE_IDPRIME_V4:
new_object.key_reference = 0x56 + key_id;
break;
}
}
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d",
@ -261,6 +265,10 @@ static int idprime_init(sc_card_t *card)
card->type = SC_CARD_TYPE_IDPRIME_V3;
sc_log(card->ctx, "Detected IDPrime applet version 3");
break;
case 0x04:
card->type = SC_CARD_TYPE_IDPRIME_V4;
sc_log(card->ctx, "Detected IDPrime applet version 4");
break;
default:
sc_log(card->ctx, "Unknown OS version received: %d", rbuf[11]);
break;
@ -299,6 +307,12 @@ static int idprime_init(sc_card_t *card)
case SC_CARD_TYPE_IDPRIME_V2:
card->name = "Gemalto IDPrime (OSv2)";
break;
case SC_CARD_TYPE_IDPRIME_V3:
card->name = "Gemalto IDPrime (OSv3)";
break;
case SC_CARD_TYPE_IDPRIME_V4:
card->name = "Gemalto IDPrime (OSv4)";
break;
case SC_CARD_TYPE_IDPRIME_GENERIC:
default:
card->name = "Gemalto IDPrime (generic)";
@ -650,11 +664,11 @@ idprime_set_security_env(struct sc_card *card,
new_env.algorithm_ref = 0x65;
}
} else { /* RSA-PKCS */
if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA256) {
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
new_env.algorithm_ref = 0x42;
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA384) {
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
new_env.algorithm_ref = 0x52;
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA512) {
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
new_env.algorithm_ref = 0x62;
} else { /* RSA-PKCS without hashing */
new_env.algorithm_ref = 0x02;

View File

@ -87,8 +87,11 @@ static struct sc_card_driver pgp_drv = {
};
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
static pgp_ec_curves_t ec_curves_openpgp[] = {
static pgp_ec_curves_t ec_curves_openpgp34[] = {
/* OpenPGP 3.4+ Ed25519 and Curve25519 */
{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, /* ed25519 for signatures => CKK_EC_EDWARDS */
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
{{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */
{{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */
@ -98,6 +101,8 @@ static pgp_ec_curves_t ec_curves_openpgp[] = {
{{{-1}}, 0} /* This entry must not be touched. */
};
static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2;
struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}};
/* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */
@ -455,6 +460,8 @@ pgp_init(sc_card_t *card)
/* With gnuk, we use different curves */
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
priv->ec_curves = ec_curves_gnuk;
} else if (priv->bcd_version >= OPENPGP_CARD_3_4) {
priv->ec_curves = ec_curves_openpgp34;
} else {
priv->ec_curves = ec_curves_openpgp;
}
@ -606,7 +613,7 @@ pgp_parse_algo_attr_blob(sc_card_t *card, const pgp_blob_t *blob,
/* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA || SC_OPENPGP_KEYALGO_EDDSA */
key_info->algorithm = blob->data[0];
/* last byte is only set if pubkey import is supported, empty otherwise*/
/* last byte is set to 0xFF if pubkey import is supported */
if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){
if (blob->len < 3)
return SC_ERROR_INCORRECT_PARAMETERS;
@ -614,9 +621,14 @@ pgp_parse_algo_attr_blob(sc_card_t *card, const pgp_blob_t *blob,
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STDPUB;
}
else {
/* otherwise, last byte could be 00, so let's ignore it, as
* it is not part of OID */
if (blob->len < 2)
return SC_ERROR_INCORRECT_PARAMETERS;
key_info->u.ec.oid_len = blob->len - 1;
if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STD)
key_info->u.ec.oid_len = blob->len - 2;
else
key_info->u.ec.oid_len = blob->len - 1;
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STD;
}
@ -1628,7 +1640,6 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
/* PKCS#11 3.0: 2.3.5 Edwards EC public keys only support the use
* of the curveName selection to specify a curve name as defined
* in [RFC 8032] */
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
break;
case SC_OPENPGP_KEYALGO_ECDH:

View File

@ -608,14 +608,12 @@ static int piv_generate_key(sc_card_t *card,
const u8 *cp;
keydata->exponent = 0;
/* expected tag is 7f49. */
/* we will whatever tag is present */
cp = rbuf;
in_len = r;
/* expected tag is 0x7f49,returned as cla_out == 0x60 and tag_out = 0x1F49 */
r = sc_asn1_read_tag(&cp, in_len, &cla_out, &tag_out, &in_len);
if (cp == NULL) {
if (cp == NULL || in_len == 0 || cla_out != 0x60 || tag_out != 0x1f49) {
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
}
if (r != SC_SUCCESS) {
@ -1032,7 +1030,7 @@ piv_cache_internal_data(sc_card_t *card, int enumtag)
priv->obj_cache[enumtag].obj_len,
0x53, &bodylen);
if (body == NULL)
if (body == NULL || priv->obj_cache[enumtag].obj_data[0] != 0x53)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OBJECT_NOT_VALID);
/* get the certificate out */
@ -1611,7 +1609,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
/* Remove the encompassing outer TLV of 0x7C and get the data */
body = sc_asn1_find_tag(card->ctx, rbuf,
r, 0x7C, &body_len);
if (!body) {
if (!body || rbuf[0] != 0x7C) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Witness Data response of NULL\n");
r = SC_ERROR_INVALID_DATA;
goto err;
@ -1753,7 +1751,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
/* Remove the encompassing outer TLV of 0x7C and get the data */
body = sc_asn1_find_tag(card->ctx, rbuf,
r, 0x7C, &body_len);
if(!body) {
if(!body || rbuf[0] != 0x7C) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not find outer tag 0x7C in response");
r = SC_ERROR_INVALID_DATA;
goto err;
@ -1914,7 +1912,7 @@ static int piv_general_external_authenticate(sc_card_t *card,
/* Remove the encompassing outer TLV of 0x7C and get the data */
body = sc_asn1_find_tag(card->ctx, rbuf,
r, 0x7C, &body_len);
if (!body) {
if (!body || rbuf[0] != 0x7C) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Challenge Data response of NULL\n");
r = SC_ERROR_INVALID_DATA;
goto err;
@ -2079,7 +2077,7 @@ piv_get_serial_nr_from_CHUI(sc_card_t* card, sc_serial_number_t* serial)
r = SC_ERROR_INTERNAL;
if (rbuflen != 0) {
body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x53, &bodylen); /* Pass the outer wrapper asn1 */
if (body != NULL && bodylen != 0) {
if (body != NULL && bodylen != 0 && rbuf[0] == 0x53) {
fascn = sc_asn1_find_tag(card->ctx, body, bodylen, 0x30, &fascnlen); /* Find the FASC-N data */
guid = sc_asn1_find_tag(card->ctx, body, bodylen, 0x34, &guidlen);
@ -2311,10 +2309,10 @@ static int piv_validate_general_authentication(sc_card_t *card,
piv_private_data_t * priv = PIV_DATA(card);
int r, tmplen, tmplen2;
u8 *p;
const u8 *tag;
const unsigned char *p2;
size_t taglen;
const u8 *body;
size_t bodylen;
unsigned int cla, tag;
unsigned int real_alg_id, op_tag;
u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */
@ -2367,20 +2365,28 @@ static int piv_validate_general_authentication(sc_card_t *card,
r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref,
sbuf, p - sbuf, rbuf, sizeof rbuf);
if (r < 0)
goto err;
if (r >= 0) {
body = sc_asn1_find_tag(card->ctx, rbuf, r, 0x7c, &bodylen);
if (body) {
tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x82, &taglen);
if (tag) {
memcpy(out, tag, taglen);
r = taglen;
} else
r = SC_ERROR_INVALID_DATA;
} else
r = SC_ERROR_INVALID_DATA;
p2 = rbuf;
r = sc_asn1_read_tag(&p2, r, &cla, &tag, &bodylen);
if (p2 == NULL || r < 0 || bodylen == 0 || (cla|tag) != 0x7C) {
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x7C");
}
r = sc_asn1_read_tag(&p2, bodylen, &cla, &tag, &taglen);
if (p2 == NULL || r < 0 || taglen == 0 || (cla|tag) != 0x82) {
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x82");
}
if (taglen > outlen) {
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "data read longer then buffer");
}
memcpy(out, p2, taglen);
r = taglen;
err:
LOG_FUNC_RETURN(card->ctx, r);
}
@ -2394,19 +2400,19 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
int i;
size_t nLen;
u8 rbuf[128]; /* For EC conversions 384 will fit */
const u8 * body;
size_t bodylen;
const u8 * tag;
size_t taglen;
const unsigned char *pseq, *pint, *ptemp, *pend;
unsigned int cla, tag;
size_t seqlen;
size_t intlen;
size_t templen;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
/* The PIV returns a DER SEQUENCE{INTEGER, INTEGER}
* Which may have leading 00 to force positive
* TODO: -DEE should check if PKCS15 want the same
* But PKCS11 just wants 2* filed_length in bytes
* Which may have leading 00 to force a positive integer
* But PKCS11 just wants 2* field_length in bytes
* So we have to strip out the integers
* if present and pad on left if too short.
* and pad on left if too short.
*/
if (priv->alg_id == 0x11 || priv->alg_id == 0x14 ) {
@ -2424,32 +2430,32 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
if (r < 0)
goto err;
body = sc_asn1_find_tag(card->ctx, rbuf, r, 0x30, &bodylen);
pseq = rbuf;
r = sc_asn1_read_tag(&pseq, r, &cla, &tag, &seqlen);
if (pseq == NULL || r < 0 || seqlen == 0 || (cla|tag) != 0x30)
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x30");
for (i = 0; i<2; i++) {
if (body) {
tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x02, &taglen);
if (tag) {
bodylen -= taglen - (tag - body);
body = tag + taglen;
pint = pseq;
pend = pseq + seqlen;
for (i = 0; i < 2; i++) {
r = sc_asn1_read_tag(&pint, (pend - pint), &cla, &tag, &intlen);
if (pint == NULL || r < 0 || intlen == 0 || (cla|tag) != 0x02)
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x02");
if (intlen > nLen + 1)
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA,"Signature too long");
if (taglen > nLen) { /* drop leading 00 if present */
if (*tag != 0x00) {
r = SC_ERROR_INVALID_DATA;
goto err;
}
tag++;
taglen--;
}
memcpy(out + nLen*i + nLen - taglen , tag, taglen);
} else {
r = SC_ERROR_INVALID_DATA;
goto err;
ptemp = pint;
templen = intlen;
if (intlen > nLen) { /* drop leading 00 if present */
if (*ptemp != 0x00) {
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA,"Signature too long");
}
} else {
r = SC_ERROR_INVALID_DATA;
goto err;
ptemp++;
templen--;
}
memcpy(out + nLen*i + nLen - templen, ptemp, templen);
pint += intlen; /* next integer */
}
r = 2 * nLen;
} else { /* RSA is all set */

View File

@ -269,6 +269,7 @@ enum {
SC_CARD_TYPE_IDPRIME_V1,
SC_CARD_TYPE_IDPRIME_V2,
SC_CARD_TYPE_IDPRIME_V3,
SC_CARD_TYPE_IDPRIME_V4,
SC_CARD_TYPE_IDPRIME_GENERIC,
/* eDO cards */

View File

@ -519,8 +519,8 @@ static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * da
* @return SC_SUCCESS if ok; else errorcode
*/
static int cwa_prepare_external_auth(sc_card_t * card,
RSA * icc_pubkey,
RSA * ifd_privkey,
const RSA * icc_pubkey,
const RSA * ifd_privkey,
u8 * sig,
size_t sig_len)
{
@ -594,7 +594,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
buf3[127] = 0xBC; /* iso padding */
/* encrypt with ifd private key */
len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
len2 = RSA_private_decrypt(128, buf3, buf2, (RSA *)ifd_privkey, RSA_NO_PADDING);
if (len2 < 0) {
msg = "Prepare external auth: ifd_privk encrypt failed";
res = SC_ERROR_SM_ENCRYPT_FAILED;
@ -630,7 +630,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
}
/* re-encrypt result with icc public key */
len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING);
len1 = RSA_public_encrypt(len3, buf3, buf1, (RSA *)icc_pubkey, RSA_NO_PADDING);
if (len1 <= 0 || (size_t) len1 != sig_len) {
msg = "Prepare external auth: icc_pubk encrypt failed";
res = SC_ERROR_SM_ENCRYPT_FAILED;
@ -842,8 +842,8 @@ static int cwa_compare_signature(u8 * data, size_t dlen, u8 * ifd_data)
* @return SC_SUCCESS if ok; else error code
*/
static int cwa_verify_internal_auth(sc_card_t * card,
RSA * icc_pubkey,
RSA * ifd_privkey,
const RSA * icc_pubkey,
const RSA * ifd_privkey,
u8 * ifdbuf,
size_t ifdlen,
u8 * sig,
@ -901,7 +901,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
*/
/* decrypt data with our ifd priv key */
len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING);
len1 = RSA_private_decrypt(sig_len, sig, buf1, (RSA *)ifd_privkey, RSA_NO_PADDING);
if (len1 <= 0) {
msg = "Verify Signature: decrypt with ifd privk failed";
res = SC_ERROR_SM_ENCRYPT_FAILED;
@ -911,7 +911,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
/* OK: now we have SIGMIN in buf1 */
/* check if SIGMIN data matches SIG or N.ICC-SIG */
/* evaluate DS[SK.ICC.AUTH](SIG) trying to decrypt with icc pubk */
len3 = RSA_public_encrypt(len1, buf1, buf3, icc_pubkey, RSA_NO_PADDING);
len3 = RSA_public_encrypt(len1, buf1, buf3, (RSA *) icc_pubkey, RSA_NO_PADDING);
if (len3 <= 0)
goto verify_nicc_sig; /* evaluate N.ICC-SIG and retry */
res = cwa_compare_signature(buf3, len3, ifdbuf);
@ -945,7 +945,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
}
/* ok: check again with new data */
/* evaluate DS[SK.ICC.AUTH](I.ICC-SIG) trying to decrypt with icc pubk */
len3 = RSA_public_encrypt(len2, buf2, buf3, icc_pubkey, RSA_NO_PADDING);
len3 = RSA_public_encrypt(len2, buf2, buf3, (RSA *)icc_pubkey, RSA_NO_PADDING);
if (len3 <= 0) {
msg = "Verify Signature: cannot get valid SIG data";
res = SC_ERROR_INVALID_DATA;

View File

@ -48,6 +48,7 @@
#include "internal.h"
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args);
static int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args);
void sc_do_log(sc_context_t *ctx, int level, const char *file, int line, const char *func, const char *format, ...)
{
@ -74,7 +75,6 @@ void sc_do_log_noframe(sc_context_t *ctx, int level, const char *format, va_list
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args)
{
char buf[4096];
#ifdef _WIN32
SYSTEMTIME st;
#else
@ -142,11 +142,9 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin
file, line, func ? func : "");
}
if (vsnprintf(buf, sizeof buf, format, args) >= 0) {
sc_color_fprintf(color, ctx, ctx->debug_file, "%s", buf);
if (strlen(buf) == 0 || buf[strlen(buf)-1] != '\n')
sc_color_fprintf(color, ctx, ctx->debug_file, "\n");
}
sc_color_fprintf_va(color, ctx, ctx->debug_file, format, args);
if (strlen(format) == 0 || format[strlen(format) - 1] != '\n')
sc_color_fprintf(color, ctx, ctx->debug_file, "\n");
fflush(ctx->debug_file);
#ifdef _WIN32
@ -202,7 +200,18 @@ static int is_a_tty(FILE *fp)
int sc_color_fprintf(int colors, struct sc_context *ctx, FILE * stream, const char * format, ...)
{
int r;
va_list ap;
va_start(ap, format);
r = sc_color_fprintf_va(colors, ctx, stream, format, ap);
va_end(ap);
return r;
}
int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args)
{
int r;
#ifdef _WIN32
WORD old_attr = 0;
@ -264,9 +273,7 @@ int sc_color_fprintf(int colors, struct sc_context *ctx, FILE * stream, const ch
#endif
}
va_start(ap, format);
r = vfprintf(stream, format, ap);
va_end(ap);
r = vfprintf(stream, format, args);
if (colors && (!ctx || (!(ctx->flags & SC_CTX_FLAG_DISABLE_COLORS)))) {
#ifdef _WIN32

View File

@ -143,7 +143,7 @@ CERT_HANDLE_FUNCTION(default_cert_handle) {
int r;
X509 *cert_data = NULL;
EVP_PKEY *pkey = NULL;
RSA * rsa = NULL;
const RSA * rsa = NULL;
int certtype = 0;
int modulus_len = 0;
const prdata* key = get_prkey_by_cert(items, cert);

View File

@ -450,11 +450,13 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
#endif
#ifdef SC_ALGORITHM_EDDSA
/* aka Ed25519 */
{ SC_ALGORITHM_EDDSA, {{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, NULL, NULL, NULL },
/* RFC 8410, needed to parse/create X509 certs/pubkeys */
{ SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL },
#endif
#ifdef SC_ALGORITHM_XEDDSA
/* aka curve25519 */
{ SC_ALGORITHM_XEDDSA, {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, NULL, NULL, NULL },
/* RFC 8410, needed to parse/create X509 certs/pubkeys */
{ SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL },
#endif
{ -1, {{ -1 }}, NULL, NULL, NULL }
};
@ -552,7 +554,11 @@ sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len,
sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1);
/* no parameters, write NULL tag */
if (!id->params || !alg_info->encode)
/* If it's EDDSA/XEDDSA, according to RFC8410, params
* MUST be absent */
if (id->algorithm != SC_ALGORITHM_EDDSA &&
id->algorithm != SC_ALGORITHM_XEDDSA &&
(!id->params || !alg_info->encode))
asn1_alg_id[1].flags |= SC_ASN1_PRESENT;
r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1);

View File

@ -98,7 +98,8 @@ static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card)
pin_info.attrs.pin.max_length = 16;
pin_info.tries_left = -1;
if (card->type == SC_CARD_TYPE_IDPRIME_V3) {
if (card->type == SC_CARD_TYPE_IDPRIME_V3 ||
card->type == SC_CARD_TYPE_IDPRIME_V4) {
pin_info.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
pin_info.attrs.pin.stored_length = 16;
pin_info.attrs.pin.pad_char = 0x00;

View File

@ -309,6 +309,11 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH ||
cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA ||
cxdata[0] == SC_OPENPGP_KEYALGO_EDDSA) {
/* Last byte could be Import-Format of private key, let's ignore it,
* as it is not part of OID */
if (cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STD ||
cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB)
cxdata_len--;
r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid);
if (r != SC_SUCCESS) {
sc_log(ctx, "Failed to parse OID for elliptic curve algorithm");
@ -429,6 +434,11 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH ||
cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA ||
cxdata[0] == SC_OPENPGP_KEYALGO_EDDSA) {
/* Last byte could be Import-Format of private key, let's ignore it,
* as it is not part of OID */
if (cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STD ||
cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB)
cxdata_len--;
r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid);
if (r != SC_SUCCESS) {
sc_log(ctx, "Failed to parse OID for elliptic curve algorithm");

View File

@ -527,7 +527,9 @@ sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15
key_info = (struct sc_pkcs15_prkey_info *) key_object->data;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ERR_load_ERR_strings();
#endif
ERR_load_crypto_strings();
sc_log(ctx, "CertValue(%"SC_FORMAT_LEN_SIZE_T"u) %p",
@ -726,13 +728,13 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key)
}
case EVP_PKEY_EC: {
struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec;
EC_KEY *src = NULL;
const EC_KEY *src = NULL;
const EC_GROUP *grp = NULL;
unsigned char buf[255];
size_t buflen = 255;
int nid;
src = EVP_PKEY_get0(pk);
src = EVP_PKEY_get0_EC_KEY(pk);
assert(src);
assert(EC_KEY_get0_private_key(src));
assert(EC_KEY_get0_public_key(src));

View File

@ -912,6 +912,14 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
break;
case SC_ALGORITHM_EDDSA:
case SC_ALGORITHM_XEDDSA:
/* For a SPKI, the pubkey is placed directly in the BIT STRING */
pkey.value = malloc(pubkey->u.eddsa.pubkey.len);
memcpy(pkey.value, pubkey->u.eddsa.pubkey.value, pubkey->u.eddsa.pubkey.len);
// Should be pkey.len = 0 there?
key_len = pubkey->u.eddsa.pubkey.len * 8;
break;
default:
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
key_len = pkey.len * 8;
@ -1507,6 +1515,12 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke
}
memcpy(pubkey->u.ec.ecpointQ.value, pk.value, pk.len);
pubkey->u.ec.ecpointQ.len = pk.len;
} else if (pk_alg.algorithm == SC_ALGORITHM_EDDSA ||
pk_alg.algorithm == SC_ALGORITHM_XEDDSA) {
/* EDDSA/XEDDSA public key is not encapsulated into BIT STRING -- it's a BIT STRING */
pubkey->u.eddsa.pubkey.value = malloc(pk.len);
memcpy(pubkey->u.eddsa.pubkey.value, pk.value, pk.len);
pubkey->u.eddsa.pubkey.len = pk.len;
} else {
/* Public key is expected to be encapsulated into BIT STRING */
r = sc_pkcs15_decode_pubkey(ctx, pubkey, pk.value, pk.len);
@ -1769,13 +1783,13 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
}
case EVP_PKEY_EC: {
struct sc_pkcs15_pubkey_ec *dst = &pkcs15_key->u.ec;
EC_KEY *src = NULL;
const EC_KEY *src = NULL;
const EC_GROUP *grp = NULL;
unsigned char buf[255];
size_t buflen = 255;
int nid;
src = EVP_PKEY_get0(pk);
src = EVP_PKEY_get0_EC_KEY(pk);
assert(src);
assert(EC_KEY_get0_public_key(src));

View File

@ -635,7 +635,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
* key is for signing and decryption, we need to emulate signing */
sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage);
if (obj->type == SC_ALGORITHM_RSA) {
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA) {
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
((prkey->usage & USAGE_ANY_SIGN) &&
(prkey->usage & USAGE_ANY_DECIPHER)) ) {

View File

@ -273,6 +273,7 @@ static sc_ossl_inline void CRYPTO_secure_malloc_done()
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -87,4 +87,4 @@ TIDY_FILES = \
framework-pkcs15init.c debug.c
check-local:
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi

View File

@ -522,7 +522,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, unsigned int pubkey_len
size_t signat_len_tmp;
unsigned char *signat_tmp = NULL;
EVP_PKEY_CTX *ctx;
EC_KEY *eckey;
const EC_KEY *eckey;
int r;
sc_log(context, "Trying to verify using EVP");

View File

@ -141,7 +141,8 @@ print_generic(FILE *f, CK_LONG type, CK_VOID_PTR value, CK_ULONG size, CK_VOID_P
CK_ULONG i;
if((CK_LONG)size != -1 && value != NULL) {
char hex[16*3+1], ascii[16+1];
char hex[16*3+1] = {0};
char ascii[16+1];
char *hex_ptr = hex, *ascii_ptr = ascii;
int offset = 0;
@ -1035,6 +1036,9 @@ print_attribute_list(FILE *f, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
CK_ULONG j, k;
int found;
if (!pTemplate)
return;
for(j = 0; j < ulCount ; j++) {
found = 0;
for(k = 0; k < ck_attribute_num; k++) {
@ -1066,6 +1070,9 @@ print_attribute_list_req(FILE *f, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
CK_ULONG j, k;
int found;
if (!pTemplate)
return;
for(j = 0; j < ulCount ; j++) {
found = 0;
for(k = 0; k < ck_attribute_num; k++) {

View File

@ -156,6 +156,8 @@ static CK_C_INITIALIZE_ARGS _def_locks = {
#endif /* PKCS11_THREAD_LOCKING */
static CK_C_INITIALIZE_ARGS_PTR global_locking;
static CK_C_INITIALIZE_ARGS app_locking = {
NULL, NULL, NULL, NULL, 0, NULL };
static void *global_lock = NULL;
#ifdef HAVE_OS_LOCKING
static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = &_def_locks;
@ -810,7 +812,7 @@ out:
*/
#define NUM_INTERFACES 2
#define DEFAULT_INTERFACE 0
ck_interface interfaces[NUM_INTERFACES] = {
CK_INTERFACE interfaces[NUM_INTERFACES] = {
{"PKCS 11", (void *)&pkcs11_function_list_3_0, 0},
{"PKCS 11", (void *)&pkcs11_function_list, 0}
};
@ -914,6 +916,8 @@ sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
if (args->pReserved != NULL_PTR)
return CKR_ARGUMENTS_BAD;
app_locking = *args;
/* If the app tells us OS locking is okay,
* use that. Otherwise use the supplied functions.
*/
@ -929,13 +933,13 @@ sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
/* Based on PKCS#11 v2.11 11.4 */
if (applock && oslock) {
/* Shall be used in threaded environment, prefer app provided locking */
global_locking = args;
global_locking = &app_locking;
} else if (!applock && oslock) {
/* Shall be used in threaded environment, must use operating system locking */
global_locking = default_mutex_funcs;
} else if (applock && !oslock) {
/* Shall be used in threaded environment, must use app provided locking */
global_locking = args;
global_locking = &app_locking;
} else if (!applock && !oslock) {
/* Shall not be used in threaded environment, use operating system locking */
global_locking = default_mutex_funcs;

View File

@ -176,7 +176,7 @@ allocate_function_list(int v3)
/* The compatibility interfaces that can be returned from Interface functions
* if the V3 API is used, but the proxied module does not support V3 API */
#define NUM_INTERFACES 1
ck_interface compat_interfaces[NUM_INTERFACES] = {
CK_INTERFACE compat_interfaces[NUM_INTERFACES] = {
{"PKCS 11", NULL, 0}
};
@ -400,6 +400,121 @@ spy_attribute_list_out(const char *name, CK_ATTRIBUTE_PTR pTemplate,
print_attribute_list(spy_output, pTemplate, ulCount);
}
static void
spy_dump_mechanism_in(const char *name, CK_MECHANISM_PTR pMechanism)
{
char param_name[64];
if (!pMechanism) {
fprintf(spy_output, "[in] %s = NULL\n", name);
return;
}
fprintf(spy_output, "[in] %s->type = %s\n", name, lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_AES_GCM:
if (pMechanism->pParameter != NULL) {
CK_GCM_PARAMS *param =
(CK_GCM_PARAMS *) pMechanism->pParameter;
snprintf(param_name, sizeof(param_name), "%s->pParameter->pIv[ulIvLen]", name);
spy_dump_string_in(param_name,
param->pIv, param->ulIvLen);
snprintf(param_name, sizeof(param_name), "%s->pParameter->ulIvBits", name);
spy_dump_ulong_in(param_name, param->ulIvBits);
snprintf(param_name, sizeof(param_name), "%s->pParameter->pAAD[ulAADLen]", name);
spy_dump_string_in(param_name,
param->pAAD, param->ulAADLen);
fprintf(spy_output, "[in] %s->pParameter->ulTagBits = %lu\n", name, param->ulTagBits);
} else {
fprintf(spy_output, "[in] %s->pParameter = NULL\n", name);
break;
}
break;
case CKM_ECDH1_DERIVE:
case CKM_ECDH1_COFACTOR_DERIVE:
if (pMechanism->pParameter != NULL) {
CK_ECDH1_DERIVE_PARAMS *param =
(CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] %s->pParameter->kdf = %s\n", name,
lookup_enum(CKD_T, param->kdf));
fprintf(spy_output, "[in] %s->pParameter->pSharedData[ulSharedDataLen] = ", name);
print_generic(spy_output, 0, param->pSharedData,
param->ulSharedDataLen, NULL);
fprintf(spy_output, "[in] %s->pParameter->pPublicData[ulPublicDataLen] = ", name);
print_generic(spy_output, 0, param->pPublicData,
param->ulPublicDataLen, NULL);
} else {
fprintf(spy_output, "[in] %s->pParameter = NULL\n", name);
break;
}
break;
case CKM_ECMQV_DERIVE:
if (pMechanism->pParameter != NULL) {
CK_ECMQV_DERIVE_PARAMS *param =
(CK_ECMQV_DERIVE_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] %s->pParameter->kdf = %s\n", name,
lookup_enum(CKD_T, param->kdf));
fprintf(spy_output, "%s->pParameter->pSharedData[ulSharedDataLen] = ", name);
print_generic(spy_output, 0, param->pSharedData,
param->ulSharedDataLen, NULL);
fprintf(spy_output, "%s->pParameter->pPublicData[ulPublicDataLen] = ", name);
print_generic(spy_output, 0, param->pPublicData,
param->ulPublicDataLen, NULL);
fprintf(spy_output, "%s->pParameter->ulPrivateDataLen = %lu", name,
param->ulPrivateDataLen);
fprintf(spy_output, "%s->pParameter->hPrivateData = %lu", name, param->hPrivateData);
fprintf(spy_output, "%s->pParameter->pPublicData2[ulPublicDataLen2] = ", name);
print_generic(spy_output, 0, param->pPublicData2,
param->ulPublicDataLen2, NULL);
fprintf(spy_output, "%s->pParameter->publicKey = %lu", name, param->publicKey);
} else {
fprintf(spy_output, "[in] %s->pParameter = NULL\n", name);
break;
}
break;
case CKM_RSA_PKCS_OAEP:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_OAEP_PARAMS *param =
(CK_RSA_PKCS_OAEP_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] %s->pParameter->hashAlg = %s\n", name,
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "[in] %s->pParameter->mgf = %s\n", name,
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "[in] %s->pParameter->source = %lu\n", name, param->source);
snprintf(param_name, sizeof(param_name), "%s->pParameter->pSourceData[ulSourceDalaLen]", name);
spy_dump_string_in(param_name,
param->pSourceData, param->ulSourceDataLen);
} else {
fprintf(spy_output, "[in] %s->pParameter = NULL\n", name);
break;
}
break;
case CKM_RSA_PKCS_PSS:
case CKM_SHA1_RSA_PKCS_PSS:
case CKM_SHA256_RSA_PKCS_PSS:
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_PSS_PARAMS *param =
(CK_RSA_PKCS_PSS_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] %s->pParameter->hashAlg = %s\n", name,
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "[in] %s->pParameter->mgf = %s\n", name,
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "[in] %s->pParameter->sLen = %lu\n", name,
param->sLen);
} else {
fprintf(spy_output, "[in] %s->pParameter = NULL\n", name);
break;
}
break;
default:
snprintf(param_name, sizeof(param_name), "%s->pParameter[ulParameterLen]", name);
spy_dump_string_in(param_name, pMechanism->pParameter, pMechanism->ulParameterLen);
break;
}
}
static void
print_ptr_in(const char *name, CK_VOID_PTR ptr)
{
@ -416,6 +531,8 @@ CK_RV C_GetFunctionList
}
enter("C_GetFunctionList");
if (ppFunctionList == NULL)
return retne(CKR_ARGUMENTS_BAD);
*ppFunctionList = pkcs11_spy;
return retne(CKR_OK);
}
@ -606,10 +723,13 @@ C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
enter("C_OpenSession");
spy_dump_ulong_in("slotID", slotID);
spy_dump_ulong_in("flags", flags);
fprintf(spy_output, "pApplication=%p\n", pApplication);
fprintf(spy_output, "Notify=%p\n", (void *)Notify);
fprintf(spy_output, "[in] pApplication = %p\n", pApplication);
fprintf(spy_output, "[in] Notify = %p\n", (void *)Notify);
rv = po->C_OpenSession(slotID, flags, pApplication, Notify, phSession);
spy_dump_ulong_out("*phSession", *phSession);
if (phSession)
spy_dump_ulong_out("*phSession", *phSession);
else
fprintf(spy_output, "[out] phSession = %p\n", phSession);
return retne(rv);
}
@ -853,27 +973,7 @@ C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT
enter("C_EncryptInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_AES_GCM:
if (pMechanism->pParameter != NULL) {
CK_GCM_PARAMS *param =
(CK_GCM_PARAMS *) pMechanism->pParameter;
spy_dump_string_in("pIv[ulIvLen]",
param->pIv, param->ulIvLen);
spy_dump_ulong_in("ulIvBits", param->ulIvBits);
spy_dump_string_in("pAAD[ulAADLen]",
param->pAAD, param->ulAADLen);
fprintf(spy_output, "pMechanism->pParameter->ulTagBits=%lu\n", param->ulTagBits);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
default:
spy_dump_string_in("pParameter[ulParameterLen]", pMechanism->pParameter, pMechanism->ulParameterLen);
break;
}
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_EncryptInit(hSession, pMechanism, hKey);
return retne(rv);
@ -931,28 +1031,7 @@ C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT
enter("C_DecryptInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS_OAEP:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_OAEP_PARAMS *param =
(CK_RSA_PKCS_OAEP_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "pMechanism->pParameter->hashAlg=%s\n",
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "pMechanism->pParameter->mgf=%s\n",
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "pMechanism->pParameter->source=%lu\n", param->source);
spy_dump_string_out("pSourceData[ulSourceDalaLen]",
param->pSourceData, param->ulSourceDataLen);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
default:
spy_dump_string_in("pParameter[ulParameterLen]", pMechanism->pParameter, pMechanism->ulParameterLen);
break;
}
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_DecryptInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1011,7 +1090,7 @@ C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
enter("C_DigestInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
rv = po->C_DigestInit(hSession, pMechanism);
return retne(rv);
}
@ -1077,28 +1156,7 @@ C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HA
enter("C_SignInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS_PSS:
case CKM_SHA1_RSA_PKCS_PSS:
case CKM_SHA256_RSA_PKCS_PSS:
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_PSS_PARAMS *param =
(CK_RSA_PKCS_PSS_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "pMechanism->pParameter->hashAlg=%s\n",
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "pMechanism->pParameter->mgf=%s\n",
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "pMechanism->pParameter->sLen=%lu\n",
param->sLen);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
}
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_SignInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1153,8 +1211,7 @@ C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OB
enter("C_SignRecoverInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n",
lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_SignRecoverInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1182,28 +1239,7 @@ C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_
enter("C_VerifyInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS_PSS:
case CKM_SHA1_RSA_PKCS_PSS:
case CKM_SHA256_RSA_PKCS_PSS:
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
if (pMechanism->pParameter != NULL) {
CK_RSA_PKCS_PSS_PARAMS *param =
(CK_RSA_PKCS_PSS_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "pMechanism->pParameter->hashAlg=%s\n",
lookup_enum(MEC_T, param->hashAlg));
fprintf(spy_output, "pMechanism->pParameter->mgf=%s\n",
lookup_enum(MGF_T, param->mgf));
fprintf(spy_output, "pMechanism->pParameter->sLen=%lu\n",
param->sLen);
} else {
fprintf(spy_output, "Parameters block for %s is empty...\n",
lookup_enum(MEC_T, pMechanism->mechanism));
}
break;
}
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_VerifyInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1256,7 +1292,7 @@ C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
enter("C_VerifyRecoverInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_VerifyRecoverInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1349,7 +1385,7 @@ C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
enter("C_GenerateKey");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_attribute_list_in("pTemplate", pTemplate, ulCount);
rv = po->C_GenerateKey(hSession, pMechanism, pTemplate, ulCount, phKey);
if (rv == CKR_OK)
@ -1368,7 +1404,7 @@ C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
enter("C_GenerateKeyPair");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_attribute_list_in("pPublicKeyTemplate", pPublicKeyTemplate, ulPublicKeyAttributeCount);
spy_attribute_list_in("pPrivateKeyTemplate", pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
rv = po->C_GenerateKeyPair(hSession, pMechanism,
@ -1391,7 +1427,7 @@ C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
enter("C_WrapKey");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hWrappingKey", hWrappingKey);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_WrapKey(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen);
@ -1411,7 +1447,7 @@ C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
enter("C_UnwrapKey");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hUnwrappingKey", hUnwrappingKey);
spy_dump_string_in("pWrappedKey[ulWrappedKeyLen]", pWrappedKey, ulWrappedKeyLen);
spy_attribute_list_in("pTemplate", pTemplate, ulAttributeCount);
@ -1430,52 +1466,7 @@ C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_H
enter("C_DeriveKey");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "[in] pMechanism->type=%s\n",
lookup_enum(MEC_T, pMechanism->mechanism));
switch (pMechanism->mechanism) {
case CKM_ECDH1_DERIVE:
case CKM_ECDH1_COFACTOR_DERIVE:
if (pMechanism->pParameter == NULL) {
fprintf(spy_output, "[in] pMechanism->pParameter = NULL\n");
break;
}
CK_ECDH1_DERIVE_PARAMS *param =
(CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] pMechanism->pParameter = {\n\tkdf=%s\n",
lookup_enum(CKD_T, param->kdf));
fprintf(spy_output, "\tpSharedData[ulSharedDataLen] = ");
print_generic(spy_output, 0, param->pSharedData,
param->ulSharedDataLen, NULL);
fprintf(spy_output, "\tpPublicData[ulPublicDataLen] = ");
print_generic(spy_output, 0, param->pPublicData,
param->ulPublicDataLen, NULL);
fprintf(spy_output, "}\n");
break;
case CKM_ECMQV_DERIVE:
if (pMechanism->pParameter == NULL) {
fprintf(spy_output, "[in] pMechanism->pParameter = NULL\n");
break;
}
CK_ECMQV_DERIVE_PARAMS *param2 =
(CK_ECMQV_DERIVE_PARAMS *) pMechanism->pParameter;
fprintf(spy_output, "[in] pMechanism->pParameter = {\n\tkdf=%s\n",
lookup_enum(CKD_T, param2->kdf));
fprintf(spy_output, "\tpSharedData[ulSharedDataLen] =");
print_generic(spy_output, 0, param2->pSharedData,
param2->ulSharedDataLen, NULL);
fprintf(spy_output, "\tpPublicData[ulPublicDataLen] = ");
print_generic(spy_output, 0, param2->pPublicData,
param2->ulPublicDataLen, NULL);
fprintf(spy_output, "\tulPrivateDataLen = %lu",
param2->ulPrivateDataLen);
fprintf(spy_output, "\thPrivateData = %lu", param2->hPrivateData);
fprintf(spy_output, "\tpPublicData2[ulPublicDataLen2] = ");
print_generic(spy_output, 0, param2->pPublicData2,
param2->ulPublicDataLen2, NULL);
fprintf(spy_output, "\tpublicKey = %lu", param2->publicKey);
fprintf(spy_output, "}\n");
break;
}
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hBaseKey", hBaseKey);
spy_attribute_list_in("pTemplate", pTemplate, ulAttributeCount);
rv = po->C_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate, ulAttributeCount, phKey);
@ -1696,7 +1687,7 @@ C_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK
enter("C_MessageEncryptInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_MessageEncryptInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1779,7 +1770,7 @@ C_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK
enter("C_MessageDecryptInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_MessageDecryptInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1862,7 +1853,7 @@ C_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OB
enter("C_MessageSignInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_MessageSignInit(hSession, pMechanism, hKey);
return retne(rv);
@ -1934,7 +1925,7 @@ C_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_
enter("C_MessageVerifyInit");
spy_dump_ulong_in("hSession", hSession);
fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism));
spy_dump_mechanism_in("pMechanism", pMechanism);
spy_dump_ulong_in("hKey", hKey);
rv = po->C_MessageVerifyInit(hSession, pMechanism, hKey);
return retne(rv);

View File

@ -63,9 +63,9 @@ extern "C" {
version of this file, please consider deleting the revision macro
(you may use a macro with a different name to keep track of your
versions). */
#define CRYPTOKI_VERSION_MAJOR 2
#define CRYPTOKI_VERSION_MINOR 20
#define CRYPTOKI_VERSION_REVISION 6
#define CRYPTOKI_VERSION_MAJOR 3
#define CRYPTOKI_VERSION_MINOR 0
#define CRYPTOKI_VERSION_REVISION 0
/* Compatibility interface is default, unless CRYPTOKI_GNU is
@ -374,8 +374,10 @@ typedef unsigned long ck_key_type_t;
#define CKK_EC_MONTGOMERY (0x41UL)
#define CKK_VENDOR_DEFINED (1UL << 31)
// A mask for new GOST algorithms.
// For details visit https://tc26.ru/standarts/perevody/guidelines-the-pkcs-11-extensions-for-implementing-the-gost-r-34-10-2012-and-gost-r-34-11-2012-russian-standards-.html
/*
* A mask for new GOST algorithms.
* For details visit https://tc26.ru/standarts/perevody/guidelines-the-pkcs-11-extensions-for-implementing-the-gost-r-34-10-2012-and-gost-r-34-11-2012-russian-standards-.html
*/
#define NSSCK_VENDOR_PKCS11_RU_TEAM (CKK_VENDOR_DEFINED | 0x54321000)
#define CK_VENDOR_PKCS11_RU_TEAM_TK26 NSSCK_VENDOR_PKCS11_RU_TEAM
@ -1784,6 +1786,8 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
#undef ck_rv_t
#undef ck_notify_t
#undef ck_interface
#undef ck_function_list
#undef ck_function_list_3_0

View File

@ -4,7 +4,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
EXTRA_DIST = Makefile.mak
noinst_LTLIBRARIES = libpkcs15init.la
noinst_HEADERS = profile.h pkcs15-init.h pkcs15-oberthur.h
noinst_HEADERS = profile.h pkcs15-init.h pkcs15-oberthur.h pkcs15-iasecc.h
dist_pkgdata_DATA = \
cyberflex.profile \
flex.profile \

View File

@ -769,7 +769,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj
int r = 0;
LOG_FUNC_CALLED(ctx);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ERR_load_ERR_strings();
#endif
ERR_load_crypto_strings();
key_info = (struct sc_pkcs15_prkey_info *)obj->data;
@ -827,7 +829,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj
sc_log(ctx, "cosm_encode_key_info() label:%s",ki->label.value);
done:
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ERR_load_ERR_strings();
#endif
ERR_load_crypto_strings();
LOG_FUNC_RETURN(ctx, r);
}
@ -933,7 +937,9 @@ awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob
LOG_FUNC_CALLED(ctx);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ERR_load_ERR_strings();
#endif
ERR_load_crypto_strings();
if (!obj || !ci)

View File

@ -40,6 +40,7 @@
#error "Need OpenSSL"
#endif
#include <openssl/evp.h>
#include <openssl/des.h>
#include <openssl/sha.h>
@ -49,6 +50,7 @@
#include "sm-common.h"
#if OPENSSL_VERSION_NUMBER < 0x30000000L
/*
* From crypto/des/des_locl.h of OpenSSL .
*/
@ -120,18 +122,34 @@ DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length,
}
memcpy(*iv,icv_out,sizeof(DES_cblock));
}
#else
#include <openssl/provider.h>
/* The single-DES algorithm is not available in the default provider anymore
* so we need to load the legacy provider. This is not done on the application
* start, but only as needed */
OSSL_PROVIDER *legacy_provider = NULL;
#endif
DES_LONG
DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
long length, DES_key_schedule *schedule, DES_key_schedule *schedule2,
long length, unsigned char *key,
const_DES_cblock *ivec)
{
register DES_LONG tout0,tout1,tin0,tin1;
register long l=length;
DES_LONG tin[2];
unsigned char *out = &(*output)[0];
const unsigned char *iv = &(*ivec)[0];
#if OPENSSL_VERSION_NUMBER < 0x30000000L
register DES_LONG tout0,tout1,tin0,tin1;
DES_LONG tin[2];
DES_cblock kk, k2;
DES_key_schedule ks,ks2;
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
DES_set_key_unchecked(&kk,&ks);
DES_set_key_unchecked(&k2,&ks2);
c2l(iv,tout0);
c2l(iv,tout1);
@ -147,7 +165,7 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
tin0^=tout0; tin[0]=tin0;
tin1^=tout1; tin[1]=tin1;
DES_encrypt1((DES_LONG *)tin,schedule, DES_ENCRYPT);
DES_encrypt1((DES_LONG *)tin, &ks, DES_ENCRYPT);
tout0=tin[0];
tout1=tin[1];
}
@ -161,9 +179,8 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
tin0^=tout0; tin[0]=tin0;
tin1^=tout1; tin[1]=tin1;
DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule);
DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks);
tout1=tin[1];
if (out != NULL)
{
l2c(tout0,out);
@ -179,22 +196,87 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
| ((tout1 << 8L) & 0x00FF0000)
| ((tout1 << 24L) & 0xFF000000);
return(tout1);
#else
EVP_CIPHER_CTX *cctx = NULL;
unsigned char outv[8], tmpout[4];
int tmplen;
/* Prepare IV */
memcpy(outv, iv, sizeof outv);
cctx = EVP_CIPHER_CTX_new();
if (l > 8) {
if (legacy_provider == NULL) {
legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
}
if (!EVP_EncryptInit_ex2(cctx, EVP_des_cbc(), key, iv, NULL)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
for (; l > 8; l -= 8, in += 8) {
if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
}
if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
}
/* We need to return first 4 bytes from here */
memcpy(tmpout, outv, 4);
if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, outv, NULL)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, l)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
if (out != NULL) {
memcpy(out, tmpout, 4);
memcpy(out+4, outv+4, 4);
}
EVP_CIPHER_CTX_free(cctx);
return ((outv[7] << 0L) & 0x000000FF) |
((outv[6] << 8L) & 0x0000FF00) |
((outv[5] << 16L) & 0x00FF0000) |
((outv[4] << 24L) & 0xFF000000);
#endif
}
DES_LONG
DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output,
long length, DES_key_schedule *schedule, DES_key_schedule *schedule2,
long length, unsigned char *key,
const_DES_cblock *ivec)
{
register DES_LONG tout0,tout1,tin0,tin1;
register long l=length;
DES_LONG tin[2];
unsigned char *out = &(*output)[0];
const unsigned char *iv = &(*ivec)[0];
#if OPENSSL_VERSION_NUMBER < 0x30000000L
register DES_LONG tout0,tout1,tin0,tin1;
DES_LONG tin[2];
DES_cblock kk, k2;
DES_key_schedule ks,ks2;
c2l(iv,tout0);
c2l(iv,tout1);
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
DES_set_key_unchecked(&kk,&ks);
DES_set_key_unchecked(&k2,&ks2);
c2l(iv, tout0);
c2l(iv, tout1);
for (; l>0; l-=8)
{
@ -208,7 +290,7 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output,
tin0^=tout0; tin[0]=tin0;
tin1^=tout1; tin[1]=tin1;
DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule);
DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks);
/* fix 15/10/91 eay - thanks to keithr@sco.COM */
tout0=tin[0];
tout1=tin[1];
@ -228,6 +310,40 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output,
| ((tout1 << 8L) & 0x00FF0000)
| ((tout1 << 24L) & 0xFF000000);
return(tout1);
#else
EVP_CIPHER_CTX *cctx = NULL;
unsigned char outv[8];
int tmplen;
/* Prepare IV */
memcpy(outv, iv, sizeof outv);
cctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, iv, NULL)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
for (; l > 0; l -= 8, in += 8) {
if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
}
if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
if (out != NULL) {
memcpy(out, outv, sizeof outv);
}
EVP_CIPHER_CTX_free(cctx);
return ((outv[7] << 0L) & 0x000000FF) |
((outv[6] << 8L) & 0x0000FF00) |
((outv[5] << 16L) & 0x00FF0000) |
((outv[4] << 24L) & 0xFF000000);
#endif
}
@ -235,9 +351,14 @@ int
sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
unsigned char **out, int *out_len)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
int ii;
DES_cblock kk,k2;
DES_key_schedule ks,ks2;
#else
EVP_CIPHER_CTX *cctx = NULL;
int tmplen;
#endif
if (!out || !out_len)
@ -251,6 +372,7 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
if (!(*out))
return -1;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
@ -260,6 +382,27 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
for (ii=0; ii<data_len; ii+=8)
DES_ecb2_encrypt( (DES_cblock *)(data + ii),
(DES_cblock *)(*out + ii), &ks, &ks2, DES_ENCRYPT);
#else
cctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_ecb(), key, NULL, NULL)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
if (!EVP_EncryptUpdate(cctx, *out, &tmplen, data, data_len)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
*out_len = tmplen;
if (!EVP_EncryptFinal_ex(cctx, *out + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
return SC_ERROR_INTERNAL;
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(cctx);
#endif
return 0;
}
@ -270,10 +413,16 @@ sm_decrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
unsigned char *data, size_t data_len,
unsigned char **out, size_t *out_len)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
DES_cblock kk,k2;
DES_key_schedule ks,ks2;
DES_cblock icv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
size_t st;
#else
unsigned char icv[] = {0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EVP_CIPHER_CTX *cctx = NULL;
int tmplen;
#endif
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_SM);
if (!out || !out_len)
@ -286,6 +435,7 @@ sm_decrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
if (!(*out))
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "SM decrypt_des_cbc3: allocation error");
#if OPENSSL_VERSION_NUMBER < 0x30000000L
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
@ -295,21 +445,48 @@ sm_decrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
for (st=0; st<data_len; st+=8)
DES_3cbc_encrypt((DES_cblock *)(data + st),
(DES_cblock *)(*out + st), 8, &ks, &ks2, &icv, DES_DECRYPT);
#else
cctx = EVP_CIPHER_CTX_new();
if (!EVP_DecryptInit_ex2(cctx, EVP_des_ede_cbc(), key, icv, NULL)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
if (!EVP_DecryptUpdate(cctx, *out, &tmplen, data, data_len)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
*out_len = tmplen;
if (!EVP_DecryptFinal_ex(cctx, *out + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(cctx);
#endif
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_SUCCESS);
}
/* This function expects the data to be a multilpe of DES block size */
int
sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
const unsigned char *in, size_t in_len,
unsigned char **out, size_t *out_len, int not_force_pad)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
DES_cblock kk,k2;
DES_key_schedule ks,ks2;
DES_cblock icv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
size_t st;
#else
unsigned char icv[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EVP_CIPHER_CTX *cctx = NULL;
int tmplen;
#endif
unsigned char *data;
size_t data_len, st;
size_t data_len;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_SM);
sc_debug(ctx, SC_LOG_DEBUG_SM,
@ -345,6 +522,7 @@ sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "SM encrypt_des_cbc3: failure");
}
#if OPENSSL_VERSION_NUMBER < 0x30000000L
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
@ -353,6 +531,27 @@ sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
for (st=0; st<data_len; st+=8)
DES_3cbc_encrypt((DES_cblock *)(data + st), (DES_cblock *)(*out + st), 8, &ks, &ks2, &icv, DES_ENCRYPT);
#else
cctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, icv, NULL)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
/* Disable padding, otherwise it will fail to decrypt non-padded inputs */
EVP_CIPHER_CTX_set_padding(cctx, 0);
if (!EVP_EncryptUpdate(cctx, *out, &tmplen, data, data_len)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
*out_len = tmplen;
if (!EVP_EncryptFinal_ex(cctx, *out + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(cctx);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_ERROR_INTERNAL);
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(cctx);
#endif
free(data);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_SM, SC_SUCCESS);

View File

@ -31,9 +31,9 @@ extern "C" {
#include "libopensc/sm.h"
DES_LONG DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, long length,
DES_key_schedule *schedule, DES_key_schedule *schedule2, const_DES_cblock *ivec);
unsigned char *key, const_DES_cblock *ivec);
DES_LONG DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
long length, DES_key_schedule *schedule, DES_key_schedule *schedule2,
long length, unsigned char *key,
const_DES_cblock *ivec);
int sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
unsigned char **out, int *out_len);

View File

@ -49,8 +49,6 @@ int
sm_cwa_get_mac(struct sc_context *ctx, unsigned char *key, DES_cblock *icv,
unsigned char *in, int in_len, DES_cblock *out, int force_padding)
{
DES_cblock kk, k2;
DES_key_schedule ks,ks2;
unsigned char padding[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char *buf;
@ -73,11 +71,7 @@ sm_cwa_get_mac(struct sc_context *ctx, unsigned char *key, DES_cblock *icv,
sc_debug(ctx, SC_LOG_DEBUG_SM, "sm_cwa_get_mac() data to MAC(%i) %s", in_len, sc_dump_hex(buf, in_len));
sc_debug(ctx, SC_LOG_DEBUG_SM, "sm_cwa_get_mac() ICV %s", sc_dump_hex((unsigned char *)icv, 8));
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
DES_set_key_unchecked(&kk,&ks);
DES_set_key_unchecked(&k2,&ks2);
DES_cbc_cksum_3des_emv96(buf, out, in_len ,&ks, &ks2, icv);
DES_cbc_cksum_3des_emv96(buf, out, in_len, key, icv);
free(buf);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);

View File

@ -129,8 +129,6 @@ sm_gp_get_cryptogram(unsigned char *session_key,
unsigned char *out, int out_len)
{
unsigned char block[24];
DES_cblock kk,k2;
DES_key_schedule ks,ks2;
DES_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
if (out_len!=8)
@ -140,11 +138,7 @@ sm_gp_get_cryptogram(unsigned char *session_key,
memcpy(block + 8, right, 8);
memcpy(block + 16, "\x80\0\0\0\0\0\0\0",8);
memcpy(&kk, session_key, 8);
memcpy(&k2, session_key + 8, 8);
DES_set_key_unchecked(&kk,&ks);
DES_set_key_unchecked(&k2,&ks2);
DES_cbc_cksum_3des(block,&cksum, sizeof(block),&ks,&ks2,&cksum);
DES_cbc_cksum_3des(block,&cksum, sizeof(block), session_key, &cksum);
memcpy(out, cksum, 8);
@ -158,8 +152,6 @@ sm_gp_get_mac(unsigned char *key, DES_cblock *icv,
{
int len;
unsigned char *block;
DES_cblock kk, k2;
DES_key_schedule ks,ks2;
block = malloc(in_len + 8);
if (!block)
@ -170,12 +162,7 @@ sm_gp_get_mac(unsigned char *key, DES_cblock *icv,
len = in_len + 8;
len -= (len%8);
memcpy(&kk, key, 8);
memcpy(&k2, key + 8, 8);
DES_set_key_unchecked(&kk,&ks);
DES_set_key_unchecked(&k2,&ks2);
DES_cbc_cksum_3des(block, out, len ,&ks, &ks2, icv);
DES_cbc_cksum_3des(block, out, len, key, icv);
free(block);
return 0;

View File

@ -602,7 +602,12 @@ int apiTests(char *reader)
unsigned char atr[36], cardid[16];
DWORD dwrc,dwlen,dwparam;
BOOL flag;
char *pinEnv = getenv("MINIDRIVER_PIN");
if (pinEnv)
printf("Running tests using PIN=%s/len=%zd\n", pinEnv, strlen(pinEnv));
else
printf("Running tests wihtout any PIN\n");
memset(&cardData, 0, sizeof(cardData));
cardData.dwVersion = 7;
cardData.pwszCardName = L"TestCard";
@ -630,8 +635,11 @@ int apiTests(char *reader)
atrlen = sizeof(atr);
if (SCardConnect(cardData.hSCardCtx, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &cardData.hScard, &protocol) != SCARD_S_SUCCESS) {
printf("SCardStatus() failed\n");
exit(1);
printf("SCardStatus(T1) failed, retry with T0\n");
if (SCardConnect(cardData.hSCardCtx, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &cardData.hScard, &protocol) != SCARD_S_SUCCESS) {
printf("SCardStatus() failed\n");
exit(1);
}
}
if (SCardStatus(cardData.hScard, NULL, &readernamelen, &state, &protocol, atr, &atrlen) != SCARD_S_SUCCESS) {
@ -703,14 +711,17 @@ int apiTests(char *reader)
printf("Calling CardGetProperty(CP_CARD_LIST_PINS)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_LIST_PINS, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == CREATE_PIN_SET(ROLE_USER))));
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (IS_PIN_SET(dwparam, ROLE_USER))));
/* let's continue the tests only for the ROLE_USER */
dwparam = 0;
SET_PIN(dwparam, ROLE_USER);
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0)));
printf("Calling CardGetProperty(CP_CARD_PIN_STRENGTH_VERIFY)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_PIN_STRENGTH_VERIFY, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_PIN_STRENGTH_VERIFY, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, ROLE_USER);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == CARD_PIN_STRENGTH_PLAINTEXT)));
printf("Calling CardGetProperty(CP_KEY_IMPORT_SUPPORT)");
@ -756,36 +767,40 @@ int apiTests(char *reader)
printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS));
printf("Calling CardAuthenticatePin(wszCARD_USER_USER)");
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, "648219", 6, &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 3)));
if (pinEnv) {
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, pinEnv, (DWORD)strlen(pinEnv), &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == -1)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2)));
printf("Calling CardAuthenticatePin(wszCARD_USER_USER) - Wrong PIN");
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, "123456", 6, &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_W_WRONG_CHV) && (dwparam == 2)));
printf("Calling CardAuthenticatePin(wszCARD_USER_USER) - Wrong PIN");
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, "3456", 4, &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_W_WRONG_CHV) && (dwparam == 2)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0)));
printf("Calling CardAuthenticatePin(wszCARD_USER_USER)");
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, "648219", 6, &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 3)));
printf("Calling CardAuthenticatePin(wszCARD_USER_USER)");
dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, pinEnv, (DWORD)strlen(pinEnv), &dwparam);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == -1)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2)));
printf("Calling CardDeAuthenticate(wszCARD_USER_USER)");
dwrc = (*cardData.pfnCardDeauthenticate)(&cardData, wszCARD_USER_USER, 0);
printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS));
printf("Calling CardDeAuthenticate(wszCARD_USER_USER)");
dwrc = (*cardData.pfnCardDeauthenticate)(&cardData, wszCARD_USER_USER, 0);
printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0)));
printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)");
dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0);
printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0)));
} else {
printf(" - skip: missing set MINIDRIVER_PIN=abcd\n");
}
printf("Calling CardDeleteContext()");
dwrc = (*cardData.pfnCardDeleteContext)(&cardData);

View File

@ -31,7 +31,7 @@ p11test_SOURCES = p11test.c p11test_loader.c \
p11test_case_pss_oaep.c \
p11test_case_interface.c \
p11test_helpers.c
p11test_CFLAGS = -DNDEBUG $(CMOCKA_CFLAGS)
p11test_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(CMOCKA_CFLAGS)
p11test_LDADD = $(OPTIONAL_OPENSSL_LIBS) $(CMOCKA_LIBS)
if WIN32

View File

@ -37,6 +37,7 @@
/* Global variable keeping information about token we are using */
token_info_t token;
int debug_flag = 0;
void display_usage() {
fprintf(stdout,
@ -98,7 +99,7 @@ int main(int argc, char** argv) {
token.slot_id = (unsigned long) -1;
token.log.outfile = NULL;
while ((command = getopt(argc, argv, "?hm:s:p:io:")) != -1) {
while ((command = getopt(argc, argv, "?hm:s:p:io:v")) != -1) {
switch (command) {
case 'o':
token.log.outfile = strdup(optarg);
@ -120,6 +121,9 @@ int main(int argc, char** argv) {
case '?':
display_usage();
return 0;
case 'v':
debug_flag = 1;
break;
default:
break;
}

View File

@ -20,6 +20,7 @@
*/
#include "p11test_case_common.h"
#include "../../libopensc/sc-ossl-compat.h"
char name_buffer[11];
char flag_buffer[11];
@ -208,8 +209,8 @@ int callback_certificates(test_certs_t *objects,
if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
/* Extract public RSA key */
RSA *rsa = EVP_PKEY_get0_RSA(evp);
if ((o->key.rsa = RSAPublicKey_dup(rsa)) == NULL) {
const RSA *rsa = EVP_PKEY_get0_RSA(evp);
if ((o->key.rsa = RSAPublicKey_dup((RSA *)rsa)) == NULL) {
fail_msg("RSAPublicKey_dup failed");
return -1;
}
@ -218,7 +219,7 @@ int callback_certificates(test_certs_t *objects,
} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
/* Extract public EC key */
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp);
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp);
if ((o->key.ec = EC_KEY_dup(ec)) == NULL) {
fail_msg("EC_KEY_dup failed");
return -1;
@ -447,7 +448,6 @@ int callback_public_keys(test_certs_t *objects,
if (strcmp((char *)curve->data, "edwards25519")) {
debug_print(" [WARN %s ] Unknown curve name. "
" expected edwards25519, got %s", o->id_str, curve->data);
return -1;
}
evp_type = EVP_PKEY_ED25519;
break;
@ -455,7 +455,6 @@ int callback_public_keys(test_certs_t *objects,
if (strcmp((char *)curve->data, "curve25519")) {
debug_print(" [WARN %s ] Unknown curve name. "
" expected curve25519, got %s", o->id_str, curve->data);
return -1;
}
evp_type = EVP_PKEY_X25519;
break;
@ -466,12 +465,13 @@ int callback_public_keys(test_certs_t *objects,
ASN1_PRINTABLESTRING_free(curve);
} else if (d2i_ASN1_OBJECT(&obj, &a, (long)template[6].ulValueLen) != NULL) {
int nid = OBJ_obj2nid(obj);
ASN1_OBJECT_free(obj);
switch (o->key_type) {
case CKK_EC_EDWARDS:
if (nid != NID_ED25519) {
debug_print(" [WARN %s ] Unknown OID. "
" expected NID_ED25519 (%d), got %d", o->id_str, NID_ED25519, nid);
return -1;
}
evp_type = EVP_PKEY_ED25519;
break;
@ -479,7 +479,6 @@ int callback_public_keys(test_certs_t *objects,
if (nid != NID_X25519) {
debug_print(" [WARN %s ] Unknown OID. "
" expected NID_X25519 (%d), got %d", o->id_str, NID_X25519, nid);
return -1;
}
evp_type = EVP_PKEY_X25519;
break;
@ -487,7 +486,6 @@ int callback_public_keys(test_certs_t *objects,
debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type);
return -1;
}
ASN1_OBJECT_free(obj);
} else {
debug_print(" [WARN %s ] Failed to convert EC_PARAMS"
" to curve name or object id", o->id_str);
@ -780,8 +778,12 @@ const char *get_mechanism_name(int mech_id)
return "ECDH1_COFACTOR_DERIVE";
case CKM_EC_KEY_PAIR_GEN:
return "EC_KEY_PAIR_GEN";
case CKM_EC_EDWARDS_KEY_PAIR_GEN:
return "EC_EDWARDS_KEY_PAIR_GEN";
case CKM_RSA_PKCS_KEY_PAIR_GEN:
return "RSA_PKCS_KEY_PAIR_GEN";
case CKM_GENERIC_SECRET_KEY_GEN:
return "GENERIC_SECRET_KEY_GEN";
case CKM_MD5_RSA_PKCS:
return "MD5_RSA_PKCS";
case CKM_RIPEMD160_RSA_PKCS:
@ -802,6 +804,8 @@ const char *get_mechanism_name(int mech_id)
return "MD5_HMAC";
case CKM_SHA_1_HMAC:
return "SHA_1_HMAC";
case CKM_SHA224_HMAC:
return "SHA224_HMAC";
case CKM_SHA256_HMAC:
return "SHA256_HMAC";
case CKM_SHA384_HMAC:

View File

@ -498,9 +498,7 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message,
CK_FUNCTION_LIST_PTR fp = info->function_pointer;
CK_MECHANISM sign_mechanism = { mech->mech, NULL_PTR, 0 };
static int verify_support = 1;
#ifndef NDEBUG
char *name;
#endif
if (!verify_support)
goto openssl_verify;
@ -531,15 +529,11 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message,
/* Final */
rv = fp->C_VerifyFinal(info->session_handle,
sign, sign_length);
#ifndef NDEBUG
name = "C_VerifyFinal";
#endif
} else {
rv = fp->C_Verify(info->session_handle,
message, message_length, sign, sign_length);
#ifndef NDEBUG
name = "C_Verify";
#endif
}
if (rv == CKR_OK) {
mech->result_flags |= FLAGS_SIGN;

View File

@ -54,9 +54,9 @@ void usage_test(void **state) {
fprintf(stderr, " [ ERROR %s ] If Unwrap is set, Wrap should be set too.\n",
objects.data[i].id_str);
}
if (objects.data[i].derive_pub) {
if (objects.data[i].derive_pub != objects.data[i].derive_priv) {
errors++;
fprintf(stderr, " [ ERROR %s ] Derive should not be set on public key\n",
fprintf(stderr, " [ ERROR %s ] Derive should be set on both private and public part.\n",
objects.data[i].id_str);
}

View File

@ -33,12 +33,12 @@
#define MAX_MECHS 200
#ifndef NDEBUG
#define debug_print(fmt, ...) \
{ fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
#else
#define debug_print(fmt, ...)
#endif
#define debug_print(fmt, ...) \
do { \
if (debug_flag) { \
fprintf(stderr, fmt "\n", ##__VA_ARGS__); \
} \
} while (0)
#define FLAGS_SIGN 0x01
#define FLAGS_SIGN_OPENSSL 0x02
@ -89,6 +89,7 @@ typedef struct {
} token_info_t;
extern token_info_t token;
extern int debug_flag;
#endif /* P11TEST_COMMON_H */

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,13 @@ compression_SOURCES = compression.c
compression_LDADD = $(LDADD) $(OPTIONAL_ZLIB_LIBS)
endif
if ENABLE_OPENSSL
noinst_PROGRAMS += sm
TESTS += sm
sm_SOURCES = sm.c
sm_LDADD = $(top_builddir)/src/sm/libsm.la $(LDADD)
endif
endif

View File

@ -241,7 +241,7 @@ static int setup_sc_context(void **state)
sc_context_t *ctx = NULL;
int rv;
rv = sc_establish_context(&ctx, "fuzz");
rv = sc_establish_context(&ctx, "asn1");
assert_non_null(ctx);
assert_int_equal(rv, SC_SUCCESS);

376
src/tests/unittests/sm.c Normal file
View File

@ -0,0 +1,376 @@
/*
* sm.c: Unit tests for Secure Messaging
*
* Copyright (C) 2021 Red Hat, Inc.
*
* Author: Jakub Jelen <jjelen@redhat.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 General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "torture.h"
#include "libopensc/log.c"
#include "sm/sm-common.h"
/* Setup context */
static int setup_sc_context(void **state)
{
sc_context_t *ctx = NULL;
int rv;
rv = sc_establish_context(&ctx, "sm");
assert_non_null(ctx);
assert_int_equal(rv, SC_SUCCESS);
*state = ctx;
return 0;
}
/* Cleanup context */
static int teardown_sc_context(void **state)
{
sc_context_t *ctx = *state;
int rv;
rv = sc_release_context(ctx);
assert_int_equal(rv, SC_SUCCESS);
return 0;
}
static void torture_sm_incr_ssc(void **state)
{
unsigned char in[] = {0x00, 0x00};
(void)state;
/* just make sure it does not crash */
sm_incr_ssc(NULL, 0);
/* zero-length input should not underflow the buffer */
sm_incr_ssc(in, 0);
/* shortest possible input */
in[0] = 0x42;
sm_incr_ssc(in, 1);
assert_int_equal(in[0], 0x43);
/* overflow to the second byte */
in[0] = 0x00;
in[1] = 0xff;
sm_incr_ssc(in, 2);
assert_int_equal(in[0], 0x01);
assert_int_equal(in[1], 0x00);
/* overflow */
in[0] = 0xff;
in[1] = 0xff;
sm_incr_ssc(in, 2);
assert_int_equal(in[0], 0x00);
assert_int_equal(in[1], 0x00);
}
static void torture_sm_crypt_des_cbc3(void **state)
{
sc_context_t *ctx = *state;
/* Test vector from
* https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf
* 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode
*/
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00};
unsigned char *out = NULL; /* allocates */
size_t out_len = 0;
int rv;
rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(out_len, sizeof(ciphertext));
assert_memory_equal(out, ciphertext, sizeof(ciphertext));
free(out);
out = NULL;
out_len = 0;
rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_memory_equal(out, plain, sizeof(plain));
free(out);
}
static void torture_sm_crypt_des_cbc3_multiblock(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
sc_context_t *ctx = *state;
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00};
unsigned char ciphertext[] = {
0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00,
0xAF, 0xA0, 0x77, 0x1d, 0x35, 0xE1, 0xCC, 0x26};
unsigned char *out = NULL; /* allocates */
size_t out_len = 0;
int rv;
rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(out_len, sizeof(ciphertext));
assert_memory_equal(out, ciphertext, sizeof(ciphertext));
free(out);
out = NULL;
out_len = 0;
rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_memory_equal(out, plain, sizeof(plain));
free(out);
}
static void torture_sm_crypt_des_cbc3_force_pad(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
sc_context_t *ctx = *state;
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ciphertext[] = {
0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00,
0xC6, 0xD3, 0xE1, 0x4F, 0xFB, 0xDE, 0xDF, 0xF9};
unsigned char *out = NULL; /* allocates */
size_t out_len = 0;
int rv;
rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 0);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(out_len, sizeof(ciphertext));
assert_memory_equal(out, ciphertext, sizeof(ciphertext));
free(out);
out = NULL;
out_len = 0;
rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_memory_equal(out, plain, sizeof(plain));
free(out);
}
static void torture_sm_encrypt_des_ecb3(void **state)
{
/* Test vector from
* https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf
* 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode
*/
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00};
unsigned char *out = NULL; /* allocates */
int out_len = 0;
int rv;
(void)state;
rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(out_len, sizeof(ciphertext));
assert_memory_equal(out, ciphertext, sizeof(ciphertext));
free(out);
out = NULL;
out_len = 0;
rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_memory_equal(out, plain, sizeof(plain));
free(out);
}
static void torture_sm_encrypt_des_ecb3_multiblock(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ciphertext[] = {
0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00,
0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F};
unsigned char *out = NULL; /* allocates */
int out_len = 0;
int rv;
(void)state;
rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_int_equal(out_len, sizeof(ciphertext));
assert_memory_equal(out, ciphertext, sizeof(ciphertext));
free(out);
out = NULL;
out_len = 0;
rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len);
assert_int_equal(rv, SC_SUCCESS);
assert_memory_equal(out, plain, sizeof(plain));
free(out);
}
static void torture_DES_cbc_cksum_3des(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char iv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char checksum_ref[] = {
0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00};
unsigned long sum_ref = 0xdd31d900UL;
unsigned char checksum[8];
unsigned long sum;
(void)state;
sum = DES_cbc_cksum_3des(plain, &checksum, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref));
/* The checksum argument is not required */
sum = DES_cbc_cksum_3des(plain, NULL, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
}
static void torture_DES_cbc_cksum_3des_multiblock(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char iv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* I think this function assumes/requires full blocks */
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char checksum_ref[] = {
0xC6, 0x3F, 0x6E, 0x72, 0xC7, 0xCF, 0x4E, 0x07};
unsigned long sum_ref = 0xc7cf4e07UL;
unsigned char checksum[8];
unsigned long sum;
(void)state;
sum = DES_cbc_cksum_3des(plain, &checksum, sizeof(plain), key, &iv);
assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref));
assert_int_equal(sum, sum_ref);
/* The checksum argument is not required */
sum = DES_cbc_cksum_3des(plain, NULL, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
}
static void torture_DES_cbc_cksum_3des_emv96(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char iv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char checksum_ref[] = {
0x00, 0x00, 0x00, 0x00, 0xDD, 0x31, 0xD9, 0x00};
unsigned long sum_ref = 0xdd31d900UL;
unsigned char checksum[8];
unsigned long sum;
(void)state;
sum = DES_cbc_cksum_3des_emv96(plain, &checksum, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref));
/* The checksum argument is not required */
sum = DES_cbc_cksum_3des_emv96(plain, NULL, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
}
static void torture_DES_cbc_cksum_3des_emv96_multiblock(void **state)
{
/* not a test vector -- generated by openssl 1.1.1 */
unsigned char key[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */};
unsigned char iv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* I think this function assumes/requires full blocks */
unsigned char plain[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char checksum_ref[] = {
0x95, 0xf8, 0xA5, 0xe5, 0xC7, 0xCF, 0x4E, 0x07};
unsigned long sum_ref = 0xc7cf4e07UL;
unsigned char checksum[8] = {0};
unsigned long sum;
(void)state;
sum = DES_cbc_cksum_3des_emv96(plain, &checksum, sizeof(plain), key, &iv);
assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref));
assert_int_equal(sum, sum_ref);
/* The checksum argument is not required */
sum = DES_cbc_cksum_3des_emv96(plain, NULL, sizeof(plain), key, &iv);
assert_int_equal(sum, sum_ref);
}
int main(void)
{
int rc;
struct CMUnitTest tests[] = {
/* sm_incr_ssc */
cmocka_unit_test(torture_sm_incr_ssc),
/* sm_encrypt_des_cbc3 and sm_decrypt_des_cbc3 */
cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3,
setup_sc_context, teardown_sc_context),
cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_multiblock,
setup_sc_context, teardown_sc_context),
cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_force_pad,
setup_sc_context, teardown_sc_context),
/* sm_encrypt_des_ecb3 */
cmocka_unit_test(torture_sm_encrypt_des_ecb3),
cmocka_unit_test(torture_sm_encrypt_des_ecb3_multiblock),
/* DES_cbc_cksum_3des */
cmocka_unit_test(torture_DES_cbc_cksum_3des),
cmocka_unit_test(torture_DES_cbc_cksum_3des_multiblock),
/* DES_cbc_cksum_3des_emv96 */
cmocka_unit_test(torture_DES_cbc_cksum_3des_emv96),
cmocka_unit_test(torture_DES_cbc_cksum_3des_emv96_multiblock),
};
rc = cmocka_run_group_tests(tests, NULL, NULL);
return rc;
}

View File

@ -182,4 +182,4 @@ noinst_DATA = org.opensc-project.mac.pkcs11-register.plist org.opensc-project.ma
$(AM_V_GEN)$(do_subst) < $< > $@
clean-local:
rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/goid-tool.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop pkcs11-register.desktop
rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/goid-tool.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop pkcs11-register.desktop org.opensc-project.mac.opensc-notify.plist org.opensc-project.mac.pkcs11-register.plist

View File

@ -248,6 +248,7 @@ static void exportprint(const char *key, const char *val)
strcat(cp, "=");
strcat(cp, val);
putenv(cp);
free(cp);
}
} else
printf("%s: %s\n", key, val);

View File

@ -118,7 +118,7 @@ static int load_object(const char * object_id, const char * object_file)
int r = -1;
struct stat stat_buf;
if(!object_file || (fp=fopen(object_file, "r")) == NULL){
if(!object_file || (fp=fopen(object_file, "rb")) == NULL){
printf("Cannot open object file, %s %s\n",
(object_file)?object_file:"", strerror(errno));
goto err;
@ -184,7 +184,7 @@ static int load_cert(const char * cert_id, const char * cert_file,
goto err;
}
if((fp=fopen(cert_file, "r"))==NULL){
if((fp=fopen(cert_file, "rb"))==NULL){
printf("Cannot open cert file, %s %s\n",
cert_file, strerror(errno));
goto err;

View File

@ -866,14 +866,14 @@ int main(int argc, char * argv[])
break;
case OPT_SLOT_DESCRIPTION:
if (opt_slot_set) {
fprintf(stderr, "Error: Only one of --slot, --slot-label, --slot-index or --token-label can be used\n");
fprintf(stderr, "Error: Only one of --slot, --slot-description, --slot-index or --token-label can be used\n");
util_print_usage_and_die(app_name, options, option_help, NULL);
}
opt_slot_description = optarg;
break;
case OPT_SLOT_INDEX:
if (opt_slot_set || opt_slot_description) {
fprintf(stderr, "Error: Only one of --slot, --slot-label, --slot-index or --token-label can be used\n");
fprintf(stderr, "Error: Only one of --slot, --slot-description, --slot-index or --token-label can be used\n");
util_print_usage_and_die(app_name, options, option_help, NULL);
}
opt_slot_index = (CK_ULONG) strtoul(optarg, NULL, 0);
@ -885,7 +885,7 @@ int main(int argc, char * argv[])
break;
case OPT_TOKEN_LABEL:
if (opt_slot_set || opt_slot_description || opt_slot_index_set) {
fprintf(stderr, "Error: Only one of --slot, --slot-label, --slot-index or --token-label can be used\n");
fprintf(stderr, "Error: Only one of --slot, --slot-description, --slot-index or --token-label can be used\n");
util_print_usage_and_die(app_name, options, option_help, NULL);
}
opt_token_label = optarg;
@ -1133,7 +1133,7 @@ int main(int argc, char * argv[])
fprintf(stderr, "Using slot with index %lu (0x%lx)\n", opt_slot_index, opt_slot);
} else {
fprintf(stderr, "Slot with index %lu (counting from 0) is not available.\n", opt_slot_index);
fprintf(stderr, "You must specify a valid slot with either --slot, --slot-index or --slot-label.\n");
fprintf(stderr, "You must specify a valid slot with either --slot, --slot-description, --slot-index or --token-label.\n");
err = 1;
goto end;
}
@ -2745,6 +2745,12 @@ static int gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
n_privkey_attr++;
}
if (opt_is_extractable != 0) {
FILL_ATTR(privateKeyTemplate[n_privkey_attr], CKA_EXTRACTABLE,
&_true, sizeof(_true));
n_privkey_attr++;
}
if (opt_allowed_mechanisms_len > 0) {
FILL_ATTR(privateKeyTemplate[n_privkey_attr],
CKA_ALLOWED_MECHANISMS, opt_allowed_mechanisms,
@ -3137,18 +3143,18 @@ parse_gost_pkey(EVP_PKEY *pkey, int private, struct gostkey_info *gost)
static int
parse_ec_pkey(EVP_PKEY *pkey, int private, struct gostkey_info *gost)
{
EC_KEY *src = EVP_PKEY_get0(pkey);
const EC_KEY *src = EVP_PKEY_get0_EC_KEY(pkey);
const BIGNUM *bignum;
if (!src)
return -1;
gost->param_oid.len = i2d_ECParameters(src, &gost->param_oid.value);
gost->param_oid.len = i2d_ECParameters((EC_KEY *)src, &gost->param_oid.value);
if (gost->param_oid.len <= 0)
return -1;
if (private) {
bignum = EC_KEY_get0_private_key(EVP_PKEY_get0(pkey));
bignum = EC_KEY_get0_private_key(src);
gost->private.len = BN_num_bytes(bignum);
gost->private.value = malloc(gost->private.len);
@ -3234,7 +3240,7 @@ static int write_object(CK_SESSION_HANDLE session)
if (opt_attr_from_file) {
if (!(f = fopen(opt_attr_from_file, "rb")))
util_fatal("Couldn't open file \"%s\"", opt_attr_from_file);
certdata_len = fread(certdata, 1, sizeof(certdata), f);
certdata_len = fread(certdata, 1, sizeof(certdata) - 1, f);
fclose(f);
if (certdata_len < 0)
util_fatal("Couldn't read from file \"%s\"", opt_attr_from_file);

View File

@ -389,7 +389,7 @@ print_data_object(const char *kind, const u8*data, size_t data_len)
if (opt_outfile != NULL) {
FILE *outf;
outf = fopen(opt_outfile, "w");
outf = fopen(opt_outfile, "wb");
if (outf == NULL) {
fprintf(stderr, "Error opening file '%s': %s\n",
opt_outfile, strerror(errno));
@ -987,13 +987,13 @@ static int read_ssh_key(void)
}
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
if (outf != stdout)
if (opt_outfile != NULL)
fclose(outf);
fprintf(stderr, "Public key with ID '%s' not found.\n", opt_pubkey);
return 2;
}
if (r < 0) {
if (outf != stdout)
if (opt_outfile != NULL)
fclose(outf);
fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
return 1;
@ -1242,7 +1242,7 @@ static int read_ssh_key(void)
print_ssh_key(outf, "ssh-dss", obj, buf, len);
}
if (outf != stdout)
if (opt_outfile != NULL)
fclose(outf);
if (cert)
sc_pkcs15_free_certificate(cert);
@ -1252,7 +1252,7 @@ static int read_ssh_key(void)
fail:
printf("can't convert key: buffer too small\n");
fail2:
if (outf && outf != stdout)
if (opt_outfile != NULL && outf != NULL)
fclose(outf);
if (cert)
sc_pkcs15_free_certificate(cert);

View File

@ -1,13 +1,21 @@
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
AM_TESTS_ENVIRONMENT = \
SOURCE_PATH='$(top_srcdir)'; \
export SOURCE_PATH; \
BUILD_PATH='$(top_builddir)'; \
export BUILD_PATH;
dist_noinst_SCRIPTS = common.sh \
test-manpage.sh \
test-duplicate-symbols.sh \
test-fuzzing.sh \
test-pkcs11-tool-test.sh \
test-pkcs11-tool-test-threads.sh \
test-pkcs11-tool-sign-verify.sh \
test-pkcs11-tool-allowed-mechanisms.sh
.NOTPARALLEL:
TESTS = \
test-manpage.sh \
test-duplicate-symbols.sh \

View File

@ -3,7 +3,7 @@
SOPIN="12345678"
PIN="123456"
PKCS11_TOOL="../src/tools/pkcs11-tool"
PKCS11_TOOL="$BUILD_PATH/src/tools/pkcs11-tool"
softhsm_paths="/usr/local/lib/softhsm/libsofthsm2.so \
/usr/lib/softhsm/libsofthsm2.so

View File

@ -1,5 +1,5 @@
#!/bin/bash
SOURCE_PATH=..
SOURCE_PATH=${SOURCE_PATH:-../}
EXPORTS=`find "${SOURCE_PATH}" -name "*exports"`

View File

@ -1,5 +1,5 @@
#!/bin/bash
SOURCE_PATH=../
#!/bin/bash -x
SOURCE_PATH=${SOURCE_PATH:-../}
# find all the manual pages in doc/tools
TOOLS=`find "${SOURCE_PATH}/doc/tools" -name "*.1.xml" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|" | grep -v goid-tool`

View File

@ -1,6 +1,7 @@
#!/bin/bash
SOURCE_PATH=${SOURCE_PATH:-../}
source common.sh
source $SOURCE_PATH/tests/common.sh
echo "======================================================="
echo "Setup SoftHSM"
@ -47,6 +48,6 @@ echo "Cleanup"
echo "======================================================="
softhsm_cleanup
rm objects.list
rm objects.list sign.log
exit $ERRORS

View File

@ -1,6 +1,7 @@
#!/bin/bash
SOURCE_PATH=${SOURCE_PATH:-../}
source common.sh
source $SOURCE_PATH/tests/common.sh
echo "======================================================="
echo "Setup SoftHSM"

View File

@ -1,6 +1,7 @@
#!/bin/bash
SOURCE_PATH=${SOURCE_PATH:-../}
source common.sh
source $SOURCE_PATH/tests/common.sh
echo "======================================================="
echo "Setup SoftHSM"

View File

@ -1,6 +1,7 @@
#!/bin/bash
SOURCE_PATH=${SOURCE_PATH:-../}
source common.sh
source $SOURCE_PATH/tests/common.sh
echo "======================================================="
echo "Setup SoftHSM"

View File

@ -63,6 +63,11 @@ typedef struct _MD_REGISTRATION
/* note: we could have added the minidriver registration data directly in OpenSC.wxs but coding it allows for more checks.
For example, do not uninstall the minidriver for a card if a middleware is already installed */
/*
* In order to compute the proper ATRMask, see:
* https://github.com/OpenSC/OpenSC/wiki/Adding-a-new-card-driver#windows-minidriver-support
*/
MD_REGISTRATION minidriver_registration[] = {
{TEXT("ePass2003"), {0x3b,0x9f,0x95,0x81,0x31,0xfe,0x9f,0x00,0x66,0x46,0x53,0x05,0x01,0x00,0x11,0x71,0xdf,0x00,0x00,0x03,0x6a,0x82,0xf8},
23, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}},
@ -183,6 +188,12 @@ MD_REGISTRATION minidriver_registration[] = {
15, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
{TEXT("Rutoken Lite SC"), {0x3B,0x8B,0x01,0x52,0x75,0x74,0x6F,0x6B,0x65,0x6E,0x6C,0x69,0x74,0x65,0xC2},
15, {0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
/* from card-iasecc.c */
{TEXT("IAS/ECC CPx"), {0x3B,0x00,0x00,0x00,0x00,0x00,0x12,0x25,0x00,0x64,0x80,0x00,0x00,0x00,0x00,0x90,0x00},
17, {0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF}},
{TEXT("IAS/ECC CPxCL"), {0x3B,0X8F,0x80,0x01,0x00,0x31,0xB8,0x64,0x00,0x00,0xEC,0xC0,0x73,0x94,0x01,0x80,0x82,0x90,0x00,0x0E},
20, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
};