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.