Compare commits

...

298 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
Anton Logachev 570fc56c47 Remove the SC_SEC_ENV_FILE_REF_PRESENT flag for Rutoken ECP cards
Rutoken ECP cards have no default SE file. Previous cards ignored
MSE with restoring default SE, but new cards don't. This requires
SC_SEC_ENV_FILE_REF_PRESENT to be removed from env flags.
2021-04-29 23:03:32 +02:00
Doug Engert 19611682bd Fix for #2283 C_Sign fails ECDSA when card can do HASH on card
Do not truncate ECDSA input to size of key if card or driver will do HASH.

 On branch Fix_for_2283_ECDSA
 Changes to be committed:
	modified:   src/libopensc/pkcs15-sec.c
2021-04-27 10:50:00 +02:00
Vincent JARDIN a21bcf4b41 IASECC/Gemalto: register application
Register application for Gemalto Dual ID ONE Cosmo.
2021-04-26 21:37:39 +02:00
Vincent JARDIN e93bd3983c IASECC/Gemalto: add support
Add support for Gemalto's IAS ECC Dual ID One Cosmo using samples from:
  http://cartesapuce-discount.com/fr/cartes-a-puce-ias-ecc/146-cartes-a-puce-protiva-ias-ecc-tpc.html

Some suppots were already available (ATR, init, etc.), but the
select_file was missing the proper cases.
2021-04-26 21:37:39 +02:00
Frank Morgner 3f19991556 updated NEWS 2021-04-26 18:13:43 +02:00
Frank Morgner 4ecb4b39ac updated documentation 2021-04-26 18:13:43 +02:00
Frank Morgner 75f24d2af7 regenerated egk-tool cmdline 2021-04-26 18:13:43 +02:00
Frank Morgner 2063a1d334 silince generation of files 2021-04-26 18:13:43 +02:00
Vincent JARDIN e3a3722ad1 IASECC/CPX: Fix SDO path
Some objects need to be read from a specific path.

IASECC_SDO_PRVKEY_TAG: from 3F00:0001
IASECC_SDO_CHV_TAG: from 3F00
2021-04-26 15:55:17 +02:00
Vincent JARDIN fcd2e665fe IASECC/CPX: fix APDU errors for SE get data
On a CPX, this object needs to be read from 3F00.

For instance:

$ opensc-explorer -r 2

OpenSC [3F00]> cd 0002
OpenSC [3F00/0002]> apdu 00 CB 3F FF 0A 4D 08 70 06 BF FB 05 02 7B 80
Sending: 00 CB 3F FF 0A 4D 08 70 06 BF FB 05 02 7B 80
Received (SW1=0x6A, SW2=0x88)
Failure: Data object not found

OpenSC [3F00/0002]> apdu 00 A4 09 04 02 3F 00
Sending: 00 A4 09 04 02 3F 00
Received (SW1=0x90, SW2=0x00)
Success!

OpenSC [3F00/0002]> apdu 00 CB 3F FF 0A 4D 08 70 06 BF FB 05 02 7B 80
Sending: 00 CB 3F FF 0A 4D 08 70 06 BF FB 05 02 7B 80
Received (SW1=0x90, SW2=0x00)
Success!

Currently, this patch limits to the CPX cards since I cannot know
the behaviour for the other cards. I could not find any reference
from the standard.

Fix: issue #2275
2021-04-26 15:55:17 +02:00
Vincent JARDIN 405ecfc402 IASECC: proper pkcs15init of Algo_refs
For some Private RSA Keys, their Algo_refs remain empty:
$ pkcs15-tool -k --verify-pin  --pin 1234
Using reader with a card: ACS ACR33U-A1 3SAM ICC Reader 00 00
Private RSA Key [CPS_PRIV_SIG]
	Object Flags   : [0x01], private
	Usage          : [0x200], nonRepudiation
	Access Flags   : [0x0D], sensitive, alwaysSensitive, neverExtract
	Algo_refs      : 0
	Access Rules   : pso_cds:01;
	ModLength      : 2048
	Key ref        : 129 (0x81)
	Native         : yes
	Path           : e828bd080f8025000001ff0010::
	Auth ID        : 01
	ID             : e828bd080f8025000001ff001001
	MD:guid        : e7aab727-f2af-e673-37bb-7d43867a6349

Private RSA Key [CPS_PRIV_AUT]
	Object Flags   : [0x07], private, modifiable
	Usage          : [0x06], decrypt, sign
	Access Flags   : [0x0D], sensitive, alwaysSensitive, neverExtract
	Algo_refs      : 6, 3, 4
	Access Rules   : pso_decrypt:01; int_auth:01;
	ModLength      : 2048
	Key ref        : 130 (0x82)
	Native         : yes
	Path           : e828bd080f8025000001ff0010::
	Auth ID        : 01
	ID             : e828bd080f8025000001ff001002
	MD:guid        : 2b6bf284-225c-80bc-8cbe-1c791db33543

Based on Usage : [0x200], nonRepudiation the SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
may be set but not the SC_PKCS15_PRKEY_USAGE_SIGN so line 801 is never tested.

Having just SC_PKCS15_PRKEY_USAGE_NONREPUDIATION set and not doing anything does not
make any sense for any card.

Suggested-by: Doug Engert <deengert@gmail.com>
Fix: issue #2270
2021-04-26 15:52:09 +02:00
Vincent JARDIN 544aa4cc6b IASECC/CPX: Fix up prkeyinfo/algo_ref
Extend the current support from 9abf8ee04c
in order to add a fixup for the CPx cards.

Since the data is not properly encoded when the card is initialized
let's re-build it for each run time from the DF.

Suggested-by: Doug Engert <deengert@gmail.com>
Fix: issue #2270
2021-04-26 15:52:09 +02:00
Vincent JARDIN 137286858f IASECC/CPX: enable calls thru pkcs15-iasecc.c
Same than Gemalto's IASECC, the CPX cards need a workaround since
the PrKey does not have its Algo_regs.

We get:
pkcs15-tool -k --verify-pin --pin 1234
Using reader with a card: ACS ACR33U-A1 3SAM ICC Reader 00 00
Private RSA Key [CPS_PRIV_SIG]
	Object Flags   : [0x01], private
	Usage          : [0x200], nonRepudiation
	Access Flags   : [0x0D], sensitive, alwaysSensitive, neverExtract
	Algo_refs      : 0
	Access Rules   : pso_cds:01;
	ModLength      : 2048
	Key ref        : 129 (0x81)
	Native         : yes
	Path           : e828bd080f8025000001ff0010::
	Auth ID        : 01
	ID             : e828bd080f8025000001ff001001
	MD:guid        : e7aab727-f2af-e673-37bb-7d43867a6349

Private RSA Key [CPS_PRIV_AUT]
	Object Flags   : [0x07], private, modifiable
	Usage          : [0x06], decrypt, sign
	Access Flags   : [0x0D], sensitive, alwaysSensitive, neverExtract
	Algo_refs      : 0
	Access Rules   : pso_decrypt:01; int_auth:01;
	ModLength      : 2048
	Key ref        : 130 (0x82)
	Native         : yes
	Path           : e828bd080f8025000001ff0010::
	Auth ID        : 01
	ID             : e828bd080f8025000001ff001002
	MD:guid        : 2b6bf284-225c-80bc-8cbe-1c791db33543

We need to get Algo_regs to be set to something that is not 0.

Fix: issue #2267
2021-04-26 15:52:09 +02:00
Vincent JARDIN 39b4472f38 IASECC/CPX: export pkcs15init for missing features
Some cards, such as the CPX are missing features that should
have been initialized using:
  iasecc_pkcs15_encode_supported_algos()

Let's export this function in order to build a fixup when the DF
should be parsed.

When OPENSSL is missing, an error should be rised since this
workaround for the CPX cards cannot work. It means that
any environments that use the CPX cards must be compiled with
ENABLE_OPENSSL.

Suggested-by: Doug Engert <deengert@gmail.com>
Fix: issue #2270
2021-04-26 15:52:09 +02:00
Vincent JARDIN 396cbc46cf IASECC/CPX: set default flags
The CPX has the standard capabilities of the IASECC standard.

Let's be carefull with memory leakage, see the
previous commit 83162c5c8

Fix: issue #2270
2021-04-26 15:52:09 +02:00
Frank Morgner 4912f05701 use OpenPACE 1.1.1 2021-04-25 12:03:52 +02:00
Peter Marschall 344ac0abe6 iasec: use proper printf format specifiers for size_t
Do not hard-code the printf format specifier for size_t: use the macro instead.

