-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
repart: support OpenSSL engines for signing #29539
Conversation
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.
Bit obtuse but found an example here: https://youtu.be/ph3QVgxUi98?t=272, why not give that a try? Seems easy enough
...is it fuck I can't make it work, the pkcs11 provider doesn't want to work with my yubikey. I've added it, but with a fallback to the legacy API, which actually works. This stuff is probably too new for now. |
So as it turns out, @simo5 is actually quite a nice guy. @simo5 any chance you can give us a hint how to use the openssl3 provider stuff correctly to get a yubikey to sign something via your pkcs11 provider? this PR is supposed to implement that, but @bluca ran into some trouble there. (background: this is for systemd's Any help appreciated. |
@bluca Can you post some logs here on what fails with the provider stuff with your yubikey? |
OSSL_STORE_load() fails with no error - ERR_error_string() just returns a helpful The PKCS11 URI I am using, which works with the engine, is: |
That error looks like an openssl engine error, not a provider error ? |
The engine fallback is commented out, so it's definitely from openssl or the pkcs11 provider |
This is the diff I'm testing with, on top of this PR:
|
Btw is this code compiled in a binary? If the latter you should really allocate a separate libctx otherwise you will interfere with the default context used also by the main application. That said I wonder if the yubikey is forcing a re-authentication before allowing the sign operation. |
Yes, the yubikey wants the pin again when signing. With the engine, I get prompted twice for the pin - once when the engine is loaded, and once per signing operation. Debug log: |
Ok then sadly what you need is this issue resolved: It won't work until this is implemented I am afraid. |
[interface.gen.c:677] p11prov_Sign(): Error: 0x00000101; Error returned by C_Sign Confirming my hypothesis. I will check if we can expedite fixing this issue, now we should have enough infrastructure in the project to make it doable, it was not easy when 42 was filed. |
Ok, thanks, then I'll go ahead and merge as-is, and the fallbacks will ensure things are usable. When those 2 code changes are in the provider let me know and I'll test again, and do any required follow-up. Thanks for the help. |
Note that there is no callback signature on signing operations, so I will need to figure out how to deal with the PIN, it may be required for you to set an option to allow the provider to cache pins, which will require a setting in openssl.cnf until this code: openssl/openssl#21604 is in a release and can be used to pass configuration at dynamic load time. |
If you subscribe to latchset/pkcs11-provider#42 you will get an automatic notification when we close it as implemented. |
if (isempty(arg_signing_provider)) { | ||
_cleanup_(erase_and_freep) char *k = NULL; | ||
size_t n = 0; | ||
|
||
r = read_full_file_full( | ||
AT_FDCWD, private_key, UINT64_MAX, SIZE_MAX, | ||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET, | ||
NULL, | ||
&k, &n); | ||
if (r < 0) | ||
return log_error_errno(r, "Failed to read key file '%s': %m", private_key); | ||
|
||
r = parse_private_key(k, n, &arg_private_key); | ||
if (r < 0) | ||
return r; |
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.
Can't we always go through the provider codepath? It should support regular paths as uris just fine no?
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.
Yes you can, the store api is fully generic and will load pem files just fine, you do not need special code if you use modern openssl 3 store apis, and that is the recommended way to deal with the pkcs11-provider, rather than having custom code.
Just rely on interested admins (or the distributions to do it for them) to configure the provider in the openssl.cnf and just provide a pkcs11 uri instead of a file name for the keys and all should just work transparently.
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.
And what about --signing-provider in that case? Does it even make sense to have such an argument? Or is it sufficient to start interpreting the --private-key= argument which currently just takes a file path as a URI. Then if we need to fallback to the engine stuff maybe we can determine the engine to use from the uri as well?
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.
Can't we always go through the provider codepath? It should support regular paths as uris just fine no?
eh not really, given providers don't really work at the moment
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.
eh not really, given providers don't really work at the moment
Not with your token, but with files on disk without pins they should work fine I think
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 think I've done enough experimenting for a while, I just want to be able to use my yubikey
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.
@DaanDeMeyer as I said the default path without any HW toke invovled can be changed to use the Store api by default. And then everything will work automatically as the store api select the correct provider based on the URI it gets provived with, and fo course if a URI is not handled by any provider then it will throw an error.
going that way you will be able to use also other providers without code changes like the tpm2 provider or the oqs-provider etc...
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.
Can't we always go through the provider codepath? It should support regular paths as uris just fine no?
Our loader is a bit fancy though, i.e. it will warn about world-readable access modes, and will connect to AF_UNIX sockets if you reference one. We try to make sure all our tools that read keys work that way. I doubt that openssl supports that (or wants to support that)
mmh but how is the pkcs11 engine doing it then? I get 2 prompts with the engine, there's no caching involved, I get a prompt when the engine is loaded, and a prompt whenever a signing operation is done. No caching at all, which seems the safe thing to do, not sure how comfortable I am at leaving the PIN around... |
I think it just uses the default prompt via UI_method_new(), but the problem here is not getting the PIN, pkcs11-provider does not support the custom login before the signature operation at all. This is something only some PIV tokens require, most HSMs or software tokens are ok with just the session login (which happens the first time you are asked for a pin). |
Right, I guess for 'unattended' HSMs it makes sense, but for all yubikeys that I've had, the signing slot was always configured to require auth on each operation |
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 still think we're using the provider API wrong. We should only require users to give us a URI, not tell us to use a specific provider. That should be communicated via the URI.
Do we need the calls to OSSL_PROVIDER_try_load()
at all? The way I understand it, you just need OSSL_STORE_open()
when using the provider stuff.
So I would suggest getting rid of the --signing-provider=
argument and just figuring out the engine to use from the given URI provided via --private-key=
if the provider stuff fails. Probably just get the string until the first colon in the URI and that should be the engine to use. Maybe @simo5 can confirm this.
OSSL_PROVIDER_try_load is needed, otherwise you need some ugly and custom configuration changes in /etc/ to make the non-default providers work at all |
This is a matter of perspective, most applications should be just fine, you change the conf once and then you are good with it. In fact we are considering dropping a config snippet in automatically when you install pkcs11-provider in fedora. If the default code path gets changed to use the store api then -signing-provider would become optional. |
Nah requiring global config to be changed with some oddly specific (and architecture specific) things is not a very good user experience. I would never ship that in Debian for example, given the path changes depending on the architecture, it would cause a ton of conflicts and break multi-arch. And then these get enabled globally, rather than per-application, which one might not even want. |
Sorry I do not understand the comment, I am not sure what there is that is architecture specific or odd here, but this is not the place to discuss distribution level changes anyway. |
The config files need an architecture-specific path on Debian/Ubuntu: |
As far as I know no path is needed, openssl will search the pkcs11.so in the openssl default path like it does for the default.so and fips.so providers. |
So can we merge this? I just wanted to use my yubikey... |
I don't want us merging code that doesn't use the provider stuff like it's intended. This is just going to lead to bug reports and complaints down the road. Like @simo5 said, the module path should not be required in the config file in which case it should default to the p11-kit proxy. So I'd like the following changes:
|
alright I'll just script around repart |
@bluca hmm, any reason you deleted the branch? i still think something like this should go in, no reason to just delete the whole thing. |
A variant of this was merged as #31261. |
This uses the deprecated ENGINE APIs, because there's no documentation anywhere on how to use the new one, and lots of engines haven't been converted anyway.
I tried to look for the 'providers' equivalent of the 'engine' interface, but the documentation is abysmal, and nobody seems to have bothered to update so far, so can't see any working examples.