Support DNIe 3.0 #810

Open
Yajo opened this Issue Jun 26, 2016 · 105 comments

Projects

None yet

10 participants

@Yajo
Yajo commented Jun 26, 2016

Expected behaviour

I should be able to use DNIe 3.0 with Firefox after configuring it.

Actual behaviour

Dialog asks for the PIN again and again endlessly, no matter if you enter the right PIN or you press Cance.

Steps to reproduce

  1. Insert your DNIe.
  2. Configure OpenSC's PKCS#11 module in Firefox.
  3. Visit a DNIe-enabled page, such as https://www1.agenciatributaria.gob.es/wlpl/DASR-CORE/AccesoCO2015RVlt

Logs

Not sure how to get those.

CC @miguel-cv @germanblanco

@frankmorgner
Member

Indeed @germanblanco wanted to look into this, see #655

@cameta
cameta commented Jul 25, 2016

With the old DNIe (personal data have been edited)

tux cameta # dnie-tool -a
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
DNIe Number: 00000000A
SurName: ESPAÑOL
Name: ESPAÑOL
IDESP: AGR148953
DNIe Version: DNIe 01.13 B11 H 4C34 EXP 1-((4.2-5))
Serial number: 06CFC2227A398A

with a DNIe 3.0

tux cameta # dnie-tool -a
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
Error: Get info failed: Unsupported CLA byte in APDU

With the old DNIe

cameta@tux ~ $ opensc-tool -a
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
3b:7f:38:00:00:00:6a:44:4e:49:65:20:02:4c:34:01:13:03:90:00

cameta@tux ~ $ opensc-tool -n
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
dnie

cameta@tux ~ $ opensc-tool --serial
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
06 CF C2 22 7A 39 8A ..."z9.

With a DNIe 3.0

cameta@tux ~ $ opensc-tool -a
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
3b:7f:96:00:00:00:6a:44:4e:49:65:20:01:01:55:04:10:03:90:00

cameta@tux ~ $ opensc-tool -n
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
dnie

cameta@tux ~ $ opensc-tool --serial
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
sc_card_ctl(*, SC_CARDCTL_GET_SERIALNR, *) failed

It also should be noted that this corrupts the pcscd service and it becomes unable to read any card until I restart it.

@Yajo
Yajo commented Jul 26, 2016

Keep in mind that DNIe 3.0 disables the "open session once and use many times" behavior. It requires PIN for each use.

@miguel-cv

DNIe 3.0 has to establish a "pin channel" before entering "secure channel" . There's some initial work here:
https://github.com/germanblanco/OpenSC/tree/dnie_dnie30/
It fails passing from one channel to another...

@frankmorgner
Member

@miguel-cv as far as I know, the SM channel is created using PACE. I have a complete implementation of EAC in #831 including PACE. The implementation is tested with various implementations in various situations, so I think it should meet your requirements. A quick way of checking if you can perform PACE with your PIN is to use npa-tool --pin.

My efforts to include EAC and PACE in OpenSC date back to 2012, so don't expect #831 to be final.

@emunicio
emunicio commented Aug 23, 2016 edited

Hi,

Same here with the DNIe 3.0. I get:
# dnie-tool -a
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
Error: Get info failed: Unsupported CLA byte in APDU

And when trying to read, it starts a loop that hungs Firefox.
With the old DNIe was working perfectly.

Kind regards

@frankmorgner
Member

Are there any test cards available from somewhere?

@frankmorgner
Member

Is there a specification available?

@miguel-cv
miguel-cv commented Sep 20, 2016 edited

As of today, we are missing the command manual for dni 3.0 . A command manual for the previous version is available (in spanish) at http://myslide.es/documents/20100930-manual-de-comandos-del-dnie-tractis.html
There is also a working driver at https://www.sede.fnmt.gob.es/descargas/descarga-software
and source for that at https://www.sede.fnmt.gob.es/documents/11614/4531260/MultiPKCS10_Fuentes+v_1_4_0.rar
In this last file, in comm_dnie.cpp is the code related to secure channel.
Will try npa-tool this weekend.

@Yajo
Yajo commented Sep 26, 2016

You can find everything about it in http://www.dnielectronico.es/, although everything is in Spanish. Be sure you use links for DNIe 3.0 (previous versions are different). If you need us to translate anything, just paste it here and ask for it 😉

@rickyepoderi
Contributor

Hi,

I have started to work in the DNIe 3.0 integration (I have a first working version that can sign but very shoddy). Besides I have the impression that there is something very wrong in the last versions of opendnie/opensc. I had to move to a previous version of opensc in order to make it work.

Can anybody test the last OpenSC code with a DNIe 2.0? Sorry, but I have now 3.0 and nobody I have asked for knows his damned pin. Please clone, compile and try to sign with the pkcs11-tool:

pkcs11-tool -d <auth_key_id> -s

I wrote a little entry in my blog with the major changes needed for 3.0 if you want to review what I'm doing:

http://blogs.nologin.es/rickyepoderi/index.php?/archives/137-Starting-to-play-with-DNIe-3.0-and-OpenSC.html

@cameta
cameta commented Oct 17, 2016

I can access to a DNIe 2.0

@rickyepoderi
Contributor

@miguel-cv told me yesterday that current opensc implementation of the DNIe is working with 2.0. So there should be something else here. I'll try to figure out what the hell is happening with the getResponse. This weekend I'll try to move all the changes again to the current opensc branch and I'll check it twice. I deeply worry that I'm going to need a DNIe 2.0 (besides my time this thing is going to cost me some beers and snacks).

@rickyepoderi
Contributor

OK, I have the current OpenSC branch working now. The problem about the getResponse was that now we need to send something in the Le (>0) in order to force the getResponse to be called.

@germanblanco I see that you changed several apdus (for example in dnie_pin_verify) this way:

-       dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, p1, p2, 0, length,
-                                       NULL, 0, buffer, length);
+       dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x22, p1, p2, 255, length,
+                                       resp, MAX_RESP_BUFFER_SIZE, buffer, length);

So, you changed an APDU with no Le=0 (no response data) to another with Le>0 (now some response data is expected). Did you changed the APDUs for that reason?

Because now the secure channel is executed over the pin channel, and therefore I needed to change some other calls doing the same trick (cwa_verify_cvc_certificate, cwa_set_security_env,...).

Just a silly question, why not doing that in the wrapping method? Because the plain APDU has no return data expected (it is OK with Le=0), it is changed when wrapped cos the new apdu is of type 4 (the encoded response is the response data).

@rickyepoderi
Contributor

Hi,

I have uploaded a first version for DNIe 3.0 in my repo. You can test it:

https://github.com/rickyepoderi/opensc/tree/dnie30

As you know I don't have easy access for a DNIe 2.0 so, if you can test it with both, it would be much appreciated. I'm going to try to understand why it is needed to send CASE 4 apdus instead of 3 now. Because I think it should be possible to send a SC_APDU_CASE_3_SHORT without any problems.

@cameta
cameta commented Oct 22, 2016

I have tested it with both.
DNI 2.0
mestres@tux ~/dni30/bin $ ./pkcs11-tool -l -O
Using slot 0 with a present token (0x0)
error: PKCS11 function C_Login failed: rv = CKR_ARGUMENTS_BAD (0x7)
Aborting.
mestres@tux ~/dni30/bin $ ./dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
DNIe Version: DNIe 01.13 B11 H 4C34 EXP 1-((4.2-5))
DNI 3.0
mestres@tux ~/dni30/bin $ ./pkcs11-tool -l -O
Using slot 0 with a present token (0x0)
Segmentation fault
mestres@tux ~/dni30/bin $ ./dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
Failed to connect to card: Card is invalid or cannot be handled
Error: Cannot connect with card

@rickyepoderi
Contributor

@cameta I can believe you with DNIe 2.0 because I haven't tested anything with it. But with DNIe 3.0 it's weird because it's working for me:

