-
Notifications
You must be signed in to change notification settings - Fork 186
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
Fix #101: Add support for PIN callback #103
Conversation
This is to address issue #101 |
Would like to add tests here as well. Saw mention of it in the README.md, but didn't see a testing framework in place or examples of how to run the tests that are there... |
I think adding new engine ctrls is a very bad idea, because it assumes the application is written for this specific engine. It may work for you, but it is not a generic solution for other users. The existing LOAD_CERT_CTRL is already bad enough. We should not make things even worse. Instead, we should use SSL_get_default_passwd_cb() to retrieve the registered callback if PKCS#11 requests a pin, and no pin was specified with existing methods, |
95c1442
to
a31c453
Compare
* "pin get" callback allows app to specify a different PIN per slot * "pin done" callback allows app to clear memory if necessary when libp11 is done using the pin. * Add `PIN_GET_CALLBACK` and `PIN_DONE_CALLBACK` internal engine control commands to configure these callbacks over the ENGINE openssl interface.
a31c453
to
aa6be9b
Compare
(fyi, rebased from master, cleaned up commits, and added some tests) re. comments above:
True, it does tie the application more to the implementation, and this is unfortunate. However, this is inevitable to some degree, right (i.e. even
This may be an option for people who can upgrade to OpenSSL 1.1, but this will not be most people for a long time I think. I'm also struggling to see how that function is relevant here -- feels like that would be overloading that function with something it is not intended for -- passwords for encrypted SSL keys is not the same thing as PCKS11 slot passwords, no? I'm also not sure that callback would provide enough context to make the right decision on the password to use. |
So, tell me the story about how your callback relates to a generic OpenSSL facility to use a cert/key by filename or PKCS#11 URI without the application having to know or care what it is. Is this going to be usable in that context, when this is just one of the types of thing that the "certificate" string might be referencing? Or is it something completely different that is going to have to be marked obsolete when we move over? |
@mtrojnar FWIW until recently applications did have to be written for this specific engine, because they had to do all that messing around to load it and load the PKCS#11 provider module manually. It's only fairly recently that we've fixed it to just work with |
I would argue that such a facility would be a layer on top of lower-level functions in OpenSSL that still do the exact thing you want them to do. Reading a PKCS8 key vs. PKCS1 key vs. PKCS11 key are all going to be different routines. I'm all for a This PR is about adding it to the lower level. It exposes a "get password" and "release password" pattern that would hopefully also exist for other lower-level APIs as well.
The most obsolete-worthy change here is the callback parameters, which in this case do not correspond to the key URI but to the slot id/label on account of the internals of pkcs11 and the fact that the password is really not on the key, but on the slot. This maybe different from other file-based keys. PKCS12 may be another interesting one to think about in the password encrypting the key store may be different (I think) from the password encrypting the key inside the store. The trickiest forward-looking thing to accomplish with a PR like this, I suppose, would be coming up with the right callback API to indicate what kind of data will be passed out to the application to figure out which password to provide in a way that can be shared across key encoding types but also reflect each of their nuances. Maybe the higher level API ends up just exposing a single "get" and "release" callback that passes an indicator (enum?) indicating key type and some structure that can store some kind of generic information that will be interpreted differently depending on key type? Behind the scenes, the higher level callback can interface with the other lower-level callbacks based on their individual needs? Release CallbackOne last thing. I do want to emphasize a bit the idea of a "release callback". I'm not sure this is on your radar, but I think it will be important for some who don't want to keep the password around in memory. Maybe it is done like I have it in this PR w/ two very similar callbacks -- maybe it is done with a single callback with an additional |
@@ -419,13 +429,20 @@ static X509 *pkcs11_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id) | |||
} | |||
|
|||
/* In several tokens certificates are marked as private. We use the pin-value */ | |||
if (tok->loginRequired && ctx->pin) { |
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.
Note: This is one area I wasn't entirely sure if I made the right change or not. The code was conflicting with the comment below. It is here required that ctx->pin
be non-null, but below, PKCS11_login
is called with the expectation that it may be null. The comment seemed more correct since a null pin should be allowed, so I took out this ctx->pin != NULL
check.
Well... Not really. Stunnel and several other applications supported MODULE_PATH and PIN with a generic text key/value interface, without a single line of code specific to engine_pkcs11. This method does not work with binary structures or callbacks.
Oops. I was wrong. I reviewed the code. The The solution would be to add a new libp11 function:
and invoke it from |
Hm, didn't spot that before. No, And as noted above, one can also handle the pin with a |
We set Would you be open to accepting a patch that uses I understand your push back and wanting the solution to work for the community and not just for me. =) I do think this is generally useful for being able to better manage the lifetime of passwords in memory. It should be discouraged to have password floating around in memory as plain text. But at the same time, I totally get that you want to make sure it fits with the future vision of libp11. |
@mtrojnar How would you recommend configuring the engine to know whether to always query the |
argh. If only I had known about
One open question I have is how to make libp11 stop caching the password. Any suggestions for how I can approach that in an acceptable way? |
Moving discussion back to #101 |
PIN_GET_CALLBACK
retrieves a PIN, andPIN_DONE_CALLBACK
releases it so that the application does not need to keep the PIN in memory in clear text if it does not want to.The ugliest part of this PR is the casting of the function pointer to support the proper parameters we need to send back and forth between the application and libp11, but I do not see any way around this.