-
Notifications
You must be signed in to change notification settings - Fork 803
enable use_file_cache by default #2501
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
Conversation
|
It looks like oseid tests are consistently failing with file caching enabled by default. @popovec , do you have an Idea how to avoid that? |
|
I will try to find where the problem is, here debug if cache is enabled: and if cache is disabled: I was looking for where the I started looking at the cache and the real contents of the file in the card during card initialization. Something is wrong, this "cached" file is incomplete. I have not yet found where the problem is that the cache does not match the contents of the card. However, OsEID uses one special thing, the empty file is filled with the value 0xff and not with the value 0x00. So I checked the MyEID (4.5.5) card (empty file is filled by 0x00), but I found same problem - Failed to store private key: Requested object not found. cached file: The User pin is missing. Of course, real file is correct (same as in opensc-explorer dump above). I have no idea where the cache is failing. |
|
For the cache to work normally, the update tokeninfo must be enabled: But that's not all, since the resolution for the update date is only in seconds, the cache does not have the correct data if something is updated more than once in one second. An example is the initialization: If this happens in one second (for script files it happens in 99% of cases), the cache responds incorrectly (data is out of date). I assume that if the cache does not have a time resolution of at least milliseconds, it will cause us a problem elsewhere as well. |
|
Thank you for the investigation! I noticed this before, but I did not have good enough reproducer to fill a bug report so I disabled file cache in pkcs15-init tool in Fedora with Would it be an option if the driver invalidated/deleted the cache in case it writes to the card or something? Or do I understand the problem wrong? |
|
Yes, I'm also considering the possibility that any write to the card would invalidate the cache. It is the easiest implementable option. All you have to do is delete the file from the cache for put-data, update-binary, etc. operations. However, we must have an active "do-last-update", because we can add new keys on one computer and they would not appear on the other computer (the cache would not be invalidated). In this case, a cache time resolution of 1 second will suffice. Still there exists race condition, if a card is updated from two concurrent tasks that use a different cache... There is another option to maintain the cache, but it will not be universal. The MyEID card contains a counter, where each write operation increments the counter. This could be used instead of "last-update" information. But I have no idea if we have similar information from other cards. |
I agree, that invalidating the cache on write would be a good way of handling this issue. However, sc_update_binary/sc_write_binary are directly called from the card specific the implmentations in src/pkcs15init without using some generic layer of writing PKCS#15 files. For reading files we have sc_pkcs15_read_file (where caching is handled transparently), but there is no such equivalent for writing files. Unfortunately, it looks like some bigger refactoring would be required to update/invalidate the file caching when writing files to the card. As simple workaround, I've changed this PR to disable file caching by default when running pkcs15-init |
|
I see that this time it crashed on keygen.... (public key can not be exported from card)... I'll guess, it would crash during the unwrap operation too. I'm afraid that the current cache implementation will not allow us to use it safely. I will still be looking for some solution .. |
|
Thank you. I'll convert this PR into a draft for now... |
|
@popovec I don't quite get the issue why oseid is failing, could you have a look? |
|
I don't have a final solution, but at least a hint: I have applied this PR to master (fa2eab8). If cache is cleared (
the OsEID test is fine. |
|
I looked at the cache implementation. Since any write to card does not pass through the cache, respectively, the cache is not invalidated if there was a write to the card, this implementation can only work if the card is in read only mode. This explains the failure of the OsEID tests, especially in cases where the previous command modified the contents of the card. If the file cache is enabled, some files are cached on computer. Then, if the card is modified on another computer (even without/with cache enabled), the cache on first computer is also not updated. The only solution that ensures the consistency of the operation when using the file cache is to use some flag (on the card) that will change when the card is updated. This flag must always be checked before using a file from the cache, and if it is invalid, the cache must be invalidated. Some of the cards contain a counter that is incremented with each write to the card. The use of such a counter to ensure the consistency of the contents of the card and the cache is sufficient. MyEID card has such a counter. I don't know if similar information is provided by other cards supported in OpenSC. (OsEID does not have this counter implemented - if necessary, I will write this code.) If similar information is available from other cards supported in OpenSC, I will write a PR that will invalidate the cache based on this information. If a card does not provide this information, file caching should be disabled for that card. The file cache implemented in this way will be a bit slower than the current implementation, because before each use of a file from the cache, one APDU will have to be used to verify the state of the change counter. |
|
I agree with @popovec Newer cards are much faster. It is not clear how fast are the cards listed in #2444. Tokens should be must fasted if they can eliminate the limitations of contact protocols, and power restrictions. |
0829dcf to
1eb9db3
Compare
|
Thanks for the feedback and i think that speaking strictly technical, you're right with your concerns. However, I still believe that
Anyway, I agree that we should try to avoid any caching conflicts in OpenSC by default. I've modified this PR to enable file caching only for the cards we cannot modify within OpenSC. If you think this list is not restrictive enough, please let me know and I'll remove more entries. @popovec versioning of the card's file cache is done using the card's meta data in EF.TokenInfo. This file contains a date that is appended to the file name (p15card->tokeninfo->last_update, see sc_pkcs15_get_lastupdate). So if you want to support your file modification counter from the card, you need to modify your PKCS#15 emulator so that this date is adjusted once that counter increments. This tells the pkcs#15 file cache that it needs to fetch the file(s) again from the card. |
doc/files/files.html
Outdated
| </p></li><li class="listitem"><p> | ||
| system-wide configuration file | ||
| (<code class="literal">/usr/etc/opensc.conf</code>) | ||
| (<code class="literal">/home/fm/.local/etc/opensc.conf</code>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these changes to the paths be included?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see this fixed with the current diff.
|
I am wondering if this should be a hardcoded list or if this should be a property of the card driver, that can be even dynamically changed based on the content of the card. For example, the cardos < v5 cards can be modified from within OpenSC, but v5 can not as we were not able to obtain any documentation. The limitation to modification by opensc only can also be a limiting for example for yubikeys with PIV applets, which can be modified by other tools and where checking of some counter/tokeninfo or something would be handy, but I dont know if there is something in the PIV specification that could be used to detect changes though. So aside of the comment inline, this looks like a step in the good direction. |
|
The problem is that the timestamp (in EF.tokeninfo) is not updated atomically. Maybe we have a new version of the file written on the card, but EF.tokeninfo is not yet updated ... and therefore the cache will provide the old version of the file. I prepared a patch for both opensc and oseid simulator, which uses Experimental run: Comments are welcome. |
I also thought about this limitation and - of course - you could do some on-the-fly magic, catching special FIDs when being called with Instead of using a card driver callback as in your suggestion, I propose to use |
we can use defensive defaults, here (e.g. excluding cardos and piv in the list). for a more flexible approach we should use Peter's suggestion for checking the date of the last change dynamically. |
|
Thanks for the hint about using Since we only need the information from the master...popovec:OpenSC:change_counter A test run including a debug log is available: |
|
The implementation of a change counter is specific to your card and may be different for others whereas we already have the last update information from the upper PKCS#15 layer. I don't like introducing new concepts for something we already have, because this raises complexity, which is bad for basically everything in the long run. That's why I would prefer a mapping of the "last update" from the PKCS#15 level to the driver level. In my view, this is less complex, because it only changes where it is implemented, but the concept stays the same. So far, I assumed that myeid doesn't encode the "last update", which is why you want to look at the change counter instead. However, looking into your driver's code (pkcs15init/pkcs15-myeid.c), I can see that the "last update" will actually written to your card with sc_pkcs15init_unbind. So when modifying the card via PKCS#11, I wonder why the "last update" isn't adjusted accordingly (which would then also fix the caching problem)... |
|
Could it be that we forgot to call sc_pkcs15init_update_lastupdate() somewhere in the PKCS#11 layer? |
I will look at the relevant code, maybe I manage to find another solution (by correcting the current code). Can we get information about other cards supported in opensc, do they support "change_counter" information? If so, consider this information authoritative for the file cache. If not, I'll assume that mapping change_counter to last_update (from EF.Tokeninfo) will be an easier - cleaner solution (specially, we can map change_counter as "subseconds" information to the last update from EF.Tokenifo). But it will cost us more APDU transfers... |
|
In I tried to use The file cache is also defective in this case. I can modify However, the I'm afraid this will be much more complicated than prioritizing the update_counter information directly for the file cache name (as I mentioned in the previous solution). Here is also information about how much time it takes to execute the command: |
|
Thank you for having a look into this @popovec ! Do I read it correctly that there is no way to update cache except for manually deleting the files right now? |
|
The problem is that we cannot determine when the cache should be invalidated. As mentioned above, the card driver can change something on the card without notifying us in any way (at the pkcs#15 layer level). Preliminarily, let's assume that such changes do not happen ... the file cache can work without problems under certain conditions. File cache currently uses file versioning based on information from EF.Tokeninfo. This information has a resolution of one second. We have some limitations from this. Cards initialized with opensc must have "do-last-update" set to "yes" (in the pkcs#15 profile used to initialize the card). Also modification of the card (generation/import of keys, update of certificates, etc.) via opensc is possible, but with the file cache disabled. Any change to the card contents made outside of opensc must guarantee a properly updated Many cards cannot be initialized/updated with opensc (read only cards). File cache can be enabled for these cards. This PR is aimed at this case, so I don't think there is anything preventing this PR from being used. (However, I don't know enough about all the supported cards to say which card will later cause a problem after turning on the file cache, specifically I can't say if any other modification of the card outside of opensc will update the EF.Tokeninfo correctly and thus not break the current version of the files). In the future, it will be possible to enable file caching for other (read write) cards as well. If the card (card driver) provides I would prefer to change the An example of changing the name of the cache file is in the patch:08b1ca6 |
|
IMHO, we should not enable caching by default. |
1eb9db3 to
36287d9
Compare
|
I've rebased the changes onto master and fixed the merge conflicts. I've also noticed a syntax error in the documentation, which is present in Looking into your suggested changes, @popovec , I think that simply using the change counter in the file name (i.e. 08b1ca6) is the best way to integrate this for dynamic cards. When you have the time to make a PR, maybe you also want to consider just appending your change counter to the last update date instead of replacing it.
I'm not aware of any other card implementing this. However, the MS Minidriver takes exactly this approach at the middleware level, so at least someone else had a similar idea before... |
|
A cache enabled by default starts to make trouble: https://support.nitrokey.com/t/hsm2-cant-figure-out-how-to-properly-wipe-and-reinitialize-device-seems-to-generate-invalid-signatures/4688 I guess we should not ship with cache enabled by default. |
We've been there already. The idea is to enable caching only for static cards (e.g. not for sc-hsm) by default. However, a dynamic mechanism has been suggested to allow this for the other cards as well |
Here is a proposal for a change counter implementation including this PR: filename is now in this format: |
|
I think we can merge, if everyone agrees that we only enable file caching for the static cards with this PR (the list given here): |
|
I agree, static cards are solved by this PR. I will prepare a separate PR for the MyEID card. |
|
I am ok with the current version (after updating the HTML mentioned in the previous comment). Ideal solution would be to have more fine-grained selection to allow file caching for NIST PIV cards, but not allow it for the Yubikeys by default, but that would complicate stuff a lot. |
use_file_cache is initially only activated for cards that can't be modified with OpenSC (i.e. with pkcs15-init). However, don't enable cache for PIV by default as many people are experimenting with a Yubikey. This also fixes a syntax error in opensc.conf.5.xml.in in the documentation for `use_file_caching` fixes OpenSC#2444
0ac1bdc to
c7f9fc8
Compare
fixes #2444
Checklist