ricky@magneto:/apps/opensc/bin$ ./dnie-tool -V
Using reader with a card: Broadcom Corp 5880 Contacted SmartCard 00 00
DNIe Version: DNIe 04.10 B5 H 0155 EXP 2-(5.2-0)
ricky@magneto:
/apps/opensc/bin$ ./pkcs11-tool -l -O
Using slot 0 with a present token (0x0)
Logging in to "PIN1 (DNI electrónico)".
Please enter User PIN:
Private Key Object; RSA
label: KprivAutenticacion
ID: 4130323035424244453037304631423230313631303130303835363237
Usage: sign
Certificate Object, type = X.509 cert
label: CertAutenticacion
ID: 4130323035424244453037304631423230313631303130303835363237
Public Key Object; RSA 2048 bits
label: CertAutenticacion
ID: 4130323035424244453037304631423230313631303130303835363237
Usage: encrypt, verify
Certificate Object, type = X.509 cert
label: CertCAIntermediaDGP
ID: 5330323035424244453037304631423230313631303130303835363237
Public Key Object; RSA 2048 bits
label: CertCAIntermediaDGP
ID: 5330323035424244453037304631423230313631303130303835363237
Usage: encrypt, verify
Private Key Object; RSA
label: KprivFirmaDigital
ID: 4630323035424244453037304631423230313631303130303835363237
Usage: sign, non-repudiation
Certificate Object, type = X.509 cert
label: CertFirmaDigital
ID: 4630323035424244453037304631423230313631303130303835363237
Public Key Object; RSA 2048 bits
label: CertFirmaDigital
ID: 4630323035424244453037304631423230313631303130303835363237
Usage: encrypt, verify
Data object 14532512
label: 'DG1'
application: ''
app_id:
flags: modifiable
Data object 14532608
label: 'DG11'
application: ''
app_id:
flags: modifiable
Data object 14532704
label: 'DG13'
application: ''
app_id:
flags: modifiable
Data object 14526976
label: 'DG2'
application: ''
app_id:
flags: modifiable
Data object 14527072
label: 'DG7'
application: ''
app_id:
flags: modifiable
Data object 14527168
label: 'DG3'
application: ''
app_id:
flags: modifiable
Data object 14527264
label: 'DG14'
application: ''
app_id:
flags: modifiable
Data object 14527360
label: 'EFCOM'
application: ''
app_id:
flags: modifiable
Data object 14527456
label: 'EFSOD'
application: ''
app_id:
flags: modifiable

@cameta
cameta commented Oct 23, 2016

My DNI 2.0 is working with opensc-0.16.0
dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
DNIe Version: DNIe 01.13 B11 H 4C34 EXP 1-((4.2-5))

@cameta
cameta commented Oct 23, 2016

You might have a different version of the DNI 3.0 that mine.

@rickyepoderi
Contributor

@cameta dni-tool works for DNIe 3.0 even in the 0.16 version. The only problem is that you cannot login. It works with 0.16.0 debian testing. So I think you have something weird with your DNIe 3.0:

ricky@magneto:~/apps/opensc/bin$ which dnie-tool
/usr/bin/dnie-tool
ricky@magneto:~/apps/opensc/bin$ dpkg -l | grep opensc
ii  opensc                                0.16.0-1                          amd64        Smart card utilities with support for PKCS#15 compatible cards
ii  opensc-pkcs11:amd64                   0.16.0-1                          amd64        Smart card utilities with support for PKCS#15 compatible cards
ricky@magneto:~/apps/opensc/bin$ dnie-tool -V
Using reader with a card: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
DNIe Version:  DNIe 04.10 B5 H 0155 EXP 2-(5.2-0)

With DNIe 2.0 I suppose that something is broken in my branch. I will need one to check what happens. I'll try to figure it out but it is going long because I have no easy access to a 2.0.

@cameta
cameta commented Oct 23, 2016

My identity card works in the machine of the police. Could the fault be in my reader?

@rickyepoderi
Contributor

@cameta Don't forget to checkout the branch dnie30 (master is just default OpenSC a few days ago, and now DNIe 3.0 is directly excluded in default):

git clone https://github.com/rickyepoderi/OpenSC.git
cd OpenSC
git checkout dnie30
./bootstrap
./configure --enable-dnie-ui --prefix=/donde/quieras
@miguel-cv

tested, works well for me with 2.0 and 3.0 .
@cameta remember to enable_pinpad = false in opensc.conf
and

card_driver dnie {
        # Disable / enable warning message when performing a
        # signature operation with the DNIe.
        # Only used if compiled with --enable-dnie-ui
        user_consent_enabled = yes;

        # Specify the pinentry application to use if warning
        # is configured to be displayed using pinentry.
        # Default: /usr/bin/pinentry
        # Only used if compiled with --enable-dnie-ui
        user_consent_app = "/usr/bin/pinentry";
    }

@emunicio

@rickyepoderi I get the error when compiling:

pkcs15-lib.c:2214:23: error: dereferencing pointer to incomplete type
GETBN(key->iqmp, rsa->iqmp, iqmp);

Am I missing something? I'm compiling with g++ 4.9.2

@rickyepoderi
Contributor

@emunicio Not related to my changes (I haven't modified anything in pkcs15) but it sounds related to openssl. Which version do you have?

@emunicio
emunicio commented Oct 24, 2016 edited

@rickyepoderi
I have: OpenSSL 1.1.0 25 Aug 2016
Anyway, thanks. I will try to find out what is happening with openssl

@dengert
Member
dengert commented Oct 24, 2016

@emunicio
Try using at least OpenSSL 1.1.0.a I don't get the error with:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2)
OpenSSL 1.1.0a 22 Sep 2016

In my source from github master 0362439
GETBN(key->iqmp, rsa->iqmp, iqmp); is line 2213, not 2214. Do you have and extra line in your source?

@rickyepoderi
Contributor

@emunicio @dengert In my branch is at line 2214 because I updated it when I started the work in 3.0 (two or three weeks ago):

https://github.com/rickyepoderi/OpenSC/blob/dnie30/src/pkcs15init/pkcs15-lib.c#L2214

I suppose some new change was made to that file during thatperiod. As I said, "pkcs15-lib.c" isn't modified in my dnie30 branch (indeed changes are exclusively related to DNIe files).

@dengert
Member
dengert commented Oct 25, 2016

Looking closer pkcs15init/pkcs15-lib.c , It looks like it had problems before converting to OpenSSL-1.1.0.

These two line a a clue to what may be going on:
2209 /* Not thread safe, but much better than a memory leak /
2210 /
TODO put on stack, or allocate and clear and then free */
There are 3 GETBN macro calls. Your compiler flagged only the last one.
key->iqmp is calculated in the routine and set to point at a static u8 iqmp[256];
That may be why the third GETBN gets the error and not the other two.

This routine needs to be rewritten and tested. (I can rewrite it, but someone else who uses it needs to test it.) (I will look at it tommorrow.)

@dengert
Member
dengert commented Oct 25, 2016
The problem could be in SM code in OpenSC, in combination with the
reader and the card. The APDU code looks at the protocol being used
T=0 or T=1.  T=1 is block mode and Le is sent to the card so it can
return the first block without requiring a getResponse  In T=0 all
data is returned via getResponses 

What readers are each of you using? 
Some only do T=0 some can do T=1.
Some cards can only do T=0.

OpenSC debugging traces would show if T=0 or T=1 is being used.
With SM encrypting the APDU, when using T=1 might require the Le to
be sent and a buffer provided. 

(I could be all wrong, but debugging traces would help a lot.)   


On 10/23/2016 2:04 PM, cameta wrote:


  My identity card works in the machine of the police. Could the
    fault be in my reader? 
  —
    You are receiving this because you are subscribed to this
    thread.
    Reply to this email directly, view
      it on GitHub, or mute
      the thread.







  {"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/OpenSC/OpenSC","title":"OpenSC/OpenSC","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/OpenSC/OpenSC"}},"updates":{"snippets":[{"icon":"PERSON","message":"@cameta in #810: My identity card  works in the machine of the police. Could the fault be in my reader?  "}],"action":{"name":"View Issue","url":"https://github.com/OpenSC/OpenSC/issues/810#issuecomment-255607376"}}}


-- 

Douglas E. Engert DEEngert@gmail.com

@cameta
cameta commented Oct 25, 2016

The code (after the edit of opensc.conf) now works for me with a DNI 2.0
mestres@tux ~/DNIE/bin $ ./pkcs11-tool -l -O
Using slot 0 with a present token (0x0)
Logging in to "PIN1 (DNI electrónico)".
Please enter User PIN:
mestres@tux ~/DNIE/bin $ ./dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
DNIe Version: DNIe 01.13 B11 H 4C34 EXP 1-((4.2-5))
The code doesn't work with a DNI 3.0
mestres@tux ~/DNIE/bin $ ./pkcs11-tool -l -O
error: PKCS11 function C_GetSlotInfo failed: rv = CKR_GENERAL_ERROR (0x5)
Aborting.
mestres@tux ~/DNIE/bin $ ./dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
Error: Get info failed: Unsupported INS byte in APDU

