Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support D-Trust Card 5.1 (Std. RSA CardOS6.0) with CAN #3131

Open
janknieling opened this issue Apr 30, 2024 · 21 comments
Open

Support D-Trust Card 5.1 (Std. RSA CardOS6.0) with CAN #3131

janknieling opened this issue Apr 30, 2024 · 21 comments

Comments

@janknieling
Copy link

janknieling commented Apr 30, 2024

Problem Description

The D-Trust Signature Card 5.1 Std. (EIDAS QES signature certificate for signing and encryption certificate on card) with CardOS6.0 is currently not supported by OpenSC.
To connect to the card/use the card a CAN number is needed (the CAN is printed on the card).
It seems that OpenSC hasn't the possibility to provide/submit a CAN.

Proposed Resolution

It would be great if this card type is supported by OpenSC. This is merely a feature request than a bug report.

Steps to reproduce

$ echo "Sign me" | pkcs11-tool --slot 1 -a Signaturzertifikat -s -m RSA-PKCS -p XXXXXXXX

error: PKCS11 function C_GetTokenInfo failed: rv = CKR_TOKEN_NOT_RECOGNIZED (0xe1)
Aborting.

Debug log:
log.txt

Logs

➜  ~ opensc-tool --version
OpenSC-<version not available>, rev: 0a4b772, commit-time: 2024-04-04 16:21:38 +0200
P:94404; T:0x140704682469312 22:40:04.528 [opensc-tool] ctx.c:747:process_config_file: scconf_parse failed: Line 2: not expecting 'default'

P:94404; T:0x140704682469312 22:40:04.529 [opensc-tool] ctx.c:981:sc_context_create: ===================================
P:94404; T:0x140704682469312 22:40:04.529 [opensc-tool] ctx.c:982:sc_context_create: OpenSC version: 0.25.1
P:94404; T:0x140704682469312 22:40:04.529 [opensc-tool] ctx.c:983:sc_context_create: Configured for opensc-tool (/Library/OpenSC/bin/opensc-tool)
P:94404; T:0x140704682469312 22:40:04.530 [opensc-tool] ctx.c:858:sc_openssl3_init: Failed to load OpenSSL Legacy provider
P:94404; T:0x140704682469312 22:40:04.530 [opensc-tool] reader-pcsc.c:897:pcsc_init: PC/SC options: connect_exclusive=0 disconnect_action=0 transaction_end_action=0 reconnect_action=0 enable_pinpad=1 enable_pace=1
P:94404; T:0x140704682469312 22:40:04.546 [opensc-tool] reader-pcsc.c:1397:pcsc_detect_readers: called
P:94404; T:0x140704682469312 22:40:04.546 [opensc-tool] reader-pcsc.c:1410:pcsc_detect_readers: Probing PC/SC readers
P:94404; T:0x140704682469312 22:40:04.546 [opensc-tool] reader-pcsc.c:1463:pcsc_detect_readers: Establish PC/SC context
P:94404; T:0x140704682469312 22:40:04.594 [opensc-tool] reader-pcsc.c:1346:pcsc_add_reader: Adding new PC/SC reader 'REINER SCT cyberJack one'
P:94404; T:0x140704682469312 22:40:04.594 [opensc-tool] reader-pcsc.c:361:refresh_attributes: REINER SCT cyberJack one check
P:94404; T:0x140704682469312 22:40:04.596 [opensc-tool] reader-pcsc.c:407:refresh_attributes: current  state: 0x00000022
P:94404; T:0x140704682469312 22:40:04.596 [opensc-tool] reader-pcsc.c:408:refresh_attributes: previous state: 0x00000000
P:94404; T:0x140704682469312 22:40:04.596 [opensc-tool] reader-pcsc.c:463:refresh_attributes: card present, changed
P:94404; T:0x140704682469312 22:40:04.804 [opensc-tool] reader-pcsc.c:1564:pcsc_detect_readers: REINER SCT cyberJack one:SCardConnect(SHARED): 0x00000000
P:94404; T:0x140704682469312 22:40:04.804 [opensc-tool] reader-pcsc.c:1145:detect_reader_features: called
P:94404; T:0x140704682469312 22:40:04.805 [opensc-tool] reader-pcsc.c:1147:detect_reader_features: Requesting reader features ... 
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1165:detect_reader_features: Reader feature 06 found
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1165:detect_reader_features: Reader feature 07 found
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1165:detect_reader_features: Reader feature 08 found
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1185:detect_reader_features: Reader feature 08 is not supported
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1165:detect_reader_features: Reader feature 09 found
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1185:detect_reader_features: Reader feature 09 is not supported
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1193:detect_reader_features: Reader supports pinpad PIN verification
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1203:detect_reader_features: Reader supports pinpad PIN modification
P:94404; T:0x140704682469312 22:40:04.806 [opensc-tool] reader-pcsc.c:1125:part10_get_vendor_product: id_vendor=ffffffff id_product=ffffffff
P:94404; T:0x140704682469312 22:40:04.807 [opensc-tool] reader-pcsc.c:1293:detect_reader_features: Reader supports sending 1014 bytes of data
P:94404; T:0x140704682469312 22:40:04.807 [opensc-tool] reader-pcsc.c:1306:detect_reader_features: Reader supports receiving 1014 bytes of data
P:94404; T:0x140704682469312 22:40:04.809 [opensc-tool] reader-pcsc.c:1579:pcsc_detect_readers: returning with: 0 (Success)
P:94404; T:0x140704682469312 22:40:04.809 [opensc-tool] ctx.c:1066:sc_release_context: called
P:94404; T:0x140704682469312 22:40:04.809 [opensc-tool] reader-pcsc.c:978:pcsc_finish: called
$ cardos-tool -i
Using reader with a card: REINER SCT cyberJack one
Card type FFFFFFFF: not a CardOS card

