Following up on the blog PKCS#11 with OP-TEE, this blog dives deeper with a hands-on example of using PKCS#11 on an NXP i.MX93 EVK running Yocto based Linux to securely connect/provision the device on the AWS IoT platform. While we have selected i.MX93 EVK as an example, the steps should work for all i.MX processors that support OP-TEE.
The below steps are for creating a Yocto Linux distribution for NXP’s i.MX93 EVK with support for PKCS#11. After building the target image, the PKCS#11 command line tools are used to create a RSA key pair secured by OP-TEE. The keys are then used to create a device certificate using OpenSSL.
1. Setup the host PC for building Yocto using the Yocto project manual or NXP’s user guide. Here we will be using NXP’s Yocto Langdale release (Linux 6.1.1_1.0.01) with imx93evk. On your host machine, setup Yocto:
$ mkdir imx $ cd imx $ repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-langdale -m imx-6.1.1-1.0.1.xml $ repo sync -j12 $ MACHINE=imx93evk DISTRO=fsl-imx-xwayland source ./imx-setup-release.sh -b bld-xwayland
2. In the local.conf, add the below line:
IMAGE_INSTALL:append = " libp11 opensc openssl-bin "
Note: OP-TEE and the PKCS#11 TA is included by default
3. Build the target image.
$ bitbake imx-image-core
4. Flash the image onto the SD card.
$ sudo bmaptool copy tmp/deploy/images/imx93evk/imx-image-core-imx93evk.wic.zst /dev/sd<X>
5. Boot the board, login as “root” user. Verify OP-TEE is installed:
$ dmesg|grep optee [ 1.454467] optee: probing for conduit method. [ 1.458939] optee: revision 3.19 (ad4e8389) [ 1.459375] optee: dynamic shared memory is enabled [ 1.468772] optee: initialized driver
6. Verify PKCS#11 TA is installed:
$ pkcs11-tool --show-info --module /usr/lib/libckteec.so.0 Cryptoki version 2.40 Manufacturer Linaro Library OP-TEE PKCS11 Cryptoki library (ver 0.1) Using slot 0 with a present token (0x0) $ pkcs11-tool --list-slots --module /usr/lib/libckteec.so.0 Available slots: Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 62bc5a04-868c-5400-b879-37436c8e4cf8 token state: uninitialized Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 62bc5a04-868c-5400-b879-37436c8e4cf8 token state: uninitialized Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 62bc5a04-868c-5400-b879-37436c8e4cf8 token state: uninitialized
7. Initialize token and set PIN
$ pkcs11-tool --module /usr/lib/libckteec.so.0 --init-token --label demo --so-pin 12345678 Using slot 0 with a present token (0x0) Token successfully initialized $ pkcs11-tool --module /usr/lib/libckteec.so.0 --label demo --login --so-pin 12345678 --init-pin --pin 12345678 Using slot 0 with a present token (0x0) User PIN successfully initialized
8. Create RSA Public Private Key
$ pkcs11-tool --module /usr/lib/libckteec.so.0 --label demo --login --pin 12345678 --keypairgen --label demokey --key-type rsa:2048 Using slot 0 with a present token (0x0) Key pair generated: Private Key Object; RSA label: demokey Usage: decrypt, sign Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: demokey Usage: encrypt, verify Access: local
9. Verify OpenSSL support for PKCS#11 Engine
$ openssl engine -c pkcs11 (pkcs11) pkcs11 engine [RSA, rsaEncryption, id-ecPublicKey]
10. Configure OpenSSL PKCS#11 engine as follows:
$ cat openssl.conf openssl_conf = openssl_conf [openssl_conf] engines = engines_config [engines_config] pkcs11 = engine_pkcs11_parameters [engine_pkcs11_parameters] engine_id = pkcs11 dynamic_path = /usr/lib/engines-3/pkcs11.so MODULE_PATH = /usr/lib/libckteec.so.0.1.0 PIN = 12345678 init = 0
11. Create a device certificate corresponding to the RSA key pair generated in step 8
$ OPENSSL_CONF=openssl.conf openssl req -new -x509 -days 365 -subj '/CN=demodevice/' -sha256 -engine pkcs11 -keyform engine -key slot_0-label_demokey -out device_cert.pem Engine "pkcs11" set. $ cat device_cert.pem -----BEGIN CERTIFICATE----- MIICsTCCAZkCFEpfYHH3vuipeXGVb45nyWoYva/MMA0GCSqGSIb3DQEBCwUAMBUx EzARBgNVBAMMCmRlbW9kZXZpY2UwHhcNMjIxMTA4MTQxMDQ5WhcNMjMxMTA4MTQx MDQ5WjAVMRMwEQYDVQQDDApkZW1vZGV2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAvX0UwecOPSojNJGmNVrDgKbmBMh0AreTFNUvSq759hDEfz4S <snip> ZEQdYVCriIrqOZYIareRqN3FXzaBteDOB4+oochEWS4vXNLBuAGfxLEBg+ip3h+c 1KVbxwHWDRxnXk1FL5YQSeK1eQRR1iDBqEq8VonuN//U4gdQoC74cGdOkVtLe1rm fBpP/cIQ0g8P0utZcneItVM8cRko -----END CERTIFICATE-----
Now the device certificate is ready for use for authenticating the device, and the device certificate can optionally be signed by a CA or OEM.
Use case: Securing your AWS IoT cloud connection using PKCS#11
Securely connecting an IoT device to a cloud platform like AWS or Azure IoT is a common use case. One of the first steps involved is authenticating the device and provisioning it. This is where device certificates and PKCS#11 comes handy. Using AWS IoT platform as an example, below is a high level overview of the steps involved:
- Step 1: At manufacturing, create a public / private key pair on the device. The keys are secured by OP-TEE / PKCS#11 TA as detailed in the hands-on section.
- Step 2: Create a certificate signing request from the device (e.g.: using openssl).
- Step 3: Either use a 3rd party Certificate Authority (CA) or self sign the certificate using the CA / OEM private key.
- Step 4: Register the trusted CA/OEM certificate with the AWS IoT platform. This allows the AWS platform to verify the signed device certificates by the CA/OEM.
- Step 5: On device boot, use the AWS client with PKCS#11 support to securely connect to the cloud and register the device, more on this in the next section.
- Step 6: The AWS IoT platform verifies the certificate presented by the device and based on the security policy allows the device to be registered
- Step 7/8: A secure / authenticated channel can now be established, and then the device can publish any telemetry data over MQTT using session keys.
The detailed documentation for AWS IoT provisioning can be found here. In this section we will only cover the PKCS#11 specific aspects.
For using PKCS#11 to connect to the AWS IoT platform, the AWS IoT SDK provided detailed instructions. For python SDK, instructions can be found here. Build the SDK by including the meta-aws layer in your Yocto build and add the aws-iot-device-sdk-python-v2 package to the target image. Then on the target device, run:
./pkcs11-connect --endpoint <endpoint> --cert <path to certificate> --pkcs11_lib <path to PKCS11 lib> --pin <user-pin> --token_label <token-label> --key_label <key-label>
In our case when using the OP-TEE PKCS#11 provider, the usage looks like this:
$ ./pkcs11-connect --endpoint a2soz3hump6hr-ats.iot.us-east-1.amazonaws.com --cert device_cert_signed.pem --pin 12345678 --token_label demo --key_label demokey --pkcs11_lib /usr/lib/libckteec.so.0.1.0
For use with other cloud providers or user space applications, the hands-on steps in the previous section largely remain the same. The application specific changes typically involves:
- Specifying PKCS#11 provider (/usr/lib/libckteec.so.0)
- Replace the location to private key in the file system with PKCS#11 URI / key slot-id.
Other platform support
While this blog focuses on the i.MX processors, the OP-TEE PKCS#11 TA is fairly platform agnostic. The instructions provided can be used on any hardware platform that supports:
- OP-TEE OS
- Implements support for Hardware Unique Key (HUK) i.e. used for OP-TEE secure storage
As of upstream OP-TEE OS v3.21.0, the platforms that meet the above criteria include: STM32MP1, Xilinx Zynq UltraScale+, Xilinx Versal, NXP i.MX6/7/8/9, TI AM62x/64x/65x “K3”, TI DRA7xx/AM57xx and Marvell Armada.
In the case of i.MX93, the EdgeLock Secure Enclave (ELE) acts as a hardware root of trust and also provides the hardware unique key within OP-TEE OS. Thus the keys stored within OP-TEE are protected by the EdgeLock Secure Enclave derived HUK.
Additionally the OEM / device manufacturer is responsible for implementing secure boot and chain of trust to ensure only authenticated software runs on the device and the keys are not exposed by running unauthorized/untrusted software.
Support for PKCS#11 is readily available out-of-the-box on multiple hardware platforms and widely adopted in open source application software. PKCS#11 with OP-TEE is an easy way of adding another layer of security as part of your defense in depth strategy to secure your device keys and certificates.
Simplify Security with Timesys
At Timesys, our goal is to keep you ahead of the next security threat, help you design security into your devices and keep them secure while in the field—AND get your products to market faster with our PSA Certified VigiShield Secure By Design security feature implementation.
Contact us today to begin your journey to a more simplified, secure product.
Timesys has extensive experience with embedded system development and lifecycle management. Timesys has been instrumental in working with global leader semiconductor manufacturers with smart, quick and quality solutions for highly complex systems with accelerated product innovation and multiple product variants.