Description of problem: This may be a duplicate of bug #1670026, I'm not sure. I long ago misfiled this as bug #1565839 under the old name of the package, libp11 and under RHEL instead of Fedora EPEL. Bugzilla won't let me change the product, so I am creating a new ticket. Even though I pass a PIN to the pkcs11 engine with -passin, version 0.4.8-1 always prompts for a PIN. This did not happen with version 0.4.6-1. This is using a Yubikey 4 on an el7.6 system. Version-Release number of selected component (if applicable): 0.4.8-1 How reproducible: Very Steps to Reproduce: 1. install openssl-pkcs11-0.4.8-1.el7 2. Do the workaround steps of bug #1728011: 2a. ln -s /usr/lib64/engines-1.1/pkcs11.so /usr/lib64/openssl/engines 2b. ln -s /usr/lib64/engines-1.1/libpkcs11.so /usr/lib64/openssl/engines 3. plug in a Yubikey 4 into USB drive with a certificate in slot 9c, for example with these instruction and yubico-piv-tool: 3a. openssl genrsa 2048 > private.pem 3b. openssl req -x509 -days 1000 -new -key private.pem -out public.pem 3c. openssl pkcs12 -export -in public.pem -inkey private.pem -out mycert.pfx 3d. yubico-piv-tool -s9c -i mycert.pfx -K PKCS12 -a import-key -a import-cert 4. sha1sum /etc/motd >motd.sha1 5. openssl rsautl -engine pkcs11 -inkey pkcs11: -keyform engine -passin pass:123456 -sign -in motd.sha1 -out motd.sig Actual results: engine "pkcs11" set. Enter PKCS#11 key PIN for SIGN key: Expected results: engine "pkcs11" set. and a motd.sig without prompting for a PIN Additional info: I can't seem to find any way to stop it from prompting, but it works with openssl-pkcs11-0.4.6-1.el7 along with engine_pkcs11-0.4.6-1.el7
This still fails when building with upstream 0.4.10.
Hello, Thank you for reporting this! My guess for this issue is that the key your device is generating has the attribute "CKA_ALWAYS_AUTHENTICATE" set, which requires authentication for every operation. The check for this attribute was introduced in version 0.4.7. I think one way to workaround this is to provide the device PIN through the PKCS#11 URI directly instead of passing through the '-passin' option. You can provide it in your command line using something like: $ openssl rsautl -engine pkcs11 -inkey "pkcs11:object=your-object-label;type=private?pin-value=123456" -keyform engine -sign -in motd.sha1 -out motd.sig The reason that could be better is that the PKCS#11 URI is provided directly to the engine while the password passed through the '-passin' option is provided through the OpenSSL UI_METHOD callback data. Let me know if that helped. If not, I need more information about the execution that causes the problem (ideally back traces of the execution). Also it would be good if you could reproduce it with SoftHSM as I don't have access to the device you are using. If the problem is in the engine, It should be reproducible with a different device.
Anderson, thanks for the thorough reply and the hint! I had seen some similar examples with pin-value and had tried to apply them but didn't have any luck figuring out the right magic. I tried the above command exactly and it also failed. Is there something in particular I need to replace "your-object-label" with, how do I find that? The errors I get are: engine "pkcs11" set. No private keys found. Key not found. PKCS11_get_private_key returned NULL cannot load Private Key from engine 140088131905424:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:eng_pkey.c:124: unable to load Private Key Oh, if I leave out "object=your-object-label;" that syntax does work instead of -passin, with 0.4.6. Unfortunately, with the 0.4.10 I built for epel7 (with my PR) it still prompts for the PIN. By the way I always get the message about No private keys found, even when it works. I ran the command using version 0.4.10 with gdb, interrupted it when it prompted for a PIN, and asked for a backtrace (I had also 0.4.10 debuginfo installed): #0 0x00007ffff66a20f0 in __read_nocancel () from /lib64/libc.so.6 #1 0x00007ffff662ec04 in __GI__IO_file_underflow () from /lib64/libc.so.6 #2 0x00007ffff662fdd2 in __GI__IO_default_uflow () from /lib64/libc.so.6 #3 0x00007ffff6622b84 in __GI__IO_getline_info () from /lib64/libc.so.6 #4 0x00007ffff6621986 in fgets () from /lib64/libc.so.6 #5 0x00007ffff6f28b38 in read_string_inner () from /lib64/libcrypto.so.10 #6 0x00007ffff6f28026 in UI_process () from /lib64/libcrypto.so.10 #7 0x00007ffff56d5b40 in pkcs11_authenticate (key=key@entry=0x73ca00) at p11_key.c:389 #8 0x00007ffff56d6f20 in pkcs11_private_encrypt (flen=52, from=0x73d610 "da39a3ee5e6b4b0d3255bfef95601890afd80709 /etc/motd\n", to=0x73d820 "", key=0x73ca00, padding=1) at p11_rsa.c:99 #9 0x000000000042ebcf in rsautl_main () #10 0x000000000041a578 in do_cmd () #11 0x000000000041a26e in main () How can I use the SoftHSM? Dave
(In reply to Dave Dykstra from comment #3) > Anderson, thanks for the thorough reply and the hint! I had seen some > similar examples with pin-value and had tried to apply them but didn't have > any luck figuring out the right magic. I tried the above command exactly > and it also failed. Is there something in particular I need to replace > "your-object-label" with, how do I find that? The errors I get are: The "your-object-label" in the command should be replaced by the label of the PKCS#11 object you want to use. One way to get this label is through "p11tool", provided by the "gnutls-utils" package. You can try: $ p11tool --list-tokens This will give you the PKCS#11 URI's for the available devices detected. They are similar to the PKCS#11 URI for the keys, something like "pkcs11:model=your-token-model;token=your-device-name;serial=your-device-SN;(...)" Find the URL of your device, copy it, and run: $ p11tool --list-all --login "PASTE THE URL HERE" This will request the device PIN and then it will list all the objects stored in that device. You want the private key object, identified by the "type=private" attribute. Copy the URL for the key. Then you can run: $ openssl rsautl -engine pkcs11 -inkey "PASTE HERE THE KEY URL?pin-value=123456" -keyform engine -sign -in motd.sha1 -out motd.sig This should work. > engine "pkcs11" set. > No private keys found. > Key not found. > PKCS11_get_private_key returned NULL > cannot load Private Key from engine > 140088131905424:error:26096080:engine > routines:ENGINE_load_private_key:failed loading private key:eng_pkey.c:124: > unable to load Private Key > > Oh, if I leave out "object=your-object-label;" that syntax does work instead > of -passin, with 0.4.6. Unfortunately, with the 0.4.10 I built for epel7 > (with my PR) it still prompts for the PIN. By the way I always get the > message about No private keys found, even when it works. Probably that happens because the engine tries to find the object without authenticating first and, if not found, it authenticates before trying again. > > I ran the command using version 0.4.10 with gdb, interrupted it when it > prompted for a PIN, and asked for a backtrace (I had also 0.4.10 debuginfo > installed): > > #0 0x00007ffff66a20f0 in __read_nocancel () from /lib64/libc.so.6 > #1 0x00007ffff662ec04 in __GI__IO_file_underflow () from /lib64/libc.so.6 > #2 0x00007ffff662fdd2 in __GI__IO_default_uflow () from /lib64/libc.so.6 > #3 0x00007ffff6622b84 in __GI__IO_getline_info () from /lib64/libc.so.6 > #4 0x00007ffff6621986 in fgets () from /lib64/libc.so.6 > #5 0x00007ffff6f28b38 in read_string_inner () from /lib64/libcrypto.so.10 > #6 0x00007ffff6f28026 in UI_process () from /lib64/libcrypto.so.10 > #7 0x00007ffff56d5b40 in pkcs11_authenticate (key=key@entry=0x73ca00) > at p11_key.c:389 > #8 0x00007ffff56d6f20 in pkcs11_private_encrypt (flen=52, > from=0x73d610 "da39a3ee5e6b4b0d3255bfef95601890afd80709 /etc/motd\n", > to=0x73d820 "", key=0x73ca00, padding=1) at p11_rsa.c:99 > #9 0x000000000042ebcf in rsautl_main () > #10 0x000000000041a578 in do_cmd () > #11 0x000000000041a26e in main () Thanks for the back trace. Indeed, your key probably has the ALWAYS_AUTHENTICATE attribute set, which makes the engine to ask for the PIN for every operation. The behaviour you see with older version is actually a bug, since it is ignoring the attribute the owner of the key set to the key, which is to request PIN for every operation. You can check the PKCS#11 specification: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html (search for CKA_ALWAYS_AUTHENTICATE) If you try the example a gave above, you probably will be able to see the Flags set to the object. > > How can I use the SoftHSM? Sorry, it seems SoftHSM is not available in EPEL7. It is an implementation of a PKCS#11 device in software, useful for testing purposes. In Fedora it is provided by the softhsm package.
Indeed the p11tool shows that it requires user PIN: # p11tool --list-all --login "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=00000000;token=cn" Token 'cn' with URL 'pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=00000000;token=cn' requires user PIN Enter PIN: Object 0: URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=00000000;token=cn;id=%02;object=SIGN%20key;type=private Type: Private key Label: SIGN key Flags: CKA_PRIVATE; CKA_SENSITIVE; ID: 02 There were a lot of objects listed but only Object 0 has type=private. Unfortunately, using that URL directly still does not override the PIN requirement: # openssl rsautl -engine pkcs11 -inkey "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=00000000;token=cn;id=%02;object=SIGN%20key;type=private?pin-value=123456" -keyform engine -sign -in motd.sha1 -out motd.sig engine "pkcs11" set. Enter PKCS#11 key PIN for SIGN key: Since there is only one private object, it's not clear to me that I need anything other than type=private. Do you have any other ideas? I looked at the spec and don't see anything about CKA_ALWAYS_AUTHENTICATE requiring prompting from a tty. Providing the PIN on the command line is still coming from the "user" as far as I am concerned. In this case the Yubikey is locked in a secure machine room and unattended operation is essential, so having to manually supply a PIN is not an option. Our reason for storing the private key in a hardware module is to avoid potential loss of the key if somebody broke into the machine as root via the internet. We don't care about loss of the PIN; if somebody broke into the machine with root access, they'd be able to read any PIN typed in anyway. I could run Fedora in a docker container if that helps, but does softhsm set CKA_ALWAYS_AUTHENTICATE? Dave
Oh I see that yubico-piv-tool -a import-key has an option --pin-policy=never. Maybe that will turn off CKA_ALWAYS_AUTHENTICATE. I remember playing with that but with version 0.4.6 it always still required the -passin password so I didn't think it made any difference. Maybe I misunderstood what it meant. I will give it a try.
Unfortunately, re-importing with --pin-policy=never (and --touch-policy=never) makes no difference on the behavior.
Hello Dave, I was searching for a way to workaround this and stumbled on this: "I am using PIV card with OpenSC and I am prompted for a PIN with every signature. It didn’t happen with CoolKey. Every PIV digial signature key operation requires “explicit user action” as described in the following NIST document to assert reliable level of security. In some cases, this requirement can be weakened by enabling PIN caching for these operation in OpenSC by setting pin_cache_ignore_user_consent in /etc/opensc-*.conf." from this article : https://access.redhat.com/articles/3034441 So, if you are using the OpenSC driver, I would try to add the options to the "framework pkcs15" section in /etc/opensc*.conf file: pin_cache_ignore_user_consent = true; use_pin_caching = true; It would end up like: app default { # debug = 3; # debug_file = opensc-debug.txt; framework pkcs15 { # use_file_caching = true; pin_cache_ignore_user_consent = true; use_pin_caching = true; } reader_driver pcsc { # The pinpad is disabled by default, # because of many broken readers out there enable_pinpad = false; } } Let me know if it works for you.
It sounded so promising! Unfortunately, I don't see any change in behavior. --- /etc/opensc-x86_64.conf.O 2019-07-22 17:10:59.187563596 -0500 +++ /etc/opensc-x86_64.conf 2019-07-22 17:11:22.833613126 -0500 @@ -502,7 +502,6 @@ # Use PIN caching? # Default: true # use_pin_caching = false; - use_pin_caching = true; # # How many times to use a PIN from cache before re-authenticating it? # Default: 10 @@ -511,7 +510,6 @@ # Older PKCS#11 applications not supporting CKA_ALWAYS_AUTHENTICATE # may need to set this to get signatures to work with some cards. # Default: false - pin_cache_ignore_user_consent = true; # # Enable pkcs15 emulation. # Default: yes @@ -756,6 +754,5 @@ # Enable pinpad if detected (PC/SC v2.0.2 Part 10) # Default: true # enable_pinpad = false; - enable_pinpad = true; } }
Looking back, it appears from the above diff that I changed the .conf.O file instead of the .conf. However, I re-did all the tests and still have the same results. The diff now looks like this: --- /etc/opensc-x86_64.conf.O 2019-07-24 12:02:58.154464547 -0500 +++ /etc/opensc-x86_64.conf 2019-07-24 12:04:47.275736025 -0500 @@ -502,6 +502,8 @@ # Use PIN caching? # Default: true # use_pin_caching = false; + pin_cache_ignore_user_consent = true; + use_pin_caching = true; # # How many times to use a PIN from cache before re-authenticating it? # Default: 10 @@ -754,5 +756,6 @@ # Enable pinpad if detected (PC/SC v2.0.2 Part 10) # Default: true # enable_pinpad = false; + enable_pinpad = true; } }
However, the Red Hat article you referred to talked about doing debugging with pkcs11-tool, and while looking at its usage I noticed that it has a "--sign" option. I figured out the options I need to get it to create the signature without prompting for a PIN: pkcs11-tool -s -p 123456 -m RSA-PKCS -i motd.sha1 -o motd.sig That tool is a standard part of the opensc package, and it works without modifying the opensc config file. I guess I'll switch to using that.
Great, so switching to it worked for you? If it did, I think I can close this bug. Do you agree?
Yes, it worked. I am closing this bug, although there's not exactly a status to indicate "worked around". I'll say "DEFERRED" to indicate that I do not need it to be fixed at this time.