Debug log:
cardostool.txt

$ opensc-tool --name
Using reader with a card: REINER SCT cyberJack one
Unsupported card

Debug log:
opensctool--name.txt

$ pkcs11-tool -T 
Available slots:
No slots.

Debug log:
pkcs11-tool.txt

$ pkcs15-tool -D   
Using reader with a card: REINER SCT cyberJack one
Failed to connect to card: Card is invalid or cannot be handled

Debug log:
pkcs15-tool.txt

$ dtrust-tool 
Using reader with a card: REINER SCT cyberJack one
Failed to connect to card: Security status not satisfied

Debug log:
dtrust-tool.txt

$ opensc-tool -a 
Using reader with a card: REINER SCT cyberJack one
3b:d2:18:00:81:31:fe:58:cb:01:16
@frankmorgner
Copy link
Member

Just to check whether PACE of the card is compatible with OpenSC's implementation, could you please try npa-tool --can=123456?

@janknieling
Copy link
Author

➜  ~ npa-tool --can=XXXXXX -v
Using reader with a card: REINER SCT cyberJack one
Connecting to card in reader REINER SCT cyberJack one...
Using card driver Default driver for unknown cards.
Established PACE channel with CAN.

@frankmorgner
Copy link
Member

Thanks, so mechanisms are in place, but we need to correctly look at the metadata. I'll try to get some developer information from D-Trust.

Maybe this is also interesting for @hamarituc

@hamarituc
Copy link
Contributor

Thanks, so mechanisms are in place, but we need to correctly look at the metadata. I'll try to get some developer information from D-Trust.

Maybe this is also interesting for @hamarituc

Today in the morning I received my account to access the developer docs. I will check it tomorrow and contact you if there are any questions, so you don't need to waste time.

@hamarituc
Copy link
Contributor

Thanks, so mechanisms are in place, but we need to correctly look at the metadata. I'll try to get some developer information from D-Trust.

Maybe this is also interesting for @hamarituc

According to the developer docs a PACE channel is necessary for:

  • PIN operations
  • private key operations
  • even for querying the vendor and product information of the card

Whilst it is evident to protect the communication via PACE for contactless usage, it is even required when using the contact based interface. This makes the driver implementation a bit complicated, because up to two separate PINs have to be queried: the CAN at least for the first time and then signature PIN every time in case of a standard card.

@frankmorgner: You developed the PACE implementation and the ePA-driver. Is this behavior implementable in the PKCS#11 workflow at all? If I understand the ePA driver correctly, the CAN is statically configured in the configuration file. This would not be an option in my use case so it needs a way to query the CAN through regular usage from the end user. Is the ePA driver a good candidate to build upon or do we need a different approach?

@frankmorgner
Copy link
Member

even for querying the vendor and product information of the card

That's not exactly true. DF.Certs, which holds all certificates is ALWAYS readable as well as, for example, EF.GDO with the serial number. So there should be enough meta data available to identify the card.

Is this behavior implementable in the PKCS#11 workflow at all?

Not exactly, no.

If I understand the ePA driver correctly, the CAN is statically configured in the configuration file.

Correct.

This would not be an option in my use case so it needs a way to query the CAN through regular usage from the end user. Is the ePA driver a good candidate to build upon or do we need a different approach?

