Bug 1728016 - openssl-pkcs11-0.4.8-1.el7 forces pkcs11 engine sign to always prompt for Yubikey 4 PIN
Summary: openssl-pkcs11-0.4.8-1.el7 forces pkcs11 engine sign to always prompt for Yub...
Keywords:
Status: CLOSED DEFERRED
Alias: None
Product: Fedora EPEL
Classification: Fedora
Component: openssl-pkcs11
Version: epel7
Hardware: Unspecified
OS: Unspecified
medium
medium
Target Milestone: ---
Assignee: Anderson Sasaki
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2019-07-08 19:51 UTC by Dave Dykstra
Modified: 2019-07-31 19:04 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-07-31 19:04:46 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Dave Dykstra 2019-07-08 19:51:08 UTC
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

Comment 1 Dave Dykstra 2019-07-08 21:21:15 UTC
This still fails when building with upstream 0.4.10.

Comment 2 Anderson Sasaki 2019-07-18 15:46:52 UTC
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.

Comment 3 Dave Dykstra 2019-07-18 16:50:09 UTC
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

Comment 4 Anderson Sasaki 2019-07-18 17:38:47 UTC
(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.

Comment 5 Dave Dykstra 2019-07-18 18:11:22 UTC
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

Comment 6 Dave Dykstra 2019-07-18 18:27:34 UTC
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.

Comment 7 Dave Dykstra 2019-07-19 19:10:21 UTC
Unfortunately, re-importing with --pin-policy=never (and --touch-policy=never) makes no difference on the behavior.

Comment 8 Anderson Sasaki 2019-07-22 11:49:45 UTC
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.

Comment 9 Dave Dykstra 2019-07-22 22:18:37 UTC
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;
 	}
 }

Comment 10 Dave Dykstra 2019-07-24 17:49:11 UTC
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;
 	}
 }

Comment 11 Dave Dykstra 2019-07-24 17:58:58 UTC
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.

Comment 12 Anderson Sasaki 2019-07-31 08:51:17 UTC
Great, so switching to it worked for you?

If it did, I think I can close this bug. Do you agree?

Comment 13 Dave Dykstra 2019-07-31 19:04:46 UTC
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.


Note You need to log in before you can comment on or make changes to this bug.