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.


Step-by-Step instructions

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 -b imx-linux-langdale -m imx-6.1.1-1.0.1.xml
$ repo sync -j12
$ MACHINE=imx93evk DISTRO=fsl-imx-xwayland source ./ -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/
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/
Available slots:
Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 
  token state:   uninitialized
Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 
  token state:   uninitialized
Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 
  token state:   uninitialized


7. Initialize token and set PIN

$ pkcs11-tool --module /usr/lib/ --init-token --label demo --so-pin 12345678
Using slot 0 with a present token (0x0)
Token successfully initialized
$ pkcs11-tool --module /usr/lib/ --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/ --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
engines = engines_config
pkcs11 = engine_pkcs11_parameters
engine_id = pkcs11
dynamic_path = /usr/lib/engines-3/
MODULE_PATH = /usr/lib/
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


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.

Figure illustrating AWS IoT provisioning flow


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 --cert device_cert_signed.pem --pin 12345678 --token_label demo --key_label demokey --pkcs11_lib /usr/lib/


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/
  • 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:

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.

Figure illustrating the system architecture for OP-TEE PKCS#11

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.


Akshay Bhat is CTO at Timesys. He oversees the strategic direction of Timesys’ technology roadmap. With more than 16 years of industry experience with embedded systems software development and security, Akshay’s focus is on Timesys solutions that transform the software development lifecycle for embedded and enable the development of embedded system products with stronger security. Akshay has authored numerous embedded Linux and industry articles and delivered several embedded systems security presentations. He received his MS in Electrical Engineering from NYU Polytechnic University.

About Timesys

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.