PKCS11 with OpenSSL 3.0

Hi,

I’m trying to configure Mender to use PKCS#11. I’m using the tpm2-pkcs11 project to provide a PKCS#11 interface to my TPM and the pkcs11-provider project to provide an OpenSSL provider for it.

I’ve configured the provider in /etc/ssl/openssl.cnf. I’ve created an EC private key in the TPM, and I can use it in openssl from the command line.

$ openssl pkey -noout -text -in "pkcs11:model=SLM9670;manufacturer=Infineon;serial=0000000000000000;token=dev;id=%01;object=my_key;type=private;pin-value=1234"
PKCS11 EC Private Key (256 bits)
[Can't export and print private key data]
URI pkcs11:model=SLM9670;manufacturer=Infineon;serial=0000000000000000;token=dev;id=%01;object=my_key;type=private

However, if I configure Mender to use this key for security
/var/lib/mender.conf:

{
"Security": {
        "AuthPrivateKey": "pkcs11:model=SLM9670;manufacturer=Infineon;serial=0000000000000000;token=dev;id=%01;object=my_key;type=private;pin-value=1234"
    }
}

the mender-authd service doesn’t start.

Jul 18 10:51:10 iot-gate-imx8plus systemd[1]: mender-authd.service: Scheduled restart job, restart counter is at 4.
Jul 18 10:51:10 iot-gate-imx8plus systemd[1]: Stopped Mender authentication service.
Jul 18 10:51:10 iot-gate-imx8plus systemd[1]: Started Mender authentication service.
Jul 18 10:51:10 iot-gate-imx8plus mender-auth[63160]: record_id=1 severity=error time="2024-Jul-18 10:51:10.477359" name="Global" msg="Failed to load the the private key: pkcs11:model=SLM9670;manufacturer=Infineon;serial=0000000000000000;token=dev;id=%01;object=my_key;type=private;pin-value=1234 trying the next object in the context: "
Jul 18 10:51:10 iot-gate-imx8plus mender-auth[63160]: record_id=2 severity=error time="2024-Jul-18 10:51:10.477632" name="Global" msg="Failed to bootstrap: Error during crypto library setup: Failed to load the private key from the configuration: Failed to load the private key: "
Jul 18 10:51:10 iot-gate-imx8plus systemd[1]: mender-authd.service: Main process exited, code=exited, status=1/FAILURE
Jul 18 10:51:10 iot-gate-imx8plus systemd[1]: mender-authd.service: Failed with result 'exit-code'.

I’ve tried setting the environment in the service file in /lib/systemd/system/mender-authd.service. But this doesn’t make a difference.

[Service]
...
Environment="OPENSSL_CONF=/etc/ssl/openssl.cnf"

However - I can run the mender-authd process manually

$ /usr/bin/mender-auth daemon

record_id=75 severity=info time="2024-Jul-18 11:32:56.736502" name="Global" msg="Signing with: pkcs11:model=SLM9670;manufacturer=Infineon;serial=0000000000000000;token=dev;id=%01;object=my_key;type=private;pin-value=1234" 
record_id=76 severity=info time="2024-Jul-18 11:32:57.105879" name="Global" msg="Successfully received new authorization data" 

Presumably this is a case of OpenSSL not finding the correct config when running as a systemd service. Does anyone have any suggestions?

Hey!

I can’t replicate your exact error, can you show me how you’re setting up pkcs11 in your openssl config?

This is part of my openssl.cnf:

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
pkcs11 = pkcs11_sect

[pkcs11_sect]
module = /path/to/pkcs11.so
pkcs11-module-path = /path/to/pkcs11-driver.so
activate = 1

[default_sect]
activate = 1

Note that you need to set pkcs11-module-path for the client to load it.

Which version of mender are you using? We’ve added a patch for explicitly loading the openssl config in the client, which is currently present in the master and the 4.0.x branch.

If you’re not using either of these branches, you could try to manually export PKCS11_PROVIDER_MODULE.

1 Like

Hi,

I’ve managed to get it working. I had some other issues with getting the TPM working, so it’s possible the issue was caused by a misconfigured TPM. I’ve got a script which is generating the key reproducibly, and Mender is authenticating with the key URI now.

Thanks for all your help - and trying to reproduce it!

2 Likes

For future reference - because it took me a while to figure this all out. I’m using Yocto Kirkstone 4.0.19 which has openssl 3.0.13. On top of that I’m using mender 4.0.2, the tpm2-pkcs11 0.19 recipe from Wind-River meta-secure-core and the pkcs11-provider 0.5 recipe back ported from Scarthgap.

I’ve configured OpenSSL similar to your example above

/etc/ssl/openssl.cnf

[openssl_init]
providers = provider_sect

# List of providers to load
[provider_sect]
default = default_sect
pkcs11 = pkcs11_sect 

[default_sect]
# Must be active or could break everything
activate = 1

[pkcs11_sect]
module = /usr/lib/ossl-modules/pkcs11.so
pkcs11-module-path = /usr/lib/pkcs11/libtpm2_pkcs11.so
activate = 1 

Using pkcs11-tool I’m creating an EC key. I run a script on startup that checks for the key and creates one if it doesn’t exist.

# First initialize the token
pkcs11-tool --module /usr/lib/pkcs11/libtpm2_pkcs11.so --init-token --label my_token --slot 1 --so-pin 0000

# And then login to the slot
pkcs11-tool --module /usr/lib/pkcs11/libtpm2_pkcs11.so --slot 1 --login --login-type so --init-pin --so-pin 0000 --pin 0000

# Then generate the key
pkcs11-tool --module /usr/lib/pkcs11/libtpm2_pkcs11.so --login --slot 1 --keypairgen --key-type EC:prime256v1 --label my_key --usage-sign --id 01 --pin 0000 --so-pin 0000

# And check OpenSSL can access it
openssl pkey -provider pkcs11 -noout -text -in pkcs11:object=my_key;type=private;pin-value=0000

And then configuring Mender to use it

{
"Security": {
        "AuthPrivateKey": "pkcs11:object=my_key;type=private;pin-value=0000"
    }
}

I actually don’t seem to need to set the OPENSSL_CONF environment variable.

So altogether pretty straightforward once you get the right pieces in place.

2 Likes

Thanks a lot @Leo for sharing!