Saturday, February 18. 2017
Supporting DNIe 3.0 inside OpenSC keeps improving. Some days ago some users reported a problem at the creation of the secure channel. The problems semmed to be related to a reset of the card that is done just before starting the process. That reset has been talked about several times since I am involved inside the DNIe driver development, it seemed unnecessary but it still remained there. I had also experienced the same issue previously but, in my case, it was very very rare (for what I understand to the affected people it was just a blocker, it never worked). Another pull was submitted for deleting the call to the reset function but some refactoring was also included.
The pull request has been accepted but at that time I asked German to check it too (four eyes see more than two). He found some problems with the signature (which I think were related to his environment and not produced by my changes, mainly because the modifications with DNIe 3.0 always affect the secure channel creation -login- and no other parts). Currently I just test code changes with my tester, I did it just for that purpose and it is very fast and (I think) complete. Besides the old page that I used to test (@firma demo page) has been removed and now you are redirected to download a new AutoFirma application. This new application does not work (at least for me) but I cannot pass the first window that asks me to introduce the DNIe (although it is there). So I finally tested the singing process using the pkcs11-tool command, my dnie-pkcs11-tester, jsignpdf as explained in this Spanish entry and the signer daemon I presented in a previous entry. All of them worked. But I had downloaded previously the @firma applet and I even tested the library with the old official application. (I knew that I had some problem because my local @firma did not work. But the problem was previous to all the DNIe 3.0 changes. This time I spent some time trying to figure out what was happening and finally I discovered that the applet used the system OpenSC library, not the compiled one. Removing the package was enough and the old @firma worked again.)
In order to not lose it (because I cannot find @firma application again) I have uploaded it to my blog. You can test it here. But I needed to change the manifest file (it was fixed to only work in the official test site) and, therefore, I also had to re-sign the applet. I did it with a self-signed certificate so it is going to be problematic for sure. In my case it works with the icedtea-plugin inside firefox (I do not know if I configured something weird in the past to make it work). Do not trust in me and do not sign anything real with it. It is just for me, to not lose it and have access to it from everywhere.
That is all. I just want to upload the @firma to the blog. As I said at the beginning the pull request is now accepted and the changes are in the master branch. So the DNIe will work better in the next OpenSC stable version.
Spiral out! Keep going!
Sunday, December 18. 2016
Finally the integration of DNIe 3.0 was committed and it is working successfully. Today Viktor Tarasov merged my final changes to force caching and increasing the number of re-tries if version 3.0 is detected. You can follow the whole process in the DNIe 3.0 bug and the final pull request.
The temporary solution for the CKA_ALWAYS_AUTHENTICATE problem commented in the previous entry is to cache both private keys (authentication and signature, the later is a non-repudiation key) and not label them with that attribute. The recommendation from OpenSC guys was to force caching and a large number of re-tries (use_pin_caching=true and pin_cache_counter=30000) inside DNIe initialization. Obviously this is a workaround for a weird implementation in the DNIe but the forced parameters make DNIe 3.0 work in any situation.
I think that all the people involved (Spanish people in the bug and OpenSC members) preferred the option of mixing the two possible solutions: the authentication key would work using the cache (like it is working now), but the non-repudiation/signature key would be marked as CKA_ALWAYS_AUTHENTICATE (the cache would not work for it except if it is explicitly enabled in the opensc.conf). Nevertheless this mixed solution needs a little change in the current pin cache implementation. It is not very important but affects to all the other drivers and the general behavior of the library. I am still interested in going to that solution but, for the moment, merging a working DNIe 3.0 was more urgent.
If you are worried about caching the pin of a non-repudiation key I can just comment the following:
The current implementation of the official driver works in the same way (there is a cache, a re-login and no CKA_ALWAYS_AUTHENTICATION is presented in any key).
The DNIe has an option (--enable-dnie-ui at configuration time) that shows a warning message before any use of the non-repudiation key. This warning is a non-standard replacement of the key attribute. I do not know how many distros include the option (but for example ubuntu seems to use it).
As I said, the mixed solution seems to be the most optimal and let us forget about the horrible warning and use the standard CKA_ALWAYS_AUTHENTICATE. Let's see what happens in the future. For the moment, what it is sure is that DNIe 3.0 will be available in the next OpenSC version.
Sunday, November 27. 2016
Another little entry about the status of the DNIe 3.0 integration into OpenSC. My first pull request was accepted and committed but, sadly, there was a mistake and a conflicting part remains unchanged (my change was conflicting with another commit and, to fix three conflicting lines, I merged default instead of rebasing it, my fault, sorry). So, for the moment, only 2.0 is available in OpenSC trunk. Nevertheless this mistake made me realize something that @germanblanco had already advised me before but I could not reproduce: sometimes firefox prompts for the pin twice or more with DNIe 3.0.
After seeing that the pull request did not have the conflicting lines I prepared another little one but, testing it, to my surprise, I reproduced the error that German had told me before. Firefox prompts for the pin several times, in my case it was only reproduced with the seguridad social site). That day I only concluded that the chip sometimes returned an error 6982 (Security status not satisfied) when performing a signature. This usually means you are not logged in. I continued the day after and finally understood what was happening: the card returned the 6982 error; OpenSC dealt with it and tried to re-login (by default there is a pin cache configured to perform that); but there was a regression and the re-login did not work; so firefox requested the pin again. I have not seen the error previously because my first integration was with an older code that did not have the regression. At that moment I decided to check official governmental code and, again to my surprise, there was some lines of code in the signature method to re-login and retry the sign operation if the card was a DNIe 3.0 and an error 6982 was returned. But... What the hell? Why do that? Is there something malfunctioning in the DNIe 3.0 chip? That day I just fixed the regression about the re-login and commented my findings in the OpenSC issue asking for clues.
Quickly @dengert (an OpenSC member) gave me a good hint. Maybe the private keys in DNIe 3.0 were CKA_ALWAYS_AUTHENTICATE, that means you have to re-login anytime you use the key. Therefore the first time the signature works but the second one fails and the re-login is necessary. On Friday I modified my tester to iterate over the signature operation and it fails at the second operation (the pin cache should be disabled). The same behavior is presented in both keys, authentication and signature (non-repudiation). The situation was quite strange so I preferred to ask for confirmation from another Spanish guy with a DNIe 3.0.
Interestingly @miguel-cv sent me a retired page about an error in the official library with DNIe 3.0 related to mac and linux systems (you can see in the web archive) that comments the following (I am going to translate it because it is in Spanish, and sorry for using lots of commas but it is written like this):
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.
So, for me it is clear that DNIe 3.0 is built to give an error if two signatures are executed without presenting the pin. But here I see two problems. First the keys are not identified with the CKA_ALWAYS_AUTHENTICATE attribute (I have checked it inside the governmental implementation and the library does not even recognize this attribute). Second, this feature is very nice for the non-repudiation key but it is quite annoying for the authentication one. The Spanish government has concluded that every application should act like Windows (it seems that Windows retry by default when that error is returned) and that is not the case.
On Friday I did another little change in order to mark both DNIe 3.0 keys as CKA_ALWAYS_AUTHENTICATE and I tested with firefox and chrome:
Chrome did not support that attribute and it fails if the pin_cache is deactivated. Nevertheless chromium seems to use the signature very efficiently and inside the same site with one signature is enough (at least I could not make it fail). But if you change from one site to another that also requires the client certificate it fails, it needs to perform a second signature and the error is returned. Refreshing the page makes the browser prompts for the pin again.
OpenSC has extra configuration to make non compliant applications work. If you configure use_pin_cache=true and pin_cache_ignore_user_consent=true chromium works because the OpenSC implementation performs the re-login for you.
Firefox supports CKA_ALWAYS_AUTHENTICATE but interestingly here the experience is much worse. Firefox prompts for the password as many times as needed and it performs a lot more signatures than chrome (I do not know why). In the seguridad social page the PIN is requested five times or more (while chrome just uses one signature).
This annoying behavior cannot be avoided (using firefox or OpenSC configuration) because it is working as expected.
So here I am now, in this unresolvable dilemma. What to do? There is no good decision in this problem. All of them are bad solutions. For the moment I decided to wait someone else to confirm that both keys are CKA_ALWAYS_AUTHENTICATE (both fails performing a second signature without re-login). The situation is so strange that maybe there is something wrong with my card (but I deeply know that this is not true, DNIe 3.0 works this way). Then I will do what OpenSC guys tell me, because I do not have a preferred solution (although I am starting to think that the correct one is marking the keys as CKA_ALWAYS_AUTHENTICATE and everyone for himself). I want to emphasize the problems in all the parts: chrome does not support CKA_ALWAYS_AUTHENTICATE; firefox performs signatures like crazy to show a single page; the Spanish government decided to use CKA_ALWAYS_AUTHENTICATE keys, even the authentication one, without tagging them and wants all the applications to re-enter the pin by themselves, then, what is the point of making them CKA_ALWAYS_AUTHENTICATE? At the end you only type it once like in 2.0. You can follow my misfortunes in the OpenSC issue about DNIe 3.0.