My card reader is a : USB SMARTCARD READER
usb 3-1: Manufacturer: C3PO (the manufacturer is out of business for bankruptcy)

@dengert
Member
dengert commented Oct 26, 2016
@rickyepoderi
Contributor
rickyepoderi commented Oct 26, 2016 edited

@cameta Very strange that even the dnie-tool -V gives you an error (all the modifications are inside the channel creation and dnie-tool does not initiate a login).

Put debug=9 in the opensc.conf file and execute the dnie-tool command to save the stderr to a file:

./dnie-tool -V 2>out.txt

And attach the file here. Let's see if I see something.

@cameta
cameta commented Oct 26, 2016

I think the problem is with the card reader. Such as you have asked me here is the debug from both the 2.0 and the 3.0 DNI.
outDNI20.txt
outDNI30.txt

@FeitianSmartcardReader
Contributor

I saw the issue of this reader, check #201

@rickyepoderi
Contributor

@cameta

The problem is in the APDU when reading the file "3F0050156004" (the first APDU inside dnie_get_info function). In DNI 3.0 when the file is read the card return an error (6D means "Instruction code not programmed or invalid"):

`Outgoing APDU (16 bytes):
00 A4 04 00 0B 4D 61 73 74 65 72 2E 46 69 6C 65 .....Master.File
0x7f0ce7195700 23:43:11.421 [dnie-tool] reader-pcsc.c:199:pcsc_internal_transmit: called
0x7f0ce7195700 23:43:11.422 [dnie-tool] reader-pcsc.c:279:pcsc_transmit: 
Incoming APDU (2 bytes):
6D 00 m.

Nevertheless the same APDU in 2.0 (same APDU and same reader) returns OK (61XX is good and means get_response to be called):

Outgoing APDU (16 bytes):
00 A4 04 00 0B 4D 61 73 74 65 72 2E 46 69 6C 65 .....Master.File
0x7fb13b342700 23:42:50.972 [dnie-tool] reader-pcsc.c:199:pcsc_internal_transmit: called
0x7fb13b342700 23:42:50.991 [dnie-tool] reader-pcsc.c:279:pcsc_transmit: 
Incoming APDU (2 bytes):
61 1B a.

It's the same APDU and before any of my changes. I would say that something is wrong with your DNIe physical card because 2.0 works and it's the same reader and the same code, but I really don't know.

@cameta
cameta commented Oct 27, 2016

I'll test again the DNI in the police station and I'll buy another card reader. Thanks for all.

@dengert
Member
dengert commented Oct 27, 2016

@cameta Looking at https://github.com/OpenSC/OpenSC/files/554497/outDNI20.txt and https://github.com/OpenSC/OpenSC/files/554498/outDNI30.txt
The ATR in the first is: 3b:7f:38:00:00:00:6a:44:4e:49:65:20:02:4c:34:01:13:03:90:00
and ATR in second is: 3b:7f:96:00:00:00:6a:44:4e:49:65:20:01:01:55:04:10:03:90:00

The DNIe 3 code is testing in may places for:
(card->atr.value[15] >= DNIE_30_VERSION) that is defined as 4

Is this the same card?
You said you changed the opensc.conf did you force an ATR?
If you did, the code is assuming a DNIe 3.0 card.

A pcscd debug output would show the ATR before OpenSC code gets control.

@rickyepoderi
Contributor

@cameta I have just tested with my DNIe 3.0 and that APDU is sent exactly as in your 2.0 (no problem):

Outgoing APDU (16 bytes):
00 A4 04 00 0B 4D 61 73 74 65 72 2E 46 69 6C 65 .....Master.File
0x7ff89b2b8700 19:27:19.473 [dnie-tool] reader-pcsc.c:199:pcsc_internal_transmit: called
0x7ff89b2b8700 19:27:19.481 [dnie-tool] reader-pcsc.c:279:pcsc_transmit:
Incoming APDU (2 bytes):
61 1B a.

@dengert The ATR is ok, the atr.value[15] is 01 in DNIe 2.0 and 04 in DNIe 3.0. So it's as expected. Think that dnie-tool does not even use any of the changes required for DNIe 3.0, as I said in a comment above, opensc 0.16 can do a dnie-tool with a DNIe 3.0 (because it was excluded from the match later).

@miguel-cv has tested my changes OK with 2.0 and 3.0. And I have changed my mind and I think now that changing something for the CASE 4 apdus is a mess and I would require changes in non dnie code. So I think is better to first add support to 3.0 and re-think that later.

My idea is the following: give more time (some days) and let other people test my changes (I'm waiting the confirmation from some friends) and then submit a pull request. How do you see it?

@dengert
Member
dengert commented Oct 27, 2016

My impression was that @cameta was using one card, with two different versions of the software. If he has two cards that is different.

Change the type 3 to type 4 APDUs (which I don't see in the debug log) could be a problem. The reader may get involved, as (I believe) with T=0 the reader gets involved, and it may be returning the 6D00

A pcscd debug log might show more then the opensc debug log.

@miguel-cv
miguel-cv commented Oct 27, 2016 edited

Here you have it (i have one of those readers too) http://pastebin.com/ukTVgZMy .
I remember doing a firmware update to make it work with dnie card...but now it's not working, so maybe @dengert is in the correct path.
But here comes the funny thing...with my old dnie it works (sometimes).....
EDIT: Here is a working log with dnie 2.0 http://pastebin.com/CdfKJNyd

@dengert
Member
dengert commented Oct 27, 2016

The logs dont show the APDU traffic.
You also need the pcscd -a option. Something like:

sudo /usr/sbin/pcscd -f -d -a

@cameta
cameta commented Oct 27, 2016

If he has two cards that is different.

I have two cards. One is a DNI 2.0 and the other is a DNI 3.0.

@rickyepoderi
Contributor

Change the type 3 to type 4 APDUs (which I don't see in the debug log) could be a problem. The reader may get involved, as (I believe) with T=0 the reader gets involved, and it may be returning the 6D00

@dengert The change is done in code when a secure channel is established (it's like this since the beginning of DNIe):

https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/cwa14890.c#L1490

The cametas's error happens previously (no secure channel is opened in a dnie-tool execution) and that part of code is more or less the same since the dnie was integrated in opensc. I don't know if it's a problem of the reader or the card but, what I'm saying, is that it's not related with the 3.0 integration. It's something else and it should happen without my changes.

@dengert
Member
dengert commented Oct 28, 2016

I agree that there is something different about his environment.

This could be caused by his reader and he said he is going to buy a new reader.

It could also be his card that may be different then your card. (I don't know much about DNIe cards) maybe his card is newer or older then yours and not quite the same.

It may be some other change in OpenSC.

Or a combination of any of the above.

A pcsc trace would be helpful in determining what else could be going on while waiting for @cameta to buy a different reader.

An example of OpenSC changes: Commit 60f2d06 introduced on 6/20/2016 in reader-pcsc.c by @frankmorgner and @viktorTarasov sends a APDU FF CA 00 00 00 with return status of 6E 00 from the initialize_uid(). This is done before the card is matched. It reads the Card UID. But ISO 7816-4-2013 section 5.4.1 Class byte Coding) says:
"Bit b8 set to 1 indicates the proprietary class, except for the value 'FF' which is invalid due to specifications in ISO/IEC 7816-3.

It is not clear if this above should be done for every card or reader, as one or the other may not handle it properly. both debug logs of @cameta show the FF CA 00 00 00 with return status of 6E 00.

Do you see this APDU in any debug logs with working DNIe 3 card?

@rickyepoderi
Contributor

@dengert Yes, that APDU is to read a file and the same one is sent every time you execute a dnie-tool command. A copy of that APDU in my own DNIe 3.0 is pasted above:

#810 (comment)

And it's working for other DNIe 3.0 like @miguel-cv or some other friends of mine. (As I said it worked even before my changes. You have always been able to execute dnie-tool successfully over a DNIe 3.0 until it was explicitly excluded from OpenSC. The problem with 3.0 is inside login as @Yajo explains in this same bug.)

@frankmorgner
Member

FF CA 00 00 00 is defined by PC/SC pt. 3:
bildschirmfoto vom 2016-10-29 01 25 31
It should be handled by the IFD, not by the card.

@dengert
Member
dengert commented Oct 29, 2016

But PC/SC also says:

"3.2.2 Contact/Contactless Environment Specifics
3.2.2.1 Storage Card Functionality Support
This section defines commands for Storage Cards (Exception : The Get UID and Load Key command, which may be used for all kinds of contactless cards)"

The Get UID is for contactless cards.

3.2.2.1.3 is in the "3.2.2.1 Storage Card Functionality Support"

Table 3-0: GET DATA Error Codes only defines 6282, 6A81 (Function not supported) and 6CXX

The way I read all of this is FF CA 00 00 is for contacless only cards, and the IFD for a contact card would just pass it on to the card and the card is returning the 6E 00. It might have other consequences.

ISO 7816-4 says:
"Bit b8 set to 1 indicates the proprietary class, except for the value 'FF' which is invalid due to specifications in ISO/IEC 7816-3."

OpenSC should not be sending this command to every card. Its a proprietary command and may have side effects. If there is some card that can handle it, it could be sent by the card driver after the card is matched.

It sounds like FF CA 00 00 may not be the issue for the DNIe card

@dengert
Member
dengert commented Oct 29, 2016

@frankmorgner
Doing some tests with pcscd -a -f -d and running: opensc-tool -a

With reader: SCM Microsystems Inc. SCR 355
WIth these cards:
GenALto PIV 1.5.5Dlv1 ( NIST demo card #1) returns 6884
Oberthur ID-One PIV (TypeA) (NIST demo card #2) returns 6881
Old GemSafe card returns 6D00
This looks like command is being passed on to the IFD, which passes it on to the card. None of the cards understand what to do with it, because 7816-4 says it is not valid.

Using a contactless reader: ACS ACR122U PICC Interface with contactless cards:
Oberthur ID-One PIV (TypeA) (NIST demo card #2 same card as above) returns 1B DB 62 0A 90 00
SmartCard-HSM v1.2 DECCC02 returns 04 23 3E C2 28 28 80 90 00
Yubico With serial 3XXXXXX returns 04 3B 13 12 CA 36 80 90 00

Run on Ubuntu-16.4
pcscd-1.8.14-1ubuntu1
libccid-1.4.22-1ubuntu0.1

The above tests indicate FF CA 00 00 should not be sent by default, as there are unknown consequences depending on the reader and/or card. The call in reader-pcsc.c: initialize_uid(reader); should be removed or made optional for contactless reader only, or only called from a card driver.

@dengert
Member
dengert commented Oct 29, 2016

@cameta
If you are willing, can you comment out in reader-pcsc.c:
553 initialize_uid(reader);
and run your DNIe 3.0 test again?
Its a simple test, and would show if the FF CA 00 00 is causing problems with your reader or card.

@miguel-cv
miguel-cv commented Oct 29, 2016 edited

@dengert i tested that change with the "broken" reader, and it's working 100%....let's wait for @cameta to confirm....

@frankmorgner
Member
frankmorgner commented Oct 31, 2016 edited

@dengert agreed to make the request for the UID optional and disabled by default. (Note, however, that it's still a problem with the reader (driver) that doesn't behave according to PC/SC.)

I suggest to enable/disable the request for the UID by using the enable_boxing switch from #831, which adds PIN verification commands that are based on CLA=0xFF.

@dengert
Member
dengert commented Oct 31, 2016

I believe the reader drivers are behaving as expected. The FF CA 00 00 is for CONTACTLESS readers only.
and was added to PC/SC to support getting a UID from a storage card. We are not supporting "storage cards".

For a contact reader, the command is just another proprietary command to be sent to the card.

@frankmorgner why did you commit: 60f2d06
The text of the commit says "For file caching, use UID if SN is not available."
But you are requesting the UID even before you know if there is a serial number.
What cards does it work with?
What readers did you test it with?

60f2d06 effects every card in ways we may not yet know.
It is not a DNIe only problem and not a PIN problem either. It has nothing to do with the boxing.

I was agreeing to only send it to the cards that understood the command. That is controlled by the card drivers. And some card drives may derive a UID form other data, not using any UID that may be gotten using the FF CA 00 00.

I would say 60f2d06 should be reverted, or modified to say if no serial number is provided by the card driver, then files will not be cached.

If you have cards that can support FF CA 00 00 but do not provide a serial number, add the code to the card driver to issue the FF CA 00 00 and return it as the serial number.

@frankmorgner
Member

Let's stay factual. PC/SC pt 3 clearly states that Get Data should also work for contact based card:

bildschirmfoto vom 2016-10-31 14-30-11

Again, I want to stress that it's a command that should not be answered by the card but by the reader (IFD). The problem is that since this is an optional IFD command, I'm not sure whether there is a possibility to probe the IFD if it implements this command. I'm encouraging everyone to read the standard and point to a good solution. Maybe @LudovicRousseau can bring some light into this.

I'm suggesting to use the enable_boxing switch because Get Data, as well as the PIN verification from #831 are extensions of the IFD that are wrapped into ISO 7816 APDUs with CLA=FF. It's the same logic that may or may not be implemented by the IFD. Additionally there are some more commands, that can be wrapped, e.g. for getting the reader's firmware version or the reader's vendor that are propagated via PKCS#11 with #831.

I've tested this with contactless JCOP and contact-only CardOS cards (see also the discussion in #804), with both, contacless and contact-only readers. Of course, the UID isn't always retrieved, but that is never a problem since it's a command that is only issued during card recognition. Similarly to a card driver that issues a SELECT AID to an application that is not available, the Get Data command should not have a bad impact on the DNIe. Skimming the discussion above I cannot say what kind of bad bahaviour FF CA 00 00 is causing. Could someone please detail the actual problem?

@frankmorgner
Member

@cameta have you tried upgrading the firmware of your reader as suggested in #201 (comment)?

@dengert
Member
dengert commented Oct 31, 2016

@frankmorgner
I showed you different cards from major manufactures that all reported different status bytes. You should know by now that we are working with cards, readers, OSes and applets on cards that don't follow standards as one might expect. And you are expecting them all to support some obscure command before the card driver even gets control.

Your commit message even says "For file caching, use UID if SN is not available." Your code does not even given the card driver a chance to read the serial number before you run the obscure command.

Could someone please detail the actual problem?
My first concern is the problem @cameta has with his DNIe 3.0 card with the reader he has. I contend that the obscure command causes the reader or card to change state or cause some internal problem.

We are waiting for @cameta to test this hypothesis by commenting out the call to initialize_uid(reader); and running his test.

My second concern is you are sending the obscure command to cards I am concerned about, when it is not needed. There is no reason to do this. It can only cause problems with other cards too. The whole point of the card match routines is to select the card driver based on ATR or AID before sending any card specific command to the card. A better place for this type of command would be in the card driver
if it knew the card could handle it.

Irregardless of the outcome of tests by @cameta 60f2d06 needs to be fixed.

@frankmorgner frankmorgner added a commit to frankmorgner/OpenSC that referenced this issue Oct 31, 2016
@frankmorgner frankmorgner reader-pcsc: use enable_boxing for UID command
allows disabling wrapped commands with CLA=0xFF on broken readers, see
OpenSC#810
4bd0e42
@frankmorgner
Member

I added the workaround here frankmorgner@4bd0e42

@dengert
Member
dengert commented Oct 31, 2016

It looks like BSI-TR-03119_V1 only defines FF 9A 01 XX XX and FF 9A 04 XX. I do not see how FF CA 00 00 is related to BSI-TR-03119_V1.

Your workaround addresses my concern as I would not be using the boxing flag, but I think it is the wrong thing to do.

Good luck.

@frankmorgner
Member

Please have a look at PC/SC pt. 3, at least once. You will come to the conclusion that...

  1. it is neither obscure nor proprietary. It was written by all major OS and reader vendors, which are part of the PC/SC working group.
  2. the commands with CLA=0xFF are not defining the communication to the card, but instead defining communication to the reader. In consequence, they should not be of relevance for a card driver in OpenSC.
  3. The structure of the boxing commands is identical to those of BSI TR-03119. If a reader does not support the format of the latter standard than it does not support the format of PC/SC's Get Uid. Hence, it makes sense to reduce this to a single configuration option.

I disagree that we need to fix the usage of a reader that is being reported to be broken in more than one way. However, I agree to disable sending APDUs with CLA=0xFF, by default, which is what frankmorgner@4bd0e42 is doing. In result, this default should even work for the broken C3PO LTC31 v2 reader.

If there is more need to discuss the usefulness of the UID or the boxing commands, I think we should do this in a separate issue. Otherwise, I'm looking forward for the PR for supporting DNIe 3.0 in OpenSC.

@cameta
cameta commented Oct 31, 2016

have you tried upgrading the firmware of your reader as suggested in #201 (comment)?

Yes, i have tried. I have downloaded the firmware from arxiv.org (the manufacturer is out of business) but in linux (wine) the program didn't work.

@frankmorgner frankmorgner added a commit to frankmorgner/OpenSC that referenced this issue Nov 1, 2016
@frankmorgner Frank Morgner + frankmorgner Added support for PIN commands via escape commands
As defined in BSI TR-03119 to issue SCardTransmit (with Uses
Pseudo-APDU) instead of SCardControl (with FEATURE_VERIFY_PIN_DIRECT).
It allows using a very basic PC/SC reader driver without special support
for PIN verification or modification (such as the default CCID driver on
Windows).

Also gets IFD vendor information via escape commands.

PC/SC's Get Uid command is now only triggered if enable_escape = true;
was set by the user to allow disabling wrapped commands on broken
readers (see OpenSC#810)
dcdd6be
@frankmorgner frankmorgner added a commit to frankmorgner/OpenSC that referenced this issue Nov 1, 2016
@frankmorgner Frank Morgner + frankmorgner Added support for PIN commands via escape commands
As defined in BSI TR-03119 to issue SCardTransmit (with Uses
Pseudo-APDU) instead of SCardControl (with FEATURE_VERIFY_PIN_DIRECT).
It allows using a very basic PC/SC reader driver without special support
for PIN verification or modification (such as the default CCID driver on
Windows).

Also gets IFD vendor information via escape commands.

PC/SC's Get Uid command is now only triggered if enable_escape = true;
was set by the user to allow disabling wrapped commands on broken
readers (see OpenSC#810)
0c07e34
@dengert
Member
dengert commented Nov 2, 2016

@frankmorgner in response to: #810 (comment) above: "Please have a look at PC/SC pt. 3, at least once."
I did: see #810 (comment) which is why I said " The FF CA 00 00 is for CONTACTLESS readers only."

pcsc3_v2.01.09
3.2 Optional Functionality
"IFD subsystems may implement optional functionality, as described in the following sections. Again provisions that apply to both contact and contactless environments are presented first. Specific provisions follow."
3.2.1 Common Functionality
3.2.2 Contact/Contactless Environment Specifics
3.2.2.1 Storage Card Functionality Support
This section defines commands for Storage Cards (Exception : The Get UID and Load Key command, which may be used for all kinds of contactless cards):

My argument was that the Get UID is for contactless only cards and is an optional feature.
(The one contactless reader I have supports it and the UID was obtained from 3 cards in my example:
#810 (comment)

You original commit did not test if the reader is contactless or if the reader supported Get UID.
It just sent the Get UID APDU FF CA 00 00 and for a reader that did not support Get UID the command is passed on to the card.

In response to: "it is neither obscure nor proprietary"
OpenSC is sending APDUs based on ISO 7816-4 which says:
5.4 Class byte
5.4.1 Coding
"Bit b8 set to 1 indicates the proprietary class, except for the value 'FF' which is invalid due..."

Which says it is proprietary and even invalid.
Sending a APDU with class FF actually violates 7816-4. Which is why (in my option) PC/SC limits it to contactless only and made it optional.

You latest commits address the optional and contactless issues by making the use of GET UID optional in opensc.conf.

@dengert
Member
dengert commented Nov 2, 2016

@cameta we would still like to see if removing the initialize_uid call in reader-pcsc.c when used with your old reader and DNIe3 card make any difference.

@cameta
cameta commented Nov 3, 2016

Commented out in reader-pcsc.c:
/initialize_uid(reader);/
make install give me this warning
reader-pcsc.c:473:13: warning: ‘initialize_uid’ defined but not used [-Wunused-function]
static void initialize_uid(sc_reader_t *reader)
./dnie-tool -V
Using reader with a card: C3PO LTC31 v2 (00509883) 00 00
Error: Get info failed: Unsupported CLA byte in APDU
./dnie-tool -V 2>outdni30_initialize_uid.txt
outdni30_initialize_uid.txt

@miguel-cv

As i said, for me it's working well commenting out initialize_uid . The only difference is (i think) the firmware version. Here's what lsusb says about mine: http://pastebin.com/cGVLy34P

And here is the start of log from the same operation as @cameta : http://pastebin.com/dv1wbE72

@dengert
Member
dengert commented Nov 3, 2016

@cameta The last trace failed much earlier and did not even get to the /*initialize_uid(reader);*/ line.

Line 13:
reader-pcsc.c:1290:pcsc_detect_readers: C3PO LTC31 v2 (00509883) 00 00:SCardConnect(SHARED): 0x80100001

This is: SCARD_F_INTERNAL_ERROR while trying to detect reader features. This sounds like a bad reader. Maybe the attempt to update the firmware made things worse?

@cameta
cameta commented Nov 3, 2016 edited

This sounds like a bad reader

I'll buy another.

@FeitianSmartcardReader
Contributor
FeitianSmartcardReader commented Nov 3, 2016 edited

You can buy a reader from us. Our r502 has passed test by FNMT. Go to http://ftsafe.com/onlinestore/product?id=12 to place one for usage. R502B with C9 casing. Thanks 

@rickyepoderi
Contributor

Finally I have had access to a DNIe 2.0 this morning and I could test it by myself. It is working with 2.0 and 3.0. Besides I have implemented a little test for DNIe you can find in one of my repos:

https://github.com/rickyepoderi/dnie-pkcs11-tester

The tester works ok for both DNIe types. Besides I have used it with some governmental pages here in Spain. In general (based on my numbers) I know of 5 people that have tested DNIe 3.0 and 3 which have tested 2.0. So I think it is ready.

What do you think? Do I submit a pull request?

@germanblanco
Contributor

Congratulations!!
Great work!
I will take a look at the changes. If you don't mind to wait for a week
more, I might be able to comment on something.

On Sat, 12 Nov 2016 at 15:21, rickyepoderi notifications@github.com wrote:

Finally I have had access to a DNIe 2.0 this morning and I could test it
by myself. It is working with 2.0 and 3.0. Besides I have implemented a
little test for DNIe you can find in one of my repos:

https://github.com/rickyepoderi/dnie-pkcs11-tester

The tester works ok for both DNIe types. Besides I have used it with some
governmental pages here in Spain. In general (based on my numbers) I know
of 5 people that have tested DNIe 3.0 and 3 which have tested 2.0. So I
think it is ready.

What do you think? Do I submit a pull request?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#810 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ADw7I8Buep6OqkusJeiCIzT6VLCX9vExks5q9ctfgaJpZM4I-hbl
.

@rickyepoderi
Contributor

@germanblanco No problem, go for it.

@germanblanco
Contributor

It looks very good. The code changes are also very clean.
I thought it was going to require more changes to add the support.
The blog entry is also nice, although it requires an update now, I guess.
Nothing to comment.

On Sun, Nov 13, 2016 at 10:12 AM, rickyepoderi notifications@github.com
wrote:

@germanblanco https://github.com/germanblanco No problem, go for it.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#810 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ADw7I_RrvRbRVPQNlu2dIZty7wtlC4MWks5q9tR8gaJpZM4I-hbl
.

@rickyepoderi
Contributor

@germanblanco Have you tested with both DNIe versions? (Just to know it).

@frankmorgner frankmorgner added a commit to frankmorgner/OpenSC that referenced this issue Nov 15, 2016
@frankmorgner Frank Morgner + frankmorgner Added support for PIN commands via escape commands
As defined in BSI TR-03119 to issue SCardTransmit (with Uses
Pseudo-APDU) instead of SCardControl (with FEATURE_VERIFY_PIN_DIRECT).
It allows using a very basic PC/SC reader driver without special support
for PIN verification or modification (such as the default CCID driver on
Windows).

Also gets IFD vendor information via escape commands.

PC/SC's Get Uid command is now only triggered if enable_escape = true;
was set by the user to allow disabling wrapped commands on broken
readers (see OpenSC#810)
be3c600
@frankmorgner frankmorgner added a commit to frankmorgner/OpenSC that referenced this issue Nov 16, 2016
@frankmorgner Frank Morgner + frankmorgner Added support for PIN commands via escape commands
As defined in BSI TR-03119 to issue SCardTransmit (with Uses
Pseudo-APDU) instead of SCardControl (with FEATURE_VERIFY_PIN_DIRECT).
It allows using a very basic PC/SC reader driver without special support
for PIN verification or modification (such as the default CCID driver on
Windows).

Also gets IFD vendor information via escape commands.

PC/SC's Get Uid command is now only triggered if enable_escape = true;
was set by the user to allow disabling wrapped commands on broken
readers (see OpenSC#810)
ed988ba
@rickyepoderi rickyepoderi referenced this issue Nov 16, 2016
Closed

Dnie30 #903

@rickyepoderi
Contributor

I have submitted the pull request #903. Comment me if you see any problem.

@rickyepoderi
Contributor

There has been a little error in the committing of the pull request. When I was ready to send the pull a previous change affected the same code and the pull was not clean. So I did a merge from default to my branch, my fault, I should have done a rebase. @viktorTarasov committed everything except the conflicting part (just a few lines) so that part is missing. I'll try to prepare another little push later when I come back home. Sorry, I'll remember to rebase next time.

@rickyepoderi
Contributor

Ok, I tried yesterday to submit the lost change but @germanblanco commented me that firefox requested him the password twice sometimes. It was impossible to me to reproduce the error until yesterday (suddenly it started to happen to me and several times when using firefox or chrome).

The problem is the DNIe 3.0 returns 6982 (Security status not satisfied) with no obvious reason. Last night I finally give up but today I tried again and I have seen the following code in the Spanish goverment implementation (file Comm_DNIe.cpp in the method to sign):

     void CComm_DNIe::SignMech ( CMech * pMechanism, byteBuffer & data, byteBuffer & signature )
    {
            bool bRetry = true;

            while(bRetry)
            {
                    bRetry = false;
                    ...

                    try{
                            sendAPDU( cmd, signature );
                    }
                    catch (Pkcs11Exception & e)
                    {
                            // Si ha ocurrido el error 6982, intentamos presentar pin de caché
                            if( ( m_DniType==0x02) &&
                                    ( e.getErrId() == 0x80106982) )  <---- if DNIe 3.0 and error 6982
                            {
                                    this->RestorePIN();  <---- Use the pin chache to relogin
                                    bRetry = true;   <---- and retry
                            }
                            else
                                    throw e;
                    }
            }
    }

So, it seems to me that DNIe 3.0 has something weird and sometimes (I don't know the conditions cos it always works with pkcs11-tool and my dnie-pkcs11-tester) it returns 6982 when performing a signature. The solution done in the official implementation is to relogin.

Although the relogin should also work with opensc (if pin cache is activated) there was a problem in dnie because now you need to change both (status in dnie and status in opensc SM) when COLD or OFF is requested. This was regressed with the commit that make dnie use the opensc sm methods.

In summary, I have created another branch and I included two things:

  • The change lost in the commit (remember I did a merge instead a better rebase, sorry again).
  • Deactivate SM completely (both marks) when resetting or closing the SM in dnie.

I have created another branch with this:

https://github.com/rickyepoderi/OpenSC/tree/dnie30b

@miguel-cv Did you see in your tests this problem previously? (As I said I couldn't reproduce it until yesterday, but now it is extremely easy to reproduce... Very weird.)
@germanblanco @miguel-cv Please test it again with 2.0 and 3.0.

If the issue is a general problem for DNIe 3.0, it's strongly recommended to use the pin cache in opensc with the 3.0 version.

@dengert
Member
dengert commented Nov 22, 2016 edited

What you describe could be the card is requiring a verify command immediately before a signature operation using the signature key. In PKCS#11 it is called CKA_ALWAYS_AUTHENTICATE in PKCS#115 is user-consent.
For example, the PIV card it is called PIN ALWAYS APDUs between them. (Its in some ISO 7816 manual that I can not find at the moment.)

It could also be caused by interference by some other process issuing commands to the card that reset the security status.

@rickyepoderi
Contributor

I think you are right @dengert. I've just modified my tester in oder to be able to sing more than once in a single login and (if I disable the pin cache) it always fails at the second try (both keys --sign and --auth).

./dnie-pkcs11-tester --auth --times=2
password: 
Starting check_dnie_inserted...
  Found 1 slots...
  Found slot: 0 - "Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00 Broadcom Corp                   "
  Found token: "PIN1 (DNI electrónico)         DGP-FNMT                        PKCS#15 emulated0205BBDE070F1B  "
Found DNIe at slot 0
Starting check_sign with KprivAutenticacion...
  Signature done successfully
  Verification done successfully
Error in C_Sign [CKR_USER_NOT_LOGGED_IN]

I think that my problem was that I first tried with the old version of opensc (relogin worked) and then I changed to the new version (relogin was broken). So I though that everything worked (I'm sure I did a test using firefox but maybe just one page).

So I have now two questions for different groups:

@germanblanco @miguel-cv
Can you check with my new dnie_pkcs11_tester and the use_pin_cache set to false in opensc.conf? (Sorry but I even thought that my DNIe was broken.)

@dengert @frankmorgner and the rest of the opensc team...
If the other people confirm that DNIe 3.0 keys are CKA_ALWAYS_AUTHENTICATE, the best way of going is marking them as such, isn't it? (Not continuing doing the relogin and so on.)

@dengert
Member
dengert commented Nov 25, 2016

If the PKCS#15 user_consent flag in a sc_pkcs15_object is set to 1, it will set the PKCS#11 CKA_ALWAYS_AUTHENTICATE attribute and pkcs15.c and pkcs15-pin.c will try and do the right thing. (Note: As best I can tell, "user_consent" has nothing to do with the user_consent_app or user_consent_enabled in card-dnie.c)
FireFox and Thunderbird should support the use of CKA_ALWAYS_AUTHENTICATE. a SPY trace would show this.

I would say try setting the user_consent on the signing private key and see what happens. Should be a one or two line modification. I would suspect that the AUTH key would not need it.

See the comments in opensc.conf dealing with pin_caching including pin_cache_ignore_user_consent.

Also look at the APDUs being sent to the card to make sure your code or a request from the calling application is not causing some APDU to be sent to the card between the verify and the sign operation. While working with FireFox a few years ago, FireFox was trying to read the certificate again by trying to read every object on the card. A fix to the PKCS#11 search template in Mozilla to only look for certificates, combined with the fact the PIV card had already cached all the certificates meant the FireFox request could be done without sending additional APDU to the card.

Do you have a opensc debug log to look at?

@rickyepoderi
Contributor

It wasn't firefox, the tests were done with my tester (you can check the code in my repo, the link is in a comment above). And I started just iterating over the signature (only the sign operation), no strange operation between.

And the real problem is that both keys present the same behavior, authentication (normal) and signature (non-repudiation). That's why @germanblanco advise me about firefox requesting the pin (he was not signing anything, he was just browsing an https page). And that's the big issue, firefox is going to ask for the pin like crazy when opening the connections against any site requiring client certificate. In the sign key is nice feature and even recommendable but not in the auth one.

IMHO this is a incredible mistake and a difficult to believe decision. That's why I'm asking for confirmation. Nevertheless @miguel-cv sent me some extracts of information (in Spanish) that seems to corroborate that the keys are CKA_ALWAYS_AUTHENTICATE but, as always, it's not clear if just one, the other or both.

@rickyepoderi
Contributor

I have done a quick test with CKA_ALWAYS_AUTHENTICATE. The flag was added to the two keys in DNIe 3.0. The behavior is different in chrome and firefox (the tests were done with the pin cache disabled):

  • Chrome (chromium in my case) seems to not follow CKA_ALWAYS_AUTHENTICATE. It seems to work inside the same site but as soon as you go to another that also requests the certificate it fails. Reloading the page you are asked again for the pin and it works. With use_pin_cache=true and pin_cache_ignore_user_consent=true it works with no problem.
  • Firefox respects the CKA_ALWAYS_AUTHENTICATE but prompts for the pin as many times as it needs, and it needs it a lot more than chrome inside the same site (In some cases I needed to type the pin four or five times). This prompting cannot be avoided using any configuration (firefox or opensc).

I don't know, let's wait the other Spanish guys to confirm that both keys are CKA_ALWAYS_AUTHENTICATE but now I worry that this is the expected behavior with DNIe 3.0.

@dengert
Member
dengert commented Nov 26, 2016

Here is something to look at...
DNIe 3.0 is a PKCS15 card. sc_pkcs15emu_dnie_init looks like it calls sc_pkcs15_parse_df which allocates sc_pkcs15_object This should eventually call asn1_decode_p15_object which may set user_consent in this line:
sc_format_asn1_entry(asn1_c_attr + 3, &p15_obj->user_consent, NULL, 0);
(I can not trace the code path, you could use a debugger break on asn1_decode_p15_object to see what if it ever gets set. in the sc_pkcs15_object.

It could be the card issuer did not set it correctly or set it on the auth key when it should not have been set. Thus, OpenSC is not enforcing it when it should, or is enforcing it when it should not.

If the card issuer did not set it correctly or set in on the wrong key, a fix could be applied to set it the way the card appears to enforce it.

@dengert
Member
dengert commented Nov 28, 2016

Is the code for your dnie-pkcs11-tester available? I don't see it in your repro.

@rickyepoderi
Contributor

Yes, it's available here:

https://github.com/rickyepoderi/dnie-pkcs11-tester

Yesterday @miguel-cv confirmed that the second signature fails with the authentication key and use_pin_caching=false. So I think we can be sure that both keys are CKA_ALWAYS_AUTHENTICATE in the new DNIe 3.0. The keys aren't tagged as that (I checked with the official pkcs#11 library and the library does not even recognize the attribute). Now we have to decide how to deal with this, I see only three (or four) possibilities but no one is perfect in my opinion:

  1. Mark both keys as CKA_ALWAYS_AUTHENTICATE programmatically. This way firefox asks a lot for the PIN and chrome should be configured as legacy in opensc. In my opinion this is the correct solution but far from perfect.

  2. Do not mark the keys as CKA_ALWAYS_AUTHENTICATE and use the pin cache to relogin. This works 10 times by default (this is the default number configured in opensc.conf but it can be increased) with all applications. But this is a big trick, only works if the cache is activated (by default it is) and do not respect the idea inside DNIe 3.0.

  3. This is indeed a mix of the previous solutions, we mark as CKA_ALWAYS_AUTHENTICATE the signature key (non-repudiation) and don't mark the authentication key. This avoids the problem with firefox but it is almost the same trick than (2) for the authentication one.

  4. Finally we can relogin internally inside the DNIe driver code. I mean, we wouldn't use the pin cache for the signature problem and just re-login (storing the pin inside the card info at login) by ourselves. This one is implementing the trick but internally, not affecting the opensc configuration. In this solution we can tag the keys as CKA_ALWAYS_AUTHETICATE or not but I suppose if we go this way the idea would be not tagging them and just re-login all the time.

I'm not sure what to do, there is no perfect solution and all the four have problems. I'm finally being more favorable for the first solution. It works although it's very annoying in firefox and no trick is involved (we also respect the idea of the DNIe 3.0 of being CKA_ALWAYS_AUTENTICATE). But I'm not completely sure, so I'm open to accept any option you like , of course, if you see another solution please add to the four I presented.

@dengert
Member
dengert commented Nov 29, 2016

The above choices would be up to the DNIe users. I do not have a DNIe card. As you pointed out the official DNIe PKCS#11 package caches the pin internally, so (choice 4) mimics what the official package does.

Is there any documentation on why DNie3 treats both keys as userConsent/CKA_ALWAYS_AUTENTICATE?
Was it an accident?

If that was the intent to have userConsent enforced by the cards and the PKCS#15 object does not have the userConsent value set that could be considered a bug and reported to the DNIe issuers.

@dengert
Member
dengert commented Nov 29, 2016

Two other thing to look at:
Iis there anyway the SM code could be causing the security status to be reset?

Look at disconnect_action in opensc.conf

@rickyepoderi
Contributor

I didn't find any documentation about this behavior but @miguel-cv sent me an old link that talks about an issue in the official pkcs#11 library that affected to mac and linux systems. The page is retired but it can be accessed via the web archive:

https://web.archive.org/web/20160522103152/http://www.dnielectronico.es/PortalDNIe/

It's in Spanish (you can use google translate or similar) but my translation is the following:

The DNIe 3.0 is developed following the most advanced European regulation, like EN14890, which defines the requirement of presenting the PIN before any signature operation, therefore if several signatures are going to be performed one after the other, the PIN should be presented before each operation and there are applications that do not follow this requirement, because they give for granted that if the PIN is presented once is enough for all the signatures.

In order to fix this issue, the applications should follow the European regulation, and present the pin before each signature.

This situation makes that the signature process fails with DNIe 3.0 in those applications or systems that use the PKCS#11 module, like Mac OS X machines or firefox browser, when consecutive signatures are requested without presenting the PIN before each one.

This issue does not happen with Internet Explorer and Windows machines because the driver (Card Module in Windows) is able to present the PIN in each signature process although the application does not follow the regulation.

I think this is the issue that made them include the cache and relogin I showed in their code. So, it is almost sure the CKA_ALWAYS_AUTHENTICATE is done on purpose. But I also think they didn't understand completely the implications of that decision. It seems that in windows it works different and they supposed that everything should act in the same way (which is obviously not true).

Please, it would be nice if all the people involved in the issue give his/her opinion to the final solution to implement. I have no preferred solution at all and I'm going to implement the one that most of you like.

@frankmorgner
Member

Typically, the intention of non-repudiation is that the user is fully aware of what he's doing (i.e. what he's signing). If the middleware chooses to magically give consent in his place, the user would certainly not be fully aware of this.

I'd recommend to keep CKA_ALWAYS_AUTHENTICATE for the non-repudiation key. But I'd use pin-caching for the key that's meant for user authentication. The latter key is surely not meant for lawfully binding signatures and so it is less critical. Also, this should be the only key being used in Firefox or Chrome since it's the only key that's useful for client authentication.

You may tweak the DNIe driver to modify the caching behavior so that the cache count doesn't get reduced for the key, if you think ten re-validations are not sufficient. (Please first check whether the key for user authentication does require the user to log in.)

Please note that PIN caching in Windows' minidriver may be disabled by the user via registry. And if I remember correctly, it could even be disabled by the middleware on purpose (e.g. for a non-repudiation key).

@dengert
Member
dengert commented Nov 29, 2016

Note on that web page, it also says:
"Plug & play on Windows and GNU / Linux."
"GNU / Linux that incorporate OpenSC."

I agree with @frankmorgner

I would also look close at the keyUsage extensions of the certificates to see if the AUTH key does not have non-repudiation and the SIGN key does.

If there are other certificates/keys on the card, such as a key management key used for encrypted traffic, does it also have the same issue? What are the keyUsage bits in its certificate?

Also look closer that some how the SM channel is not getting reset and causing the card security state to change.

@rickyepoderi
Contributor

I would also look close at the keyUsage extensions of the certificates to see if the AUTH key does not have non-repudiation and the SIGN key does.

Yes, it's exactly like this, You can see it above in my output of pkcs11-tool -l -O

label: KprivAutenticacion
ID: 4130323035424244453037304631423230313631303130303835363237
Usage: sign
label: KprivFirmaDigital
ID: 4630323035424244453037304631423230313631303130303835363237
Usage: sign, non-repudiation

If there are other certificates/keys on the card, such as a key management key used for encrypted traffic, does it also have the same issue? What are the keyUsage bits in its certificate?

No more private keys, just those two.

Also look closer that some how the SM channel is not getting reset and causing the card security state to change.

I'll try tomorrow to test if I can verify (with a Public Key) a lot of times and just perform one signature with the authentication private key. But @miguel-cv has also confirmed that the problem happens with both keys (and remember the bug in official implementation was also with the authentication key in firefox).

@germanblanco
Contributor
@rickyepoderi
Contributor

@frankmorgner
I tried today to do a little test to the recommended solution (sign key CKA_ALWAYS_AUTHENTICATE=1 and the authentication not) but the pin cache doesn't work in that case. The pin is not stored cos there is another key which is CHA_ALWAYS_AUTHENTICATE. See this line:

https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/pkcs15-pin.c#L675

Indeed this is a double check cos when doing the sc_pkcs15_pincache_revalidate it is again checked if the key is CKA_ALWAYS_REVALIDATE. I tried to put the keys in different authid but in that case I cannot see both keys doing C_FindObjects. Am I missing something?

@frankmorgner
Member

Do you have a single PIN that protects both, the authentication and the signature key? The code you referenced refuses to cache the PIN if there is some key that requires consent, although there may be others that don't require consent. Although this approach is very sane, it's also very inflexible.

An alternative could be to evaluate the consent property when the key is actually used and not when the pin is about to be cached. This approach seems to be taken by your "official" implementation... Do you think the latter approach could be mimicked within your card driver?

@rickyepoderi
Contributor

Do you have a single PIN that protects both, the authentication and the signature key? The code you referenced refuses to cache the PIN if there is some key that requires consent, although there may be others that don't require consent. Although this approach is very sane, it's also very inflexible.

Yes, DNIe has only one pin for everything. And that part of code avoids the use of the pin cache if there's one key with CKA_ALWAYS_AUTHENTICATE. Therefore the option (3) is not an option anymore.

An alternative could be to evaluate the consent property when the key is actually used and not when the pin is about to be cached. This approach seems to be taken by your "official" implementation... Do you think the latter approach could be mimicked within your card driver?

it is indeed like this right now, if the key is marked as CKA_ALWAYS_AUTHENTICATE in the revalidate the use of the cache is avoided if not explicitly set in the pin_cache_ignore_user_consent (that's why I said it is double checked):

https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/pkcs15-pin.c#L718

In summary, right now we cannot go for the option (3). Only 1, 2 or 4.

@frankmorgner
Member

As said above, you could also check whether you can mimic the official behavior in the DNIe card driver.

Anyway, there is (yet) an other approach:

  1. Force caching of the PIN (either by removing CKA_ALWAYS_AUTHENTICATE or by forcing pin_cache_ignore_user_consent) and explicitly ask the user for consent when using the non-repudiation key. DNIe already has this logic for user interaction already.
@dengert
Member
dengert commented Dec 1, 2016

This is a little off topic, but does the DNIe3 and the SM allow for creating a session PIN? I think Windows has such a concept, but don't know of any cards that support this. I forgot what Windows calls it, but it sounds like it is to avoid caching the real PIN, caching the session PIN instead. This would allow for using the card with a PIN PAD reader.

@rickyepoderi
Contributor

I interchanged some emails with @germanblanco and @miguel-cv and we decided to finally go without any CKA_ALWAYS_AUTHENTICATE and reuse the opensc pin cache for both keys. This way opensc will use the same solution that the official implementation is using after the fix.

The three of us agree with the idea of using CKA_ALWAYS_AUTHENTICATE in the non-repudiation key and the cache for the other but that option is complicated right now and we'll try to go for it later. Besides I personally think that option 4 (using our own cache) is a nonsense.

So I'm going to recheck my dnie30b branch with both DNIe types (today I have access to a 2.0 DNIe) and submit another pull request.

@rickyepoderi
Contributor

Once the #914 request is merged the DNIe 3.0 should work with current default branch (I have tested with 3.0 and 2.0 and everything looks fine). I think this issue is finished and future enhancements or bugs will be dealt in new issue numbers. Thanks everybody involved here.

Nevertheless I wanted to continue with the idea of making the non-repudiation key CKA_ALWAYS_AUTHENTICATE...

@frankmorgner @dengert What do you think about the idea of the three configuration values for the pin_cache_ignore_user_consent option? (Explained in the pull request). I will implement and test it if you think it is valuable.

@dengert
Member
dengert commented Dec 29, 2016

Some of the flags should be on a card bases. For some cards, CKA_ALWAYS_AUTHENTICATE is used to enforce a policy, and the card may also enforce it. I would not like to see us add too many flags that make it easy to violate the policies of the card issuer. But for the DNIE, it sounds like the card has set CKA_ALWAYS_AUTHENTICATE by mistake for all keys.

If you can call it something like pin_cache_ignore_user_consent_for_buggy cards, and then only use it for the buggy cards i.e. DNIE 3.0 that would be OK with me.

@rickyepoderi
Contributor

Take in mind that adding a third option helps in a case that is possible with a perfect (not buggy) card. Imagine a card with two or more keys under the same pin, and only one of them is CKA_ALWAYS_AUTHENTICATE, then the cache cannot be used for all the normal keys (if pin_cache_ignore_user_consent=false cache is forbidden for all the keys, if pin_cache_ignore_user_consent=true cache is admitted for all). So the new option is intended to cover that workable case (the new option would store the pin in the cache but only would be permitted its use for the non CKA_ALWAYS_AUTHENTICATE keys). Nevertheless I understand your reservations about this point, that's why I'm asking...

@davernos

Ubuntu 16.10 & opensc 0.16.0-1ubuntu2. Firefox 50 keeps asking for password on DNIe 3.
I've downloaded and compiled the DNIe tester. This is the result:

./dnie-pkcs11-tester -l
password:
Starting check_dnie_inserted...
Found 1 slots...
Found slot: 0 - "Cherry GmbH SmartBoard XX44 [Smart Card Reader USB] 00 00 Cherry GmbH "
�"Found token: "DNI electrónico (PIN1) DGP-FNMT PKCS#15 emulated0205A10016130F
Found DNIe at slot 0
Starting check_login...
Session status: CKS_RW_PUBLIC_SESSION
Error in C_Login [CKR_GENERAL_ERROR]

The password is correct, tested on Windows 10 w/o problems.

@rickyepoderi
Contributor

@davernos Thanks for testing, we need more people doing it.

I would need the debug, put the level debug to 9 in opensc.conf and execute the tester redirecting the error to a file:

./dnie-pkcs11-tester -l 2>/path/to/file.dump

And attach the file here. Please be aware that there are some sensible information in the file (dnie, names, password,...). I recommend you to change that information for asterisks or something similar.

@davernos

Ok, heres the debug file. Please, let me know if I left any sensible information.
debug.zip

@rickyepoderi
Contributor

Ok, the error is just after the sc_reset:

0x7fec9f630700 12:35:29.520 [opensc-pkcs11] reader-pcsc.c:228:pcsc_internal_transmit: Cherry GmbH SmartBoard XX44 [Smart Card Reader USB] 00 00:SCardTransmit/Control failed: 0x80100068

This happens to me from time to time (although it is very rare). That is why I was investigating removing the sc_reset. Can you try with this branch? (This one has no sc_reset.)

https://github.com/rickyepoderi/opensc/tree/new-sm

It's the same but using my repo and the new-sm branch:

git clone https://github.com/rickyepoderi/OpenSC.git
cd OpenSC
git checkout new-sm
# compile and so on
@dengert
Member
dengert commented Jan 12, 2017

debug.zip was against 0.16.0. But master has a number of changes to improve PC/SC debugging and to handling of failures of any PC/SC SCard command.

There is some question as to how soon after a reset is done can the next PC/SC command be done. The reset may have been from a processs that does not show up in the debug log.

I see:
Line 13194: 0x7fec9f630700 12:35:28.696 [opensc-pkcs11] cwa14890.c:1088:cwa_create_secure_channel: Resseting card
with what appears to be the next PC/SC operation being:
line 13228: 0x7fec9f630700 12:35:29.520 [opensc-pkcs11] reader-pcsc.c:463:pcsc_reconnect: Cherry GmbH SmartBoard XX44 [Smart Card Reader USB] 00 00:SCardReconnect failed: 0x80100066

@davernos

Ok, I can confirm its working now with the "new-sm" branch.

$ ./dnie-pkcs11-tester -l 2> dnietester.dump
password: 
Starting check_dnie_inserted...
  Found 1 slots...
  Found slot: 0 - "Cherry GmbH SmartBoard XX44 [Smart Card Reader USB] 00 00       Cherry GmbH                     "
�"Found token: "PIN1 (DNI electrónico)         DGP-FNMT                        PKCS#15 emulated0205A10016130F  
Found DNIe at slot 0
Starting check_login...
  Session status: CKS_RW_PUBLIC_SESSION
  Session status: CKS_RW_USER_FUNCTIONS
login OK

Firefox is now accepting my password and certificate is working correctly.

Let me know if you need more debug info or more tests.
Thanks for your time and effort.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment