PKCS#11 support for Zymkey is now available from our main repo for Raspbian Jessie/Stretch/Buster and Ubuntu Bionic 64-bit. This package is called zkpkcs11 and can be installed on existing installations with:
sudo apt -y update
sudo apt -y upgrade
If you are working off of a fresh install of the Zymbit host packages as detailed in Getting Started, package zkpkcs11 will come over automatically.
We have based the zkpkcs11 package on the SoftHSM2 source code. We have added 2 extra features to this:
Zymkey private keys can be used for signing by specifying --use-zkslot when creating a new key object with zk_pkcs11-util. This only applies to NIST-P256 (secp256r1) for Zymkey 4i. Future Zymbit products will support secp256k1 as well.
Even though SoftHSM2 does key wrapping to protect its key objects, Zymbit goes a step further and protects all key material in its private object store with its data lock/unlock feature, even for slots that are Zymkey does not support, such as RSA. For example, if you wanted to setup a zkpkcs11 slot that was RSA, you could do that as well and, even though all actions would be done by OpenSSL in software on the host computer rather than the Zymkey, Zymkey would still use its lock/unlock feature to protect the generated RSA private key.
Example:
Let’s say you need to create a slot that uses Zymkey as the root of trust for ECDSA signature generation as part of a framework like AWS Greengrass.
First, add your user account to the group zkpkcs11: sudo usermod -a -G zk_pkcs11 <username>
Exit and re-enter your ssh or console session for the new group to take effect.
Initialize a new token at slot 0: zk_pkcs11-util --init-token --slot 0 --label "greengrass"
Enter the SO PIN and the User PIN when prompted. Be sure to note the new slot reassignment when the message The token has been initialized and is reassigned to slot <new slot number> shows up.
Create a new key object which specifies that a zymkey private key slot should be used. Here we’ll use Zymkey key slot 2: zk_pkcs11-util --use-zkslot 2 --slot <new slot number> --label iotkey --id 0000
Be sure to use the slot reassignment that was printed out in step 3.
That’s it! You should now have a PKCS#11 object defined that knows how to use Zymkey when that slot is called out.
The username is whatever your account username is. For example, the default user on Raspbian is ‘pi’, so the command would be: sudo usermod -a -G zk_pkcs11 pi
$ zk_pkcs11-util --init-token --slot 0 --label "greengrass"
=== SO PIN (4-255 characters) ===
Please enter SO PIN: ****
Please reenter SO PIN: ****
=== User PIN (4-255 characters) ===
Please enter user PIN: ****
Please reenter user PIN: ****
The token has been initialized and is reassigned to slot 419907394
$ zk_pkcs11-util --use-zkslot 2 --slot 419907394 --label iotkey --id 0000
=== User PIN (4-255 characters) ===
Please enter user PIN: ****
Please reenter user PIN: ****
ERROR: Could not save the private key in the token. Maybe the algorithm is not supported.
Hi Micah,
I tried the same two commands and did not get any error. Can you confirm which model PI you are using, as well as the OS version? Do you have the Zymkey installed and bound, i.e. is the blue LED flashing once every three seconds?
I have followed the description found in the example here. The commands for init-token and use-zkslot seem to succeed, but I get an error when I try to use the slot with awsiotsdk. The call to mqtt_connection_builder.mtls_with_pkcs11 (from awsiot) fails with error: “RuntimeError: 1074 (AWS_ERROR_PKCS11_TOKEN_NOT_FOUND): Could not pick PKCS#11 token matching search criteria (none found, or multiple found)”. I have tried both with and without token_label (greengrass) and private_key_label (iotkey).
This is part of the output from the python script where the library path, slot id and labels used are printed in the log:
loglevel=INFO message=Loading PKCS#11 library: "/usr/lib/libzk_pkcs11.so", using slot id: "961662786", token label: "greengrass", private key label: "iotkey"
Traceback (most recent call last):
...
File "/***/***.py", line 40, in __init__
connection = mqtt_connection_builder.mtls_with_pkcs11(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "***/venv/lib/python3.11/site-packages/awsiot/mqtt_connection_builder.py", line 351, in mtls_with_pkcs11
return _builder(tls_ctx_options, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "***/venv/lib/python3.11/site-packages/awsiot/mqtt_connection_builder.py", line 231, in _builder
tls_ctx = awscrt.io.ClientTlsContext(tls_ctx_options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "***/venv/lib/python3.11/site-packages/awscrt/io.py", line 596, in __init__
self._binding = _awscrt.client_tls_ctx_new(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: 1074 (AWS_ERROR_PKCS11_TOKEN_NOT_FOUND): Could not pick PKCS#11 token matching search criteria (none found, or multiple found)
Thank you for your prompt response. Let me introduce my situation.
I noticed that zymbit supports PKCS11, and the AWS IoT device client also supports secure elements. I attempted to use the AWS IoT device client to log in with zymbit’s private key.
There was indeed a bug/regression introduced that we did not catch. We have issued a fix, and added a test to make sure that such a regression does not reappear.
That will ensure that you have the new (fixed) version of the zkpkcs11 package. I have verified that this fix works on my Pi 4 and Pi 5 so hopefully it will also work for you.
Let me know if you’re still having trouble after applying this fix.