First, you will always need to request the CAN via a propriatery PIN dialog, because of the PKCS#11 limitations. Read src/libopensc/card-dnie.c and search for ENABLE_DNIE_UI - there you will find PIN dialogs for Windows, macOS and Linux. By default, this code is not enabled so please use with care. If you have a reader capable of doing PACE when inputting the CAN on the pin pad, then you may even do so without spawning a dedicated window and just use sc_notify().

Second, once you collected the CAN, you may want to cache this on disk to avoid prompting the user too often (remember that the user always needs to enter PIN.AUT or PIN.QES as well!). (Only) On Windows, you could use RegSetValueEx() in the user context (see src/minidriver/minidriver.c for example). The other option which works on any OS, is to use sc_pkcs15_cache_file() to cache the CAN on disk using a virtual file path. This virtual file will be associated with the serial number of your card and should work even with using multiple cards (with different CANs) for a single user.

@janknieling
Copy link
Author

@frankmorgner @hamarituc if you need some help with debugging/testing I am happy to assist you with my signature card

@hamarituc
Copy link
Contributor

@frankmorgner @hamarituc if you need some help with debugging/testing I am happy to assist you with my signature card

Which operating system do you use? I can only test Linux and Windows. Finding a Mac user would be helpful.

But to be honest, it seems to be a lot work to be done because of the PACE encryption required by these cards. I cannot make an estimate when I am able to deliver a first test candidate.

@janknieling
Copy link
Author

janknieling commented May 7, 2024

My primary operating system is macOS (x86 and Apple Silicon/ARM architecture). But I have windows and linux machines too

@frankmorgner
Copy link
Member

Establishing PACE channels for a hard coded CAN is implemented here (according to the specification) if you want to try:
frankmorgner@80349e2

hamarituc added a commit to hamarituc/OpenSC that referenced this issue May 24, 2024
@hamarituc
Copy link
Contributor

Establishing PACE channels for a hard coded CAN is implemented here (according to the specification) if you want to try: frankmorgner@80349e2

@frankmorgner Thank for the sample code. I was able to get PACE authentication working in dtrust-tool. Currently it shows the status of the transport protection and the PIN status. Next step will be implementing the card initialization procedure.

@janknieling If you already initialized your card with the D-Trust provided Card Assistant I would be happy if you could provide me the output of dtrust-tool -s -c. This can confirm my patches are working as they should.

@janknieling
Copy link
Author

janknieling commented May 24, 2024

@hamarituc yes my card is already initialized.
I have tried to build OpenSC on my mac but it seems that there is something wrong.

../../src/sm/sm-eac.h:37:10: fatal error: 'eac/cv_cert.h' file not found
#include <eac/cv_cert.h>
         ^~~~~~~~~~~~~~~
