-
Notifications
You must be signed in to change notification settings - Fork 51
Fix handling of invalid object handles #495
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
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Jakub Zelenka <[email protected]>
This is useful for refreshing invalid object handles Signed-off-by: Jakub Zelenka <[email protected]>
Signed-off-by: Jakub Zelenka <[email protected]>
6b2529b
to
c925ead
Compare
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.
Sounds reasonable in principle, however this change would have to be added to any "_init()" for any operation.
So all the operation in asymmetric_cpiher.c and exchange.c etc...
ret = p11prov_sig_operate_init(sigctx, false, &session); | ||
if (ret != CKR_OK) { | ||
return ret; | ||
if (ret == CKR_OBJECT_HANDLE_INVALID && p11prov_obj_refresh_invalid(sigctx->key) == CKR_OK) { |
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.
you should move this whole section directly in p11prov_sig_operate_init()
@@ -870,7 +870,7 @@ static CK_RV p11prov_sig_operate_init(P11PROV_SIG_CTX *sigctx, bool digest_op, | |||
} | |||
|
|||
done: | |||
if (ret != CKR_OK) { | |||
if (ret != CKR_OK && ret != CKR_OBJECT_HANDLE_INVALID) { |
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.
if you do the refreshing in this function, as you should, then this will go away, as it should.
This exception here is a trap for any of the callers.
Note that this kind of change will need tests, or it will regress easily. |
@simo5 Cool, thanks. Ok I will look into adding that to other _init and make it more generic and will also take into account your comments. In terms of test I could look into adding an integration test for nginx and pkcs11-proxy which should cover the sign one and would be probably useful for testing the fork reload as nginx forks workers. Would you also want tests for other _init? If so, I would probably have to look into some longer running app so I can restart daemon and then retry it. If you have an idea about some existing application for such testing, that would be great! |
Assuming we can make a generic function for this, then just one test application with the proxy should be fine. Let's see where it goes as you add code. |
Just a word of warning, closing sessions means destroying all ephemeral keys created as session objects. |
Ah yeah, good point. I will look into it. |
So after doing various tests with it, I think this approach is not viable becuase it can result in a situation when sessions can get mixed up. In my case the problem is that when the proxy daemon is restarted it resets all sessions (and all handles). What it means is that the session handles will be indexed from 1 after the restart because that's how SoftHSMv2 session manager works. What might then happen is that it might try to use a handle created before the restart that was in the meantime (after the restart) recreated in another slot so there will be an existing handle available but it will represent a different key. I think it just cannot work with continuous refreshing on an invalid handle and it needs to reset all sessions as it's done after the fork. What I'm thinking instead is the do a slot refresh if there is a device error (maybe having a config option for it so the current behaviour of trying to continue works fine in case there are device that can still work after the device error). @simo5 Would that be an acceptable approach? |
Yes this is what I would expect.
Sessions never represent keys, but sessions can hold ephemeral keys and they would simply lost. Also sessions are not hermetic, if you have a key with a handle you can use it on any sessions, even if the key was created as an ephemeral key o a different sessions, but then keys are lost. More problematic is that key handles will also be reset, and now you may be using a completely random key, that does not match type or anything. This is why on fork we refresh all handles by re-fetching the keys. Unfortunately this means losing again all ephemeral keys because they are lost when the holding session is closed.
Exactly.
I am not sure, I think that in order to have the ability to recover from a token error you may also need to cache any key data that was imported in the session, so that you can restore ephemeral keys that openssl copied in to do some operation. But this will still miss any session key generated directly on the token.. oh well. I wonder if it wouldn't be better to just put pkcs11-provider in an error state and have the application restart ... But perhaps it is sufficient to ensure that all the objects that went lost stay around but somehow are neutered (invalid handle) and always return errors when OpenSSL tries to use them, you can't just drop objects because they are pointed at by EVP_PEKY->keydata so they need to stay around until openssl frees the data. |
Yeah the fork logic just marks the object as invalid but does not free it. Specifically this happens in In terms of the actual change I was thinking to do something like this bukka@34d43a8 (the diff looks a bit bigger but effectively it's just renaming
This is actually quite difficult because the application is nginx so it would have to use some external application that would monitor errors and restarted nginx... I initially thought about handling it in pkcs11-proxy but it's just a dummy forwarder so I would have to add there all caching logic (remembering all objects and sessions) so they can be restarted and then some sort of re-mapping. But provider have all this logic so I think it seems like the ideal place to do the recovery in my use case. |
Description
This is an initial fix for #494 which describes all the details about the actual issue.
The fix first removes the errors in session refreshing if the session was successfully re-opened.
It then exposes function for refreshing of invalid objects - this uses the same logic as after the fork refreshing triggered from store.
And it adds a logic in signature for handling
CKR_OBJECT_HANDLE_INVALID
error. It basically refreshes the object and repeat the operation. It also clears errors if refreshing and repeated operation is successful.For my use case signInit is enough but I realise that this would be quite incomplete so other places should be addressed in the similar way. But before I look into it, I wanted to hear if this approach would be acceptable so please let me know your thoughts. Also if acceptable I will be happy to look into providing some tests.
Checklist
Reviewer's checklist: