easy-rsa icon indicating copy to clipboard operation
easy-rsa copied to clipboard

Added improved support for CA stored in PKCS#11 based token (RFC 7512 URIs).

Open robpower opened this issue 4 years ago • 11 comments

Add support for PKCS11 tokens, based on initial proposal #332 in response to #268. In comparison to previous implementation, this one makes use of RFC 7512 scheme to address tokens and keys, instead of legacy engine_PKCS11 ID (apparently going to be deprecated in openssl).

Tested on Smartcard-HSM, Nitrokey HSM, Nitrokey Pro, SoftHSM2 and Yubikey 5 NFC.

Introduces a new format for the ./pki/private/ca.key which can specify environment variables to point to the PKCS#11 private key on a specific token.

Modification of op_test.orig support initial testing on SoftHSM2.

Please see ./PKCS11.md for more details on the changes as well as tested configurations for Smartcard-HSM, Nitrokey HSM, Nitrokey Pro, SoftHSM2 and Yubikey 5 NFC.

Please share any useful feedback needed to get this PR merged.

robpower avatar Feb 23 '21 11:02 robpower

Added support to use existing keys from a PKCS11 token, if a matching pair is found, before trying to generate them. There is still room for improvement, but I would appreciate some feedback before moving further.

In particular I would like to ask on a couple of points (though any other suggestion is of course welcome):

  • Is it okay to use p11tool --generate-[rsa,ecc] commands (which are deprecated in recent versions of GnuTLS) instead of p11tool --generate-privkey=[rsa,ecc,..] (not deprecated but not yet present on Ubuntu Bionic 18.04 used for current testing)?
  • For sake of simplicity, I would suggest to drop SO/Admin login support for key generation. I implemented it as a first workaround solution for some token like Nitrokey Pro or Yubikey 5, but I would suggest using the "existing key" feature instead, after following the manufacturer suggested procedure to generate the keys.

robpower avatar Mar 11 '21 08:03 robpower

These fixes look pretty good. I will review them and merge this weekend. Poke me if I forget. :)

Eric F Crist

On Mar 11, 2021, at 02:58, Rob @.***> wrote:

Added support to use existing keys from a PKCS11 token, if a matching pair is found, before trying to generate them. There is still room for improvement, but I would appreciate some feedback before moving further.

In particular I would like to ask on a couple of points (though any other suggestion is of course welcome):

Is it okay to use p11tool --generate-[rsa,ecc] commands (which are deprecated in recent versions of GnuTLS) instead of p11tool --generate-privkey=[rsa,ecc,..] (not deprecated but not yet present on Ubuntu Bionic 18.04 used for current testing)? For sake of simplicity, I would suggest to drop SO/Admin login support for key generation. I implemented it as a first workaround solution for some token like Nitrokey Pro or Yubikey 5, but I would suggest using the "existing key" feature instead, after following the manufacturer suggested procedure to generate the keys. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/OpenVPN/easy-rsa/pull/433#issuecomment-796579052, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANXQPY5ENDMVEIC5AO4OBDTDCA4BANCNFSM4YCJIVYA.

ecrist avatar Mar 11 '21 16:03 ecrist

@ecrist, thanks for the feedback! Let me know if you think it would be better to remove PKCS11 SO/Admin Pin support from the PR or add any extra fix.

robpower avatar Mar 14 '21 18:03 robpower

Thank you for working on this.

PKCS11_MODULE_PATH is consumed by libp11, while other PKCS11_* variables are consumed by easy-rsa. Although libp11 does not consume any other environment variables beginning with PKCS11_, it would be better if we stick on EASYRSA_ prefix.

p11tool is used for list and manipulate keys on token. It might be better to use pkcs11-tool comes with opensc, instead of p11tool from gnutls, to avoid extra dependency and configuration. (to make p11tool work under macOS, some manual configuration is needed, like echo 'module: /usr/local/lib/opensc-pkcs11.so' >/usr/local/etc/pkcs11/modules/opensc.module)

zhangyoufu avatar Jun 30 '21 15:06 zhangyoufu

I'm using an openssl wrapper like this in my setup.

#!/bin/sh
if [ "$1" = "ca" ]; then
	shift
	set -- ca -engine pkcs11 -keyform ENGINE -keyfile 'pkcs11:token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29' "$@"
	export OPENSSL_ENGINES=/usr/local/lib/engines-1.1
	export PKCS11_MODULE_PATH=/usr/local/lib/opensc-pkcs11.so
fi
exec openssl "$@"

easy-rsa works quite well with my YubiKey 4 (I choose openpgp app instead of PIV, for RSA4096).

My snippet is rather small, comparing to this PR. IMHO, leave the init-pki part to user is still a good choice. There are just too many ways to generate key pairs on a token or import existing keys to a token.

zhangyoufu avatar Jun 30 '21 15:06 zhangyoufu

Hi,

some $EASYRSA_P11TOOL commands do not use the $PKCS11_MODULE_PATH provider, specifically those listing tokens urls / keys and labels.

This prevents using Yubikey own pkcs11 module (libykcs11.so) which for Yubikey 5 NFC list all retired slots (82 through 95) by default thus allowing usage with easy-rsa / openssl.

Patch here: Patch - Always use pkcs11 provider module for $EASYRSA_P11TOOL

PS: Sorry if this is not the right way to post a patch to an issue, first time doing this on github.

lainwir3d avatar Jul 22 '21 11:07 lainwir3d

Hi,

I did some tests and I can confirm that this PR works perfectly with Gemalto MD840 smart card. I can create CA with private key generated and stored on the SC and I can sign other certs using this CA. It works even on the remote server using the "p11-kit server" and SSH tunneling (sources here and here).

There are some small bugs like 'echo "\t…' is not printed as tab, just '\t' is printed.

@robpower Thank you for your good job! @lainwir3d I can confirm your patch. It is needed for me and it is working.

I hope this PR will be merged soon.

Du-St avatar Jan 14 '22 09:01 Du-St

I'm not sure overloading the [private].key file is the correct approach: I'd propose using something like [private].pk11 or [private].hsm and rather than a fork to grep, test presence of the [private].pk11 (or chosen f.ext).

reasoning: lets assume sometime in the (not too distant) future, usb HSMs are cheap enough (and fast enough) that just about every small-mid sized server is using one. At that point all the end-entity certs have their private keys protected by the HSM. Performing a grep through each private/[basename].key during request generation / regeneration seems excessive compared to an if exists [basename].pk11.

dekeonus avatar Sep 08 '22 22:09 dekeonus

It seems some recent OpenSSL upgrade broke that functionality for me:

Note: using Easy-RSA configuration from: /opt/nanl/nanl_decrypted/easy-rsa.git/easyrsa3/vars
Using SSL: openssl OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022)

Engine "pkcs11" set.
Error setting keysize
80AB6C6FED7F0000:error:03000093:digital envelope routines:evp_pkey_ctx_ctrl_int:command not supported:../crypto/evp/pmeth_lib.c:1321:

Easy-RSA error:

Failed to generate request

ca.key:

PKCS11_MODULE_PATH="/usr/lib/x86_64-linux-gnu/libykcs11.so"
PKCS11_TOKEN_URI="pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=X;token=YubiKey%20PIV%20%X;id=%12;object=X.509%20Certificate%20for%20Retired%20Key%2014;type=cert"
PKCS11_KEY_ID="12"
PKCS11_KEY_LABEL="SIGN"

Invoked openssl command resulting in above error:

openssl req -config /tmp/ssl.cfg -engine pkcs11 -keyform engine -utf8 -new -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/crt.pem -nodes -batch

Might be related to: https://github.com/OpenSC/libp11/issues/444

mirko avatar Nov 20 '22 15:11 mirko

Hi. I'm curious. Are there plans to merge this PR?

ikruglov avatar Jul 11 '23 18:07 ikruglov

Are there plans to merge this PR?

At this current time; No, there are no plans to merge this PR.

This remains open, pending thorough review.

TinCanTech avatar Jul 11 '23 19:07 TinCanTech