This fixes compliation on 32-bit architectures.
2021-04-20 14:26:37 +02:00
Jakub Jelen d6ec00c870 cardos: Add ATR for CardOS 5.4
Hopefully fixes #2296
2021-04-15 17:59:31 +02:00
Peter Popovec dd48facd38 travis CI: testsuite fix (tests/test-pkcs11-tool-allowed-mechanisms.sh)
Ubuntu (focal) softhsm2 workaround - mechanism listing incorrect
2021-04-14 11:02:58 +02:00
Peter Popovec 7d274a0d72 travis-ci: Try to run the tests on Ubuntu 20 (Focal Fossa) 2021-04-14 11:02:58 +02:00
Jakub Jelen ef17b3fb89 tests: Fix comparison for osx 2021-04-13 21:58:47 +02:00
Jakub Jelen cae5c71f90 oberthur: Handle 1B OIDs
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32807
2021-04-13 21:58:47 +02:00
Jakub Jelen 4b3c6dec07 .travis: Fail if tests fail 2021-04-13 21:58:47 +02:00
Frank Morgner 991bb8a141 add CPDK include flags 2021-04-08 15:15:46 +02:00
Frank Morgner a83069b89f updated to Microsoft Cryptographic Provider Development Kit (CPDK) Version 8.0 2021-04-08 11:25:08 +02:00
Carsten Blüggel edb7ed25e4 pkcs11-tool: disable wrap/unwrap test until OpenSC#1796 is resolved 2021-04-07 10:25:54 +02:00
Frank Morgner 545e47b29e preparation for 0.22.0 2021-04-06 13:42:50 +02:00
Vincent JARDIN 1a3666364d IASECC/CPX: Avoid APDU Incorrect Parameters
Without this patch, we would get from the logs:
Outgoing APDU (18 bytes):
00 A4 04 00 0D E8 28 BD 08 0F 80 25 00 00 01 FF ......(....%....
00 10                                           ..
 [opensc-pkcs11] reader-pcsc.c:242:pcsc_internal_transmit: called
 [opensc-pkcs11] reader-pcsc.c:333:pcsc_transmit:
Incoming APDU (2 bytes):
6A 86 j.
 [opensc-pkcs11] apdu.c:382:sc_single_transmit: returning with: 0 (Success)
 [opensc-pkcs11] apdu.c:537:sc_transmit: returning with: 0 (Success)
 [opensc-pkcs11] card.c:523:sc_unlock: called
 [opensc-pkcs11] iso7816.c:128:iso7816_check_sw: Incorrect parameters P1-P2
 [opensc-pkcs11] card-iasecc.c:1064:iasecc_select_file: Warning: SC_ERROR_INCORRECT_PARAMETERS for SC_PATH_TYPE_DF_NAME, try again with P2=0x0C
 [opensc-pkcs11] apdu.c:548:sc_transmit_apdu: called
 [opensc-pkcs11] card.c:473:sc_lock: called
 [opensc-pkcs11] card.c:513:sc_lock: returning with: 0 (Success)
 [opensc-pkcs11] apdu.c:515:sc_transmit: called
 [opensc-pkcs11] apdu.c:363:sc_single_transmit: called
 [opensc-pkcs11] apdu.c:367:sc_single_transmit: CLA:0, INS:A4, P1:4, P2:C, data(13) 0x7fff4b339b20
 [opensc-pkcs11] reader-pcsc.c:323:pcsc_transmit: reader 'Ingenico TL TELIUM (25005334) 00 02'
 [opensc-pkcs11] reader-pcsc.c:324:pcsc_transmit:
Outgoing APDU (18 bytes):
00 A4 04 0C 0D E8 28 BD 08 0F 80 25 00 00 01 FF ......(....%....
00 10                                           ..
 [opensc-pkcs11] reader-pcsc.c:242:pcsc_internal_transmit: called
 [opensc-pkcs11] reader-pcsc.c:333:pcsc_transmit:
Incoming APDU (2 bytes):
90 00 ..

Let's align it with the behaviour of the other IASECC cards.
2021-04-01 11:11:33 +02:00
Vincent JARDIN 0df0f80b55 IASECC: log any APDU Incorrect parameters
From the logs, we can detect many 6A 86 (Incorrect P1 or P2 paremeters).
A deeper analysis will be required, but the best option to check them
is to start emitting any Warning for such events.
2021-04-01 11:11:33 +02:00
Philip Prindeville b9c0addf88 update configure.ac to be less noisy
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
2021-04-01 11:09:22 +02:00
yehj c3c5f2d518 Add criteria to check if card capability SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH is available
The code segment checks the response to determine if the
SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH is available.
From the APDU manual of the sc-hsm, there's one status word:
SC_ERROR_REF_DATA_NOT_USABLE(0x6984) that should also be taken into account.
2021-04-01 10:29:33 +02:00
Frank Morgner 83162c5c87 fixed memory leak
fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32324

sc_enum_apps() causes card->cache.current_ef to be allocated for
IAS/ECC, but not freed if any other error occurs during initialization.
since sc_enum_apps() is called anyway during PKCS#15 initialization.
Having this at the card driver level (instead of the PKCS#15 level) is
not needed.
2021-03-24 23:27:01 +01:00
Frank Morgner ce0d409205 Avoid accessing Uninitialized scalar variable
regression of c581d1b26

coverity scan CID 367545
2021-03-24 23:27:01 +01:00
Jakub Jelen 7114fb71b5 coolkey: Initialize potentially uninitialized memory
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28855
2021-03-24 16:25:08 +01:00
Jakub Jelen 9cc942fd47 framework-pkcs15: Fix PKCS#11 semantics while encoding EC pubkey params 2021-03-24 16:25:08 +01:00
Jakub Jelen 7d0abdc192 p11test: Remove unnecessary spaces in JSON output 2021-03-24 16:25:08 +01:00
Jakub Jelen 370eda4bd8 framework-pkcs15: Avoid strict aliasing issues 2021-03-24 16:25:08 +01:00
Frank Morgner 5f9085fedb
Merge pull request #1960 from Jakuje/eddsa
Add support for (X)EdDSA keys in OpenPGP driver
2021-03-22 15:36:59 +01:00
Marco Trevisan (Treviño) 845eac4250 pkcs11-global: Obey to the tokenPresent parameter on C_GetSlotList
Since commit dba0f56 the tokenPresent parameter is ignored in case the
slot has been already seen.

This breaks the API expectations as we may return a slot that has no
token inserted.

So, only consider the SC_PKCS11_SLOT_FLAG_SEEN if tokenPresent is false
2021-03-22 15:35:55 +01:00
Vincent JARDIN 40e9a9c830 pkcs15: log HSM capabilities (can_do)
Some Smartcards have some capabilities (for instance the IASECC)
that can influence the can_do cases. In order to track them, it
is useful to log any checks.
2021-03-22 13:15:12 +01:00
Vincent JARDIN b18234a7d9
iasecc: Fix ACLs support when length is 6 (#2264)
* IASECC: offset is a size_t

Let's use a size_t for the offset in order to have a proper logic
along with the related arithmetics.

Fix: part if issue #2262
Suggested-by: Frank Morgner <frankmorgner@gmail.com>

* iasecc: Fix ACLs support when length is 6

ACLs with length < 6 are allowed, depending on the mask of the offset 0.
For instance, when the offset 0 is 0x7B, then length can be up to 7
when the offset 0 is 0x7A, the loop was never performing any access to
the acls[7] thanks to:
  if (!(mask & acls[0]))
    continue;

However, the oss-fuzz tools cannot guess such behavior. So let's have a
robust boundary check.

Fix: issue #2262
Fix: ae1cf0be90 'Prevent stack buffer overflow when empty ACL is returned'

Co-authored-by: Vincent JARDIN <vjardin@free.fr>
Co-authored-by: Frank Morgner <frankmorgner@gmail.com>
2021-03-22 13:08:28 +01:00
Jakub Jelen 5d4daf6c92 oberthur: One more overlooked buffer overflow
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32202
2021-03-21 09:53:13 +01:00
Jakub Jelen 715c17c469 oberthur: Fix memory leaks
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32149
2021-03-18 13:18:10 +01:00
Jakub Jelen d5dea2dd1b tests: Investigate test failure on bionic 2021-03-18 09:58:21 +01:00
Jakub Jelen 16b7c60fd3 Fix more issues with strict aliasing reported by gcc v8
Thanks popoves for reporting this issue
2021-03-18 09:58:21 +01:00
Frank Morgner 05648b0604 oberthur: fixed Heap-buffer-overflow
fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32149
2021-03-18 09:56:46 +01:00
Vincent JARDIN fc0df4e5d5 IASECC/CPX: revert removal of 3F00 from the path
Few years ago, the commit 03628449b7
did squash the 3F00nnnn path to nnnn. For instance, 3F002F00
becomes 2F00. It is an issue such as:
  00000200 [139681798813440] APDU: 00 A4 09 04 02 2F 00
  00029790 [139681798813440] SW: 6A 82

Fix: issue #2231
2021-03-17 10:58:20 +01:00
Vincent JARDIN 76507508d7 IASECC/CPX: code factorization
There are two flavours of CPX cards:
  - contact mode,
  - contactless mode
2021-03-17 10:58:20 +01:00
Vincent JARDIN 4119b2c3e7 ASN1 lax bit string decoding
Some ASN1 objects stored on some smartcards (for instance the
IASECC/CPX ones) do not comply strictly with the rules
8.6.2.3 and 8.6.2.3 from the ITU.

Since these rules are not some strict ones, let's have a loose
decoding option that can be displayed by the command:
opensc-explorer
  asn1 7001 # for instance

Fix: issue #2224
2021-03-17 10:58:20 +01:00
Vincent JARDIN b508349010 IASECC/CPX: opensc-explorer asn1 EF.ATR parsing
Let's the advance users be able to parse the ASN1 contant
for any offset.

OpenSC [3F00]> asn1 2F01 0
Error in decoding.
OpenSC [3F00]> asn1 2F01 1
43 Application 3  (1 byte): decode error, : B8 .
46 Application 6  (4 bytes): decode error: 04 B0 EC C1 ....
47 Application 7  (3 bytes): 94 01 80 ...
4F Application 15 (8 bytes): 80 25 00 00 01 FF 01 00 .%......
E0 Private 0  (16 bytes)
   02 INTEGER (2 bytes): 260
   02 INTEGER (2 bytes): 260
   02 INTEGER (2 bytes): 256
   02 INTEGER (2 bytes): 256
78 Application 24 (8 bytes)
   06 OBJECT IDENTIFIER (6 bytes):  1.3.162.15480.2
82 Context 2  (2 bytes): 36864: 90 00 ..

Fix: issue #2220
2021-03-17 10:58:20 +01:00
Vincent JARDIN 20f359ea04 IASECC/CPX: SC_PATH_TYPE_FILE_ID, wrong APDU
For SC_PATH_TYPE_FILE_ID, P2 should be 0x04, if not,
then we get the following errors:
 [opensc-pkcs11] reader-pcsc.c:324:pcsc_transmit:
Outgoing APDU (7 bytes):
00 A4 02 00 02 A0 01 .......
 [opensc-pkcs11] reader-pcsc.c:242:pcsc_internal_transmit: called
 [opensc-pkcs11] reader-pcsc.c:333:pcsc_transmit:
Incoming APDU (2 bytes):
6A 86 j.
 [opensc-pkcs11] apdu.c:382:sc_single_transmit: returning with: 0 (Success)
 [opensc-pkcs11] apdu.c:535:sc_transmit: returning with: 0 (Success)
 [opensc-pkcs11] card.c:523:sc_unlock: called
 [opensc-pkcs11] iso7816.c:128:iso7816_check_sw: Incorrect parameters P1-P2
 [opensc-pkcs11] card-iasecc.c:1107:iasecc_select_file: iasecc_select_file() check SW failed: -1205 (Incorrect parameters in APDU)
 [opensc-pkcs11] card.c:866:sc_select_file: 'SELECT' error: -1205 (Incorrect parameters in APDU)

when running:
  ./pkcs11-tool --test --login --pin abcd
2021-03-17 10:58:20 +01:00
Vincent JARDIN c581d1b26f IASECC/CPX: opensc-explorer asn1 of EF.ATR objects
Workaround the parsing of EF.ATR objects, for instance:

./opensc-explorer -r 0

OpenSC [3F00]> cat 2F01
00000000: 80 43 01 B8 46 04 04 B0 EC C1 47 03 94 01 80 4F .C..F.....G....O
00000010: 08 80 25 00 00 01 FF 01 00 E0 10 02 02 01 04 02 ..%.............
00000020: 02 01 04 02 02 01 00 02 02 01 00 78 08 06 06 2B ...........x...+
00000030: 81 22 F8 78 02 82 02 90 00                      .".x.....

OpenSC [3F00]> info 2F01
Working Elementary File  ID 2F01, SFI E8

File path:               3F00/2F01
File size:               57 bytes
EF structure:            Transparent
ACL for READ:            NONE
ACL for UPDATE:          SecOx45
ACL for DELETE:          SecOx45
ACL for WRITE:           N/A
ACL for REHABILITATE:    N/A
ACL for INVALIDATE:      N/A
ACL for LIST FILES:      N/A
ACL for CRYPTO:          N/A
Type attributes:         01
Life cycle:              Operational, activated

In order to avoid adding an offset of 1 for such objects on some
  OpenSC [3F00]> asn1 2F01 1
specific cards, then, we get:

OpenSC [3F00]> asn1 2F01
80 Context 0  (0 bytes)
43 Application 3  (1 byte): decode error: B8 .
46 Application 6  (4 bytes): decode error: 04 B0 EC C1 ....
47 Application 7  (3 bytes): 94 01 80 ...
4F Application 15 (8 bytes): 80 25 00 00 01 FF 01 00 .%......
E0 Private 0  (16 bytes)
   02 INTEGER (2 bytes): 260
   02 INTEGER (2 bytes): 260
   02 INTEGER (2 bytes): 256
   02 INTEGER (2 bytes): 256
78 Application 24 (8 bytes)
   06 OBJECT IDENTIFIER (6 bytes):  1.3.162.15480.2
82 Context 2  (2 bytes): 36864: 90 00 ..
OpenSC [3F00]>

which means:
 ef-atr.c:49:sc_parse_ef_atr_content: EF.ATR: card service 0xB8
 ef-atr.c:59:sc_parse_ef_atr_content: EF.ATR: Pre-Issuing data '04B0ECC1'
 ef-atr.c:67:sc_parse_ef_atr_content: EF.ATR: DF selection 94, unit_size 1, card caps 80
 ef-atr.c:95:sc_parse_ef_atr_content: EF.ATR: AID '8025000001FF0100'
 ef-atr.c:106:sc_parse_ef_atr_content: EF.ATR: Issuer data '02020104020201040202010002020100'
 ef-atr.c:111:sc_parse_ef_atr_content: EF.ATR: DER encoded OID 06062B8122F87802
 ef-atr.c:114:sc_parse_ef_atr_content: EF.ATR: OID 2B8122F87802
 ef-atr.c:123:sc_parse_ef_atr_content: EF.ATR: status word 0x9000

Fix: issue #2220
2021-03-17 10:58:20 +01:00
Vincent JARDIN fd83e885f7 IASECC/CPX: parse EF.ATR from ASN1 2F01 object
2F01 is:
./opensc-explorer -r 0
OpenSC [3F00]> cat 2F01
00000000: 80 43 01 B8 46 04 04 B0 EC C1 47 03 94 01 80 4F .C..F.....G....O
00000010: 08 80 25 00 00 01 FF 01 00 E0 10 02 02 01 04 02 ..%.............
00000020: 02 01 04 02 02 01 00 02 02 01 00 78 08 06 06 2B ...........x...+
00000030: 81 22 F8 78 02 82 02 90 00                      .".x.....

so the ASN1 decoder gets confused because it assumes that two bytes are
needed before getting the first tag 43/ISO7816_TAG_II_CARD_SERVICE.
In order to avoid such confusion, whenever the content of the EF.ATR/2F01 starts
with ISO7816_II_CATEGORY_TLV, we skip the first byte in order to parse
the ASN1 payload.

Fix: issue #2220
2021-03-17 10:58:20 +01:00
Vincent JARDIN 6efd7b3029 IASECC: send/recv from EF.ATR
Log the send/recv data extracted from the EF.ATR (2F01).
2021-03-17 10:58:20 +01:00
Vincent JARDIN 41edcaa413 IASECC/CPX: proper set of RSA support
The previous commit was over simplified. According to the known
mechanism, we should have the following scope:

./pkcs11-tool --module ../lib/onepin-opensc-pkcs11.so -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5, digest
  RIPEMD160, digest
  GOSTR3411, digest
  RSA-X-509, keySize={512,2048}, hw, decrypt, sign, verify
  RSA-PKCS, keySize={512,2048}, hw, decrypt, sign, verify
  SHA1-RSA-PKCS, keySize={512,2048}, sign, verify
  SHA256-RSA-PKCS, keySize={512,2048}, sign, verify
  RSA-PKCS-PSS, keySize={512,2048}, hw, sign, verify
  SHA1-RSA-PKCS-PSS, keySize={512,2048}, sign, verify
  SHA256-RSA-PKCS-PSS, keySize={512,2048}, sign, verify

do not use the default flags yet:
  _sc_card_add_rsa_alg(card, 1024, IASECC_CARD_DEFAULT_FLAGS, 0x10001);
  _sc_card_add_rsa_alg(card, 2048, IASECC_CARD_DEFAULT_FLAGS, 0x10001);
  _sc_card_add_rsa_alg(card, 512, IASECC_CARD_DEFAULT_FLAGS, 0x10001);

Contactless specific behaviour shall be added later on.
2021-03-17 10:58:20 +01:00
Vincent JARDIN 7cd713d15d IASECC/CPX: enable RSA algorithms
Without this fix, we get:
./pkcs11-tool --module ../lib/onepin-opensc-pkcs11.so -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5, digest
  RIPEMD160, digest
  GOSTR3411, digest

Once we include it, we get:
./pkcs11-tool --module ../lib/onepin-opensc-pkcs11.so -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5, digest
  RIPEMD160, digest
  GOSTR3411, digest
  RSA-9796, keySize={1024,2048}, hw, decrypt, sign, verify
  RSA-PKCS, keySize={1024,2048}, hw, decrypt, sign, verify
  SHA1-RSA-PKCS, keySize={1024,2048}, sign, verify
  SHA256-RSA-PKCS, keySize={1024,2048}, sign, verify
  RSA-PKCS-KEY-PAIR-GEN, keySize={1024,2048}, generate_key_pair
2021-03-17 10:58:20 +01:00
Vincent JARDIN fd97f49a84 IASECC: CPX have 2 applications
There are 2 applications: default one (contact mode) and the contactless
mode.
2021-03-17 10:58:20 +01:00
Vincent JARDIN 560692221b IASECC/CPX: file selection and app enumeration
Thanks to this commit, we get the full support of:
  - ./opensc-explore
    cd 0001
    asn1 2F00
  - ./pkcs11-tool -O
  - etc.
2021-03-17 10:58:20 +01:00
Vincent JARDIN acb8822444 IASECC: Add support for CPx cards
The French CPx Healthcare cards are designed to support the IASECC
standard.
2021-03-17 10:58:20 +01:00
Jakub Jelen 40c50a3a42 oberthur: Handle more memory issues during initialization
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=31540
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=31448
2021-03-16 12:02:05 +01:00
Frank Morgner 4512676795 Nightly: in case of conflicts, add "our" changes on top 2021-03-16 11:49:02 +01:00
Frank Morgner 26fac9592d macos: add a tokend postfix for dmg 2021-03-16 11:49:02 +01:00
Raul Metsma b9080c16d6 Make sure that we build always x86_64 openssl on macOS
Signed-off-by: Raul Metsma <raul@metsma.ee>
2021-03-16 11:49:02 +01:00
Frank Morgner aae9254018 Fixed syntax error 2021-03-16 11:49:02 +01:00
Raul Metsma 578128e464 Fix build on travis and with CryptoTokenKit enabled 2021-03-16 11:49:02 +01:00
Frank Morgner 1325d5c333 travis: use newer version of xcode for pushed binaries 2021-03-16 11:49:02 +01:00
Raul Metsma 85c5610d39 Build arm64 on macOS with Xcode 12.2
Signed-off-by: Raul Metsma <raul@metsma.ee>
2021-03-16 11:49:02 +01:00
Frank Morgner 63e6683384 mac: use dedicated entitlements for binaries and scripts
fixes the codesigning issue with the unknown blobs in the entitlements

(missing "/" to complete blob)
2021-03-16 11:49:02 +01:00
Peter Popovec f46b617397 Skip authentication if card access control mechanism is not active.
Depending on the "lifecycle" of the file, we may omit the authentication
operation.  Typically if the card is in initialization or creation state,
the access control mechanism is inactive.  If authentification can be
skiped, the card driver is responsible for setting the "acl_inactive"
variable in sc_file structure.
2021-03-16 10:57:05 +01:00
Frank Morgner 8e614bfe6e Nightly: unencrypt only if encrypted key is in available 2021-03-15 14:16:12 +01:00
Jakub Jelen 8d61d0d20d Use more portable switch for uniq to unbreak osx build 2021-03-15 09:33:55 +01:00
Jakub Jelen 1ef79e99f7 reader-pcsc: Avoid strict aliasing issues 2021-03-09 23:59:58 +01:00
Jakub Jelen 60632100a0 pkcs11: Avoid redefinition of ck_interface (#2243) 2021-03-09 23:59:58 +01:00
Jakub Jelen 63031b2193 pkcs11-tool: Avoid strict-aliasing issues on 32b architectures 2021-03-09 23:59:58 +01:00
Jakub Jelen 544dcc6827 configure: Warn about strict alliasing issues in strict builds 2021-03-09 23:59:58 +01:00
Jakub Jelen 2fa6700599 Remove more issues with strict aliasing
These would demonstrate with gcc11 and can be detected with gcc
flag -Wstrict-aliasing=2 (also with older gcc)
2021-03-09 23:59:58 +01:00
Jakub Jelen 45e262f537 westcos: Avoid strict aliasing violations 2021-03-09 23:59:58 +01:00
Jakub Jelen b5f26051bb Fix build on gcc11
This made most of the applications crashing in Fedora 34 when
smart card was plugged in.

The suggested patch makes the code path more obvious for gcc to
handle.

https://bugzilla.redhat.com/show_bug.cgi?id=1930652
2021-03-09 23:59:58 +01:00
Jakub Jelen b8266a4c86 Revert "fixed atrmask for gnuk"
This reverts commit 98beb86a38.
2021-03-01 15:43:28 +01:00
Jakub Jelen 0ce245a411 p11test: Fix one-off comparison 2021-03-01 15:43:28 +01:00
Jakub Jelen 56af7de137 Change (X)EDDSA EC_PARAMS encoding to OID
This is the current interpretation of the specs after talking with
several members of PKCS #11 TC.
2021-03-01 15:43:28 +01:00
Jakub Jelen c39e31b274 pkcs11: Rewrite ec params to use sc_asn1_put_tag() 2021-03-01 15:43:28 +01:00
Jakub Jelen ae771a135f openpgp: Rewrite decipher/derive to use asn1 functions 2021-03-01 15:43:28 +01:00
Jakub Jelen cb8c7647ca asn1: Do not crash on invalid arguments 2021-03-01 15:43:28 +01:00
Jakub Jelen a020b85d94 unittests: Briefly test asn1_encode 2021-03-01 15:43:28 +01:00
Jakub Jelen 73e283b4b1 openpgp: Correctly handle curve25519 keys 2021-03-01 15:43:28 +01:00
Jakub Jelen 64b61a7556 openpgp: Do not fail hard if unknown algorithm is encountered and fix typo 2021-03-01 15:43:28 +01:00
Jakub Jelen 9bd139d1e4 openpgp: Check return code of OID decoding from ASN1 2021-03-01 15:43:28 +01:00
Jakub Jelen 8c4d325576 framework-pkcs15: Fix typo in comment 2021-03-01 15:43:28 +01:00
Doug Engert 0380142482 Fix obtaining key_length i.e. field_length pkcs15-openpgp
card-opennpgp.c and pkcs15-openpgp.c have a strang way of
using sc_object_id_t to store what they call a binary_oid
or oid_binary.  It is used to convert the EC curve asn1
returned in the cxdata.

This code uses asn1_decode_object_id to use sc_object_id_t
as used in the rest of the code.

The code and ec_curve tabes in card-openpgp.c where not changed.

pkcs15-openpgp.c was channge si to can use:
algorithm_info = sc_card_find_ec_alg(card, 0, &oid);
to retried the key_length to add to the pubkey and prkey entries.
The EC and EDDSA needs (i.e. field_length)  to run.

 On branch eddsa
 Your branch is up to date with 'Jakuje/eddsa'.

 Changes to be committed:
	modified:   card.c
	modified:   pkcs15-openpgp.c
2021-03-01 15:43:28 +01:00
Jakub Jelen 091b7670eb p11test: Reformat the script and allow running against softhsm ed25519 keys (with few tweaks)
The Ed25519 implementation in SoftHSM is now broken /non-interoperable. After fixing that,
the interoperability tests should work with this script:

 * SoftHSMv2#528: Avoid creating duplicate mechanisms
 * SoftHSMv2#522: Fix advertised min and max mechanism sizes according to final PKCS#11 3.0 specification
 * SoftHSMv2#526: Adjust EDDSA code to return valid EC_PARAMS according to the final PKCS #11 3.0 specification
2021-03-01 15:43:28 +01:00
Jakub Jelen 35cfc291ce pkcs11-tool: Add support for (X)EDDSA key generation 2021-03-01 15:43:24 +01:00
Jakub Jelen 485b6cff44 p11test: Add support for EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen 32ec1f92b9 openpgp: Set reasonable usage for (X)EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen e7d390f9dd openpgp: Unbreak EC algorithms for GNUK
Since 09a594d bringing ECC support to openPGP card, it did not count
with GNUK. This adds exception for GNUK to unbreak ECC signatures
as GNUK presents BCD version < 3.
2021-03-01 15:42:29 +01:00
Jakub Jelen a965829f52 openpgp: Use only Derive mechanism for curve25519 keys 2021-03-01 15:42:29 +01:00
Jakub Jelen 5d5c391793 opensc-tool: Support for new (X)EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen 5178e74e1b pkcs11-tool: Support for new (X)EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen 2fb688683e pkcs15-tool: Support for new (X)EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen b351bf5ea4 openpgp: Initial support for (X)EdDSA keys 2021-03-01 15:42:29 +01:00
Jakub Jelen caae75758c Add internal support for (X)EdDSA keys 2021-03-01 15:42:26 +01:00
Jakub Jelen 80f80317d1 pkcs11: Add new SHA3 identifiers 2021-03-01 14:35:51 +01:00
Jakub Jelen 095c28e372 pkcs11: Add new (X)EDDSA identifiers 2021-03-01 14:35:51 +01:00
Jakub Jelen 0455a5665e winscard: Add missing constant define 2021-03-01 14:35:51 +01:00
Jakub Jelen c78fa164c9 openpgp-tool: Fix typos OpenGPG -> OpenPGP 2021-03-01 14:35:51 +01:00
Jakub Jelen a30bf95eed openpgp: Fix typo in the card name 2021-03-01 14:35:51 +01:00
Jakub Jelen a5a6757d10 pkcs11-tool: Add CKA_KEY_TYPE attribute for keygen as recommeneded in specification 2021-03-01 14:35:50 +01:00
Jakub Jelen e82f875047 pkcs11-spy: Systematize output of C_GetMechanismInfo 2021-03-01 14:35:50 +01:00
Jakub Jelen 86e01d7c47 pkcs11: Prefer CKA_EC_PARAMS over deprecated CKA_ECDSA_PARAMS by listing it first in the list 2021-03-01 14:35:50 +01:00
Jakub Jelen f726d4f201 Improve logging mostly in opengpg 2021-03-01 14:35:50 +01:00
Frank Morgner 5b42a62ec0 use macos' ${Caches} by default 2021-03-01 11:49:14 +01:00
Frank Morgner fe6864c5f3 fixed 354852 Invalid type in argument to printf format specifier 2021-02-25 23:34:57 +01:00
Frank Morgner c2670b0787 fixed 13755 Resource leak
... as reported by coverity scan.

p11cards are freed by emptying the virtual slots. virtual slots are
creatd with the framework's create_tokens. Hence, we need to free
p11card if no tokens were created.
2021-02-25 23:34:57 +01:00
Frank Morgner 881dca94ef avoid memory leak when creating pkcs#15 files 2021-02-25 23:34:57 +01:00
Frank Morgner d353a46d04 tcos: fixed memcpy with 0 or less bytes 2021-02-25 23:34:57 +01:00
Peter Popovec 6738d456ac ECDSA verify
Added support for raw ECDSA verify.
2021-02-25 18:37:18 +01:00
Frank Morgner 999874fb1c fixed potential memory issue
closes https://github.com/OpenSC/OpenSC/pull/2230
2021-02-25 18:36:39 +01:00
Luka Logar c80375eb4c Minidriver RSA-PSS signing not working
I am using a somewhat modified version of IsoApplet. Up till now it worked fine. However recently I stumbled upon a web site that
forces a client cert auth with RSA-PSS. And (at least on windows, using minidriver) it didn't work. It looks to me, that it's a bug
in the PSS support code in minidriver, as I cannot find any place where a MGF1 padding scheme is specified. And since none is specified
signing fails. This patch fixes this. It assumes, that the same hash is used for hashing and padding.
2021-02-25 18:35:57 +01:00
Frank Morgner a322c95d35 mac: disable binary verification
fixes https://github.com/OpenSC/OpenSC/issues/2194
2021-02-25 18:35:10 +01:00
Jakub Jelen 5f7c91e54f pkcs15-isoApplet: Avoid uninitialized reads
Thanks coverity

CID 365817
2021-02-25 09:08:52 +01:00
Jakub Jelen 46cfe89b3c pkcs15-iasecc: Avoid memory leak
Thanks coverity

CID 365818
2021-02-25 09:08:52 +01:00
Jakub Jelen a567ab9dca p11test: Fix possible resource leak
Thanks coverity

CID 365819
2021-02-25 09:08:52 +01:00
Jakub Jelen cee431a3ce pkcs15-iasecc: Check return value as in other cases
Thanks coverity

CID 365820
2021-02-25 09:08:52 +01:00
Jakub Jelen ffed34663d sm-global-platform: Fix possible memory leak
Thanks coverity

CID 365821
2021-02-25 09:08:52 +01:00
Jakub Jelen 3b556ef618 sm-cwa14890: Fix resource leak
CID 365822

Thanks oss-fuzz
2021-02-25 09:08:52 +01:00
Jakub Jelen 1dbe4b5a5b isoApplet: Prevent reading uninitialized values
CID 365823

Thanks coverity
2021-02-25 09:08:52 +01:00
Jakub Jelen 2f232f217b pkcs11-tool: Avoid double free and check allocation
366349 Double free

Thanks coverity
2021-02-25 09:08:52 +01:00
Jakub Jelen ae1cf0be90 iasecc: Prevent stack buffer overflow when empty ACL is returned
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30800
2021-02-25 09:08:52 +01:00
Jakub Jelen 1252aca9f1 cardos: Correctly calculate the left bytes to avoid buffer overrun
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29912
2021-02-25 09:08:52 +01:00
Jakub Jelen 17d8980cde oberthur: Avoid two buffer overflows
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30112
2021-02-25 09:08:52 +01:00
Jakub Jelen 9c91a4327e oberthur: Free another read data on failure paths 2021-02-25 09:08:52 +01:00
Jakub Jelen 7ba89daae6 apdu: Do not insert delay while fuzzing
This was timeout after 60 seconds. After skipping this call, we
get down to 1 s for the same input

Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27423
2021-02-25 09:08:52 +01:00
Jakub Jelen 251c4f6b76 oberthur: Avoid memory leaks
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29998
2021-02-25 09:08:52 +01:00
alt3r 3go 3044557299 openpgp: fix DO deletion
This fixes a problem reported in Nitrokey forum at

https://support.nitrokey.com/t/veracrypt-encryption-with-nitrokey-error/2872

as inability to save the VeraCrypt's keyfile onto the token
after deleting an existing one, unless the PKCS11 is reinitialized.

Reason: commit cbc53b9 "OpenPGP: Support write certificate for Gnuk"
introduced a condition on getting the blob handle, which is surplus
(the pgp_find_blob() function actually does that) and prevents
the blob refresh upon deletion, breaking the logic introduced
earlier in commit 9e04ae4 and causing the higher-level effect reported.

While at it, corrected comments to actually reflect the flow logic.

Tested on Fedora 33 using the repro steps from the forum and Nitrokey Pro.

Signed-off-by: alt3r 3go <alt3r.3go@protonmail.com>
2021-02-16 13:07:19 +01:00
ihsinme 6372adeb20 Update card-oberthur.c 2021-02-11 12:32:19 +01:00
ihsinme 0a3d7a28a7 Update card-epass2003.c 2021-02-11 12:32:19 +01:00
Zhang Xiaohui 49788678fe Small memory leak fix 2021-02-10 09:26:37 +01:00
Zhang Xiaohui 1c4a01d766 Small memory leak fix 2021-02-10 09:26:11 +01:00
Vincent JARDIN 66e5600b27 IASECC: log AID selection
Record the selection of the AID for better debugging
2021-02-05 12:09:20 +01:00
Jakub Jelen 8a6026abf5 Avoid memory leak from profile objects 2021-02-05 00:22:43 +01:00
Jakub Jelen da247384e7 pkcs11: Do not advertize VERIFY flag on the EC derive mechanisms
Amends 285db1ef
2021-02-05 00:22:43 +01:00
Jakub Jelen 176b20f339 pkcs11-tool: Display additional EC mechanism flags 2021-02-05 00:22:43 +01:00
Jakub Jelen cb074c5fa0 pkcs11: Add new mechanism flags from EC curves from current PKCS #11 3.0 2021-02-05 00:22:43 +01:00
Jakub Jelen 5633129bd8 p11test: Add CKM_ECDSA_SHA224 2021-02-05 00:22:43 +01:00
Jakub Jelen 0d693f63cb pkcs11-spy: Fix behavior of PKCS#11 3.0 applications when proxying PKCS#11 2.x module
Fixes #2204
2021-01-26 13:52:23 +01:00
Doug Engert b5ddaf6e02 Add tests of pkcs11-tool --test-threads
These should run when a PR is submitted.

 Changes to be committed:
	modified:   tests/Makefile.am
	new file:   tests/test-pkcs11-tool-test-threads.sh
2021-01-26 12:50:39 +01:00
Doug Engert f704e4f23e Pkcs11-tool changes to test a modules ability to use threads
Option --use-locking has C_Initialize pass in parameters with the
CKF_OS_LOCKING_OK to tell module to use threads. The default is it passes NULL
which says threads are not needed.

The following is not designed to be used by the general user. There are for debugging
and test scripts and only compiled if the system has threads.

    Option --test-threads <arg> can be passed multiple times. Each one starts a thread.
    <arg> is a list of 2 byte commands seperated by ":". The thread will execute these.
    Current commands are:
       IN - C_Initialize(NULL)
       IL - C_Initialize with CKF_OS_LOCKING_OK
       Pn - Pause for n seconds
       GI - C_GetInfo
       SL - C_GetSlotList
       Tn - C_GetTokenInfo  from slot_index n

These are just enough calls to see if threads are working in the module.
Output is written to stderr.

 Changes to be committed:
	modified:   doc/tools/pkcs11-tool.1.xml
	modified:   src/tools/Makefile.am
	modified:   src/tools/pkcs11-tool.c
2021-01-26 12:50:39 +01:00
Doug Engert 1b4e9f1d4a C_Initialize may be called by multiple threads
While trying to setup an OpenSC context, the global_locking
and detect cards, it is possible that multiple threads may
call C_Initialize. The current code tries to prevent this using
"if (context == NULL)"  but this is not a mutex, and
multiple threads may endup overwrite contexts and global locking and
cause additional problems, with pcsc and segfault.

FireFox appears to do this see #2032

The PR adds a mutex or Critical section to make sure only one
thread creates the context sets the global_locking  and does
the initial detect cards, etc.

This allows the global_lock (if requested) to be setup
which is then used for other calls.

All but the first call to C_Initialize will return with CKR_OK,
others will return CKR_CRYPTOKI_ALREADY_INITIALIZED.

 Date:      Mon Jan 11 12:47:12 2021 -0600
 Changes to be committed:
	modified:   src/pkcs11/pkcs11-global.c
2021-01-26 12:50:39 +01:00
Doug Engert d369965a7f pkcs11-tool support key-gen for GENERIC secret key
Fixes #2139

Added code to support  mechanism GENERIC-SECRET-KEY-GEN.

Improved --help  and doc/tools/pkcs11-tool.1.xml because key gen
of symmetric keys pass CKA_VALUE_LEN which is length of key in bytes.

Tested with:

./pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \
 --login --label generic-64 --keygen --key-type GENERIC:64 \
 --mechanism GENERIC-SECRET-KEY-GEN

./pkcs11-tool --module /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so --login -O
2021-01-26 12:34:15 +01:00
Jakub Jelen e1c8361ff3 idprime: Create algorithme reference based on the MGF1 flags as the HASH flags are no longer present for RSA-PSS mechanism 2021-01-26 10:53:30 +01:00
Jakub Jelen 44d429c3ad padding: Pass the MGF1 information to the card driver for RSA-PSS mechanism 2021-01-26 10:53:30 +01:00
Jakub Jelen edaf921eb6 idprime: Support V3 key references 2021-01-26 10:53:30 +01:00
Jakub Jelen ac81764308 idprime: Try to use different key_reference for V3 2021-01-26 10:53:30 +01:00
Jakub Jelen a6ed34bbb5 Add support for Gemalto IDPrime OS version 3 (padded pin to 16 bytes with zeroes)
Fixes #2202
2021-01-26 10:53:30 +01:00
Peter Popovec 26adaf519c man page update, info about generating EC keys
modified:   doc/tools/pkcs15-init.1.xml
2021-01-26 10:51:44 +01:00
Peter Popovec a3ca7613cd MyEID: opensc.conf - option to disable PKCS1 padding in card.
config option for MyEID:  "disable_hw_pkcs1_padding"

If user set this option to non zero, OpenSC is forced to calculate padding
in software. This will allow users to use RSA 1024 with SHA512.
2021-01-26 00:27:47 +01:00
Doug Engert 0b0deae4be unused code removed
On branch ECDSA-flags
 Changes to be committed:
	modified:   framework-pkcs15.c
2021-01-24 23:48:00 +01:00
Doug Engert 521d420c42 pkcs11 ECDSA verify need rs converted to sequence
The --signature-format openssl in pkcs11-tool does the correct
operation to convert the OpenSSL formated signature to rs for PKCS11

This commit modifies pkcs11/openssl.c to convert back to sequence
for EVP_VerifyFinal

Without this mod the signature file was passed unmodified to
PKCS11, then to EVP_VerifyFinal but this violates PKCS11 standard.

 On branch ECDSA-flags
 Changes to be committed:
	modified:   openssl.c
2021-01-24 23:48:00 +01:00
Doug Engert 285db1ef29 ECDSA Signatures with hashes
This PR is based on discussion with @popovec in
https://github.com/OpenSC/OpenSC/issues/2181
and https://github.com/OpenSC/OpenSC/pull/2187
which was cherry-picked as 5e5300816c8

This has been tested with PIV, MyEID and Smartcard-HSM.
with ECDSA keys.

The main fixes include :
 - Setting "flags" in card drivers
 - added code to sc_pkcs15-compute-signature for handle ECDSA with hashes
 - code in framework-pkcs15.c

Signatures made by pkcs11-tool -sigm verify with openssl
but pkcs11-tool --verify  does not work with ECDSA but does with RSA
I suspect it has to do with:
and some  then creating the wrong PKCS11 mechanisms

It should work with the epass2003 which does hashes in the driver.
2021-01-24 23:48:00 +01:00
Peter Popovec 6049cb926c ECDSA-SHA1: Apply SHA1 to input data before PSO compute signature.
CKM_ECDSA and CKM_ECDSA_SHA1 cannot be registered in the same way.
We need to use sc_pkcs11_register_sign_and_hash_mechanism ()
for CKM_ECDSA_SHA1.

This fix  also enables more ECDSA-SHAxxx mechanisms in framework-pkcs15.c

Tested: MyEID 4.0.1 (secp256r1 with SHA1, SHA224, SHA256, SHA384, SHA512)

CI tests (Travis + OsEID) for ECDSA-SHAxxx mechanisms are also enabled.
2021-01-24 23:48:00 +01:00
Jakub Jelen 5f16ffae84 p11test: Explicitly return in case of SKIP macro is used
Thanks coverity

Fixes CID 365263
2021-01-22 19:07:05 +01:00
Jakub Jelen 03cbf91be5 iasecc: Avoid another memory leak
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29456
2021-01-22 19:07:05 +01:00
Jakub Jelen b820bdf5b3 tcos: Reformat tcos_decipher 2021-01-22 19:07:05 +01:00
Jakub Jelen 1db88374bb oberthur: Correctly check for return values
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28843
2021-01-22 19:07:05 +01:00
Peter Popovec ba85ae75e3 opensc-explorer, command "info" - added information about LCS
Information about "Life cycle status byte" is now available in listing.
Also src/libopensc/types.h update - added more LCSB definitions.
iso7816_process_fci () update: improved tag 0x8A parsing.

Fixes in card-flex.c and card-miocos.c - SC_FILE_STATUS_xxx is not
bitfield.
2021-01-22 19:04:22 +01:00
Peter Popovec ce7fa42958 Use fresh data from FCI instead of FCP for sc_pkcs15init_authenticate()
Function sc_pkcs15init_update_file(): we will try to select the file, if
file can not be selected, the file is created, and select operation is
repeated. In both cases, the "selected_file" variable contains the current
FCI of the selected file.

Then the sc_pkcs15init_authenticate () function is called, but not with
"selected_file" variable, but "file" variable where the FCP data is present
(from the file creation operation).

Difference between FCP and FCI  (pkcs15-init -C  / MyEID card).
62 17 80 02 00 FF 82 01 01 83 02 50 31 86 03 01 3F FF 85 02 00 00 8A 01 00
6F 17 80 02 00 FF 82 01 01 83 02 50 31 86 03 01 3F FF 85 02 00 00 8A 01 01

Here it is clear that the data from FCP are outdated.  The card changed the
TAG 0x8a from 0 to 1 ("no information given", "creation state".) We need to
respect the authority of the card, FCI is to be used in next code, not FCP.

	modified:   src/pkcs15init/pkcs15-lib.c
2021-01-22 18:59:22 +01:00
Frank Morgner 7a090b994e essentially revert 1bb2547
fixes #2199

returns not allowed PKCS#11 codes to applications, however
2021-01-22 13:19:33 +01:00
Jakub Jelen 219c6cc494 framework-pkcs15: Avoid leaking memory when create object fails 2021-01-11 14:49:22 +01:00
Jakub Jelen 96ae693d5a framework-pkcs15: Return success from __pkcs15_create_object 2021-01-11 14:49:22 +01:00
Jakub Jelen db18a72c64 pkcs11: Implement PKCS #11 3.0 Profile object and its handling in tools 2021-01-11 14:49:22 +01:00
Jakub Jelen 7f9e8ba85c pkcs11-tool: Add option to list PKCS #11 3.0 interfaces 2021-01-11 14:49:22 +01:00
Jakub Jelen d224b2612d pkcs11-spy: Implement new functions and interfaces to intercept PKCS #11 3.0 calls 2021-01-11 14:49:22 +01:00
Jakub Jelen 03079a9413 pkcs11: Add missing flag for new PKCS #11 3.0 functions 2021-01-11 14:49:22 +01:00
Jakub Jelen 6e25924eb0 common, pkcs11-tool: Use new PKCS #11 API with fallback to old one 2021-01-11 14:49:22 +01:00
Jakub Jelen 224e265266 Implement C_SessionCancel from PKCS #11 3.0 2021-01-11 14:49:22 +01:00
Jakub Jelen 8e71118cd4 Ignore build artifacts 2021-01-11 14:49:22 +01:00
Jakub Jelen 7f0166ab12 p11test: Basic test for C_GetInterface API from PKCS#11 3.0 2021-01-11 14:49:22 +01:00
Jakub Jelen 95122abe2e pkcs11: Implement PKCS#11 3.0 stubs for required functions 2021-01-11 14:49:22 +01:00
Jakub Jelen 47151e9335 pkcs11: Implement getInterface() for accessing PKCS #11 3.0 functions 2021-01-11 14:49:22 +01:00
Jakub Jelen e58e7e1428 Standardize PKCS #11 version to 2.20 systematically 2021-01-11 14:49:22 +01:00
Jakub Jelen 23eb606d86 Print testsuite logs on error 2021-01-06 14:15:06 +01:00
Jakub Jelen c7c689c74d .travis.yml: Install clang-tidy to run some static code analysis early 2021-01-06 14:15:06 +01:00
Jakub Jelen 910020aeec Ignore non-useful check in clang-tidy as we have ton of memset/memcpy 2021-01-06 14:15:06 +01:00
Jakub Jelen 9cda87e200 authentic: Initialize structure to avoid comparison against garbage
Thanks clang:

/src/libopensc/card-authentic.c:1564:47: warning: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
        if (acls[AUTHENTIC_ACL_NUM_PIN_RESET].method == SC_AC_CHV)   {
                                                     ^
2021-01-06 14:15:06 +01:00
Jakub Jelen d25009cde6 belpic: Remove unused variable
Thanks clang

/src/libopensc/card-belpic.c:230:7: warning: Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r' [clang-analyzer-deadcode.DeadStores]
                if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) {
                    ^
/src/libopensc/card-belpic.c:230:7: note: Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
2021-01-06 14:15:06 +01:00
Jakub Jelen 3135fccdca itacns: Correctly free allocated memory
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28510
2021-01-06 14:15:06 +01:00
Jakub Jelen 049b2a8754 pkcs15: Do not override tokeninfo in bind_internal
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28550
2021-01-06 14:15:06 +01:00
Jakub Jelen 66f274dcaf authentic: Fix copy&paste error in log message 2021-01-06 14:15:06 +01:00
Jakub Jelen b48696539d tests: Verify there are no duplicate symbols exported 2021-01-06 14:15:06 +01:00
Jakub Jelen 88543529a2 pkcs11.exports: Remove duplicate symbols 2021-01-06 14:15:06 +01:00
Jakub Jelen f7b0ce3dac Remove duplicate symbols from libopensc.exports 2021-01-06 14:15:06 +01:00
Doug Engert f443c391b0 PIV whitespace cleanup and addtion of // clang-format off|on
Cleanup trailing whitespaces and protect hand formated structures
in card-piv.c and pkcs15-piv.c

 On branch PIV-whitespace
 Changes to be committed:
	modified:   card-piv.c
	modified:   pkcs15-piv.c
2020-12-15 11:14:15 +01:00
Carsten Blüggel f8af905574 Fixes #2175, C_GetAttributeValue for CKA_EXTRACTABLE, CKA_MODIFIABLE 2020-12-10 13:04:11 +01:00
Jakub Jelen 1ae8b60425 mcrd: Do not leak memory
Similar as in 62049ea18c

Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28405
2020-12-09 15:50:54 +01:00
Jakub Jelen 5df913b7f5 tcos: Check bounds in insert_pin()
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28383
2020-12-09 15:50:54 +01:00
Jakub Jelen 69544553c3 tcos: Reformat insert_pin() for readability 2020-12-09 15:50:54 +01:00
Jakub Jelen 196bf9e574 gpk: Replace assert with error
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28306
2020-12-09 15:50:54 +01:00
Peter Popovec a089353e1f MyEID: enable more PKCS11 mechanisms
This patch enables using of: SHA224-RSA-PKCS, SHA256-RSA-PKCS,
SHA384-RSA-PKCS, SHA512-RSA-PKCS and PSS variants of these mechanism for
MyEID users. (This patch is related to issue #2173.)

CI tests for these mechanisms are also enabled (using OsEID emulation).
2020-12-09 04:29:46 +01:00
Jakub Jelen f015746d22 idprime: Use temporary variable instead of messing up the passed one
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28185
2020-12-04 09:30:10 +01:00
Jakub Jelen 78cdab949f tcos: prevent out of bounds read
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27719
2020-12-04 09:30:10 +01:00
Jakub Jelen 3ffe24cfb6 pkcs15: Clean tokeninfo on parse errors to avoid memory leaks
Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27779
2020-12-04 09:30:10 +01:00
Jakub Jelen fb83cd0439 asn1: Improve logging 2020-12-04 09:30:10 +01:00
Jakub Jelen 61eb4e487e card: Correctly free pointers durint cache invalidation
As the whole structure is memset(0) on the following line,
we need to clean the pointers before doing so.

Thanks oss-fuzz

Related to:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27797
2020-12-04 09:30:10 +01:00
Frank Morgner 175c357c37 opensctoken: avoid component spec when it's not built 2020-12-01 15:54:27 +01:00
Jakub Jelen 85e08ae675 pkcs11-tool: Avoid calloc with 0 argument 2020-11-25 14:38:23 +01:00
rickyepoderi 3ce249f365 Issue 2153: organizationIdentifier is not translated by openssl 1.1.0/1.0.x 2020-11-25 09:33:20 +01:00
Frank Morgner 98beb86a38 fixed atrmask for gnuk
fixes https://github.com/OpenSC/OpenSC/issues/2155
2020-11-25 09:28:00 +01:00
Frank Morgner 480da424a5
fix possible infinite recursion (#2151)
fixes https://github.com/OpenSC/OpenSC/issues/2149
2020-11-25 09:27:28 +01:00
Jakub Jelen 0365c3ce6c westcos: Avoid assigning local variable to function arguments 2020-11-25 09:26:42 +01:00
Jakub Jelen 3d257410b2 sc-hsm: Avoid assigning local variable to function arguments 2020-11-25 09:26:42 +01:00
Jakub Jelen 63bb85b050 gpk: Avoid assigning local variable to function arguments 2020-11-25 09:26:42 +01:00
Jakub Jelen 871e4f2ac6 flex: Avoid assigning local variable to function arguments 2020-11-25 09:26:42 +01:00
Jakub Jelen 55a5556949 dnie: Remove unused assignment leaking local variable through parameters 2020-11-25 09:26:42 +01:00
Jakub Jelen af2fb6938c cac: Avoid assigning local variable to function arguments
Reported by cppcheck. The argument is not used after
returning from this function, but better make it explicit.
2020-11-25 09:26:42 +01:00
Jakub Jelen 8a6708c163 doc: Update documentation about the cache location 2020-11-25 09:26:18 +01:00
Jakub Jelen d0e5d62bf5 Verify the cache dir is correctly set with different combination of variables 2020-11-25 09:26:18 +01:00
Jakub Jelen 3eae6a031c ctx: Use more standard cache directory
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
2020-11-25 09:26:18 +01:00
Jakub Jelen 00ad8644e6 Enable CIFuzz to run fuzzers even before merging changes 2020-11-25 08:54:54 +01:00
Doug Engert 483e153182 ASN1 cleanup part 1
ASN1 tags are represented in two many ways within OpenSC.
This is a trivial change to simplify one aspect of this.
It also makes the code more readable.

SC_ASN1_CLASS_MASK, SC_ASN1_APP, SC_ASN1_CTX, SC_ASN1_PRV,
SC_ASN1_CONS are changed, and SC_ASN1_CLASS_MASK is added.

These then align with the bits defined by SC_ASN1_TAG_CLASS,
SC_ASN1_TAG_APPLICATION, SC_ASN1_TAG_CONTEXT, SC_ASN1_TAG_PRIVATE,
and SC_ASN1_TAG_CONSTRUCTED.

(SC_ASN1_UNI and SC_ASN1_TAG_UNIVERSAL are both 0x00 thus no change
is needed).

(No sign of a right shift of SC_ASN1_CTX or SC_ASN1_PRV causeing
problems has been seen in the code.) If found, can be solved.)

Close examination of the OpenSC code base shows all uses of tags
used by routines and sc_asn1_entry use the defines.

This could allows 26 lines of code in sc_asn1_skip_tag used to test
the 3 CLASS and CONSTRUCTED bits to be replaced by:

	if (((cla << 24) | tag) != tag_in)
		return NULL;

The 26 lines still work as will any other code in OpenSC
that tests the bits using the defines. It also allows new code
to be simplified.

Problem identified while looking at better way to check response
on GET_DATA (0xCB) that returns TLV as used in card-piv.c

Changes tested using pkcs11-tool --test --login with PIV, SC_HSM
and OpenPGP cards.
2020-11-25 08:50:13 +01:00
179 changed files with 10256 additions and 1731 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
@ -30,6 +30,7 @@ i=0
while [ $i -le 10 ] && ! git push --quiet --set-upstream origin "${BRANCH}"
do
sleep $[ ( $RANDOM % 32 ) + 1 ]s
git pull --rebase origin "${BRANCH}"
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

28
.github/workflows/cifuzz.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: CIFuzz
on:
pull_request:
paths:
- '**.c'
- '**.h'
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'opensc'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'opensc'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

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

4
.gitignore vendored
View File

@ -64,6 +64,7 @@ ChangeLog
doc/tools/*-tool
doc/tools/eidenv
doc/tools/opensc-explorer
doc/tools/pkcs11-register
doc/tools/pkcs15-crypt
doc/tools/pkcs15-init
doc/tools/opensc-asn1
@ -79,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
@ -120,5 +122,7 @@ tests/*.trs
src/tests/unittests/*.log
src/tests/unittests/*.trs
src/tests/unittests/asn1
src/tests/unittests/compression
src/tests/unittests/simpletlv
version.m4.ci

View File

@ -6,9 +6,13 @@ matrix:
os: osx
osx_image: xcode9.4
env: DO_PUSH_ARTIFACT=yes
- compiler: clang
os: osx
osx_image: xcode12.2
env: DO_PUSH_ARTIFACT=yes
- compiler: clang
os: linux
dist: bionic
dist: focal
- compiler: gcc
os: linux
dist: bionic
@ -17,7 +21,7 @@ matrix:
- ENABLE_DOC=--enable-doc
- compiler: gcc
os: linux
dist: bionic
dist: focal
env:
- DO_SIMULATION=oseid
- env:
@ -47,25 +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
# 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.
@ -85,8 +93,9 @@ before_install:
popd;
export PATH="/usr/local/opt/ccache/libexec:$PATH";
git clone https://github.com/frankmorgner/OpenSCToken.git;
sudo rm -rf /Library/Developer/CommandLineTools;
fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$TRAVIS_PULL_REQUEST" = "false" -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
@ -107,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
@ -245,7 +260,7 @@ script:
fi;
fi
- if [ -z "$HOST" -a "${DO_COVERITY_SCAN}" != "yes" -a -z "$DO_SIMULATION" ]; then
make check && make dist;
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;
@ -318,9 +333,11 @@ script:
./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;
kill -9 $PID;
@ -328,7 +345,7 @@ script:
fi
- if [ "${DO_SIMULATION}" = "cac" ]; then
cd $TRAVIS_BUILD_DIR;
make check && sudo make install || (cat tests/*log src/tests/unittests/*log && exit);
make check && sudo make install || (cat tests/*log src/tests/unittests/*log && exit 1);
export LD_LIBRARY_PATH=/usr/local/lib;
cd src/tests/p11test/;
./p11test -s 0 -p 12345678 -i &

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@ -13,11 +13,11 @@ set -ex
test -x ./configure || ./bootstrap
BUILDPATH=${PWD}
# Locate the latest OSX SDK
SDK_PATH=$(xcrun --sdk macosx --show-sdk-path)
# Set SDK path
export CFLAGS="$CFLAGS -isysroot $SDK_PATH -arch x86_64"
xcode_ver=$(xcodebuild -version | sed -En 's/Xcode[[:space:]](.*)/\1/p')
base_ver="12.2"
if [ $(echo -e $base_ver"\n"$xcode_ver | sort -V | head -1) == "$base_ver" ]; then
export BUILD_ARM="true"
fi
export SED=/usr/bin/sed
PREFIX=/Library/OpenSC
@ -31,19 +31,39 @@ if ! pkg-config libcrypto --atleast-version=1.0.1; then
git clone --depth=1 https://github.com/openssl/openssl.git -b OpenSSL_1_1_1-stable
fi
cd openssl
KERNEL_BITS=64 ./config no-shared --prefix=$PREFIX
MACHINE=x86_64 ./config no-shared --prefix=$PREFIX
make clean
make -j 4
make DESTDIR=$BUILDPATH/openssl_bin install_sw
if test -n "${BUILD_ARM}"; then
make clean
MACHINE=arm64 KERNEL_BITS=64 ./config no-shared --prefix=$PREFIX
make -j 4
make DESTDIR=$BUILDPATH/openssl_arm64 install_sw
lipo -create $BUILDPATH/openssl_arm64/$PREFIX/lib/libcrypto.a $BUILDPATH/openssl_bin/$PREFIX/lib/libcrypto.a -output libcrypto.a
lipo -create $BUILDPATH/openssl_arm64/$PREFIX/lib/libssl.a $BUILDPATH/openssl_bin/$PREFIX/lib/libssl.a -output libssl.a
mv libcrypto.a $BUILDPATH/openssl_bin/$PREFIX/lib/libcrypto.a
mv libssl.a $BUILDPATH/openssl_bin/$PREFIX/lib/libssl.a
fi
cd ..
fi
export OPENSSL_CFLAGS="`env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --cflags libcrypto`"
export OPENSSL_LIBS="` env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --libs libcrypto`"
fi
# Locate the latest OSX SDK
SDK_PATH=$(xcrun --sdk macosx --show-sdk-path)
export CFLAGS="$CFLAGS -isysroot $SDK_PATH"
if test -n "${BUILD_ARM}"; then
export CFLAGS="$CFLAGS -arch x86_64 -arch arm64"
export LDFLAGS="$LDFLAGS -arch x86_64 -arch arm64"
fi
export OBJCFLAGS=$CFLAGS
if ! test -e $BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig; then
if ! test -e openpace; then
git clone --depth=1 https://github.com/frankmorgner/openpace.git -b 1.1.0
git clone --depth=1 https://github.com/frankmorgner/openpace.git -b 1.1.1
fi
cd openpace
autoreconf -vis
@ -99,7 +119,7 @@ fi
mkdir -p "$BUILDPATH/target/Applications/Utilities"
osacompile -o "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app" "MacOSX/OpenSC_Notify.applescript"
if test -n "${CODE_SIGN_IDENTITY}"; then
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app"
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_applescripts.entitlements --deep --timestamp --options runtime "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app"
fi
@ -120,9 +140,12 @@ if (( $(xcodebuild -version | sed -En 's/Xcode[[:space:]]+([0-9]+)(\.[0-9]*)*/\1
else
xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${BUILDPATH}/target_tokend
fi
TOKEND="-tokend"
else
# https://github.com/OpenSC/OpenSC.tokend/issues/33
mkdir -p ${BUILDPATH}/target_tokend
TOKEND=""
fi
#if ! test -e $BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications/terminal-notifier.app; then
@ -173,6 +196,8 @@ if test -e OpenSCToken -a -n "${CODE_SIGN_IDENTITY}" -a -n "${DEVELOPMENT_TEAM}"
xcodebuild -target OpenSCTokenApp -configuration Debug -project OpenSCTokenApp.xcodeproj install DSTROOT=${BUILDPATH}/target_token \
CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" OTHER_CODE_SIGN_FLAGS="--timestamp --options=runtime" CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO CODE_SIGN_STYLE=Manual
cd ..
COMPONENT_TOKEN="--component-plist MacOSX/target_token.plist"
else
# if no OpenSCToken is checked out, then we create a dummy package
mkdir -p ${BUILDPATH}/target_token
@ -183,7 +208,7 @@ if test -n "${CODE_SIGN_IDENTITY}"; then
do
# find executable files and run codesign on them
find ${d} -type f -perm +111 -print -exec \
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime {} \;
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_binaries.entitlements --deep --timestamp --options runtime {} \;
done
fi
@ -191,7 +216,7 @@ fi
# Build package
pkgbuild --root ${BUILDPATH}/target --component-plist MacOSX/target.plist --scripts MacOSX/scripts --identifier org.opensc-project.mac --version @PACKAGE_VERSION@ --install-location / OpenSC.pkg
pkgbuild --root ${BUILDPATH}/target_tokend --component-plist MacOSX/target_tokend.plist --identifier org.opensc-project.tokend --version @PACKAGE_VERSION@ --install-location / OpenSC-tokend.pkg
pkgbuild --root ${BUILDPATH}/target_token --component-plist MacOSX/target_token.plist --identifier org.opensc-project.mac.opensctoken --version @PACKAGE_VERSION@ --install-location / OpenSCToken.pkg
pkgbuild --root ${BUILDPATH}/target_token $COMPONENT_TOKEN --identifier org.opensc-project.mac.opensctoken --version @PACKAGE_VERSION@ --install-location / OpenSCToken.pkg
pkgbuild --root ${BUILDPATH}/target_startup --component-plist MacOSX/target_startup.plist --identifier org.opensc-project.startup --version @PACKAGE_VERSION@ --install-location / OpenSC-startup.pkg
# Build product
@ -206,13 +231,13 @@ fi
# Build "Uninstaller"
osacompile -o "${imagedir}/OpenSC Uninstaller.app" "MacOSX/OpenSC_Uninstaller.applescript"
if test -n "${CODE_SIGN_IDENTITY}"; then
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime "${imagedir}/OpenSC Uninstaller.app"
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_applescripts.entitlements --deep --timestamp --options runtime "${imagedir}/OpenSC Uninstaller.app"
fi
# Create .dmg
rm -f OpenSC-@PACKAGE_VERSION@.dmg
rm -f OpenSC-@PACKAGE_VERSION@$TOKEND.dmg
i=0
while ! hdiutil create -srcfolder "${imagedir}" -volname "@PACKAGE_NAME@" -fs JHFS+ OpenSC-@PACKAGE_VERSION@.dmg
while ! hdiutil create -srcfolder "${imagedir}" -volname "@PACKAGE_NAME@" -fs JHFS+ OpenSC-@PACKAGE_VERSION@$TOKEND.dmg
do
i=$[$i+1]
if [ $i -gt 2 ]

38
NEWS
View File

@ -1,5 +1,43 @@
NEWS for OpenSC -- History of user visible changes
# 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)
* Add threading test to `pkcs11-tool` (#2067)
* Add support to generate generic secret keys (#2140)
* `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, #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
* Fix DO deletion (#2215)
* 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)
* Enable more mechanisms (#2178)
* Fixed asking for a user pin when formatting a card (#1737)
## IAS/ECC
* Added support for French CPx Healthcare cards (#2217)
## CardOS
* Added ATR for new CardOS 5.4 version (#2296)
# New in 0.21.0; 2020-11-24
## General Improvements
* fixed security problems

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

@ -1,4 +1,4 @@
version: 0.21.0.{build}
version: 0.22.0.{build}
platform:
- x86
@ -12,7 +12,7 @@ environment:
GH_TOKEN:
secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY
PATH: C:\cygwin\bin;%PATH%
OPENPACE_VER: 1.1.0
OPENPACE_VER: 1.1.1
ZLIB_VER_DOT: 1.2.11
matrix:
# not compatible with OpenSSL 1.1.1:
@ -59,12 +59,12 @@ install:
Rename-Item -path "c:\openpace-${env:OPENPACE_VER}" -newName "openpace"
}
}
If (!(Test-Path cngsdk.msi )) {
appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi"
If (!(Test-Path cpdksetup.exe )) {
appveyor DownloadFile "https://download.microsoft.com/download/1/7/6/176909B0-50F2-4DF3-B29B-830A17EA7E38/CPDK_RELEASE_UPDATE/cpdksetup.exe"
}
- echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%"
- call "%VCVARSALL%" %Platform%
- cngsdk.msi /quiet
- cpdksetup.exe /quiet
- uname -a
- set
@ -126,4 +126,4 @@ cache:
- C:\openpace -> appveyor.yml
- C:\openpace-Win32 -> appveyor.yml
- C:\openpace-Win64 -> appveyor.yml
- cngsdk.msi -> appveyor.yml
- cpdksetup.exe -> appveyor.yml

View File

@ -1,13 +1,13 @@
dnl -*- mode: m4; -*-
AC_PREREQ(2.60)
AC_PREREQ(2.68)
define([PRODUCT_NAME], [OpenSC])
define([PRODUCT_TARNAME], [opensc])
define([PRODUCT_BUGREPORT], [https://github.com/OpenSC/OpenSC/issues])
define([PRODUCT_URL], [https://github.com/OpenSC/OpenSC])
define([PACKAGE_VERSION_MAJOR], [0])
define([PACKAGE_VERSION_MINOR], [21])
define([PACKAGE_VERSION_MINOR], [22])
define([PACKAGE_VERSION_FIX], [0])
define([PACKAGE_SUFFIX], [])
@ -45,8 +45,8 @@ OPENSC_VS_FF_PRODUCT_URL="VS_FF_PRODUCT_URL"
# (Code changed: REVISION++)
# (Oldest interface changed/removed: OLDEST++)
# (Interfaces added: CURRENT++, REVISION=0)
OPENSC_LT_CURRENT="7"
OPENSC_LT_OLDEST="7"
OPENSC_LT_CURRENT="8"
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(
@ -188,7 +188,7 @@ AC_ARG_ENABLE(
)
AC_ARG_ENABLE([openssl-secure-malloc],
[AC_HELP_STRING([--openssl-secure-malloc=<SIZE_IN_BYTES>],
[AS_HELP_STRING([--openssl-secure-malloc=<SIZE_IN_BYTES>],
[Enable OpenSSL secure memory by specifying its size in bytes, must be a power of 2 @<:@disabled@:>@])],
[], [enable_openssl_secure_malloc=no])
AS_IF([test $enable_openssl_secure_malloc != no],
@ -394,7 +394,6 @@ dnl C Compiler features
AC_C_INLINE
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_ASSERT
AC_CHECK_HEADERS([ \
@ -408,7 +407,6 @@ dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_UID_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
dnl Checks for library functions.
AC_FUNC_ERROR_AT_LINE
@ -729,7 +727,7 @@ LIBS="$saved_LIBS"
AC_ARG_ENABLE(cvcdir,
AC_HELP_STRING([--enable-cvcdir=DIR],
AS_HELP_STRING([--enable-cvcdir=DIR],
[directory containing CV certificates (default is determined by libeac)]),
[cvcdir="${enableval}"],
[cvcdir=false])
@ -751,7 +749,7 @@ AC_SUBST(CVCDIR)
AC_DEFINE_UNQUOTED([CVCDIR], ["${CVCDIR}"], [CVC directory])
AC_ARG_ENABLE(x509dir,
AC_HELP_STRING([--enable-x509dir=DIR],
AS_HELP_STRING([--enable-x509dir=DIR],
[directory containing X.509 certificates (default is determined by libeac)]),
[x509dir="${enableval}"],
[x509dir=false])
@ -953,6 +951,7 @@ AC_PATH_PROG(GENGETOPT, gengetopt, not found)
AC_ARG_VAR([CLANGTIDY],
[absolute path to clang-tidy used for static code analysis])
AC_PATH_PROG(CLANGTIDY, clang-tidy, not found)
TIDY_CHECKS="-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
AX_FUNC_GETOPT_LONG
#AH_BOTTOM([#include "common/compat_getopt.h"])
@ -1060,6 +1059,7 @@ AC_SUBST([PROFILE_DIR])
AC_SUBST([PROFILE_DIR_DEFAULT])
AC_SUBST([OPTIONAL_NOTIFY_CFLAGS])
AC_SUBST([OPTIONAL_NOTIFY_LIBS])
AC_SUBST([TIDY_CHECKS])
AM_CONDITIONAL([ENABLE_MAN], [test "${enable_man}" = "yes"])
AM_CONDITIONAL([ENABLE_THREAD_LOCKING], [test "${enable_thread_locking}" = "yes"])
@ -1089,7 +1089,7 @@ if test "${enable_pedantic}" = "yes"; then
CFLAGS="-pedantic ${CFLAGS}"
fi
if test "${enable_strict}" = "yes"; then
CFLAGS="-Wall -Wextra -Wno-unused-parameter -Werror ${CFLAGS}"
CFLAGS="-Wall -Wextra -Wno-unused-parameter -Werror -Wstrict-aliasing=2 ${CFLAGS}"
fi
AC_CONFIG_FILES([

View File

@ -10,7 +10,7 @@ man5_MANS = pkcs15-profile.5 opensc.conf.5
endif
opensc.conf.5.xml opensc.conf.5: $(srcdir)/opensc.conf.5.xml.in
sed \
@sed \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-e 's|@docdir[@]|$(docdir)|g' \
-e 's|@libdir[@]|$(libdir)|g' \
@ -19,14 +19,14 @@ opensc.conf.5.xml opensc.conf.5: $(srcdir)/opensc.conf.5.xml.in
-e 's|@PROFILE_DIR_DEFAULT[@]|$(PROFILE_DIR_DEFAULT)|g' \
-e 's|@DEFAULT_SM_MODULE[@]|$(DEFAULT_SM_MODULE)|g' \
< $< > opensc.conf.5.xml
$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl opensc.conf.5.xml
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl opensc.conf.5.xml 2>/dev/null
files.html: $(srcdir)/files.xml $(wildcard $(srcdir)/*.5.xml) opensc.conf.5.xml
$(XSLTPROC) --nonet --path "$(builddir):$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $<
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(builddir):$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $< 2>/dev/null
%.5: $(srcdir)/%.5.xml
sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $<
$(AM_V_GEN)sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $< 2>/dev/null
clean-local:
-rm -rf $(html_DATA) $(man5_MANS) opensc.conf.5.xml

View File

@ -43,7 +43,7 @@ span.errortext {
font-style: italic;
}
--></style></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"><div class="titlepage"><div><div><h1 class="title"><a name="idm1"></a>OpenSC Manual Pages: Section 5</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="refentrytitle"><a href="#opensc.conf">opensc.conf</a></span><span class="refpurpose"> &#8212; configuration file for OpenSC</span></dt><dt><span class="refentrytitle"><a href="#pkcs15-profile">pkcs15-profile</a></span><span class="refpurpose"> &#8212; format of profile for <span class="command"><strong>pkcs15-init</strong></span></span></dt></dl></div><div class="refentry"><a name="opensc.conf"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>opensc.conf &#8212; configuration file for OpenSC</p></div><div class="refsect1"><a name="idm13"></a><h2>Description</h2><p>
--></style></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"><div class="titlepage"><div><div><h1 class="title"><a name="id-1"></a>OpenSC Manual Pages: Section 5</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="refentrytitle"><a href="#opensc.conf">opensc.conf</a></span><span class="refpurpose"> &#8212; configuration file for OpenSC</span></dt><dt><span class="refentrytitle"><a href="#pkcs15-profile">pkcs15-profile</a></span><span class="refpurpose"> &#8212; format of profile for <span class="command"><strong>pkcs15-init</strong></span></span></dt></dl></div><div class="refentry"><a name="opensc.conf"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>opensc.conf &#8212; configuration file for OpenSC</p></div><div class="refsect1"><a name="id-1.2.3"></a><h2>Description</h2><p>
OpenSC obtains configuration data from the following sources in the following order
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>
command-line options
@ -122,7 +122,7 @@ app <em class="replaceable"><code>application</code></em> {
<code class="literal">westcos-tool</code>:
Configuration block for OpenSC tools
</p></li></ul></div><p>
</p></div><div class="refsect1"><a name="idm103"></a><h2>Configuration Options</h2><div class="variablelist"><dl class="variablelist"><dt><a name="debug"></a><span class="term">
</p></div><div class="refsect1"><a name="id-1.2.4"></a><h2>Configuration Options</h2><div class="variablelist"><dl class="variablelist"><dt><a name="debug"></a><span class="term">
<code class="option">debug = <em class="replaceable"><code>num</code></em>;</code>
</span></dt><dd><p>
Amount of debug info to print (Default:
@ -153,6 +153,12 @@ app <em class="replaceable"><code>application</code></em> {
<code class="filename">Software\OpenSC
Project\OpenSC\ProfileDir</code> is
checked.
</p></dd><dt><span class="term">
<code class="option">disable_colors = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
Disable colors of log messages (Default:
<code class="literal">false</code> if attached to a console,
<code class="literal">true</code> otherwise).
</p></dd><dt><span class="term">
<code class="option">disable_popups = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
@ -176,7 +182,7 @@ app <em class="replaceable"><code>application</code></em> {
default) will load all statically linked drivers.
</p><p>
If an unknown (i.e. not internal or old) driver is
supplied, a separate configuration configuration
supplied, a separate configuration
block has to be written for the driver. A special
value <code class="literal">old</code> will load all
statically linked drivers that may be removed in
@ -227,6 +233,10 @@ app <em class="replaceable"><code>application</code></em> {
<code class="literal">npa</code>: See <a class="xref" href="#npa" title="Configuration Options for German ID Card">the section called &#8220;Configuration Options for German ID Card&#8221;</a>
</p></li><li class="listitem"><p>
<code class="literal">dnie</code>: See <a class="xref" href="#dnie" title="Configuration Options for DNIe">the section called &#8220;Configuration Options for DNIe&#8221;</a>
</p></li><li class="listitem"><p>
<code class="literal">edo</code>: See <a class="xref" href="#edo" title="Configuration Options for Polish eID Card">the section called &#8220;Configuration Options for Polish eID Card&#8221;</a>
</p></li><li class="listitem"><p>
<code class="literal">myeid</code>: See <a class="xref" href="#myeid" title="Configuration Options for MyEID Card">the section called &#8220;Configuration Options for MyEID Card&#8221;</a>
</p></li><li class="listitem"><p>
Any other value: Configuration block for an externally loaded card driver
</p></li></ul></div><p>
@ -332,7 +342,7 @@ app <em class="replaceable"><code>application</code></em> {
Parameters for the OpenSC PKCS11 module.
</p><p>
For details see <a class="xref" href="#pkcs11" title="Configuration of PKCS#11">the section called &#8220;Configuration of PKCS#11&#8221;</a>.
</p></dd></dl></div><div class="refsect2"><a name="reader_driver"></a><h3>Configuration of Smart Card Reader Driver</h3><div class="refsect3"><a name="idm330"></a><h4>Configuration Options for all Reader Drivers</h4><div class="variablelist"><dl class="variablelist"><dt><span class="term">
</p></dd></dl></div><div class="refsect2"><a name="reader_driver"></a><h3>Configuration of Smart Card Reader Driver</h3><div class="refsect3"><a name="id-1.2.4.3.2"></a><h4>Configuration Options for all Reader Drivers</h4><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">max_send_size = <em class="replaceable"><code>num</code></em>;</code>
<code class="option">max_recv_size = <em class="replaceable"><code>num</code></em>;</code>
</span></dt><dd><p>
@ -429,7 +439,27 @@ app <em class="replaceable"><code>application</code></em> {
<code class="option">readers = <em class="replaceable"><code>num</code></em>;</code>
</span></dt><dd><p>
Virtual readers to allocate (Default: <code class="literal">2</code>).
</p></dd></dl></div></div></div><div class="refsect2"><a name="npa"></a><h3>Configuration Options for German ID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
</p></dd></dl></div></div></div><div class="refsect2"><a name="myeid"></a><h3>Configuration Options for MyEID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">disable_hw_pkcs1_padding = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
The MyEID card can internally
encapsulate the data (hash code)
into a DigestInfo ASN.1 structure
according to the selected hash
algorithm (currently only for SHA1).
DigestInfo is padded to RSA key
modulus length according to PKCS#1
v1.5, block type 01h. Size of the
DigestInfo must not exceed 40%
of the RSA key modulus length. If
this limit is unsatisfactory (for
example someone needs RSA 1024
with SHA512), the user can disable
this feature. In this case, the
card driver will do everything
necessary before sending the data
(hash code) to the card.
</p></dd></dl></div></div><div class="refsect2"><a name="npa"></a><h3>Configuration Options for German ID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">can = <em class="replaceable"><code>value</code></em>;</code>
</span></dt><dd><p>
German ID card requires the CAN to
@ -478,6 +508,16 @@ app <em class="replaceable"><code>application</code></em> {
<code class="literal">/usr/bin/pinentry</code>).
Only used if compiled with
<code class="option">--enable-dnie-ui</code>
</p></dd></dl></div></div><div class="refsect2"><a name="edo"></a><h3>Configuration Options for Polish eID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">can = <em class="replaceable"><code>value</code></em>;</code>
</span></dt><dd><p>
CAN (Card Access Number &#8211; 6 digit number
printed on the right bottom corner of the
front side of the document) is required
to establish connection with the card.
It might be overwritten by <code class="literal">EDO_CAN</code>
environment variable. Currently, it is not
possible to set it in any other way.
</p></dd></dl></div></div><div class="refsect2"><a name="card_atr"></a><h3>Configuration based on ATR</h3><p>
</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">atrmask = <em class="replaceable"><code>hexstring</code></em>;</code>
@ -554,10 +594,10 @@ app <em class="replaceable"><code>application</code></em> {
<code class="literal">raw</code>
</p></li></ul></div><p>
</p></dd><dt><span class="term">
<code class="option">md_read_only = <em class="replaceable"><code>bool</code></em>;</code>
<code class="option">read_only = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
Mark card as read/only card in
Minidriver/BaseCSP interface
PKCS#11/Minidriver/BaseCSP interface
(Default: <code class="literal">false</code>).
</p></dd><dt><span class="term">
<code class="option">md_supports_X509_enrollment = <em class="replaceable"><code>bool</code></em>;</code>
@ -724,9 +764,11 @@ app <em class="replaceable"><code>application</code></em> {
</span></dt><dd><p>
Where to cache the card's files. The default values are:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
<code class="filename"><code class="envar">HOME</code>/.eid/cache/</code> (Unix)
<code class="filename"><code class="envar">$XDG_CACHE_HOME</code>/opensc/</code> (If <code class="envar">$XDG_CACHE_HOME</code> is defined)
</p></li><li class="listitem"><p>
<code class="filename"><code class="envar">USERPROFILE</code>\.eid-cache\</code> (Windows)
<code class="filename"><code class="envar">$HOME</code>/.cache/opensc/</code> (Unix)
</p></li><li class="listitem"><p>
<code class="filename"><code class="envar">$USERPROFILE</code>\.eid-cache\</code> (Windows)
</p></li></ul></div><p>
</p><p>
If caching is done by a system process, the
@ -753,6 +795,26 @@ app <em class="replaceable"><code>application</code></em> {
<code class="literal">CKA_ALWAYS_AUTHENTICATE</code> may
need to set this to get signatures to work with
some cards (Default: <code class="literal">false</code>).
</p><p>
It is recommended to enable also PIN caching using
<code class="literal">use_pin_caching</code> option for OpenSC
to be able to provide PIN for the card when needed.
</p></dd><dt><span class="term">
<code class="option">private_certificate = <em class="replaceable"><code>value</code></em>;</code>
</span></dt><dd><p>
How to handle a PIN-protected certificate. Known
parameters:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
<code class="literal">protect</code>: The certificate stays PIN-protected.
</p></li><li class="listitem"><p>
<code class="literal">declassify</code>: Allow
reading the certificate without
enforcing verification of the PIN.
</p></li><li class="listitem"><p>
<code class="literal">ignore</code>: Ignore PIN-protected certificates.
</p></li></ul></div><p>
(Default: <code class="literal">ignore</code> in Tokend,
<code class="literal">protect</code> otherwise).
</p></dd><dt><span class="term">
<code class="option">enable_pkcs15_emulation = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
@ -775,7 +837,7 @@ app <em class="replaceable"><code>application</code></em> {
<code class="option">builtin_emulators = <em class="replaceable"><code>emulators</code></em>;</code>
</span></dt><dd><p>
List of the builtin pkcs15 emulators to test
(Default: <code class="literal">westcos, openpgp,
(Default: <code class="literal">westcos, openpgp,
starcert, tcos, esteid, itacns,
PIV-II, cac, gemsafeGPK, gemsafeV1, actalis,
atrust-acos, tccardos, entersafe, pteid,
@ -854,13 +916,6 @@ app <em class="replaceable"><code>application</code></em> {
Score for <span class="application">OpenSC.tokend</span>
(Default: <code class="literal">300</code>). The tokend with
the highest score shall be used.
</p></dd><dt><span class="term">
<code class="option">ignore_private_certificate = <em class="replaceable"><code>bool</code></em>;</code>
</span></dt><dd><p>
Tokend ignore to read PIN protected certificate
that is set
<code class="literal">SC_PKCS15_CO_FLAG_PRIVATE</code> flag
(Default: <code class="literal">true</code>).
</p></dd></dl></div></div><div class="refsect2"><a name="pkcs11"></a><h3>Configuration of PKCS#11</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="option">max_virtual_slots = <em class="replaceable"><code>num</code></em>;</code>
</span></dt><dd><p>
@ -1020,7 +1075,7 @@ app <em class="replaceable"><code>application</code></em> {
For the module to simulate the opensc-onepin module
behavior the following option
<code class="option">create_slots_for_pins = "user";</code>
</p></dd></dl></div></div></div><div class="refsect1"><a name="idm971"></a><h2>Environment</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
</p></dd></dl></div></div></div><div class="refsect1"><a name="id-1.2.5"></a><h2>Environment</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="envar">OPENSC_CONF</code>
</span></dt><dd><p>
Filename for a user defined configuration file
@ -1063,7 +1118,7 @@ app <em class="replaceable"><code>application</code></em> {
</span></dt><dd><p>
PIV configuration during initialization with
<span class="application">piv-tool</span>.
</p></dd></dl></div></div><div class="refsect1"><a name="idm1012"></a><h2>Files</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
</p></dd></dl></div></div><div class="refsect1"><a name="id-1.2.6"></a><h2>Files</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
<code class="filename">/usr/etc/opensc.conf</code>
</span></dt><dd><p>
System-wide configuration file
@ -1071,7 +1126,7 @@ app <em class="replaceable"><code>application</code></em> {
<code class="filename">/usr/share/doc/opensc/opensc.conf</code>
</span></dt><dd><p>
Extended example configuration file
</p></dd></dl></div></div></div><div class="refentry"><div class="refentry.separator"><hr></div><a name="pkcs15-profile"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>pkcs15-profile &#8212; format of profile for <span class="command"><strong>pkcs15-init</strong></span></p></div><div class="refsect1"><a name="idm1036"></a><h2>Description</h2><p>
</p></dd></dl></div></div></div><div class="refentry"><div class="refentry.separator"><hr></div><a name="pkcs15-profile"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>pkcs15-profile &#8212; format of profile for <span class="command"><strong>pkcs15-init</strong></span></p></div><div class="refsect1"><a name="id-1.3.3"></a><h2>Description</h2><p>
The <span class="command"><strong>pkcs15-init</strong></span> utility for PKCS #15 smart card
personalization is controlled via profiles. When starting, it will read two
such profiles at the moment, a generic application profile, and a card
@ -1087,10 +1142,10 @@ app <em class="replaceable"><code>application</code></em> {
The card specific profile contains additional information required during
card initialization, such as location of PIN files, key references etc.
Profiles currently reside in <code class="filename">@pkgdatadir@</code>
</p></div><div class="refsect1"><a name="idm1044"></a><h2>Syntax</h2><p>
</p></div><div class="refsect1"><a name="id-1.3.4"></a><h2>Syntax</h2><p>
This section should contain information about the profile syntax. Will add
this soonishly.
</p></div><div class="refsect1"><a name="idm1047"></a><h2>See also</h2><p>
</p></div><div class="refsect1"><a name="id-1.3.5"></a><h2>See also</h2><p>
<span class="citerefentry"><span class="refentrytitle">pkcs15-init</span>(1)</span>,
<span class="citerefentry"><span class="refentrytitle">pkcs15-crypt</span>(1)</span>
</p></div></div></div></body></html>

View File

@ -296,6 +296,9 @@ app <replaceable>application</replaceable> {
<listitem><para>
<literal>edo</literal>: See <xref linkend="edo"/>
</para></listitem>
<listitem><para>
<literal>myeid</literal>: See <xref linkend="myeid"/>
</para></listitem>
<listitem><para>
Any other value: Configuration block for an externally loaded card driver
</para></listitem>
@ -639,6 +642,37 @@ app <replaceable>application</replaceable> {
</refsect2>
<refsect2 id="myeid">
<title>Configuration Options for MyEID Card</title>
<variablelist>
<varlistentry>
<term>
<option>disable_hw_pkcs1_padding = <replaceable>bool</replaceable>;</option>
</term>
<listitem><para>
The MyEID card can internally
encapsulate the data (hash code)
into a DigestInfo ASN.1 structure
according to the selected hash
algorithm (currently only for SHA1).
DigestInfo is padded to RSA key
modulus length according to PKCS#1
v1.5, block type 01h. Size of the
DigestInfo must not exceed 40%
of the RSA key modulus length. If
this limit is unsatisfactory (for
example someone needs RSA 1024
with SHA512), the user can disable
this feature. In this case, the
card driver will do everything
necessary before sending the data
(hash code) to the card.
</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2 id="npa">
<title>Configuration Options for German ID Card</title>
<variablelist>
@ -1116,12 +1150,17 @@ app <replaceable>application</replaceable> {
<itemizedlist>
<listitem>
<para>
<filename><envar>HOME</envar>/.eid/cache/</filename> (Unix)
<filename><envar>$XDG_CACHE_HOME</envar>/opensc/</filename> (If <envar>$XDG_CACHE_HOME</envar> is defined)
</para>
</listitem>
<listitem>
<para>
<filename><envar>USERPROFILE</envar>\.eid-cache\</filename> (Windows)
<filename><envar>$HOME</envar>/.cache/opensc/</filename> (Unix)
</para>
</listitem>
<listitem>
<para>
<filename><envar>$USERPROFILE</envar>\.eid-cache\</filename> (Windows)
</para>
</listitem>
</itemizedlist>

View File

@ -14,15 +14,14 @@ endif
completion_DATA = $(patsubst $(srcdir)/%.1.xml, %, $(wildcard $(srcdir)/*.1.xml))
tools.html: $(srcdir)/tools.xml $(wildcard $(srcdir)/*.1.xml)
$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $<
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $< 2>/dev/null
%.1: $(srcdir)/%.1.xml
sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $<
$(AM_V_GEN)sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $< 2>/dev/null
%: $(srcdir)/%.1.xml
@echo $< $@
@cat $(srcdir)/completion-template \
$(AM_V_GEN)cat $(srcdir)/completion-template \
| sed "s,ALLOPTS,\
$(shell sed -n 's,.*<option>\([^<]*\)</option>.*,\1,pg' $< \
| sort -u | grep -- '^\-' | tr '\n' ' ')," \

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

@ -146,7 +146,9 @@
<term>
<option>--key-type</option> <replaceable>specification</replaceable>
</term>
<listitem><para>Specify the type and length of the key to create, for example rsa:1024 or EC:prime256v1.</para></listitem>
<listitem><para>Specify the type and length (bytes if symmetric) of the key to create,
for example RSA:1024, EC:prime256v1, GOSTR3410-2012-256:B,
DES:8, DES3:24, AES:16 or GENERIC:64.</para></listitem>
</varlistentry>
<varlistentry>
@ -219,6 +221,13 @@
<listitem><para>List slots with tokens.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--list-interfaces</option>
</term>
<listitem><para>List interfaces of PKCS #11 3.0 library.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--login</option>,
@ -417,6 +426,22 @@
<listitem><para>Specify the index of the object to use.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--use-locking</option>
</term>
<listitem><para>Tell pkcs11 module it should use OS thread locking.
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--test-threads</option> <replaceable>options</replaceable>
</term>
<listitem><para>Test a pkcs11 module's thread implication. (See source code).
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--token-label</option> <replaceable>label</replaceable>

View File

@ -136,11 +136,12 @@
<command>pkcs15-init --generate-key " keyspec " --auth-id " nn</command>
</para>
<para>
where <replaceable>keyspec</replaceable> describes the algorithm and length of the
key to be created, such as <literal>rsa/512</literal>. This will create a 512 bit
RSA key. Currently, only RSA key generation is supported. Note that cards
usually support just a few different key lengths. Almost all cards will support
512 and 1024 bit keys, some will support 768 or 2048 as well.
where <replaceable>keyspec</replaceable> describes the algorithm and the parameters
of the key to be created. For example, <literal>rsa:2048</literal> generates a RSA key
with 2048-bit modulus. If you are generating an EC key, the curve designation must
be specified, for example <literal>ec:prime256v1</literal>. For symmetric key,
the length of key is specified in bytes, for example <literal>AES:32</literal>
or <literal>DES3:24</literal>.
</para>
<para>
<replaceable>nn</replaceable> is the ID of a user PIN installed previously,
@ -242,7 +243,7 @@
you would use
</para>
<para>
<command>pkcs15-init --store-secret-key /dev/urandom --secret-key-algorithm aes/256 --auth-id 01</command>
<command>pkcs15-init --store-secret-key /dev/urandom --secret-key-algorithm aes:256 --auth-id 01</command>
</para>
<para>
By default a random ID is generated for the secret key. You may specify an ID
@ -332,9 +333,9 @@
<listitem>
<para>
Tells the card to generate new key and store it on the card.
<replaceable>keyspec</replaceable> consists of an algorithm name
(currently, the only supported name is <option>RSA</option>),
optionally followed by a slash and the length of the key in bits.
<replaceable>keyspec</replaceable> consists of an algorithm name,
optionally followed by a colon ":", slash "/" or hyphen "-" and
the parameters of the key to be created.
It is a good idea to specify the key ID along with this command,
using the <option>id</option> option, otherwise an intrinsic ID
will be calculated from the key material. Look the description of
@ -417,7 +418,7 @@
<listitem>
<para>
<replaceable>keyspec</replaceable> describes the algorithm and length of the
key to be created or downloaded, such as <literal>aes/256</literal>.
key to be created or downloaded, such as <literal>aes:256</literal>.
This will create a 256 bit AES key.
</para>
</listitem>

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ force:
opensc.conf.example: opensc.conf.example.in force
.in:
@sed \
$(AM_V_GEN)sed \
-e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
-e 's|@DEBUG_FILE[@]|$(DEBUG_FILE)|g' \
-e 's|@DEFAULT_PCSC_PROVIDER[@]|$(DEFAULT_PCSC_PROVIDER)|g' \

View File

@ -43,4 +43,4 @@ TIDY_FILES = \
libpkcs11.c libscdl.c
check-local:
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' -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

@ -49,6 +49,7 @@ C_LoadModule(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs)
{
sc_pkcs11_module_t *mod;
CK_RV rv, (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
CK_RV (*c_get_interface)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS);
mod = calloc(1, sizeof(*mod));
if (mod == NULL) {
return NULL;
@ -65,6 +66,24 @@ C_LoadModule(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs)
goto failed;
}
c_get_interface = (CK_RV (*)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS))
sc_dlsym(mod->handle, "C_GetInterface");
if (c_get_interface) {
CK_INTERFACE *interface = NULL;
/* Get default PKCS #11 interface */
rv = c_get_interface((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface, 0);
if (rv == CKR_OK) {
/* this is actually 3.0 function list, but it starts
* with the same fields. Only for new functions, it
* needs to be casted to new structure */
*funcs = interface->pFunctionList;
return (void *) mod;
} else {
fprintf(stderr, "C_GetInterface failed %lx, retry 2.x way", rv);
}
}
/* Get the list of function pointers */
c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
sc_dlsym(mod->handle, "C_GetFunctionList");

View File

@ -28,7 +28,9 @@
#if !defined(_WIN32)
#include <arpa/inet.h> /* for htons() */
#include <unistd.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h> /* for gettimeofday() */
#endif
#include <stdint.h>
#else
#include <winsock2.h>

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='' -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

@ -401,11 +401,13 @@ sc_set_le_and_transmit(struct sc_card *card, struct sc_apdu *apdu, size_t olen)
/* set the new expected length */
apdu->resplen = olen;
apdu->le = nlen;
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Belpic V1 applets have a problem: if the card sends a 6C XX (only XX bytes available),
* and we resend the command too soon (i.e. the reader is too fast), the card doesn't respond.
* So we build in a delay. */
if (card->type == SC_CARD_TYPE_BELPIC_EID)
msleep(40);
#endif
/* re-transmit the APDU with new Le length */
rv = sc_single_transmit(card, apdu);

View File

@ -253,10 +253,15 @@ static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen, size_t depth
if (buflen > sizeof(a) + 1) {
print_hex(buf, buflen, depth);
} else {
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a));
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 1);
if (r < 0) {
printf("decode error");
return;
printf("decode error, ");
/* try again without the strict mode */
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 0);
if (r < 0) {
printf("even for lax decoding");
return ;
}
}
for (i = r - 1; i >= 0; i--) {
printf("%c", ((a >> i) & 1) ? '1' : '0');
@ -567,7 +572,7 @@ const u8 *sc_asn1_verify_tag(sc_context_t *ctx, const u8 * buf, size_t buflen,
}
static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
size_t outlen, int invert)
size_t outlen, int invert, const int strict)
{
const u8 *in = inbuf;
u8 *out = (u8 *) outbuf;
@ -577,13 +582,19 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
if (inlen < 1)
return SC_ERROR_INVALID_ASN1_OBJECT;
/* 8.6.2.3 If the bitstring is empty, there shall be no subsequent octets,
* and the initial octet shall be zero. */
if (inlen == 1 && *in != 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
if ((*in & ~0x07) != 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
/* The formatting is only enforced by SHALL keyword so we should accept
* by default also non-strict values. */
if (strict) {
/* 8.6.2.3 If the bitstring is empty, there shall be no
* subsequent octets,and the initial octet shall be zero. */
if (inlen == 1 && *in != 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
if ((*in & ~0x07) != 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
}
memset(outbuf, 0, outlen);
zero_bits = *in & 0x07;
in++;
@ -622,15 +633,15 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
}
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
void *outbuf, size_t outlen)
void *outbuf, size_t outlen, const int strict)
{
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1);
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1, strict);
}
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
void *outbuf, size_t outlen)
void *outbuf, size_t outlen, const int strict)
{
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0);
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0, strict);
}
static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
@ -675,7 +686,7 @@ static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
* Bitfields are just bit strings, stored in an unsigned int
* (taking endianness into account)
*/
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen)
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen, const int strict)
{
u8 data[sizeof(unsigned int)];
unsigned int field = 0;
@ -684,7 +695,7 @@ static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t
if (outlen != sizeof(data))
return SC_ERROR_BUFFER_TOO_SMALL;
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1);
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1, strict);
if (n < 0)
return n;
@ -1235,9 +1246,12 @@ static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen,
size_t idx, ptrlen = objlen;
int ret;
LOG_FUNC_CALLED(ctx);
ses = calloc(SC_MAX_SE_NUM, sizeof(sc_pkcs15_sec_env_info_t *));
if (ses == NULL)
return SC_ERROR_OUT_OF_MEMORY;
if (ses == NULL) {
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_OUT_OF_MEMORY);
}
for (idx=0; idx < SC_MAX_SE_NUM && ptrlen; ) {
struct sc_asn1_entry asn1_se[2];
@ -1281,7 +1295,7 @@ err:
free(ses);
}
return ret;
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, ret);
}
@ -1535,7 +1549,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
*len = objlen-1;
parm = *buf;
}
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert);
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert, 0);
if (r >= 0) {
*len = r;
r = 0;
@ -1544,7 +1558,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
break;
case SC_ASN1_BIT_FIELD:
if (parm != NULL)
r = decode_bit_field(obj, objlen, (u8 *) parm, *len);
r = decode_bit_field(obj, objlen, (u8 *) parm, *len, 0);
break;
case SC_ASN1_OCTET_STRING:
if (parm != NULL) {
@ -1988,6 +2002,10 @@ static int asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1,
u8 *obj = NULL, *buf = NULL, *tmp;
size_t total = 0, objsize;
if (asn1 == NULL) {
return SC_ERROR_INVALID_ARGUMENTS;
}
for (idx = 0; asn1[idx].name != NULL; idx++) {
r = asn1_encode_entry(ctx, &asn1[idx], &obj, &objsize, depth);
if (r) {

View File

@ -96,10 +96,10 @@ void sc_asn1_print_tags(const u8 * buf, size_t buflen);
int sc_asn1_utf8string_to_ascii(const u8 * buf, size_t buflen,
u8 * outbuf, size_t outlen);
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
void *outbuf, size_t outlen);
void *outbuf, size_t outlen, const int strict);
/* non-inverting version */
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
void *outbuf, size_t outlen);
void *outbuf, size_t outlen, const int strict);
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out, int strict);
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
struct sc_object_id *id);
@ -127,13 +127,16 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
const unsigned char *in, size_t inlen,
unsigned char *buf, size_t buflen);
#define SC_ASN1_CLASS_MASK 0x30000000
/* long form tags use these */
/* Same as SC_ASN1_TAG_* shifted left by 24 bits */
#define SC_ASN1_CLASS_MASK 0xC0000000
#define SC_ASN1_UNI 0x00000000 /* Universal */
#define SC_ASN1_APP 0x10000000 /* Application */
#define SC_ASN1_CTX 0x20000000 /* Context */
#define SC_ASN1_PRV 0x30000000 /* Private */
#define SC_ASN1_CONS 0x01000000
#define SC_ASN1_APP 0x40000000 /* Application */
#define SC_ASN1_CTX 0x80000000 /* Context */
#define SC_ASN1_PRV 0xC0000000 /* Private */
#define SC_ASN1_CONS 0x20000000
#define SC_ASN1_CLASS_CONS 0xE0000000 /* CLASS and CONS */
#define SC_ASN1_TAG_MASK 0x00FFFFFF
#define SC_ASN1_TAGNUM_SIZE 3
@ -173,6 +176,7 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
/* use callback function */
#define SC_ASN1_CALLBACK 384
/* use with short one byte tags */
#define SC_ASN1_TAG_CLASS 0xC0
#define SC_ASN1_TAG_UNIVERSAL 0x00
#define SC_ASN1_TAG_APPLICATION 0x40
@ -181,6 +185,7 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
#define SC_ASN1_TAG_CONSTRUCTED 0x20
#define SC_ASN1_TAG_PRIMITIVE 0x1F
#define SC_ASN1_TAG_CLASS_CONS 0xE0
#define SC_ASN1_TAG_EOC 0
#define SC_ASN1_TAG_BOOLEAN 1

View File

@ -1558,6 +1558,7 @@ authentic_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tri
pin_cmd.pin_type = data->pin_type;
pin_cmd.pin1.tries_left = -1;
memset(&acls, 0, sizeof(acls));
rv = authentic_pin_get_policy(card, &pin_cmd, acls);
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");

View File

@ -215,7 +215,6 @@ static int belpic_match_card(sc_card_t *card)
static int belpic_init(sc_card_t *card)
{
int key_size = 1024;
int r;
sc_log(card->ctx, "Belpic V%s\n", BELPIC_VERSION);
@ -227,7 +226,7 @@ static int belpic_init(sc_card_t *card)
u8 carddata[BELPIC_CARDDATA_RESP_LEN];
memset(carddata, 0, sizeof(carddata));
if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) {
if(get_carddata(card, carddata, sizeof(carddata)) < 0) {
return SC_ERROR_INVALID_CARD;
}
if (carddata[BELPIC_CARDDATA_OFF_APPLETVERS] >= 0x17) {

View File

@ -1872,6 +1872,7 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
sc_apdu_t apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
int rv;
if (data->cmd == SC_PIN_CMD_CHANGE) {
int i = 0;
@ -1897,7 +1898,10 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
}
}
return iso_drv->ops->pin_cmd(card, data, tries_left);
rv = iso_drv->ops->pin_cmd(card, data, tries_left);
data->apdu = NULL;
return rv;
}
static struct sc_card_operations cac_ops;

View File

@ -55,6 +55,8 @@ static const struct sc_atr_table cardos_atrs[] = {
/* CardOS v5.3 */
{ "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
{ "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
/* CardOS v5.4 */
{ "3b:d2:18:00:81:31:fe:58:c9:04:11", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
{ NULL, NULL, NULL, 0, 0, NULL }
};
@ -159,7 +161,7 @@ static int cardos_have_2048bit_package(sc_card_t *card)
sc_apdu_t apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
int r;
const u8 *p = rbuf, *q;
const u8 *p = rbuf, *q, *pp;
size_t len, tlen = 0, ilen = 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
@ -175,10 +177,10 @@ static int cardos_have_2048bit_package(sc_card_t *card)
return 0;
while (len != 0) {
p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
if (p == NULL)
pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
if (pp == NULL)
return 0;
q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen);
if (q == NULL || ilen != 4)
return 0;
if (q[0] == 0x1c)

View File

@ -2143,7 +2143,6 @@ static int dnie_pin_verify(struct sc_card *card,
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_ON);
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
data->apdu = &apdu; /* prepare apdu struct */
/* compose pin data to be inserted in apdu */
if (data->flags & SC_PIN_CMD_NEED_PADDING)
padding = 1;

View File

@ -948,7 +948,7 @@ decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned
des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
/* unpadding */
while (0x80 != plaintext[cipher_len - 2] && (cipher_len - 2 > 0))
while (0x80 != plaintext[cipher_len - 2] && (cipher_len > 2))
cipher_len--;
if (2 == cipher_len || *out_len < cipher_len - 2)

View File

@ -815,7 +815,7 @@ cryptoflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
r = acl_to_keynum_nibble(entry);
p[13 + i/2] |= (r & 0x0F) << (((i+1) % 2) * 4);
}
p[11] = (file->status & SC_FILE_STATUS_INVALIDATED) ? 0x00 : 0x01;
p[11] = (file->status == SC_FILE_STATUS_INVALIDATED) ? 0x00 : 0x01;
if (file->type != SC_FILE_TYPE_DF &&
(file->ef_structure == SC_FILE_EF_LINEAR_FIXED ||
file->ef_structure == SC_FILE_EF_CYCLIC))
@ -1284,6 +1284,7 @@ static int flex_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
r = iso_ops->pin_cmd(card, data, NULL);
if (old_cla != -1)
card->cla = old_cla;
data->apdu = NULL;
return r;
}

View File

@ -552,7 +552,9 @@ gpk_select_id(sc_card_t *card, int kind, unsigned int fid,
cp->len = 0;
/* fallthru */
case GPK_SEL_DF:
assert(cp->len + 1 <= SC_MAX_PATH_SIZE / 2);
if (cp->len + 1 > SC_MAX_PATH_SIZE / 2) {
return SC_ERROR_INTERNAL;
}
path = (unsigned short int *) cp->value;
path[cp->len++] = fid;
}
@ -1795,7 +1797,10 @@ gpk_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
data->apdu = &apdu;
return iso_ops->pin_cmd(card, data, tries_left);
r = iso_ops->pin_cmd(card, data, tries_left);
data->apdu = NULL;
return r;
}
/*

View File

@ -95,6 +95,18 @@ static const struct sc_atr_table iasecc_known_atrs[] = {
"IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL },
{ "3B:DC:18:FF:81:91:FE:1F:C3:80:73:C8:21:13:66:01:0B:03:52:00:05:38", NULL,
"IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL },
{
.atr = "3B:AC:00:40:2A:00:12:25:00:64:80:00:03:10:00:90:00",
.atrmask = "FF:00:00:00:00:FF:FF:FF:FF:FF:FF:00:00:00:FF:FF:FF",
.name = "IAS/ECC CPx",
.type = SC_CARD_TYPE_IASECC_CPX,
},
{
.atr = "2B:8F:80:01:00:31:B8:64:04:B0:EC:C1:73:94:01:80:82:90:00:0E",
.atrmask = "FF:FF:FF:FF:FF:FF:FF:FF:00:00:FF:C0:FF:FF:FF:FF:FF:FF:FF:FF",
.name = "IAS/ECC CPxCL",
.type = SC_CARD_TYPE_IASECC_CPXCL,
},
{ NULL, NULL, NULL, 0, 0, NULL }
};
@ -310,12 +322,14 @@ iasecc_select_mf(struct sc_card *card, struct sc_file **file_out)
mf_file->type = SC_FILE_TYPE_DF;
mf_file->path = path;
if (card->cache.valid)
sc_file_free(card->cache.current_df);
if (card->cache.valid) {
sc_file_free(card->cache.current_df);
}
card->cache.current_df = NULL;
if (card->cache.valid)
if (card->cache.valid) {
sc_file_free(card->cache.current_ef);
}
card->cache.current_ef = NULL;
sc_file_dup(&card->cache.current_df, mf_file);
@ -337,6 +351,8 @@ iasecc_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out,
unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
int rv;
LOG_FUNC_CALLED(card->ctx);
/* Select application (deselect previously selected application) */
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
apdu.lc = aid->len;
@ -354,7 +370,7 @@ iasecc_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out,
LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, "Cannot select AID");
memcpy(out, apdu.resp, apdu.resplen);
return SC_SUCCESS;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@ -405,6 +421,11 @@ static int iasecc_parse_ef_atr(struct sc_card *card)
sizes->recv = card->ef_atr->issuer_data[10] * 0x100 + card->ef_atr->issuer_data[11];
sizes->recv_sc = card->ef_atr->issuer_data[14] * 0x100 + card->ef_atr->issuer_data[15];
sc_log(ctx,
"EF.ATR: IO Buffer Size send/sc %"SC_FORMAT_LEN_SIZE_T"d/%"SC_FORMAT_LEN_SIZE_T"d "
"recv/sc %"SC_FORMAT_LEN_SIZE_T"d/%"SC_FORMAT_LEN_SIZE_T"d",
sizes->send, sizes->send_sc, sizes->recv, sizes->recv_sc);
card->max_send_size = sizes->send;
card->max_recv_size = sizes->recv;
@ -591,6 +612,45 @@ iasecc_init_amos_or_sagem(struct sc_card *card)
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
inline static int
iasecc_is_cpx(const struct sc_card *card)
{
switch(card->type) {
case SC_CARD_TYPE_IASECC_CPX:
case SC_CARD_TYPE_IASECC_CPXCL:
return 1;
default:
return 0;
}
return 0;
}
static int
iasecc_init_cpx(struct sc_card *card)
{
struct sc_context *ctx = card->ctx;
unsigned int flags;
int rv = 0;
LOG_FUNC_CALLED(ctx);
card->caps = IASECC_CARD_DEFAULT_CAPS;
flags = IASECC_CARD_DEFAULT_FLAGS;
_sc_card_add_rsa_alg(card, 512, flags, 0);
_sc_card_add_rsa_alg(card, 1024, flags, 0);
_sc_card_add_rsa_alg(card, 2048, flags, 0);
rv = iasecc_parse_ef_atr(card);
if (rv)
sc_invalidate_cache(card); /* avoid memory leakage */
LOG_TEST_RET(ctx, rv, "Parse EF.ATR");
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static int
iasecc_init(struct sc_card *card)
@ -618,6 +678,8 @@ iasecc_init(struct sc_card *card)
rv = iasecc_init_amos_or_sagem(card);
else if (card->type == SC_CARD_TYPE_IASECC_MI)
rv = iasecc_init_amos_or_sagem(card);
else if (iasecc_is_cpx(card))
rv = iasecc_init_cpx(card);
else {
LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_CARD, "");
}
@ -857,9 +919,11 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
sc_log(ctx, "iasecc_select_file() path:%s", sc_print_path(path));
sc_print_cache(card);
if (path->type != SC_PATH_TYPE_DF_NAME
if ((!iasecc_is_cpx(card)) &&
(card->type != SC_CARD_TYPE_IASECC_GEMALTO) &&
(path->type != SC_PATH_TYPE_DF_NAME
&& lpath.len >= 2
&& lpath.value[0] == 0x3F && lpath.value[1] == 0x00) {
&& lpath.value[0] == 0x3F && lpath.value[1] == 0x00)) {
sc_log(ctx, "EF.ATR(aid:'%s')", card->ef_atr ? sc_dump_hex(card->ef_atr->aid.value, card->ef_atr->aid.len) : "");
rv = iasecc_select_mf(card, file_out);
@ -940,7 +1004,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
&& card->type != SC_CARD_TYPE_IASECC_SAGEM
&& card->type != SC_CARD_TYPE_IASECC_AMOS
&& card->type != SC_CARD_TYPE_IASECC_MI
&& card->type != SC_CARD_TYPE_IASECC_MI2) {
&& card->type != SC_CARD_TYPE_IASECC_MI2
&& !iasecc_is_cpx(card)) {
rv = SC_ERROR_NOT_SUPPORTED;
LOG_TEST_GOTO_ERR(ctx, rv, "Unsupported card");
}
@ -952,7 +1017,10 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
card->type == SC_CARD_TYPE_IASECC_AMOS ||
card->type == SC_CARD_TYPE_IASECC_MI ||
card->type == SC_CARD_TYPE_IASECC_MI2) {
card->type == SC_CARD_TYPE_IASECC_MI2 ||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
iasecc_is_cpx(card)
) {
apdu.p2 = 0x04;
}
}
@ -961,7 +1029,9 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
card->type == SC_CARD_TYPE_IASECC_AMOS ||
card->type == SC_CARD_TYPE_IASECC_MI ||
card->type == SC_CARD_TYPE_IASECC_MI2) {
card->type == SC_CARD_TYPE_IASECC_MI2 ||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
iasecc_is_cpx(card)) {
apdu.p2 = 0x04;
}
}
@ -974,7 +1044,9 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
apdu.p1 = 0x04;
if (card->type == SC_CARD_TYPE_IASECC_AMOS ||
card->type == SC_CARD_TYPE_IASECC_MI2 ||
card->type == SC_CARD_TYPE_IASECC_OBERTHUR) {
card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
iasecc_is_cpx(card)) {
apdu.p2 = 0x04;
}
}
@ -998,6 +1070,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (rv == SC_ERROR_INCORRECT_PARAMETERS &&
lpath.type == SC_PATH_TYPE_DF_NAME && apdu.p2 == 0x00) {
sc_log(ctx, "Warning: SC_ERROR_INCORRECT_PARAMETERS for SC_PATH_TYPE_DF_NAME, try again with P2=0x0C");
apdu.p2 = 0x0C;
continue;
}
@ -1069,25 +1142,23 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
sc_log(ctx, "FileType %i", file->type);
if (file->type == SC_FILE_TYPE_DF) {
if (card->cache.valid)
if (card->cache.valid) {
sc_file_free(card->cache.current_df);
}
card->cache.current_df = NULL;
if (card->cache.valid)
sc_file_free(card->cache.current_ef);
card->cache.current_ef = NULL;
sc_file_dup(&card->cache.current_df, file);
card->cache.valid = 1;
}
else {
if (card->cache.valid)
if (card->cache.valid) {
sc_file_free(card->cache.current_ef);
}
card->cache.current_ef = NULL;
sc_file_dup(&card->cache.current_ef, file);
card->cache.valid = 1;
}
if (file_out) {
@ -1125,8 +1196,8 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
const unsigned char *buf, size_t buflen)
{
struct sc_context *ctx = card->ctx;
size_t taglen;
int rv, ii, offs;
size_t taglen, offs, ii;
int rv;
const unsigned char *acls = NULL, *tag = NULL;
unsigned char mask;
unsigned char ops_DF[7] = {
@ -1182,10 +1253,15 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
for (ii = 0; ii < 7; ii++, mask /= 2) {
unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii];
/* avoid any access to acls[offs] beyond the taglen */
if (offs >= taglen) {
sc_log(ctx, "Warning: Invalid offset reached during ACL parsing");
break;
}
if (!(mask & acls[0]))
continue;
sc_log(ctx, "ACLs mask 0x%X, offs %i, op 0x%X, acls[offs] 0x%X", mask, offs, op, acls[offs]);
sc_log(ctx, "ACLs mask 0x%X, offs %"SC_FORMAT_LEN_SIZE_T"u, op 0x%X, acls[offs] 0x%X", mask, offs, op, acls[offs]);
if (op == 0xFF) {
;
}
@ -1493,8 +1569,9 @@ iasecc_delete_file(struct sc_card *card, const struct sc_path *path)
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(ctx, rv, "Delete file failed");
if (card->cache.valid)
if (card->cache.valid) {
sc_file_free(card->cache.current_ef);
}
card->cache.current_ef = NULL;
}
@ -1641,6 +1718,11 @@ iasecc_se_get_info(struct sc_card *card, struct iasecc_se_info *se)
LOG_FUNC_CALLED(ctx);
if (iasecc_is_cpx(card)) {
rv = iasecc_select_mf(card, NULL);
LOG_TEST_RET(ctx, rv, "MF invalid");
}
if (se->reference > IASECC_SE_REF_MAX)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -2797,6 +2879,34 @@ iasecc_sdo_get_tagged_data(struct sc_card *card, int sdo_tag, struct iasecc_sdo
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "sdo_tag=0x%x sdo_ref=0x%x sdo_class=0x%x", sdo_tag,
sdo->sdo_ref, sdo->sdo_class);
/* XXX: for the CPx, the SDO are available from some specific path */
if (iasecc_is_cpx(card)) {
struct sc_path path;
char *path_str = NULL;
switch(sdo_tag) {
case IASECC_SDO_PRVKEY_TAG:
/* APDU 00 CB 3F FF 0B 4D 09 70 07 BF 90 02 03 7F 48 80 */
path_str = "3F00:0001";
break;
case IASECC_SDO_CHV_TAG:
/* APDU 00 CB 3F FF 0B 4D 09 70 07 BF 81 01 03 7F 41 80 */
path_str = "3F00";
break;
default:
path_str = NULL;
break;
}
if (path_str) {
sc_log(ctx, "Warning: Enforce the path=%s", path_str);
sc_format_path(path_str, &path);
rv = iasecc_select_file(card, &path, NULL);
LOG_TEST_RET(ctx, rv, "path error");
}
}
sbuf[offs--] = 0x80;
sbuf[offs--] = sdo_tag & 0xFF;
if ((sdo_tag >> 8) & 0xFF)

View File

@ -195,16 +195,25 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv,
if (((memcmp(&start[4], "ksc", 3) == 0) || memcmp(&start[4], "kxc", 3) == 0)
&& (memcmp(&start[12], "mscp", 5) == 0)) {
new_object.fd++;
if (card->type == SC_CARD_TYPE_IDPRIME_V2) {
/* The key reference starts from 0x11 and increments by the key id (ASCII) */
if (card->type == SC_CARD_TYPE_IDPRIME_V1) {
/* The key reference is one bigger than the value found here for some reason */
new_object.key_reference = start[8] + 1;
} else {
int key_id = 0;
if (start[8] >= '0' && start[8] <= '9') {
key_id = start[8] - '0';
}
new_object.key_reference = 0x11 + key_id;
} else {
/* The key reference is one bigger than the value found here for some reason */
new_object.key_reference = start[8] + 1;
switch (card->type) {
case SC_CARD_TYPE_IDPRIME_V2:
new_object.key_reference = 0x11 + key_id;
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",
new_object.fd, new_object.key_reference);
@ -252,6 +261,14 @@ static int idprime_init(sc_card_t *card)
card->type = SC_CARD_TYPE_IDPRIME_V2;
sc_log(card->ctx, "Detected IDPrime applet version 2");
break;
case 0x03:
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;
@ -290,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)";
@ -418,6 +441,7 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
sc_path_t tinfo_path = {"\x00\x00", 2, 0, 0, SC_PATH_TYPE_PATH, {"", 0}};
sc_file_t *file = NULL;
u8 buf[2];
char *name;
int r;
LOG_FUNC_CALLED(card->ctx);
@ -445,20 +469,22 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
}
sc_file_free(file);
*tname = malloc(buf[1]);
if (*tname == NULL) {
name = malloc(buf[1]);
if (name == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0);
r = iso_ops->read_binary(card, 2, (unsigned char *)name, buf[1], 0);
if (r < 1) {
free(*tname);
free(name);
LOG_FUNC_RETURN(card->ctx, r);
}
if ((*tname)[r-1] != '\0') {
(*tname)[r-1] = '\0';
if (name[r-1] != '\0') {
name[r-1] = '\0';
}
*tname = name;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@ -615,13 +641,13 @@ idprime_set_security_env(struct sc_card *card,
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_OAEP) {
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA1) {
new_env.algorithm_ref = 0x1D;
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA256) {
new_env.algorithm_ref = 0x4D;
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA384) {
new_env.algorithm_ref = 0x5D;
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA512) {
new_env.algorithm_ref = 0x6D;
}
} else { /* RSA-PKCS without hashing */
@ -630,11 +656,11 @@ idprime_set_security_env(struct sc_card *card,
break;
case SC_SEC_OPERATION_SIGN:
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PSS) {
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA256) {
new_env.algorithm_ref = 0x45;
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA384) {
new_env.algorithm_ref = 0x55;
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA512) {
new_env.algorithm_ref = 0x65;
}
} else { /* RSA-PKCS */

View File

@ -503,6 +503,7 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
return SC_ERROR_WRONG_CARD;
}
len = file->size;
sc_file_free(file);
//Returned file->size should be 16.
//We choose to not consider it as critical, because some cards

View File

@ -882,6 +882,11 @@ select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
priv->curpathlen--;
priv->is_ef = 0;
}
/* Free the previously allocated file so we do not leak memory here */
if (file) {
sc_file_free(*file);
*file = NULL;
}
r = select_down(card, pathptr, 1, 0, file);
}

View File

@ -187,7 +187,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
*p++ = file->record_length;
else
*p++ = 0;
if (file->status & SC_FILE_STATUS_INVALIDATED)
if (file->status == SC_FILE_STATUS_INVALIDATED)
*p++ = 0;
else
*p++ = 0x01;

View File

@ -43,9 +43,6 @@
#define LOAD_KEY_EC_PRIVATE 0x1087
#define LOAD_KEY_SYMMETRIC 0x20a0
#define MYEID_STATE_CREATION 0x01
#define MYEID_STATE_ACTIVATED 0x07
#define MYEID_CARD_NAME_MAX_LEN 100
/* The following flags define the features supported by the card currently in use.
@ -86,6 +83,7 @@ typedef struct myeid_private_data {
ECDH key agreement. Note that this pointer is usually not valid
after this pair of calls and must not be used elsewhere. */
const struct sc_security_env* sec_env;
int disable_hw_pkcs1_padding;
} myeid_private_data_t;
typedef struct myeid_card_caps {
@ -166,6 +164,34 @@ myeid_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out, s
return SC_SUCCESS;
}
static int myeid_load_options(sc_context_t *ctx, myeid_private_data_t *priv)
{
int r;
size_t i, j;
scconf_block **found_blocks, *block;
if (!ctx || !priv) {
r = SC_ERROR_INTERNAL;
goto err;
}
priv->disable_hw_pkcs1_padding = 0;
for (i = 0; ctx->conf_blocks[i]; i++) {
found_blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
"card_driver", "myeid");
if (!found_blocks)
continue;
for (j = 0, block = found_blocks[j]; block; j++, block = found_blocks[j]) {
priv->disable_hw_pkcs1_padding = scconf_get_int(block, "disable_hw_pkcs1_padding", 0);
sc_log(ctx,"Found config option: disable_hw_pkcs1_padding = %d\n", priv->disable_hw_pkcs1_padding);
}
free(found_blocks);
}
r = SC_SUCCESS;
err:
return r;
}
static int myeid_init(struct sc_card *card)
{
unsigned long flags = 0, ext_flags = 0;
@ -196,6 +222,9 @@ static int myeid_init(struct sc_card *card)
if (!priv)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
rv = myeid_load_options (card->ctx, priv);
LOG_TEST_GOTO_ERR(card->ctx, rv, "Unable to read options from opensc.conf");
priv->card_state = SC_FILE_STATUS_CREATION;
card->drv_data = priv;
@ -224,8 +253,10 @@ static int myeid_init(struct sc_card *card)
}
}
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN;
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN;
if (priv->disable_hw_pkcs1_padding == 0)
flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
flags |= SC_ALGORITHM_RSA_HASH_NONE;
_sc_card_add_rsa_alg(card, 512, flags, 0);
_sc_card_add_rsa_alg(card, 768, flags, 0);
@ -245,7 +276,7 @@ static int myeid_init(struct sc_card *card)
int i;
flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN;
flags |= SC_ALGORITHM_ECDSA_HASH_NONE | SC_ALGORITHM_ECDSA_HASH_SHA1;
flags |= SC_ALGORITHM_ECDSA_HASH_NONE;
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
for (i=0; ec_curves[i].curve_name != NULL; i++) {
@ -441,20 +472,18 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
sc_log(card->ctx, "id (%X) sec_attr (%X %X %X)", file->id,
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
}
tag = sc_asn1_find_tag(NULL, buf, buflen, 0x8A, &taglen);
if (tag != NULL && taglen > 0)
{
if(tag[0] == MYEID_STATE_CREATION) {
file->status = SC_FILE_STATUS_CREATION;
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_CREATION (0x%X)",
file->id, tag[0]);
}
else if(tag[0] == MYEID_STATE_ACTIVATED) {
file->status = SC_FILE_STATUS_ACTIVATED;
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_ACTIVATED (0x%X)",
file->id, tag[0]);
}
priv->card_state = file->status;
priv->card_state = file->status;
switch (file->status) {
case SC_FILE_STATUS_CREATION:
file->acl_inactive = 1;
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_CREATION", file->id);
break;
case SC_FILE_STATUS_ACTIVATED:
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_ACTIVATED", file->id);
break;
default:
sc_log(card->ctx, "File id (%X) unusual status (0x%X)", file->id, file->status);
}
LOG_FUNC_RETURN(card->ctx, 0);

View File

@ -539,7 +539,7 @@ auth_select_file(struct sc_card *card, const struct sc_path *in_path,
}
}
if (path.len - offs > 0) {
if (path.len > offs) {
struct sc_path tmp_path;
memset(&tmp_path, 0, sizeof(struct sc_path));
@ -2206,6 +2206,9 @@ auth_read_record(struct sc_card *card, unsigned int nr_rec,
"auth_read_record(): nr_rec %i; count %"SC_FORMAT_LEN_SIZE_T"u",
nr_rec, count);
if (nr_rec > 0xFF)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, nr_rec, 0);
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
if (flags & SC_RECORD_BY_REC_NR)

View File

@ -87,7 +87,11 @@ static struct sc_card_driver pgp_drv = {
};
static pgp_ec_curves_t ec_curves[] = {
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 */
@ -97,11 +101,16 @@ static pgp_ec_curves_t ec_curves[] = {
{{{-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 */
static pgp_ec_curves_t ec_curves_gnuk[] = {
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
{{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */
/*{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, //cv25519
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, // ed25519 */
{{{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 */
{{{-1}}, 0} /* This entry must not be touched. */
};
@ -448,6 +457,15 @@ pgp_init(sc_card_t *card)
: (priv->bcd_version < OPENPGP_CARD_3_4) ? pgp33_objects
: pgp34_objects;
/* 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;
}
/* change file path to MF for re-use in MF */
sc_format_path("3f00", &file->path);
@ -500,22 +518,15 @@ pgp_init(sc_card_t *card)
switch (card->type) {
case SC_CARD_TYPE_OPENPGP_V3:
/* RSA 1024 was removed for v3+ */
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 4096, flags_rsa, 0);
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
for (i=0; ec_curves[i].oid.value[0] >= 0; i++)
{
_sc_card_add_ec_alg(card, ec_curves[i].size, flags_ecc, ext_flags, &ec_curves[i].oid);
}
break;
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
/* fallthrough */
case SC_CARD_TYPE_OPENPGP_GNUK:
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
/* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */
for (i=0; ec_curves_gnuk[i].oid.value[0] >= 0; i++)
for (i=0; priv->ec_curves[i].oid.value[0] >= 0; i++)
{
_sc_card_add_ec_alg(card, ec_curves_gnuk[i].size,
flags_ecc, ext_flags, &ec_curves_gnuk[i].oid);
_sc_card_add_ec_alg(card, priv->ec_curves[i].size,
flags_ecc, ext_flags, &priv->ec_curves[i].oid);
}
break;
case SC_CARD_TYPE_OPENPGP_V2:
@ -565,21 +576,27 @@ pgp_parse_hist_bytes(sc_card_t *card, u8 *ctlv, size_t ctlv_len)
* Internal: parse an algorithm attributes DO
**/
static int
pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_t *key_info)
pgp_parse_algo_attr_blob(sc_card_t *card, const pgp_blob_t *blob,
sc_cardctl_openpgp_keygen_info_t *key_info)
{
struct pgp_priv_data *priv = DRVDATA(card);
struct sc_object_id oid;
unsigned int j, r;
LOG_FUNC_CALLED(card->ctx);
if (blob == NULL || blob->data == NULL || blob->len == 0 ||
blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL)
return SC_ERROR_INCORRECT_PARAMETERS;
blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
}
key_info->key_id = blob->id - 0x00c0; /* attribute algorithm blobs are C1 - C3 */
switch (blob->data[0]) {
case SC_OPENPGP_KEYALGO_RSA:
if (blob->len < 5)
return SC_ERROR_INCORRECT_PARAMETERS;
if (blob->len < 5) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
}
key_info->algorithm = SC_OPENPGP_KEYALGO_RSA;
key_info->u.rsa.modulus_len = bebytes2ushort(blob->data + 1);
@ -591,11 +608,12 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
break;
case SC_OPENPGP_KEYALGO_ECDH:
case SC_OPENPGP_KEYALGO_ECDSA:
case SC_OPENPGP_KEYALGO_EDDSA:
/* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA */
/* 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;
@ -603,9 +621,14 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
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;
}
@ -618,20 +641,25 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
return r;
}
/* compare with list of supported ec_curves */
for (j=0; ec_curves[j].oid.value[0] >= 0; j++){
if (sc_compare_oid(&ec_curves[j].oid, &oid)){
key_info->u.ec.oid = ec_curves[j].oid;
key_info->u.ec.key_length = ec_curves[j].size;
for (j = 0; priv->ec_curves[j].oid.value[0] >= 0; j++) {
if (sc_compare_oid(&priv->ec_curves[j].oid, &oid)) {
sc_log(card->ctx, "Matched EC oid %s (%d)",
sc_dump_oid(&oid), j);
key_info->u.ec.oid = priv->ec_curves[j].oid;
key_info->u.ec.key_length = priv->ec_curves[j].size;
break;
}
}
/* We did not match the OID */
if (priv->ec_curves[j].oid.value[0] < 0) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
}
break;
default:
return SC_ERROR_NOT_IMPLEMENTED;
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
return SC_SUCCESS;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@ -647,6 +675,8 @@ pgp_get_card_features(sc_card_t *card)
size_t i;
pgp_blob_t *blob, *blob6e, *blob73;
LOG_FUNC_CALLED(card->ctx);
/* parse card capabilities from historical bytes in ATR */
if (hist_bytes_len > 0) {
/* category indicator 0x00, 0x10 or 0x80 => compact TLV (ISO) */
@ -776,24 +806,46 @@ pgp_get_card_features(sc_card_t *card)
for (i = 0x00c1; i <= 0x00c3; i++) {
sc_cardctl_openpgp_keygen_info_t key_info;
sc_log(card->ctx, "Parsing algorithm attribues DO %zX" , i);
/* OpenPGP card spec 1.1 & 2.x section 4.3.3.6 / v3.x section 4.4.3.7 */
if ((pgp_get_blob(card, blob73, i, &blob) >= 0) &&
(pgp_parse_algo_attr_blob(blob, &key_info) >= 0)) {
(pgp_parse_algo_attr_blob(card, blob, &key_info) >= 0)) {
unsigned long flags = 0, ext_flags = 0;
/* RSA [RFC 4880] */
if (key_info.algorithm == SC_OPENPGP_KEYALGO_RSA){
switch (key_info.algorithm) {
case SC_OPENPGP_KEYALGO_RSA:
/* OpenPGP card spec 1.1 & 2.x, section 7.2.9 & 7.2.10 /
* v3.x section 7.2.11 & 7.2.12 */
unsigned long flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
SC_ALGORITHM_RSA_HASH_NONE |
SC_ALGORITHM_ONBOARD_KEY_GEN; /* key gen on card */
_sc_card_add_rsa_alg(card, key_info.u.rsa.modulus_len, flags, 0);
}
/* v3.0+: ECC [RFC 4880 & 6637] */
else if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info.algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
SC_ALGORITHM_RSA_HASH_NONE |
SC_ALGORITHM_ONBOARD_KEY_GEN; /* key gen on card */
unsigned long flags, ext_flags;
_sc_card_add_rsa_alg(card, key_info.u.rsa.modulus_len, flags, 0);
sc_log(card->ctx, "DO %zX: Added RSA algorithm, mod_len = %"
SC_FORMAT_LEN_SIZE_T"u",
i, key_info.u.rsa.modulus_len);
break;
case SC_OPENPGP_KEYALGO_ECDH:
/* The montgomery curve (curve25519) needs to go through
* different paths, otherwise we handle it as a normal EC key */
if (sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) {
/* CKM_XEDDSA supports both Sign and Derive, but
* OpenPGP card supports only derivation using these
* keys as far as I know */
_sc_card_add_xeddsa_alg(card, key_info.u.ec.key_length,
SC_ALGORITHM_ECDH_CDH_RAW, 0, &key_info.u.ec.oid);
sc_log(card->ctx, "DO %zX: Added XEDDSA algorithm (%d), mod_len = %d" ,
i, key_info.algorithm, key_info.u.ec.key_length);
break;
}
/* fall through */
case SC_OPENPGP_KEYALGO_ECDSA:
/* v3.0+: ECC [RFC 4880 & 6637] */
/* EdDSA from draft-ietf-openpgp-rfc4880bis-08 */
flags = 0, ext_flags = 0;
if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH)
flags = SC_ALGORITHM_ECDH_CDH_RAW;
@ -804,7 +856,21 @@ pgp_get_card_features(sc_card_t *card)
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE;
_sc_card_add_ec_alg(card, key_info.u.ec.key_length, flags, ext_flags,
&key_info.u.ec.oid);
&key_info.u.ec.oid);
sc_log(card->ctx, "DO %zX: Added EC algorithm (%d), mod_len = %d" ,
i, key_info.algorithm, key_info.u.ec.key_length);
break;
case SC_OPENPGP_KEYALGO_EDDSA:
_sc_card_add_eddsa_alg(card, key_info.u.ec.key_length,
SC_ALGORITHM_EDDSA_RAW, 0, &key_info.u.ec.oid);
sc_log(card->ctx, "DO %zX: Added EDDSA algorithm (%d), mod_len = %d" ,
i, key_info.algorithm, key_info.u.ec.key_length);
break;
default:
sc_log(card->ctx, "DO %zX: Unknown algorithm ID (%d)" ,
i, key_info.algorithm);
break;
}
}
}
@ -1551,10 +1617,6 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
else if ((r = pgp_get_blob(card, blob, 0x0086, &pubkey_blob)) >= 0
&& (r = pgp_read_blob(card, pubkey_blob)) >= 0) {
p15pubkey.algorithm = SC_ALGORITHM_EC;
p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data;
p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len;
switch(tag & 0xFFFE) {
case DO_SIGN: aa_tag = 0x00C1; break;
case DO_ENCR: aa_tag = 0x00C2; break;
@ -1567,31 +1629,73 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
if (aa_tag && ((r = pgp_get_blob(card, priv->mf, 0x006e, &blob6e)) >= 0) &&
((r = pgp_get_blob(card, blob6e, 0x0073, &blob73)) >= 0) &&
((r = pgp_get_blob(card, blob73, aa_tag, &aa_blob)) >= 0) &&
((r = pgp_parse_algo_attr_blob(aa_blob, &key_info)) >= 0)) {
if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid,
&p15pubkey.u.ec.params.der.value,
&p15pubkey.u.ec.params.der.len)) == 0) {
p15pubkey.u.ec.params.type = 1;
((r = pgp_parse_algo_attr_blob(card, aa_blob, &key_info)) >= 0)) {
switch (key_info.algorithm) {
case SC_OPENPGP_KEYALGO_EDDSA:
/* In EDDSA key case we do not have to care about OIDs
* as we support only one for now */
p15pubkey.algorithm = SC_ALGORITHM_EDDSA;
p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data;
p15pubkey.u.eddsa.pubkey.len = pubkey_blob->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:
/* This yields either EC(DSA) key or EC_MONTGOMERY (curve25519) key */
if (sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) {
p15pubkey.algorithm = SC_ALGORITHM_XEDDSA;
p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data;
p15pubkey.u.eddsa.pubkey.len = pubkey_blob->len;
/* PKCS#11 3.0 2.3.7 Montgomery EC public keys only support
* the use of the curveName selection to specify a curve
* name as defined in [RFC7748] */
/* XXX only curve25519 supported now. Theoretically could be
* also curve448 or OIDs */
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
break;
}
/* fall through */
case SC_OPENPGP_KEYALGO_ECDSA:
if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid,
&p15pubkey.u.ec.params.der.value,
&p15pubkey.u.ec.params.der.len)) == 0) {
p15pubkey.algorithm = SC_ALGORITHM_EC;
p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data;
p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len;
p15pubkey.u.ec.params.type = 1;
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
} else {
sc_log(card->ctx, "Unable to encode EC curve OID from algorithm info");
}
break;
default:
sc_log(card->ctx, "Unknown algorithm ID received (%d)", key_info.algorithm);
break;
}
} else
} else {
sc_log(card->ctx, "Unable to find Algorithm Attribute for EC curve OID");
}
else
}
} else {
LOG_TEST_RET(card->ctx, r, "error getting elements");
}
/* clean up anything we may have set in p15pubkey that can not be freed */
if (p15pubkey.algorithm == SC_ALGORITHM_RSA) {
if (p15pubkey.algorithm == SC_ALGORITHM_RSA) {
p15pubkey.u.rsa.modulus.data = NULL;
p15pubkey.u.rsa.modulus.len = 0;
p15pubkey.u.rsa.exponent.data = NULL;
p15pubkey.u.rsa.exponent.len = 0;
} else
if (p15pubkey.algorithm == SC_ALGORITHM_EC) {
} else if (p15pubkey.algorithm == SC_ALGORITHM_EC) {
p15pubkey.u.ec.ecpointQ.value = NULL;
p15pubkey.u.ec.ecpointQ.len = 0;
/* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */
} else if (p15pubkey.algorithm == SC_ALGORITHM_EDDSA
|| p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) {
p15pubkey.u.eddsa.pubkey.value = NULL;
p15pubkey.u.eddsa.pubkey.len = 0;
}
sc_pkcs15_erase_pubkey(&p15pubkey);
@ -1769,9 +1873,8 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
LOG_FUNC_CALLED(card->ctx);
/* check if the tag is writable */
if (priv->current->id != tag)
affected_blob = pgp_find_blob(card, tag);
/* Check if there is a blob for the given tag */
affected_blob = pgp_find_blob(card, tag);
/* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
if (affected_blob == NULL)
@ -1779,6 +1882,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
else
dinfo = affected_blob->info;
/* Make sure the DO exists and is writeable */
if (dinfo == NULL) {
sc_log(card->ctx, "The DO %04X does not exist.", tag);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -1843,7 +1947,7 @@ pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
/* In general, the PIN Reference is extracted from the key-id,
* for example, CHV0 -> Ref=0, CHV1 -> Ref=1.
* However, in the case of OpenGPG, the PIN Ref to compose APDU
* However, in the case of OpenPGP, the PIN Ref to compose APDU
* must be 81, 82, 83.
* So, if we receive Ref=1, Ref=2, we must convert to 81, 82...
* In OpenPGP v1, the PINs are named CHV1, CHV2, CHV3.
@ -1964,6 +2068,7 @@ int pgp_logout(struct sc_card *card)
/**
* ABI: ISO 7816-8 SET SECURITY ENVIRONMENT.
* This is optional in the OpenPGP Card 3.4 specs
*/
static int
pgp_set_security_env(sc_card_t *card,
@ -1973,9 +2078,11 @@ pgp_set_security_env(sc_card_t *card,
LOG_FUNC_CALLED(card->ctx);
/* The SC_SEC_ENV_ALG_PRESENT is set always so let it pass for GNUK */
if ((env->flags & SC_SEC_ENV_ALG_PRESENT)
&& (env->algorithm != SC_ALGORITHM_RSA)
&& (priv->bcd_version < OPENPGP_CARD_3_0))
&& (priv->bcd_version < OPENPGP_CARD_3_0)
&& (card->type != SC_CARD_TYPE_OPENPGP_GNUK))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"only RSA algorithm supported");
@ -2006,6 +2113,9 @@ pgp_set_security_env(sc_card_t *card,
"requested usage");
}
break;
case SC_SEC_OPERATION_DERIVE:
sc_log(card->ctx, "Operation: Derive: No particular action needed");
break;
default:
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
@ -2093,6 +2203,9 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
break;
case 0x01:
default:
/* From PKCS #11 point of view, we should be able to use
* curve25519 to do digital signature, but it is not how it
* is used in OpenPGP so we will not allow it here */
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid key reference");
}
@ -2129,21 +2242,86 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
sc_security_env_t *env = &priv->sec_env;
sc_apdu_t apdu;
u8 apdu_case = SC_APDU_CASE_4;
u8 *temp = NULL;
u8 *temp = NULL, *p = NULL;
size_t templen, pklen, dolen;
int r;
LOG_FUNC_CALLED(card->ctx);
/* padding according to OpenPGP card spec 1.1 & 2.x section 7.2.9 / 3.x section 7.2.11 */
if (!(temp = malloc(inlen + 1)))
/* padding according to OpenPGP card spec 1.1 & 2.x section 7.2.9 / 3.x section 7.2.11
* The longest possible prefix is 10 bytes for ECDH */
templen = inlen + 10;
if (!(temp = malloc(templen)))
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
/* padding byte: 0xa6 = ECC; 0x00 = RSA; 0x02 = AES */
(env->algorithm == SC_ALGORITHM_EC) ? (temp[0] = 0xa6) : (temp[0] = 0x00);
memcpy(temp + 1, in, inlen);
in = temp;
inlen += 1;
if (env->operation != SC_SEC_OPERATION_DECIPHER) {
/* padding byte: 0xa6 = ECC; 0x00 = RSA; 0x02 = AES */
switch (env->algorithm) {
case SC_ALGORITHM_RSA:
/* This is just PKCS#1.5 start byte and it should be already
* provided by the padding routines. But it lets put it here
* to make sure it does not conflict with following indicators */
temp[0] = 0x00;
memcpy(temp + 1, in, inlen);
inlen += 1;
break;
case SC_ALGORITHM_EC:
case SC_ALGORITHM_XEDDSA:
/* Calculate length of External Public Key (0x86) */
r = sc_asn1_put_tag(0x86, NULL, inlen, NULL, 0, NULL);
if (r <= 0) {
free(temp);
LOG_FUNC_RETURN(card->ctx, r);
}
pklen = r;
/* Calculate lenght of Public Key DO (0x7F49) */
r = sc_asn1_put_tag(0x7f49, NULL, pklen, NULL, 0, NULL);
if (r <= 0) {
free(temp);
LOG_FUNC_RETURN(card->ctx, r);
}
dolen = r;
p = temp;
/* This is 0xA6 Cipher DO with associated length field */
r = sc_asn1_put_tag(0xA6, NULL, dolen, p, templen - (p - temp), &p);
if (r != SC_SUCCESS) {
free(temp);
LOG_FUNC_RETURN(card->ctx, r);
}
/* Public Key DO (0x7F49) with associated length field */
r = sc_asn1_put_tag(0x7F49, NULL, pklen, p, templen - (p - temp), &p);
if (r != SC_SUCCESS) {
free(temp);
LOG_FUNC_RETURN(card->ctx, r);
}
/* External Public Key (0x86) with associated length */
r = sc_asn1_put_tag(0x86, in, inlen, p, templen - (p - temp), &p);
if (r != SC_SUCCESS) {
free(temp);
LOG_FUNC_RETURN(card->ctx, r);
}
inlen = (p - temp);
break;
case SC_ALGORITHM_AES:
/* not supported yet */
/*
temp[0] = 0x02;
memcpy(temp + 1, in, inlen);
inlen += 1;
*/
/* fall through */
default:
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
in = temp;
if (env->operation != SC_SEC_OPERATION_DECIPHER &&
env->operation != SC_SEC_OPERATION_DERIVE) {
free(temp);
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
@ -2223,7 +2401,8 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_
if (priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) {
/* ECDSA and ECDH */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA
|| key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){
data_len = key_info->u.ec.oid_len+1;
data = malloc(data_len);
if (!data)
@ -2270,7 +2449,7 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_
} else {
sc_cardctl_openpgp_keygen_info_t old_key_info;
if (pgp_parse_algo_attr_blob(algo_blob, &old_key_info) != SC_SUCCESS
if (pgp_parse_algo_attr_blob(card, algo_blob, &old_key_info) != SC_SUCCESS
|| old_key_info.algorithm != key_info->algorithm)
LOG_TEST_RET(card->ctx, SC_ERROR_NO_CARD_SUPPORT,
"Requested algorithm not supported");
@ -2427,7 +2606,8 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime,
}
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA
|| key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) {
/* Algorithm ID, see https://tools.ietf.org/html/rfc6637#section-5 */
*p = key_info->algorithm + 6;
p += 1;
@ -2721,6 +2901,9 @@ pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
&& card->type < SC_CARD_TYPE_OPENPGP_V3
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
if (key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
/* set Control Reference Template for key */
if (key_info->key_id == SC_OPENPGP_KEY_SIGN)

View File

@ -184,6 +184,8 @@ struct pgp_priv_data {
size_t max_cert_size;
size_t max_specialDO_size;
pgp_ec_curves_t *ec_curves;
sc_security_env_t sec_env;
};

View File

@ -305,6 +305,7 @@ struct piv_object {
};
/* Must be in order, and one per enumerated PIV_OBJ */
// clang-format off
static const struct piv_object piv_objects[] = {
{ PIV_OBJ_CCC, "Card Capability Container",
"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0},
@ -455,6 +456,7 @@ static const struct piv_object piv_objects[] = {
"2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY},
{ PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0}
};
// clang-format on
static struct sc_card_operations piv_ops;
@ -606,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) {
@ -1030,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 */
@ -1609,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;
@ -1751,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;
@ -1912,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;
@ -2077,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);
@ -2309,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 */
@ -2365,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);
}
@ -2392,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 ) {
@ -2422,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 */
@ -2732,7 +2740,7 @@ static int piv_find_discovery(sc_card_t *card)
/*
* During piv_match or piv_card_reader_lock_obtained,
* we use the discovery object to test if card present, and
* we use the discovery object to test if card present, and
* if PIV AID is active. So we can not use the cache
*/
@ -3039,8 +3047,8 @@ static int piv_match_card(sc_card_t *card)
return 0; /* can not handle the card */
}
/* its one we know, or we can test for it in piv_init */
/*
* We will call piv_match_card_continued here then
/*
* We will call piv_match_card_continued here then
* again in piv_init to avoid any issues with passing
* anything from piv_match_card
* to piv_init as had been done in the past
@ -3187,7 +3195,7 @@ static int piv_match_card_continued(sc_card_t *card)
* Try to avoid doing a select_aid and losing the login state on some cards.
* We may get interference on some cards by other drivers trying SELECT_AID before
* we get to see if PIV application is still active
* putting PIV driver first might help.
* putting PIV driver first might help.
* This may fail if the wrong AID is active.
* Discovery Object introduced in 800-73-3 so will return 0 if found and PIV applet active.
* Will fail with SC_ERROR_FILE_NOT_FOUND if 800-73-3 and no Discovery object.
@ -3264,10 +3272,10 @@ static int piv_match_card_continued(sc_card_t *card)
sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
if (i >= 0 && (priv->card_issues & CI_DISCOVERY_USELESS) == 0) {
/*
* We now know PIV AID is active, test DISCOVERY object again
* Some PIV don't support DISCOVERY and return
* SC_ERROR_INCORRECT_PARAMETERS. Any error
* including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
* We now know PIV AID is active, test DISCOVERY object again
* Some PIV don't support DISCOVERY and return
* SC_ERROR_INCORRECT_PARAMETERS. Any error
* including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
* to test for active AID.
*/
int i7e = piv_find_discovery(card);
@ -3350,18 +3358,18 @@ static int piv_init(sc_card_t *card)
}
/*
* Set card_issues flags based card->type and version numbers if available.
* Set card_issues flags based card->type and version numbers if available.
*
* YubiKey NEO, Yubikey 4 and other devices with PIV applets, have compliance
* issues with the NIST 800-73-3 specs. The OpenSC developers do not have
* access to all the different devices or versions of the devices.
* Vendor and user input is welcome on any compliance issues.
* access to all the different devices or versions of the devices.
* Vendor and user input is welcome on any compliance issues.
*
* For the Yubico devices The assumption is also made that if a bug is
* For the Yubico devices The assumption is also made that if a bug is
* fixed in a Yubico version that means it is fixed on both NEO and Yubikey 4.
*
* The flags CI_CANT_USE_GETDATA_FOR_STATE and CI_DISCOVERY_USELESS
* may be set earlier or later then in the following code.
* may be set earlier or later then in the following code.
*/
sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r);
@ -3463,7 +3471,7 @@ static int piv_init(sc_card_t *card)
* We want to process them now as this has information on what
* keys and certs the card has and how the pin might be used.
* If they fail, ignore it there are optional and introduced in
* NIST 800-73-3 and NIST 800-73-2 so some older cards may
* NIST 800-73-3 and NIST 800-73-2 so some older cards may
* not handle the request.
*/
piv_process_history(card);
@ -3626,7 +3634,7 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
/*
* If called to check on the login state for a context specific login
* return not logged in. Needed because of logic in e6f7373ef066
* return not logged in. Needed because of logic in e6f7373ef066
*/
if (data->pin_type == SC_AC_CONTEXT_SPECIFIC) {
data->pin1.logged_in = 0;
@ -3648,9 +3656,9 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
/*
* If this was for a CKU_CONTEXT_SPECFIC login, lock the card one more time.
* to avoid any interference from other applications.
* Sc_unlock will be called at a later time after the next card command
* that should be a crypto operation. If its not then it is a error by the
* to avoid any interference from other applications.
* Sc_unlock will be called at a later time after the next card command
* that should be a crypto operation. If its not then it is a error by the
* calling application.
*/
if (data->cmd == SC_PIN_CMD_VERIFY && data->pin_type == SC_AC_CONTEXT_SPECIFIC) {

View File

@ -366,6 +366,19 @@ static int rtecp_logout(sc_card_t *card)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
static int rtecp_set_security_env( struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
struct sc_security_env se_env;
if(!env)
return SC_ERROR_INVALID_ARGUMENTS;
se_env= *env;
se_env.flags &= ~SC_SEC_ENV_FILE_REF_PRESENT;
return iso_ops->set_security_env(card, &se_env, se_num);
}
static int rtecp_cipher(sc_card_t *card, const u8 *data, size_t data_len,
u8 *out, size_t out_len, int sign)
{
@ -824,7 +837,7 @@ struct sc_card_driver * sc_get_rtecp_driver(void)
rtecp_ops.verify = rtecp_verify;
rtecp_ops.logout = rtecp_logout;
/* restore_security_env */
/* set_security_env */
rtecp_ops.set_security_env = rtecp_set_security_env;
rtecp_ops.decipher = rtecp_decipher;
rtecp_ops.compute_signature = rtecp_compute_signature;
rtecp_ops.change_reference_data = rtecp_change_reference_data;

View File

@ -718,6 +718,7 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
data->pin2.offset = 5;
r = (*iso_ops->pin_cmd)(card, data, tries_left);
data->apdu = NULL;
}
LOG_TEST_RET(card->ctx, r, "Verification failed");

View File

@ -654,16 +654,18 @@ static int tcos_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_len,
LOG_TEST_RET(ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
size_t len = (apdu.resplen>outlen) ? outlen : apdu.resplen;
size_t len = (apdu.resplen > outlen) ? outlen : apdu.resplen;
unsigned int offset = 0;
if (tcos3 && (data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) && apdu.resp[0] == 0 && apdu.resp[1] == 2) {
if (tcos3 && (data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
&& len > 2 && apdu.resp[0] == 0 && apdu.resp[1] == 2) {
offset = 2;
while (offset < len && apdu.resp[offset] != 0)
++offset;
offset = (offset < len - 1) ? offset + 1 : 0;
}
memcpy(out, apdu.resp + offset, len-offset);
if (offset < len)
memcpy(out, apdu.resp + offset, len - offset);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, len - offset);
}
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));

View File

@ -805,6 +805,7 @@ static int westcos_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data *data,
} else {
r = SC_ERROR_NOT_SUPPORTED;
}
data->apdu = NULL;
}
if (r)
return (r);

View File

@ -163,7 +163,7 @@ static void sc_card_free(sc_card_t *card)
int i;
for (i=0; i<card->algorithm_count; i++) {
struct sc_algorithm_info *info = (card->algorithms + i);
if (info->algorithm == SC_ALGORITHM_EC) {
if (info->algorithm == SC_ALGORITHM_EC) {
struct sc_ec_parameters ep = info->u._ec.params;
free(ep.named_curve);
@ -1096,16 +1096,18 @@ int _sc_card_add_symmetric_alg(sc_card_t *card, unsigned int algorithm,
return _sc_card_add_algorithm(card, &info);
}
int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
static int
_sc_card_add_ec_alg_int(sc_card_t *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid)
struct sc_object_id *curve_oid,
int algorithm)
{
sc_algorithm_info_t info;
memset(&info, 0, sizeof(info));
sc_init_oid(&info.u._ec.params.id);
info.algorithm = SC_ALGORITHM_EC;
info.algorithm = algorithm;
info.key_length = key_length;
info.flags = flags;
@ -1116,6 +1118,32 @@ int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
return _sc_card_add_algorithm(card, &info);
}
int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid)
{
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
curve_oid, SC_ALGORITHM_EC);
}
int _sc_card_add_eddsa_alg(sc_card_t *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid)
{
/* For simplicity, share the ec union with the curve information */
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
curve_oid, SC_ALGORITHM_EDDSA);
}
int _sc_card_add_xeddsa_alg(sc_card_t *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid)
{
/* For simplicity, share the ec union with the curve information */
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
curve_oid, SC_ALGORITHM_XEDDSA);
}
sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
unsigned int algorithm, unsigned int key_length, void *param)
{
@ -1126,13 +1154,15 @@ sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
if (info->algorithm != algorithm)
continue;
if (param) {
if (info->algorithm == SC_ALGORITHM_EC ||
info->algorithm == SC_ALGORITHM_EDDSA ||
info->algorithm == SC_ALGORITHM_XEDDSA)
if (sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
return info;
}
if (info->key_length != key_length)
continue;
if (param) {
if (info->algorithm == SC_ALGORITHM_EC)
if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
continue;
}
return info;
}
return NULL;
@ -1144,6 +1174,18 @@ sc_algorithm_info_t * sc_card_find_ec_alg(sc_card_t *card,
return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length, curve_name);
}
sc_algorithm_info_t * sc_card_find_eddsa_alg(sc_card_t *card,
unsigned int key_length, struct sc_object_id *curve_name)
{
return sc_card_find_alg(card, SC_ALGORITHM_EDDSA, key_length, curve_name);
}
sc_algorithm_info_t * sc_card_find_xeddsa_alg(sc_card_t *card,
unsigned int key_length, struct sc_object_id *curve_name)
{
return sc_card_find_alg(card, SC_ALGORITHM_XEDDSA, key_length, curve_name);
}
int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
unsigned long flags, unsigned long exponent)
{
@ -1367,6 +1409,8 @@ scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char
void sc_invalidate_cache(struct sc_card *card)
{
if (card) {
sc_file_free(card->cache.current_ef);
sc_file_free(card->cache.current_df);
memset(&card->cache, 0, sizeof(card->cache));
card->cache.valid = 0;
}

View File

@ -974,6 +974,7 @@ typedef struct sc_cardctl_piv_genkey_info_st {
#define SC_OPENPGP_KEYALGO_RSA 0x01
#define SC_OPENPGP_KEYALGO_ECDH 0x12
#define SC_OPENPGP_KEYALGO_ECDSA 0x13
#define SC_OPENPGP_KEYALGO_EDDSA 0x16
#define SC_OPENPGP_KEYFORMAT_RSA_STD 0 /* See 4.3.3.6 Algorithm Attributes */
#define SC_OPENPGP_KEYFORMAT_RSA_STDN 1 /* OpenPGP card spec v2 */

View File

@ -205,6 +205,8 @@ enum {
SC_CARD_TYPE_IASECC_AMOS,
SC_CARD_TYPE_IASECC_MI,
SC_CARD_TYPE_IASECC_MI2,
SC_CARD_TYPE_IASECC_CPX,
SC_CARD_TYPE_IASECC_CPXCL,
/* SmartCard-HSM */
SC_CARD_TYPE_SC_HSM = 26000,
@ -266,6 +268,8 @@ enum {
SC_CARD_TYPE_IDPRIME_BASE = 37000,
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

@ -1008,7 +1008,16 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
}
#ifndef _WIN32
cache_dir = ".eid/cache";
#ifdef __APPLE__
cache_dir = getenv("Caches");
#else
cache_dir = getenv("XDG_CACHE_HOME");
#endif
if (cache_dir != NULL && cache_dir[0] != '\0') {
snprintf(buf, bufsize, "%s/%s", cache_dir, "opensc");
return SC_SUCCESS;
}
cache_dir = ".cache/opensc";
homedir = getenv("HOME");
#else
cache_dir = "eid-cache";
@ -1020,7 +1029,7 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
homedir = temp_path;
}
#endif
if (homedir == NULL)
if (homedir == NULL || homedir[0] == '\0')
return SC_ERROR_INTERNAL;
if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
return SC_ERROR_BUFFER_TOO_SMALL;

View File

@ -405,6 +405,7 @@ static u8 sn_ifd_pin_1[] = { 0xd0, 0x02, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x04 };
#define AC_RAIZ_COMPONENTES_ISSUER "/C=ES/O=DIRECCION GENERAL DE LA POLICIA/OU=DNIE/OU=AC RAIZ COMPONENTES/CN=000000006573524449600006"
#define AC_RAIZ_COMPONENTES_2_NEW_IDX 1
#define AC_RAIZ_COMPONENTES_2_ISSUER "/C=ES/O=DIRECCION GENERAL DE LA POLICIA/OU=DNIE/organizationIdentifier=VATES-S2816015H/OU=AC RAIZ COMPONENTES 2/CN=000000006573524449620018"
#define AC_RAIZ_COMPONENTES_2_ISSUER_OU "/OU=AC RAIZ COMPONENTES 2/"
/**
* The DNIe secure channel uses some static configuration.
@ -649,7 +650,7 @@ static int dnie_set_channel_data(sc_card_t * card, X509 * icc_intermediate_ca_ce
sc_log(card->ctx, "icc_intermediate_ca_cert issuer %s", buf);
}
if (buf && strcmp(buf, AC_RAIZ_COMPONENTES_2_ISSUER) == 0) {
if (buf && strstr(buf, AC_RAIZ_COMPONENTES_2_ISSUER_OU)) {
sc_log(card->ctx, "assigning new data channel configuration");
priv_data->channel_data = &channel_data[AC_RAIZ_COMPONENTES_2_NEW_IDX];
} else {

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

@ -39,7 +39,11 @@ static const struct app_entry apps[] = {
{ (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" },
{ (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" },
{ (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" },
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"}
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"},
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\x80\x25\x00\x00\x01\xFF\x00\x10", 13, "CPx IAS"},
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\x80\x25\x00\x00\x01\xFF\x00\x20", 13, "CPx IAS CL"},
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xD2\x50\x45\x43\x43\x2D\x65\x49\x44", 14, "ECC eID"},
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xD2\x50\x47\x65\x6E\x65\x72\x69\x63", 14, "ECC Generic PKI"},
};
static const struct sc_asn1_entry c_asn1_dirrecord[] = {

View File

@ -143,6 +143,7 @@ int sc_parse_ef_atr(struct sc_card *card)
int rv;
unsigned char *buf = NULL;
size_t size;
size_t off = 0;
LOG_FUNC_CALLED(ctx);
@ -162,8 +163,16 @@ int sc_parse_ef_atr(struct sc_card *card)
}
rv = sc_read_binary(card, 0, buf, size, 0);
LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file");
rv = sc_parse_ef_atr_content(card, buf, rv);
/* Workaround: Some cards seem to have a buggy storage of the EF.ATR */
if ((card->type == SC_CARD_TYPE_IASECC_CPX) ||
(card->type == SC_CARD_TYPE_IASECC_CPXCL)) {
/* Let's keep the first byte */
if ((rv > 1) &&
(buf[0] == ISO7816_II_CATEGORY_TLV))
off++;
}
rv = sc_parse_ef_atr_content(card, buf + off, rv - off);
LOG_TEST_GOTO_ERR(ctx, rv, "EF(ATR) parse error");
rv = SC_SUCCESS;

View File

@ -133,4 +133,5 @@ struct iasecc_private_data {
struct iasecc_se_info *se_info;
};
#endif

View File

@ -93,6 +93,7 @@ typedef unsigned __int8 uint8_t;
#define SCARD_S_SUCCESS 0x00000000 /**< No error was encountered. */
#define SCARD_E_CANCELLED 0x80100002 /**< The action was cancelled by an SCardCancel request. */
#define SCARD_E_INVALID_HANDLE 0x80100003 /**< The supplied handle was invalid. */
#define SCARD_E_UNKNOWN_READER 0x80100009 /**< The specified reader name is not recognized. */
#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout value has expired. */
#define SCARD_E_SHARING_VIOLATION 0x8010000B /**< The smart card cannot be accessed because of other connections outstanding. */
#define SCARD_E_NO_SMARTCARD 0x8010000C /**< The operation requires a smart card, but no smart card is currently in the device. */

View File

@ -153,6 +153,12 @@ int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid);
int _sc_card_add_eddsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid);
int _sc_card_add_xeddsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, unsigned long ext_flags,
struct sc_object_id *curve_oid);
/********************************************************************/
/* pkcs1 padding/encoding functions */

View File

@ -172,6 +172,9 @@ iso7816_read_record(struct sc_card *card,
struct sc_apdu apdu;
int r;
if (rec_nr > 0xFF)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
apdu.le = count;
apdu.resplen = count;
@ -328,6 +331,8 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
size_t length;
int size;
file->status = SC_FILE_STATUS_UNKNOWN;
for (p = buf, length = buflen, end = buf + buflen;
p < end;
p += length, length = end - p) {
@ -448,12 +453,48 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
case 0x8A:
if (length == 1) {
if (p[0] == 0x01)
file->status = SC_FILE_STATUS_CREATION;
else if (p[0] == 0x07 || p[0] == 0x05)
file->status = SC_FILE_STATUS_ACTIVATED;
else if (p[0] == 0x06 || p[0] == 0x04)
file->status = SC_FILE_STATUS_INVALIDATED;
switch (p[0]) {
case 0:
file->status =SC_FILE_STATUS_NO_INFO;
break;
case 1:
file->status = SC_FILE_STATUS_CREATION;
break;
case 3:
file->status = SC_FILE_STATUS_INITIALISATION;
break;
case 4:
case 6:
file->status = SC_FILE_STATUS_INVALIDATED;
break;
case 5:
case 7:
file->status = SC_FILE_STATUS_ACTIVATED;
break;
case 12:
case 13:
case 14:
case 15:
file->status = SC_FILE_STATUS_TERMINATION;
break;
case 2:
file->status = SC_FILE_STATUS_RFU_2;
break;
case 8:
file->status = SC_FILE_STATUS_RFU_8;
break;
case 9:
file->status = SC_FILE_STATUS_RFU_9;
break;
case 10:
file->status = SC_FILE_STATUS_RFU_10;
break;
case 11:
file->status = SC_FILE_STATUS_RFU_11;
break;
default:
file->status = SC_FILE_STATUS_PROPRIETARY;
}
}
break;

View File

@ -114,7 +114,6 @@ sc_bytes2apdu
sc_format_asn1_entry
sc_format_oid
sc_init_oid
sc_compare_oid
sc_valid_oid
sc_format_path
sc_free_apps
@ -150,8 +149,6 @@ sc_pkcs15_cache_file
sc_pkcs15_card_clear
sc_pkcs15_card_free
sc_pkcs15_card_new
sc_pkcs15_tokeninfo_new
sc_pkcs15_free_tokeninfo
sc_pkcs15_change_pin
sc_pkcs15_compare_id
sc_pkcs15_compute_signature
@ -178,6 +175,7 @@ sc_pkcs15_encode_pubkey
sc_pkcs15_encode_pubkey_dsa
sc_pkcs15_encode_pubkey_rsa
sc_pkcs15_encode_pubkey_ec
sc_pkcs15_encode_pubkey_eddsa
sc_pkcs15_encode_pubkey_gostr3410
sc_pkcs15_encode_pubkey_as_spki
sc_pkcs15_encode_pukdf_entry

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

@ -78,6 +78,8 @@ extern "C" {
#define SC_ALGORITHM_DSA 1
#define SC_ALGORITHM_EC 2
#define SC_ALGORITHM_GOSTR3410 3
#define SC_ALGORITHM_EDDSA 4
#define SC_ALGORITHM_XEDDSA 5
/* Symmetric algorithms */
#define SC_ALGORITHM_DES 64
@ -189,6 +191,10 @@ extern "C" {
SC_ALGORITHM_ECDSA_HASH_SHA384 | \
SC_ALGORITHM_ECDSA_HASH_SHA512)
/* EdDSA algorithms */
#define SC_ALGORITHM_EDDSA_RAW 0x00400000
#define SC_ALGORITHM_XEDDSA_RAW 0x00800000
/* define mask of all algorithms that can do raw */
#define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | \
SC_ALGORITHM_GOSTR3410_RAW | \
@ -1555,6 +1561,10 @@ struct sc_algorithm_info * sc_card_find_rsa_alg(struct sc_card *card,
unsigned int key_length);
struct sc_algorithm_info * sc_card_find_ec_alg(struct sc_card *card,
unsigned int field_length, struct sc_object_id *curve_oid);
struct sc_algorithm_info * sc_card_find_eddsa_alg(struct sc_card *card,
unsigned int field_length, struct sc_object_id *curve_oid);
struct sc_algorithm_info * sc_card_find_xeddsa_alg(struct sc_card *card,
unsigned int field_length, struct sc_object_id *curve_oid);
struct sc_algorithm_info * sc_card_find_gostr3410_alg(struct sc_card *card,
unsigned int key_length);
struct sc_algorithm_info * sc_card_find_alg(sc_card_t *card,

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

@ -491,6 +491,8 @@ int sc_get_encoding_flags(sc_context_t *ctx,
} else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) &&
(iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
*sflags |= iflags & SC_ALGORITHM_MGF1_HASHES;
*pflags = iflags & ~(iflags & (SC_ALGORITHM_MGF1_HASHES | SC_ALGORITHM_RSA_PAD_PSS));
} else if ((caps & SC_ALGORITHM_RSA_RAW) &&
(iflags & SC_ALGORITHM_RSA_PAD_PKCS1

View File

@ -412,7 +412,6 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
asn1_encode_pbes2_params,
asn1_free_pbes2_params },
#endif
#ifdef SC_ALGORITHM_EC
{ SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1, -1}},
asn1_decode_ec_params,
@ -448,6 +447,16 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
asn1_decode_ec_params,
asn1_encode_ec_params,
asn1_free_ec_params },
#endif
#ifdef SC_ALGORITHM_EDDSA
/* aka Ed25519 */
/* 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 */
/* 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 }
};
@ -545,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

@ -425,7 +425,8 @@ coolkey_get_public_key_from_certificate(sc_pkcs15_card_t *p15card, sc_cardctl_co
sc_pkcs15_pubkey_t *key = NULL;
int r;
cert_info.value.value = NULL;
memset(&cert_info, 0, sizeof(cert_info));
r = coolkey_get_certificate(p15card->card, obj, &cert_info.value);
if (r < 0) {
goto fail;

View File

@ -34,6 +34,7 @@
#include "internal.h"
#include "pkcs15.h"
#include "../pkcs15init/pkcs15-iasecc.h"
#include "iasecc.h"
#include "aux-data.h"
@ -103,6 +104,38 @@ _iasecc_md_update_keyinfo(struct sc_pkcs15_card *p15card, struct sc_pkcs15_objec
}
/*
* CPx cards have an undocumented issue: they lack of
* Algorithm's reference into their PKCS's ASN1 encoding.
*/
static int
_iasecc_cpx_fixup_prkdf(struct sc_pkcs15_card *p15card)
{
struct sc_context * const ctx = p15card->card->ctx;
struct sc_pkcs15_object *pkobjs[32];
int ii, count;
int rv = SC_SUCCESS;
LOG_FUNC_CALLED(ctx);
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, pkobjs, sizeof(pkobjs)/sizeof(pkobjs[0]));
LOG_TEST_RET(ctx, rv, "Cannot get PRKEY objects list");
count = rv;
for(ii=0; ii<count; ii++) {
rv = iasecc_pkcs15_encode_supported_algos(p15card, pkobjs[ii]);
LOG_TEST_RET(ctx, rv, "Cannot fix suported_algos");
}
LOG_FUNC_RETURN(ctx, rv);
}
/*
* It is the entry point for 2 models of cards that need some hot patching
* - Gemalto cards
* - CPx: fixup algo_refs from the prkey
*/
static int
_iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
{
@ -122,14 +155,29 @@ _iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
rv = sc_pkcs15_parse_df(p15card, df);
LOG_TEST_RET(ctx, rv, "DF parse error");
if (p15card->card->type != SC_CARD_TYPE_IASECC_GEMALTO)
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
switch(p15card->card->type) {
/* enumerate the IASECC cards that need a fixup of the keyInfo */
case SC_CARD_TYPE_IASECC_GEMALTO:
case SC_CARD_TYPE_IASECC_CPX:
case SC_CARD_TYPE_IASECC_CPXCL:
sc_log(ctx, "Warning: the %d card has an invalid DF, hot patch to be applied",
p15card->card->type);
break;
default:
sc_log(ctx, "the %d card has a proper DF, no need for a hot patch",
p15card->card->type);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
break;
}
if (df->type != SC_PKCS15_PRKDF)
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
sc_log(ctx, "parse of SC_PKCS15_PRKDF");
rv = _iasecc_cpx_fixup_prkdf(p15card);
LOG_TEST_RET(ctx, rv, "Cannot fixup PrKDF");
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, sizeof(dobjs)/sizeof(dobjs[0]));
LOG_TEST_RET(ctx, rv, "Cannot get DATA objects list");

View File

@ -98,6 +98,13 @@ 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 ||
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;
}
sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label);
strncpy(pin_obj.label, pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1);
pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;

View File

@ -211,6 +211,7 @@ sc_oberthur_get_certificate_authority(struct sc_pkcs15_der *der, int *out_author
BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE);
x = d2i_X509_bio(bio, 0);
free(buf_mem.data);
BIO_free(bio);
if (!x)
return SC_ERROR_INVALID_DATA;
@ -304,7 +305,7 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
int ii;
int ii, nobjs;
if (acl == NULL) {
sc_file_free(file);
@ -313,18 +314,19 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
}
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
if (rv != SC_SUCCESS) {
nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
if (nobjs < 1) {
sc_file_free(file);
free(*out);
*out = NULL;
LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error");
LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND,
"Cannot read oberthur file: get AUTH objects error");
}
for (ii=0; ii<rv; ii++) {
for (ii = 0; ii < nobjs; ii++) {
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) {
pin_obj = objs[ii];
break;
@ -574,7 +576,7 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_pubkey_info key_info;
struct sc_pkcs15_object key_obj;
char ch_tmp[0x100];
unsigned char *info_blob;
unsigned char *info_blob = NULL;
size_t len, info_len, offs;
unsigned flags;
int rv;
@ -591,8 +593,10 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
/* Flags */
offs = 2;
if (offs > info_len)
if (offs > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'tag'");
}
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
key_info.usage = sc_oberthur_decode_usage(flags);
if (flags & OBERTHUR_ATTR_MODIFIABLE)
@ -600,10 +604,15 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
sc_log(ctx, "Public key key-usage:%04X", key_info.usage);
/* Label */
if (offs + 2 > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'Label'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (len) {
if (offs + 2 + len > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'Label' length");
} else if (len) {
if (len > sizeof(key_obj.label) - 1)
len = sizeof(key_obj.label) - 1;
memcpy(key_obj.label, info_blob + offs + 2, len);
@ -611,14 +620,22 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
offs += 2 + len;
/* ID */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'ID'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (!len || len > sizeof(key_info.id.value))
if (len == 0
|| len > sizeof(key_info.id.value)
|| offs + 2 + len > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'ID' length");
}
memcpy(key_info.id.value, info_blob + offs + 2, len);
key_info.id.len = len;
free(info_blob);
/* Ignore Start/End dates */
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
@ -648,7 +665,7 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_cert_info cinfo;
struct sc_pkcs15_object cobj;
unsigned char *info_blob, *cert_blob;
unsigned char *info_blob = NULL, *cert_blob = NULL;
size_t info_len, cert_len, len, offs;
unsigned flags;
int rv;
@ -664,16 +681,23 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
LOG_TEST_RET(ctx, rv, "Failed to add certificate: read oberthur file error");
if (info_len < 2)
if (info_len < 2) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
}
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
offs = 2;
/* Label */
if (offs + 2 > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'CN'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (len) {
if (len + offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
} else if (len) {
if (len > sizeof(cobj.label) - 1)
len = sizeof(cobj.label) - 1;
memcpy(cobj.label, info_blob + offs + 2, len);
@ -681,14 +705,23 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
offs += 2 + len;
/* ID */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'ID'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (len > sizeof(cinfo.id.value))
if (len + offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
} else if (len > sizeof(cinfo.id.value)) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add certificate: invalid 'ID' length");
}
memcpy(cinfo.id.value, info_blob + offs + 2, len);
cinfo.id.len = len;
free(info_blob);
/* Ignore subject, issuer and serial */
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
@ -700,7 +733,10 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
cinfo.value.len = cert_len;
rv = sc_oberthur_get_certificate_authority(&cinfo.value, &cinfo.authority);
LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
if (rv != SC_SUCCESS) {
free(cinfo.value.value);
LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
}
if (flags & OBERTHUR_ATTR_MODIFIABLE)
cobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
@ -773,15 +809,23 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
LOG_TEST_RET(ctx, rv, "Failed to add private key: read oberthur file error");
if (info_len < 2)
if (info_len < 2) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'tag'");
}
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
offs = 2;
/* CN */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'CN'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (len + offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
}
if (len && !strlen(kobj.label)) {
if (len > sizeof(kobj.label) - 1)
len = sizeof(kobj.label) - 1;
@ -790,13 +834,21 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
offs += 2 + len;
/* ID */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'ID'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (!len)
if (!len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: zero length ID");
else if (len > sizeof(kinfo.id.value))
} else if (len + offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
} else if (len > sizeof(kinfo.id.value)) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add private key: invalid ID length");
}
memcpy(kinfo.id.value, info_blob + offs + 2, len);
kinfo.id.len = len;
offs += 2 + len;
@ -805,19 +857,28 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
offs += 16;
/* Subject encoded in ASN1 */
if (offs > info_len)
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'subject'");
}
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (len) {
if (len + offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'subject' length");
} else if (len) {
kinfo.subject.value = malloc(len);
if (!kinfo.subject.value)
if (!kinfo.subject.value) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Failed to add private key: memory allocation error");
}
kinfo.subject.len = len;
memcpy(kinfo.subject.value, info_blob + offs + 2, len);
}
/* Modulus and exponent are ignored */
free(info_blob);
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id);
sc_format_path(ch_tmp, &kinfo.path);
sc_log(ctx, "Private key info path %s", ch_tmp);
@ -865,37 +926,59 @@ sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
LOG_TEST_RET(ctx, rv, "Failed to add data: read oberthur file error");
if (info_len < 2)
if (info_len < 2) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
}
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
offs = 2;
/* Label */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'label'");
}
label = info_blob + offs + 2;
label_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (offs + 2 + label_len > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'label' received");
}
if (label_len > sizeof(dobj.label) - 1)
label_len = sizeof(dobj.label) - 1;
offs += 2 + *(info_blob + offs + 1);
/* Application */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'application'");
}
app = info_blob + offs + 2;
app_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (offs + 2 + app_len > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'application' received");
}
if (app_len > sizeof(dinfo.app_label) - 1)
app_len = sizeof(dinfo.app_label) - 1;
offs += 2 + app_len;
/* OID encode like DER(ASN.1(oid)) */
if (offs > info_len)
if (offs + 2 > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'OID'");
}
oid_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
if (oid_len) {
if (offs + 2 + oid_len > info_len) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'oid' received");
}
if (oid_len > 2) {
oid = info_blob + offs + 2;
if (*oid != 0x06 || (*(oid + 1) != oid_len - 2))
if (*oid != 0x06 || (*(oid + 1) != oid_len - 2)) {
free(info_blob);
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: invalid 'OID' format");
}
oid += 2;
oid_len -= 2;
}
@ -922,6 +1005,7 @@ sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
rv = sc_pkcs15emu_add_data_object(p15card, &dobj, &dinfo);
free(info_blob);
LOG_FUNC_RETURN(p15card->card->ctx, rv);
}

View File

@ -70,6 +70,7 @@ static const pgp_pin_cfg_t pin_cfg_v2[3] = {
{ "Admin PIN", 0x03, PGP_ADMIN_PIN_FLAGS, 8, 2 }
};
static struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}};
#define PGP_SIG_PRKEY_USAGE (SC_PKCS15_PRKEY_USAGE_SIGN \
| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER \
@ -169,6 +170,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
sc_path_t path;
sc_file_t *file = NULL;
LOG_FUNC_CALLED(ctx);
set_string(&p15card->tokeninfo->label, "OpenPGP card");
set_string(&p15card->tokeninfo->manufacturer_id, "OpenPGP project");
@ -203,6 +206,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
* 01-03: max length of pins 1-3
* 04-07: tries left for pins 1-3
*/
sc_log(ctx, "Reading PW status bytes");
if ((r = read_file(card, "006E:0073:00C4", c4data, sizeof(c4data))) < 0)
goto failed;
if (r != 7) {
@ -251,19 +255,22 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
* 20-39: finger print for ENC key
* 40-59: finger print for AUT key
*/
sc_log(ctx, "Reading Fingerprints");
if ((r = read_file(card, "006E:0073:00C5", c5data, sizeof(c5data))) < 0)
goto failed;
if (r < 60) {
sc_log(ctx,
sc_log(ctx,
"finger print bytes have unexpected length (expected 60, got %d)\n", r);
return SC_ERROR_OBJECT_NOT_VALID;
}
sc_log(ctx, "Adding private keys");
/* XXX: check if "halfkeys" can be stored with gpg2. If not, add key pairs in one loop */
for (i = 0; i < 3; i++) {
sc_pkcs15_prkey_info_t prkey_info;
sc_pkcs15_object_t prkey_obj;
u8 cxdata[12];
int cxdata_len = sizeof(cxdata);
char path_template[] = "006E:0073:00Cx";
int j;
@ -272,7 +279,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
memset(&cxdata, 0, sizeof(cxdata));
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
if ((cxdata_len = read_file(card, path_template, cxdata, sizeof(cxdata))) < 1)
goto failed;
/* check validity using finger prints */
@ -283,6 +290,10 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
if (j >= 0 && cxdata[0] != 0) {
struct sc_object_id oid;
struct sc_algorithm_info * algorithm_info; /* no need to free */
algorithm_info = NULL;
prkey_info.id.len = 1;
prkey_info.id.value[0] = i + 1;
prkey_info.usage = key_cfg[i].prkey_usage;
@ -294,24 +305,101 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
prkey_obj.auth_id.len = 1;
prkey_obj.auth_id.value[0] = key_cfg[i].prkey_pin;
if (cxdata[0] == SC_OPENPGP_KEYALGO_RSA && r >= 3) {
prkey_info.modulus_length = bebytes2ushort(cxdata + 1);
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
/* need to get size from algorithms using oid */
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");
}
}
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH
|| cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA) {
switch (cxdata[0]) {
case SC_OPENPGP_KEYALGO_ECDH:
if (sc_compare_oid(&oid, &curve25519_oid)) {
if ((algorithm_info = sc_card_find_xeddsa_alg(card, 0, &oid)))
prkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
}
/* Fall through */
case SC_OPENPGP_KEYALGO_ECDSA:
if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid)))
prkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
case SC_OPENPGP_KEYALGO_EDDSA:
if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid)))
prkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
}
switch (cxdata[0]) {
case SC_OPENPGP_KEYALGO_EDDSA:
/* Filter out invalid usage: EdDSA does not support anything but sign */
prkey_info.usage &= PGP_SIG_PRKEY_USAGE;
r = sc_pkcs15emu_add_eddsa_prkey(p15card, &prkey_obj, &prkey_info);
break;
case SC_OPENPGP_KEYALGO_ECDH:
/* This can result in either ECDSA key or EC_MONTGOMERY
* so we need to check OID */
if (sc_compare_oid(&oid, &curve25519_oid)) {
/* This can do only DERIVE */
prkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
r = sc_pkcs15emu_add_xeddsa_prkey(p15card, &prkey_obj, &prkey_info);
break;
}
prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
prkey_info.usage &= ~PGP_ENC_PRKEY_USAGE;
r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info);
break;
case SC_OPENPGP_KEYALGO_ECDSA:
prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN;
r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info);
break;
case SC_OPENPGP_KEYALGO_RSA:
if (cxdata_len >= 3) {
prkey_info.modulus_length = bebytes2ushort(cxdata + 1);
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
break;
}
/* Fallthrough */
default:
sc_log(ctx, "Invalid algorithm identifier %x (length = %d)",
cxdata[0], r);
}
if (r < 0)
return SC_ERROR_INTERNAL;
}
}
sc_log(ctx, "Adding public keys");
/* Add public keys */
for (i = 0; i < 3; i++) {
sc_pkcs15_pubkey_info_t pubkey_info;
sc_pkcs15_object_t pubkey_obj;
u8 cxdata[10];
u8 cxdata[12];
int cxdata_len = sizeof(cxdata);
char path_template[] = "006E:0073:00Cx";
int j;
@ -320,7 +408,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
memset(&cxdata, 0, sizeof(cxdata));
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
if ((cxdata_len = read_file(card, path_template, cxdata, sizeof(cxdata))) < 1)
goto failed;
/* check validity using finger prints */
@ -331,6 +419,10 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
if (j >= 0 && cxdata[0] != 0) {
struct sc_object_id oid;
struct sc_algorithm_info * algorithm_info; /* no need to free */
algorithm_info = NULL;
pubkey_info.id.len = 1;
pubkey_info.id.value[0] = i + 1;
pubkey_info.usage = key_cfg[i].pubkey_usage;
@ -339,13 +431,83 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
strlcpy(pubkey_obj.label, key_cfg[i].label, sizeof(pubkey_obj.label));
pubkey_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
if (cxdata[0] == SC_OPENPGP_KEYALGO_RSA && r >= 3) {
pubkey_info.modulus_length = bebytes2ushort(cxdata + 1);
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
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");
}
}
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH
|| cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA) {
switch (cxdata[0]) {
case SC_OPENPGP_KEYALGO_ECDH:
if (sc_compare_oid(&oid, &curve25519_oid)) {
if ((algorithm_info = sc_card_find_xeddsa_alg(card, 0, &oid)))
pubkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
}
/* Fall through */
case SC_OPENPGP_KEYALGO_ECDSA:
if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid)))
pubkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
case SC_OPENPGP_KEYALGO_EDDSA:
if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid)))
pubkey_info.field_length = algorithm_info->key_length;
else {
sc_log(ctx, "algorithm not found");
continue;
}
break;
}
switch (cxdata[0]) {
case SC_OPENPGP_KEYALGO_EDDSA:
/* assuming Ed25519 as it is the only supported now */
/* Filter out invalid usage: ED does not support anything but sign */
pubkey_info.usage &= PGP_SIG_PUBKEY_USAGE;
r = sc_pkcs15emu_add_eddsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
break;
case SC_OPENPGP_KEYALGO_ECDH:
/* This can result in either ECDSA key or EC_MONTGOMERY
* so we need to check OID */
if (sc_compare_oid(&oid, &curve25519_oid)) {
/* XXX What can this key do? */
pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
r = sc_pkcs15emu_add_xeddsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
break;
}
pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
break;
case SC_OPENPGP_KEYALGO_ECDSA:
pubkey_info.usage = PGP_SIG_PUBKEY_USAGE;
r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
break;
case SC_OPENPGP_KEYALGO_RSA:
if (cxdata_len >= 3) {
pubkey_info.modulus_length = bebytes2ushort(cxdata + 1);
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
break;
}
/* Fall through */
default:
sc_log(ctx, "Invalid algorithm identifier %x (length = %d)",
cxdata[0], r);
}
if (r < 0)
@ -388,13 +550,13 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
failed:
if (r < 0) {
sc_log(card->ctx,
sc_log(card->ctx,
"Failed to initialize OpenPGP emulation: %s\n",
sc_strerror(r));
}
sc_file_free(file);
return r;
LOG_FUNC_RETURN(ctx, r);
}
static int

View File

@ -2,10 +2,10 @@
* partial PKCS15 emulation for PIV-II cards
* only minimal use of the authentication cert and key
*
* Copyright (C) 2005,2006,2007,2008,2009,2010
* Douglas E. Engert <deengert@anl.gov>
* Copyright (C) 2005,2006,2007,2008,2009,2010
* Douglas E. Engert <deengert@anl.gov>
* 2004, Nils Larsch <larsch@trustcenter.de>
* Copyright (C) 2006, Identity Alliance,
* Copyright (C) 2006, Identity Alliance,
* Thomas Harning <thomas.harning@identityalliance.com>
* Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
*
@ -66,11 +66,11 @@ typedef struct pdata_st {
unsigned int maxlen;
unsigned int minlen;
unsigned int storedlen;
int flags;
int flags;
int tries_left;
const unsigned char pad_char;
int obj_flags;
} pindata;
} pindata;
typedef struct pubdata_st {
const char *id;
@ -93,7 +93,7 @@ typedef struct prdata_st {
int ref;
const char *auth_id;
int obj_flags;
int user_consent;
int user_consent;
} prdata;
typedef struct common_key_info_st {
@ -116,11 +116,11 @@ typedef struct common_key_info_st {
* is used, or the GUID is used as a serial number.
* We need to return a GUID like value for each object
* But this needs to be some what unique.
* So we will use two different methods, depending
* So we will use two different methods, depending
* on the size of the serial number.
* If it is 25 bytes, then it was from a FASCN. If 16 bytes
* its from a GUID.
* If neither, we will uase the default method.
* If neither, we will uase the default method.
*/
static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj,
@ -152,13 +152,13 @@ static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_o
/* It is from a FASCN, and we need to shorten it but keep
* as much uniqueness as possible.
* FASC-N is stored like a ISO 7811 Magnetic Strip Card
* FASC-N is stored like a ISO 7811 Magnetic Strip Card
* Using the ANSI/ISO BCD Data Format
* 4 data bit + 1 parity bit (odd) least significant bit first.
* It starts with the Start Sentinel 0x0b ";"
* 4 data bit + 1 parity bit (odd) least significant bit first.
* It starts with the Start Sentinel 0x0b ";"
* Fields are separated by 0x0d "="
* Ends with End Sentinel 0x0f "?"
* Its 39 characters + the LRC
* Its 39 characters + the LRC
* http://www.dataip.co.uk/Reference/MagneticCardBCD.php
* 0x0a, 0x0c, 0x0e are some type of control
* the FASCN has a lot of extra bits, with only 32 digits.
@ -194,14 +194,14 @@ static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_o
}
/* overwrite two insignificant digits in middle with id */
memcpy(guid_bin + 7, id.value, id.len);
memcpy(guid_bin + 7, id.value, id.len);
tlen = 16;
}
else if (id.len == 1 && serialnr.len == 16) {
/* its from a GUID, we will overwrite the
/* its from a GUID, we will overwrite the
* first byte with id.value, as this preserves most
* of the uniqueness.
*/
* of the uniqueness.
*/
memcpy(guid_bin, id.value, id.len);
memcpy(guid_bin + id.len, serialnr.value + 1, serialnr.len - 1);
@ -247,8 +247,9 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
/* The cert objects will return all the data */
/* Note: pkcs11 objects do not have CK_ID values */
// clang-format off
static const objdata objects[] = {
{"01", "Card Capability Container",
{"01", "Card Capability Container",
"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
{"02", "Card Holder Unique Identifier",
"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
@ -260,11 +261,11 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
"2.16.840.1.101.3.7.2.96.16", "01", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
{"06", "Printed Information",
"2.16.840.1.101.3.7.2.48.1", "01", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
{"07", "Cardholder Facial Image",
{"07", "Cardholder Facial Image",
"2.16.840.1.101.3.7.2.96.48", "01", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
{"08", "X.509 Certificate for Digital Signature",
"2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0},
{"09", "X.509 Certificate for Key Management",
{"09", "X.509 Certificate for Key Management",
"2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
{"10","X.509 Certificate for Card Authentication",
"2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
@ -277,50 +278,51 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{"14", "Cardholder Iris Image",
"2.16.840.1.101.3.7.2.16.21", NULL, "1015", SC_PKCS15_CO_FLAG_PRIVATE},
{"15", "Retired X.509 Certificate for Key Management 1",
{"15", "Retired X.509 Certificate for Key Management 1",
"2.16.840.1.101.3.7.2.16.1", NULL, "1001", 0},
{"16", "Retired X.509 Certificate for Key Management 2",
{"16", "Retired X.509 Certificate for Key Management 2",
"2.16.840.1.101.3.7.2.16.2", NULL, "1002", 0},
{"17", "Retired X.509 Certificate for Key Management 3",
{"17", "Retired X.509 Certificate for Key Management 3",
"2.16.840.1.101.3.7.2.16.3", NULL, "1003", 0},
{"18", "Retired X.509 Certificate for Key Management 4",
{"18", "Retired X.509 Certificate for Key Management 4",
"2.16.840.1.101.3.7.2.16.4", NULL, "1004", 0},
{"19", "Retired X.509 Certificate for Key Management 5",
{"19", "Retired X.509 Certificate for Key Management 5",
"2.16.840.1.101.3.7.2.16.5", NULL, "1005", 0},
{"20", "Retired X.509 Certificate for Key Management 6",
{"20", "Retired X.509 Certificate for Key Management 6",
"2.16.840.1.101.3.7.2.16.6", NULL, "1006", 0},
{"21", "Retired X.509 Certificate for Key Management 7",
{"21", "Retired X.509 Certificate for Key Management 7",
"2.16.840.1.101.3.7.2.16.7", NULL, "1007", 0},
{"22", "Retired X.509 Certificate for Key Management 8",
{"22", "Retired X.509 Certificate for Key Management 8",
"2.16.840.1.101.3.7.2.16.8", NULL, "1008", 0},
{"23", "Retired X.509 Certificate for Key Management 9",
{"23", "Retired X.509 Certificate for Key Management 9",
"2.16.840.1.101.3.7.2.16.9", NULL, "1009", 0},
{"24", "Retired X.509 Certificate for Key Management 10",
{"24", "Retired X.509 Certificate for Key Management 10",
"2.16.840.1.101.3.7.2.16.10", NULL, "100A", 0},
{"25", "Retired X.509 Certificate for Key Management 11",
{"25", "Retired X.509 Certificate for Key Management 11",
"2.16.840.1.101.3.7.2.16.11", NULL, "100B", 0},
{"26", "Retired X.509 Certificate for Key Management 12",
{"26", "Retired X.509 Certificate for Key Management 12",
"2.16.840.1.101.3.7.2.16.12", NULL, "100C", 0},
{"27", "Retired X.509 Certificate for Key Management 13",
{"27", "Retired X.509 Certificate for Key Management 13",
"2.16.840.1.101.3.7.2.16.13", NULL, "100D", 0},
{"28", "Retired X.509 Certificate for Key Management 14",
{"28", "Retired X.509 Certificate for Key Management 14",
"2.16.840.1.101.3.7.2.16.14", NULL, "100E", 0},
{"29", "Retired X.509 Certificate for Key Management 15",
{"29", "Retired X.509 Certificate for Key Management 15",
"2.16.840.1.101.3.7.2.16.15", NULL, "100F", 0},
{"30", "Retired X.509 Certificate for Key Management 16",
{"30", "Retired X.509 Certificate for Key Management 16",
"2.16.840.1.101.3.7.2.16.16", NULL, "1010", 0},
{"31", "Retired X.509 Certificate for Key Management 17",
{"31", "Retired X.509 Certificate for Key Management 17",
"2.16.840.1.101.3.7.2.16.17", NULL, "1011", 0},
{"32", "Retired X.509 Certificate for Key Management 18",
{"32", "Retired X.509 Certificate for Key Management 18",
"2.16.840.1.101.3.7.2.16.18", NULL, "1012", 0},
{"33", "Retired X.509 Certificate for Key Management 19",
{"33", "Retired X.509 Certificate for Key Management 19",
"2.16.840.1.101.3.7.2.16.19", NULL, "1013", 0},
{"34", "Retired X.509 Certificate for Key Management 20",
{"34", "Retired X.509 Certificate for Key Management 20",
"2.16.840.1.101.3.7.2.16.20", NULL, "1014", 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
/*
* NIST 800-73-1 lifted the restriction on
};
// clang-format on
/*
* NIST 800-73-1 lifted the restriction on
* requiring pin protected certs. Thus the default is to
* not require this.
*/
@ -329,6 +331,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
#define PIV_NUM_CERTS_AND_KEYS 24
// clang-format off
static const cdata certs[PIV_NUM_CERTS_AND_KEYS] = {
{"01", "Certificate for PIV Authentication", "0101cece", 0, 0},
{"02", "Certificate for Digital Signature", "0100cece", 0, 0},
@ -355,47 +358,50 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{"23", "Retired Certificate for Key Management 19", "1013cece", 0, 0},
{"24", "Retired Certificate for Key Management 20", "1014cece", 0, 0}
};
// clang-format on
// clang-format off
static const pindata pins[] = {
{ "01", "PIN", "", 0x80,
/* label, flag and ref will change if using global pin */
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
8, 4, 8,
8, 4, 8,
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
SC_PKCS15_PIN_FLAG_INITIALIZED |
SC_PKCS15_PIN_FLAG_LOCAL,
SC_PKCS15_PIN_FLAG_LOCAL,
-1, 0xFF,
SC_PKCS15_CO_FLAG_PRIVATE },
{ "02", "PIV PUK", "", 0x81,
{ "02", "PIV PUK", "", 0x81,
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
8, 4, 8,
8, 4, 8,
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
SC_PKCS15_PIN_FLAG_INITIALIZED |
SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
-1, 0xFF,
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
-1, 0xFF,
SC_PKCS15_CO_FLAG_PRIVATE },
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
// clang-format on
/*
* The size of the key or the algid is not really known
* but can be derived from the certificates.
* the cert, pubkey and privkey are a set.
* but can be derived from the certificates.
* the cert, pubkey and privkey are a set.
* Key usages bits taken from pkcs15v1_1 Table 2
* RSA and EC have different sets of usage
*/
// clang-format off
static const pubdata pubkeys[PIV_NUM_CERTS_AND_KEYS] = {
{ "01", "PIV AUTH pubkey",
{ "01", "PIV AUTH pubkey",
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT |
SC_PKCS15_PRKEY_USAGE_WRAP |
SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY,
"9A06", 0x9A, NULL, 0, "PIV_9A_KEY"},
{ "02", "SIGN pubkey",
{ "02", "SIGN pubkey",
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT |
SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
@ -403,13 +409,13 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
"9C06", 0x9C, NULL, 0, "PIV_9C_KEY"},
{ "03", "KEY MAN pubkey",
{ "03", "KEY MAN pubkey",
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT| SC_PKCS15_PRKEY_USAGE_WRAP,
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
"9D06", 0x9D, NULL, 0, "PIV_9D_KEY"},
{ "04", "CARD AUTH pubkey",
{ "04", "CARD AUTH pubkey",
/*RSA*/SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY,
"9E06", 0x9E, NULL, 0, "PIV_9E_KEY"}, /* no pin, and avail in contactless */
@ -492,33 +498,36 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{ "24", "Retired KEY MAN 20",
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP,
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
"9506", 0x95, NULL, 0, NULL} };
"9506", 0x95, NULL, 0, NULL}
};
// clang-format on
/*
* note some of the SC_PKCS15_PRKEY values are dependent
* on the key algorithm, and will be reset.
* on the key algorithm, and will be reset.
*/
// clang-format off
static const prdata prkeys[PIV_NUM_CERTS_AND_KEYS] = {
{ "01", "PIV AUTH key",
{ "01", "PIV AUTH key",
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT |
SC_PKCS15_PRKEY_USAGE_UNWRAP |
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN,
"", 0x9A, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0},
{ "02", "SIGN key",
{ "02", "SIGN key",
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT |
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN |
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
"", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1},
{ "03", "KEY MAN key",
{ "03", "KEY MAN key",
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP,
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
"", 0x9D, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0},
{ "04", "CARD AUTH key",
{ "04", "CARD AUTH key",
/*RSA*/SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN,
@ -604,6 +613,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
"", 0x95, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0}
};
// clang-format on
int r, i;
sc_card_t *card = p15card->card;
@ -624,10 +634,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
/*
* get serial number
* get serial number
* We will use the FASC-N from the CHUID
* Note we are not verifying CHUID, belongs to this card
* but need serial number for Mac tokend
* but need serial number for Mac tokend
*/
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
@ -671,36 +681,36 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
obj_obj.flags = objects[i].obj_flags;
r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
&obj_obj, &obj_info);
r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
&obj_obj, &obj_info);
if (r < 0)
LOG_FUNC_RETURN(card->ctx, r);
/* TODO
* PIV key 9C requires the pin verify be done just before any
* crypto operation using the key.
*
* crypto operation using the key.
*
* Nss 3.12.7 does not check the CKA_ALWAYS_AUTHENTICATE attribute of a key
* and will do a C_FindObjects with only CKA_VALUE looking for a certificate
* it had found earlier after c_Login. The template does not add CKA_TYPE=cert.
* This will cause the card-piv to read all the objects and will reset
* the security status for the 9C key.
* Mozilla Bug 357025
* Mozilla Bug 357025
* Mozilla Bug 613507
* on 5/16/2012, both scheduled for NSS 3.14
*
* on 5/16/2012, both scheduled for NSS 3.14
*
* We can not read all the objects, as some need the PIN!
*/
*/
}
/*
* certs, pubkeys and priv keys are related and we assume
* they are in order
* We need to read the cert, get modulus and keylen
* We use those for the pubkey, and priv key objects.
* they are in order
* We need to read the cert, get modulus and keylen
* We use those for the pubkey, and priv key objects.
* If no cert, then see if pubkey (i.e. we are initializing,
* and the pubkey is in a file,) then add pubkey and privkey
* If no cert and no pubkey, skip adding them.
* If no cert and no pubkey, skip adding them.
*/
/* set certs */
sc_log(card->ctx, "PIV-II adding certs...");
@ -789,7 +799,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
}
}
/*
/*
* get keyUsage if present save in ckis[i]
* Will only use it if this in a non FED issued card
* which has a CHUID with FASC-N not starting with 9999
@ -973,9 +983,9 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
/* set public keys */
/* We may only need this during initialization when genkey
* gets the pubkey, but it can not be read from the card
* gets the pubkey, but it can not be read from the card
* at a later time. The piv-tool can stash pubkey in file
*/
*/
sc_log(card->ctx, "PIV-II adding pub keys...");
for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) {
struct sc_pkcs15_pubkey_info pubkey_info;
@ -1002,7 +1012,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
/* If no cert found, piv-tool may have stashed the pubkey
* so we can use it when generating a certificate request
* The file is a OpenSSL DER EVP_KEY, which looks like
* The file is a OpenSSL DER EVP_KEY, which looks like
* a certificate subjectPublicKeyInfo.
*
*/
@ -1011,7 +1021,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
sc_log(card->ctx, "No cert for this pub key i=%d",i);
/*
/*
* If we used the piv-tool to generate a key,
* we would have saved the public key as a file.
* This code is only used while signing a request
@ -1020,15 +1030,15 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
*/
sc_log(card->ctx, "DEE look for env %s",
sc_log(card->ctx, "DEE look for env %s",
pubkeys[i].getenvname?pubkeys[i].getenvname:"NULL");
if (pubkeys[i].getenvname == NULL)
if (pubkeys[i].getenvname == NULL)
continue;
filename = getenv(pubkeys[i].getenvname);
filename = getenv(pubkeys[i].getenvname);
sc_log(card->ctx, "DEE look for file %s", filename?filename:"NULL");
if (filename == NULL)
if (filename == NULL)
continue;
sc_log(card->ctx, "Adding pubkey from file %s",filename);
@ -1044,16 +1054,16 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
LOG_TEST_GOTO_ERR(card->ctx, r, "SPKI encode public key error");
/* Only get here if no cert, and the the above found the
* pub key file (actually the SPKI version). This only
* happens when trying initializing a card and have set
* env PIV_9A_KEY or 9C, 9D, 9E to point at the file.
* pub key file (actually the SPKI version). This only
* happens when trying initializing a card and have set
* env PIV_9A_KEY or 9C, 9D, 9E to point at the file.
*
* We will cache it using the PKCS15 emulation objects
*/
pubkey_info.path.len = 0;
ckis[i].key_alg = p15_key->algorithm;
ckis[i].key_alg = p15_key->algorithm;
switch (p15_key->algorithm) {
case SC_ALGORITHM_RSA:
/* save pubkey_len in pub and priv */
@ -1107,7 +1117,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
pubkey_info.usage = pubkeys[i].usage_ec;
}
pubkey_info.field_length = ckis[i].pubkey_len;
pubkey_info.field_length = ckis[i].pubkey_len;
strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
/* should not fail */
@ -1121,7 +1131,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
continue;
}
sc_log(card->ctx, "USAGE: cert_keyUsage_present:%d usage:0x%8.8x",
ckis[i].cert_keyUsage_present ,pubkey_info.usage);
ckis[i].cert_keyUsage_present ,pubkey_info.usage);
}
@ -1150,10 +1160,10 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
/*
* When no cert is present and a pubkey in a file was found,
* When no cert is present and a pubkey in a file was found,
* means the caller is initializing a card. A sign operation
* will be required to sign a certificate request even if
* normal usage would not allow it. Set SC_PKCS15_PRKEY_USAGE_SIGN
* will be required to sign a certificate request even if
* normal usage would not allow it. Set SC_PKCS15_PRKEY_USAGE_SIGN
* TODO if code is added to allow key generation and request
* sign in the same session, similar code will be needed.
*/

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",
@ -617,6 +619,14 @@ sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key)
if (key->u.ec.ecpointQ.value)
free(key->u.ec.ecpointQ.value);
break;
case SC_ALGORITHM_EDDSA:
free(key->u.eddsa.pubkey.value);
key->u.eddsa.pubkey.value = NULL;
key->u.eddsa.pubkey.len = 0;
free(key->u.eddsa.value.value);
key->u.eddsa.value.value = NULL;
key->u.eddsa.value.len = 0;
break;
}
}
@ -718,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));
@ -783,6 +793,13 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key)
break;
}
#endif /* !defined(OPENSSL_NO_EC) */
#ifdef EVP_PKEY_ED25519
case EVP_PKEY_ED25519: {
/* TODO */
break;
}
#endif /* EVP_PKEY_ED25519 */
default:
return SC_ERROR_NOT_SUPPORTED;
}

View File

@ -580,6 +580,12 @@ static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = {
{ NULL, 0, 0, 0, NULL, NULL }
};
#define C_ASN1_EDDSA_PUBKEY_SIZE 2
static struct sc_asn1_entry c_asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE] = {
{ "pubkey", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
int
sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
@ -767,6 +773,47 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key,
sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen));
}
/*
* EdDSA keys are just byte strings. For now only
* for Ed25519 keys 32B length are supported
*/
int
sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx,
struct sc_pkcs15_pubkey_eddsa *key,
const u8 *buf, size_t buflen)
{
int r;
u8 * pubkey = NULL;
size_t pubkey_len;
struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE];
LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey);
sc_format_asn1_entry(asn1_eddsa_pubkey + 0, &pubkey, &pubkey_len, 1);
r = sc_asn1_decode(ctx, asn1_eddsa_pubkey, buf, buflen, NULL, NULL);
if (r < 0)
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
key->pubkey.len = pubkey_len;
key->pubkey.value = pubkey;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
int
sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_eddsa *key,
u8 **buf, size_t *buflen)
{
struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE];
LOG_FUNC_CALLED(ctx);
sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey);
sc_format_asn1_entry(asn1_eddsa_pubkey + 0, key->pubkey.value, &key->pubkey.len, 1);
LOG_FUNC_RETURN(ctx,
sc_asn1_encode(ctx, asn1_eddsa_pubkey, buf, buflen));
}
int
sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
@ -780,6 +827,9 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len);
if (key->algorithm == SC_ALGORITHM_EC)
return sc_pkcs15_encode_pubkey_ec(ctx, &key->u.ec, buf, len);
if (key->algorithm == SC_ALGORITHM_EDDSA ||
key->algorithm == SC_ALGORITHM_XEDDSA) /* XXX encoding is the same here */
return sc_pkcs15_encode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len);
sc_log(ctx, "Encoding of public key type %u not supported", key->algorithm);
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
@ -862,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;
@ -897,6 +955,9 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len);
if (key->algorithm == SC_ALGORITHM_EC)
return sc_pkcs15_decode_pubkey_ec(ctx, &key->u.ec, buf, len);
if (key->algorithm == SC_ALGORITHM_EDDSA ||
key->algorithm == SC_ALGORITHM_XEDDSA)
return sc_pkcs15_decode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len);
sc_log(ctx, "Decoding of public key type %u not supported", key->algorithm);
return SC_ERROR_NOT_SUPPORTED;
@ -939,6 +1000,12 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj
case SC_PKCS15_TYPE_PUBKEY_EC:
algorithm = SC_ALGORITHM_EC;
break;
case SC_PKCS15_TYPE_PUBKEY_EDDSA:
algorithm = SC_ALGORITHM_EDDSA;
break;
case SC_PKCS15_TYPE_PUBKEY_XEDDSA:
algorithm = SC_ALGORITHM_XEDDSA;
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported public key type.");
}
@ -984,7 +1051,8 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len);
LOG_TEST_GOTO_ERR(ctx, r, "Failed to read public key file.");
if (algorithm == SC_ALGORITHM_EC && *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED))
if ((algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA)
&& *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED))
r = sc_pkcs15_pubkey_from_spki_sequence(ctx, data, len, &pubkey);
else
r = sc_pkcs15_decode_pubkey(ctx, pubkey, data, len);
@ -1067,6 +1135,22 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv
}
memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len);
pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len;
break;
case SC_ALGORITHM_EDDSA:
case SC_ALGORITHM_XEDDSA:
/* Copy pubkey */
if (prvkey->u.eddsa.pubkey.value == NULL || prvkey->u.eddsa.pubkey.len <= 0) {
sc_pkcs15_free_pubkey(pubkey);
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
}
pubkey->u.eddsa.pubkey.value = malloc(prvkey->u.eddsa.pubkey.len);
if (!pubkey->u.eddsa.pubkey.value) {
sc_pkcs15_free_pubkey(pubkey);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(pubkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.len);
pubkey->u.eddsa.pubkey.len = prvkey->u.eddsa.pubkey.len;
break;
default:
sc_log(ctx, "Unsupported private key algorithm");
@ -1160,6 +1244,18 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc
rv = SC_ERROR_NOT_SUPPORTED;
}
break;
case SC_ALGORITHM_EDDSA:
case SC_ALGORITHM_XEDDSA:
/* Copy pubkey */
pubkey->u.eddsa.pubkey.value = malloc(key->u.eddsa.pubkey.len);
if (!pubkey->u.eddsa.pubkey.value) {
rv = SC_ERROR_OUT_OF_MEMORY;
break;
}
memcpy(pubkey->u.eddsa.pubkey.value, key->u.eddsa.pubkey.value, key->u.eddsa.pubkey.len);
pubkey->u.eddsa.pubkey.len = key->u.eddsa.pubkey.len;
break;
default:
sc_log(ctx, "Unsupported private key algorithm");
@ -1215,6 +1311,12 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
if (key->u.ec.ecpointQ.value)
free(key->u.ec.ecpointQ.value);
break;
case SC_ALGORITHM_EDDSA:
case SC_ALGORITHM_XEDDSA:
free(key->u.eddsa.pubkey.value);
key->u.eddsa.pubkey.value = NULL;
key->u.eddsa.pubkey.len = 0;
break;
}
sc_mem_clear(key, sizeof(*key));
}
@ -1413,8 +1515,13 @@ 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 {
} 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);
LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 parsing of subjectPubkeyInfo failed");
@ -1517,7 +1624,11 @@ static struct ec_curve_info {
{"secp192k1", "1.3.132.0.31", "06052B8104001F", 192},
{"secp256k1", "1.3.132.0.10", "06052B8104000A", 256},
{NULL, NULL, NULL, 0},
{"ed25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255},
{"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255},
{NULL, NULL, NULL, 0}, /* Do not touch this */
};
@ -1672,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));
@ -1715,6 +1826,12 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
break;
}
#endif /* !defined(OPENSSL_NO_EC) */
#ifdef EVP_PKEY_ED25519
case EVP_PKEY_ED25519: {
/* TODO */
break;
}
#endif /* EVP_PKEY_ED25519 */
default:
return SC_ERROR_NOT_SUPPORTED;
}

View File

@ -1026,7 +1026,7 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
r = sc_pin_cmd(card, &pindata, NULL);
}
if ((r != SC_ERROR_DATA_OBJECT_NOT_FOUND) && (r != SC_ERROR_INCORRECT_PARAMETERS))
if ((r != SC_ERROR_DATA_OBJECT_NOT_FOUND) && (r != SC_ERROR_INCORRECT_PARAMETERS) && (r != SC_ERROR_REF_DATA_NOT_USABLE))
card->caps |= SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH;

View File

@ -166,7 +166,7 @@ static int use_key(struct sc_pkcs15_card *p15card,
sc_unlock(p15card->card);
return r;
LOG_FUNC_RETURN(p15card->card->ctx, r);
}
static int format_senv(struct sc_pkcs15_card *p15card,
@ -213,6 +213,28 @@ static int format_senv(struct sc_pkcs15_card *p15card,
senv_out->algorithm = SC_ALGORITHM_GOSTR3410;
break;
case SC_PKCS15_TYPE_PRKEY_EDDSA:
*alg_info_out = sc_card_find_eddsa_alg(p15card->card, prkey->field_length, NULL);
if (*alg_info_out == NULL) {
sc_log(ctx,
"Card does not support EDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
prkey->field_length);
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
}
senv_out->algorithm = SC_ALGORITHM_EDDSA;
break;
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
*alg_info_out = sc_card_find_xeddsa_alg(p15card->card, prkey->field_length, NULL);
if (*alg_info_out == NULL) {
sc_log(ctx,
"Card does not support XEDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
prkey->field_length);
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
}
senv_out->algorithm = SC_ALGORITHM_XEDDSA;
break;
case SC_PKCS15_TYPE_PRKEY_EC:
*alg_info_out = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
if (*alg_info_out == NULL) {
@ -320,6 +342,7 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
switch (obj->type) {
case SC_PKCS15_TYPE_PRKEY_EC:
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) {
*poutlen = (prkey->field_length + 7) / 8;
r = 0; /* say no data to return */
@ -580,7 +603,9 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
modlen = (prkey->modulus_length + 7) / 8 * 2;
break;
case SC_PKCS15_TYPE_PRKEY_EC:
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
case SC_PKCS15_TYPE_PRKEY_EDDSA:
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
break;
default:
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
@ -608,56 +633,69 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
/* if the card has SC_ALGORITHM_NEED_USAGE set, and the
* key is for signing and decryption, we need to emulate signing */
/* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */
sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage);
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
((prkey->usage & USAGE_ANY_SIGN) &&
(prkey->usage & USAGE_ANY_DECIPHER)) ) {
size_t tmplen = sizeof(buf);
if (flags & SC_ALGORITHM_RSA_RAW) {
r = sc_pkcs15_decipher(p15card, obj, flags, in, inlen, out, outlen);
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)) ) {
size_t tmplen = sizeof(buf);
if (flags & SC_ALGORITHM_RSA_RAW) {
r = sc_pkcs15_decipher(p15card, obj, flags, in, inlen, out, outlen);
LOG_FUNC_RETURN(ctx, r);
}
if (modlen > tmplen)
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
/* XXX Assuming RSA key here */
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
/* no padding needed - already done */
flags &= ~SC_ALGORITHM_RSA_PADS;
/* instead use raw rsa */
flags |= SC_ALGORITHM_RSA_RAW;
LOG_TEST_RET(ctx, r, "Unable to add padding");
r = sc_pkcs15_decipher(p15card, obj, flags, buf, modlen, out, outlen);
LOG_FUNC_RETURN(ctx, r);
}
if (modlen > tmplen)
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
/* XXX Assuming RSA key here */
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
/* no padding needed - already done */
flags &= ~SC_ALGORITHM_RSA_PADS;
/* instead use raw rsa */
flags |= SC_ALGORITHM_RSA_RAW;
/* If the card doesn't support the requested algorithm, we normally add the
* padding here in software and ask the card to do a raw signature. There's
* one exception to that, where we might be able to get the signature to
* succeed by stripping padding if the card only offers higher-level
* signature operations. The only thing we can strip is the DigestInfo
* block from PKCS1 padding. */
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
!(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE) &&
(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
unsigned int algo;
size_t tmplen = sizeof(buf);
LOG_TEST_RET(ctx, r, "Unable to add padding");
r = sc_pkcs15_decipher(p15card, obj, flags, buf, modlen, out, outlen);
LOG_FUNC_RETURN(ctx, r);
r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen);
if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
sc_mem_clear(buf, sizeof(buf));
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
}
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
flags |= algo;
inlen = tmplen;
}
}
/* If the card doesn't support the requested algorithm, we normally add the
* padding here in software and ask the card to do a raw signature. There's
* one exception to that, where we might be able to get the signature to
* succeed by stripping padding if the card only offers higher-level
* signature operations. The only thing we can strip is the DigestInfo
* block from PKCS1 padding. */
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
!(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE) &&
(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
unsigned int algo;
size_t tmplen = sizeof(buf);
r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen);
if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
sc_mem_clear(buf, sizeof(buf));
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
/* ECDSA sofware hash has already been done, or is not needed, or card will do hash */
/* if card can not do the hash, will use SC_ALGORITHM_ECDSA_RAW */
if (obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
if ((alg_info->flags & SC_ALGORITHM_ECDSA_RAW)
&& !(flags & SC_ALGORITHM_ECDSA_HASHES & alg_info->flags)) {
sc_log(ctx, "ECDSA using SC_ALGORITHM_ECDSA_RAW flags before 0x%8.8lx", flags);
flags |= SC_ALGORITHM_ECDSA_RAW;
flags &= ~SC_ALGORITHM_ECDSA_HASHES;
}
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
flags |= algo;
inlen = tmplen;
}
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
@ -665,6 +703,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
sc_mem_clear(buf, sizeof(buf));
LOG_FUNC_RETURN(ctx, r);
}
/* senv now has flags card or driver will do */
senv.algorithm_flags = sec_flags;
sc_log(ctx, "DEE flags:0x%8.8lx alg_info->flags:0x%8.8x pad:0x%8.8lx sec:0x%8.8lx",
@ -695,9 +734,10 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
* If the length of the hash value is larger than the bit length of n, only
* the leftmost bits of the hash up to the length of n will be used. Any
* truncation is done by the token.
* But if card is going to do the hash, pass in all the data
*/
else if (senv.algorithm == SC_ALGORITHM_EC &&
(flags & SC_ALGORITHM_ECDSA_HASH_NONE) != 0) {
(senv.algorithm_flags & SC_ALGORITHM_ECDSA_HASHES) == 0) {
inlen = MIN(inlen, (prkey->field_length+7)/8);
}

View File

@ -91,6 +91,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
case SC_CARD_TYPE_DNIE_USER:
case SC_CARD_TYPE_DNIE_TERMINATED:
case SC_CARD_TYPE_IASECC_GEMALTO:
case SC_CARD_TYPE_IASECC_CPX:
case SC_CARD_TYPE_IASECC_CPXCL:
case SC_CARD_TYPE_PIV_II_GENERIC:
case SC_CARD_TYPE_PIV_II_HIST:
case SC_CARD_TYPE_PIV_II_NEO:
@ -364,6 +366,7 @@ int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *p15card,
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EC, obj, &key);
}
int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
{
@ -375,6 +378,56 @@ int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card,
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EC, obj, &key);
}
int sc_pkcs15emu_add_eddsa_prkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key)
{
sc_pkcs15_prkey_info_t key = *in_key;
if (key.access_flags == 0)
key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EDDSA, obj, &key);
}
int sc_pkcs15emu_add_eddsa_pubkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
{
sc_pkcs15_pubkey_info_t key = *in_key;
if (key.access_flags == 0)
key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EDDSA, obj, &key);
}
int sc_pkcs15emu_add_xeddsa_prkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key)
{
sc_pkcs15_prkey_info_t key = *in_key;
if (key.access_flags == 0)
key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_XEDDSA, obj, &key);
}
int sc_pkcs15emu_add_xeddsa_pubkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
{
sc_pkcs15_pubkey_info_t key = *in_key;
if (key.access_flags == 0)
key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_XEDDSA, obj, &key);
}
int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *p15card,
const sc_pkcs15_object_t *obj, const sc_pkcs15_cert_info_t *cert)
{

Some files were not shown because too many files have changed in this diff Show More