1 error generated.
make[3]: *** [dtrust-tool.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [all-recursive] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

The CI/CD pipeline has the same problem (https://github.com/OpenSC/OpenSC/actions/runs/9227516607/job/25389623718#step:4:12322)

@frankmorgner
Copy link
Member

dtrust-tool needs to be compiled with OpenPACE...

Implementing the sample, I also noticed some other problems:

  1. I suggested to use a virtual smart card file in order to store the cached CAN, i.e. by using sc_pkcs15_cache_file()). Since you're currently using the synthetic PKCS#15 layer, you cannot customize this behavior at the moment. So for caching the CAN, I see two options:
    1.1 use dtrust-tool to store a CAN in the local file system, then read this local file in card-dtrust.c (CAN is queried via CLI in dtrust-tool)
    1.2 implement a PKCS#15 layer (i.e. pkcs15-dtrust.c) based on the synthetic behavior and add a virtual file for CAN. (CAN is queried via deditacted window in card-dtrust.c)

  2. You will likely run into problems with PIN pad readers, because sc_pin_cmd() or SC_READER_CAP_PIN_PAD currently only knows FEATURE_VERIFY_PIN_DIRECT, but not SC_READER_CAP_PACE_EID. However, if perform_pace() is executed with an empty PIN and the reader has a PIN pad with PACE capabilities, then the PACE PIN is requested on the PIN pad. To work around this, I suggest that you set SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH if the reader supports PACE via PIN pad. This notifies the upper layers that the PIN doesn't need to be prompted by the application, instead you are handling this in card-dtrust.c by executing perform_pace() with an empty PIN. Unfortunately, this also means that you will have to manually deal with FEATURE_MODIFY_PIN_DIRECT, e.g for PIN modification...

@janknieling
Copy link
Author

@frankmorgner is there a documentation for compiling with openpace on macOS available?
Seems that the CI/CD pipeline isn't compiling with openpace too because there is the same error that openpace is missing

@frankmorgner
Copy link
Member

./MacOSX/build will do all the work for you. This is also what we successfully use in our pipeline https://github.com/OpenSC/OpenSC/actions/workflows/macos.yml

@janknieling
Copy link
Author

janknieling commented May 30, 2024

Unfortunately ./MacOSX/build drops the same error.
Regarding the pipeline: If you'll take a look at the pipeline execution from the pull request (#3137) for this issue you will see the same error that eac/cv_cert.h is missing/was not found (https://github.com/OpenSC/OpenSC/actions/runs/9227516607/job/25389623718?pr=3137).

@frankmorgner
Copy link
Member

src/tools/Makefile.am needs to add $(OPENPACE_LIBS) and $(OPENPACE_CFLAGS) for dtrust-tool. But that is a problem of the OpenSC build system - OpenPACE is built in CI and works as expected.

@hamarituc
Copy link
Contributor

dtrust-tool needs to be compiled with OpenPACE...

...

src/tools/Makefile.am needs to add (OPENPACELIBS)and(OPENPACE_CFLAGS) for dtrust-tool. But that is a problem of the OpenSC build system - OpenPACE is built in CI and works as expected.

I will add it. Strictly speaking OpenPACE is only necessary for D-Trust Card 5, but not for version 4. So at least the D-Trust Card 4 should should still be supported without enabling OpenPACE. Is adding

dtrust_tool_LDADD = $(OPENPACE_LIBS)
dtrust_tool_CFLAGS = $(OPENPACE_CFLAGS)

unconditionally OK? The variables should be empty i think, when OpenPACE is disabled, weren't they?

In the D-Trust driver the parts which are specific to OpenPACE should not be compiled when OpenPACE support is disabled. Is

#ifdef ENABLE_OPENPACE
#endif

sufficient or does it need to be?

#if defined(ENABLE_SM) && defined(ENABLE_OPENPACE)
#endif

@frankmorgner
Copy link
Member

just add cflags and libs. as long as you don't use any openpace specific header files or function calls, sm/eac.h will handle non-availability of openpace.

@janknieling
Copy link
Author

janknieling commented Jun 6, 2024

@hamarituc here is the output of dtrust-tool -s -c

➜  OpenSC git:(dtrust-5) ✗ dtrust-tool -s -c
Using reader with a card: REINER SCT cyberJack one
Enter CAN:
Authentication PIN: usable (3 tries left)
Transport PIN (Authentication): not usable (transport protection still in force)
Card Holder PUK: not usable (transport protection still in force)
Signature PIN: usable (3 tries left)
Transport PIN (Signature): not usable (transport protection still in force)
Transport protection of Authentication PIN is broken.
Transport protection of Signature PIN is broken.

pkcs11-tool -T

➜  OpenSC git:(dtrust-5) ✗ pkcs11-tool -T 
Available slots:
Slot 0 (0x0): REINER SCT cyberJack one
  token label        : D-TRUST Card 5.1 Std. R... (CAN)
  token manufacturer : D-TRUST GmbH (C)
  token model        : PKCS#15
  token flags        : login required, PIN pad present, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 003212310002329f
  pin min/max        : 6/6
  uri                : pkcs11:model=PKCS%2315;manufacturer=D-TRUST%20GmbH%20%28C%29;serial=003212310002329f;token=D-TRUST%20Card%205.1%20Std.%20R...%20%28CAN%29
Slot 1 (0x1): REINER SCT cyberJack one
  token label        : D-TRUST Card ... (Signature-PIN)
  token manufacturer : D-TRUST GmbH (C)
  token model        : PKCS#15
  token flags        : login required, PIN pad present, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 003212310002329f
  pin min/max        : 8/8
  uri                : pkcs11:model=PKCS%2315;manufacturer=D-TRUST%20GmbH%20%28C%29;serial=003212310002329f;token=D-TRUST%20Card%20...%20%28Signature-PIN%29
Slot 2 (0x2): REINER SCT cyberJack one
  token label        : D-TRUST ... (Authentication-PIN)
  token manufacturer : D-TRUST GmbH (C)
  token model        : PKCS#15
  token flags        : login required, PIN pad present, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 003212310002329f
  pin min/max        : 8/8
  uri                : pkcs11:model=PKCS%2315;manufacturer=D-TRUST%20GmbH%20%28C%29;serial=003212310002329f;token=D-TRUST%20...%20%28Authentication-PIN%29

pkcs15-tool -D

➜  OpenSC git:(dtrust-5) ✗ pkcs15-tool -D   
Using reader with a card: REINER SCT cyberJack one
PKCS#15 Card [D-TRUST Card 5.1 Std. RSA 2ca]:
	Version        : 1
	Serial number  : 9276003212310002329f
	Manufacturer ID: D-TRUST GmbH (C)
	Flags          : Login required, PRN generation


PIN [CAN]
	Object Flags   : [0x01], private
	ID             : 03
	Flags          : [0x11], case-sensitive, initialized
	Length         : min_len:6, max_len:6, stored_len:6
	Pad char       : 0x00
	Reference      : 3 (0x03)
	Type           : UTF-8

PIN [Card-PUK]
	Object Flags   : [0x03], private, modifiable
	ID             : 04
	Flags          : [0x859], case-sensitive, unblock-disabled, initialized, unblockingPin, exchangeRefData
	Length         : min_len:8, max_len:8, stored_len:8
	Pad char       : 0x00
	Reference      : 4 (0x04)
	Type           : UTF-8

PIN [Signature-PIN]
	Object Flags   : [0x03], private, modifiable
	Auth ID        : 04
	ID             : 07
	Flags          : [0x2813], case-sensitive, local, initialized, exchangeRefData
	Length         : min_len:8, max_len:8, stored_len:8
	Pad char       : 0x00
	Reference      : 135 (0x87)
	Type           : UTF-8
	Path           : 3f000101

PIN [Authentication-PIN]
	Object Flags   : [0x03], private, modifiable
	Auth ID        : 04
	ID             : 11
	Flags          : [0x2813], case-sensitive, local, initialized, exchangeRefData
	Length         : min_len:8, max_len:8, stored_len:8
	Pad char       : 0x00
	Reference      : 145 (0x91)
	Type           : UTF-8
	Path           : 3f000102
	Tries left     : 3

Private RSA Key [Authentisierungsschluessel]
	Object Flags   : [0x01], private
	Usage          : [0x2E], decrypt, sign, signRecover, unwrap
	Access Flags   : [0x00]
	Algo_refs      : 0
	ModLength      : 3072
	Key ref        : 3 (0x03)
	Native         : yes
	Path           : 3f000102
	Auth ID        : 11
	ID             : 03
	MD:guid        : f8d9b5ed-1251-c905-70c6-3bd8613a840c

Private RSA Key [Signaturschluessel]
	Object Flags   : [0x01], private
	Usage          : [0x200], nonRepudiation
	Access Flags   : [0x00]
	Algo_refs      : 0
	ModLength      : 3072
	Key ref        : 2 (0x02)
	Native         : yes
	Path           : 3f000101
	Auth ID        : 07
	ID             : 02
	MD:guid        : fbaa8582-260d-f5c4-f830-1e3962a0a1ef

X.509 Certificate [Authentisierungszertifikat]
	Object Flags   : [0x02], modifiable
	Authority      : no
	Path           : 3f0001030204
	ID             : 03
	Encoded serial : 02 03 68D858

X.509 Certificate [Signaturzertifikat]
	Object Flags   : [0x02], modifiable
	Authority      : no
	Path           : 3f0001030201
	ID             : 02
	Encoded serial : 02 10 71B5D5B5F85868B8763E8B300B6ECC4A

X.509 Certificate [CA-Zertifikat fuer Authentisierung]
	Object Flags   : [0x02], modifiable
	Authority      : yes
	Path           : 3f0001030205
	ID             : 03
	Encoded serial : 02 03 0FE54B

X.509 Certificate [Root-CA-Zertifikat fuer Authentisierung]
	Object Flags   : [0x02], modifiable
	Authority      : yes
	Path           : 3f0001030206
	ID             : 03
	Encoded serial : 02 03 0FE529

X.509 Certificate [CA-Zertifikat fuer Signatur]
	Object Flags   : [0x02], modifiable
	Authority      : yes
	Path           : 3f0001030202
	ID             : 02
	Encoded serial : 02 10 69F4C9580F580F631488B9632371E72E

X.509 Certificate [Root-CA-Zertifikat fuer Signatur]
	Object Flags   : [0x02], modifiable
	Authority      : yes
	Path           : 3f0001030203
	ID             : 02
	Encoded serial : 02 10 6BC22A5479D8EA68A9C5A27A909BA938

@janknieling
Copy link
Author

@hamarituc just write me if you need further debugging assistance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants