Hello, NXP Community,
I am currently working on integrating the Plug and Trust Middleware into OP-TEE based on the environment described in this post: How to integrate Plug and Trust MW into OP-TEE.
My goal is to achieve the following operations from a user-space application running on Linux, leveraging the SE051 secure element:
Generate an AES key and store it in SE051.
Generate an RSA key pair and store it in SE051.
Encrypt a file using the AES key stored in SE051.
Decrypt the file using the AES key stored in SE051.
Sign data using the RSA private key in SE051.
Verify the signature using the RSA public key in SE051.
Encrypt data using the RSA public key in SE051.
Decrypt data using the RSA private key in SE051.
Could anyone guide me on the best approach to achieve these operations? I am open to using any of the following command-line tools (or a combination of them), provided they are supported in this OP-TEE setup:
openssl commands (via OpenSSL provider)
ssscli tool
pkcs11-tool (via PKCS#11 interface)
Any examples, documentation links, or command usage samples for this specific OP-TEE environment would be greatly appreciated.
Hi @Uc_S ,
There are three supported paths from Linux user-space to the SE051. All three are available with Plug & Trust MW v04.07.01:
| Path | Library | Best For |
|---|---|---|
| PKCS#11 | libsss_pkcs11.so |
AES, RSA key gen/sign/verify/enc/dec via pkcs11-tool |
| OpenSSL Provider (3.x) | libsss_provider.so |
RSA sign/verify/enc/dec via openssl pkeyutl |
| ssscli | Python CLI | Key injection / provisioning only |
Important note for OP-TEE environment: In your OP-TEE setup (
CFG_NXP_SE05X=y), the SE051 is accessed by OP-TEE core directly via the native I2C driver. Linux user-space applications do not own the I2C bus. All three paths above work correctly because the Plug & Trust MW Access Manager (accessManager) or the T1oI2C socket interface routes commands through OP-TEE's trusted world to the SE051.
Use ssscli to generate an AES-256 key at a specific Key ID (object ID in SE051):
# Generate AES-256 key at Key ID 0x20000001
ssscli generate aes 0x20000001 256
To verify the key exists:
ssscli get aes 0x20000001 aes_key_info.txt
Note: AES keys are symmetric and cannot be exported from SE051. The Key ID
0x20000001is a 32-bit object identifier stored persistently in SE051 NVM.
pkcs11-tool (recommended)RSA key labels use the format sss::
# Generate RSA-2048 key pair at Key ID 0x10101010
pkcs11-tool --module $PKCS11_MODULE --keypairgen --key-type rsa:2048 --label "sss:10101010"
sssclissscli generate rsa 0x10101010 2048
AN13030 Section 3.3.8.3 notes: RSA key pairs must be DER encoded using PKCS#8 or traditional OpenSSL format when injecting externally. When retrieved via
sss_key_store_get_key(), only the public key is returned.
AES symmetric encryption is performed via the SSS API (sss_cipher_one_go) or, for command-line use, through a small wrapper application. The MW provides a built-in symmetric example at:
simw-top/sss/ex/symmetric/ex_sss_symmetric.c
For direct command-line use, build and run the example:
# After building the MW examples:
./se05x_symmetric_aes_cbc_encrypt --keyid 0x20000001 --input plaintext.bin --output ciphertext.bin --iv 00000000000000000000000000000000
The MW supports:
kAlgorithm_SSS_AES_ECB,kAlgorithm_SSS_AES_CBC,kAlgorithm_SSS_AES_CTR,kAlgorithm_SSS_AES_GCM,kAlgorithm_SSS_AES_CCM(from Section 3.3.9.1 of AN13030).
./se05x_symmetric_aes_cbc_decrypt --keyid 0x20000001 --input ciphertext.bin --output decrypted.bin --iv 00000000000000000000000000000000
The SSS API uses
kMode_SSS_Decryptmode withsss_cipher_one_go()for one-shot decryption, or the multi-stepsss_cipher_init()/sss_cipher_update()/sss_cipher_finish()sequence for streaming.
pkcs11-tool (key stays in SE051)# Sign with RSA private key (key never leaves SE051)
pkcs11-tool --module $PKCS11_MODULE --sign --label sss:10101010 -m SHA256-RSA-PKCS --slot 1 -i in.der -o signature.der
Supported sign mechanisms via PKCS#11:
SHA256-RSA-PKCS (RSASSA-PKCS1-v1_5 with SHA-256)SHA1-RSA-PKCS, SHA384-RSA-PKCS, SHA512-RSA-PKCSRSA-PKCS-PSS (PSS padding)# Configure OpenSSL to use the NXP provider (see /etc/ssl/openssl.cnf)
openssl pkeyutl -provider nxp -sign -inkey "pkcs11:token=sss;object=sss:10101010;type=private" -in in.txt -out signature.der
# Method A: via ssscli
ssscli get rsa pub 0x10101010 rsa_pub.der
# Method B: via pkcs11-tool
pkcs11-tool --module $PKCS11_MODULE --read-object --type pubkey --slot 1 --label sss:10101010 -o pubkey.der
# Convert DER to PEM for OpenSSL
openssl rsa -in pubkey.der -inform der -out pubkey.pem -outform pem -pubin
openssl dgst -keyform PEM -verify pubkey.pem -sha256 -signature signature.der in.txt
# Expected output: Verified OK
RSA encryption uses the public key (no secure element needed for encrypt):
# Encrypt with public key (host side)
openssl rsautl -encrypt -inkey pubkey.pem -in in.txt -pubin -out crypt.txt
For OAEP padding (recommended), use:
openssl pkeyutl -encrypt -inkey pubkey.pem -pubin > -pkeyopt rsa_padding_mode:oaep > -pkeyopt rsa_oaep_md:sha256 > -in in.txt -out crypt.txtAN13030 Section 3.3.5.6 lists supported algorithms including
kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256andkAlgorithm_SSS_RSAES_PKCS1_V1_5.
The RSA private key decryption is performed entirely inside SE051. The private key never leaves the secure element.
pkcs11-toolpkcs11-tool --module $PKCS11_MODULE --decrypt --label sss:10101010 --slot 1 -i crypt.txt -o decrypt.txt
cat decrypt.txt
openssl pkeyutl -provider nxp -decrypt -inkey "pkcs11:token=sss;object=sss:10101010;type=private" -in crypt.txt -out decrypt.txt
AN13030 Section 2.3.4 confirms: "RSA Encrypt and decrypt feature added in provider" (from v04.05.03 onwards, included in v04.07.01).
When using pkcs11-tool with the NXP PKCS#11 library, the Key ID label format is:
sss:
For example, Key ID 0x10101010 → label sss:10101010
Breaking change in v04.07.00 (PKCS#11 v4.7): The
CKA_IDattribute (--id) is now treated as a byte array to avoid byte swapping. Pass the ID without changing endianness.
Before using pkcs11-tool, you may need to initialize the token slot:
# Initialize slot 0
pkcs11-tool --module $PKCS11_MODULE --init-token --slot 0 --label "SE051_Token" --so-pin 12345678
# Set user PIN
pkcs11-tool --module $PKCS11_MODULE --init-pin --slot 0 --login --so-pin 12345678 --pin 87654321
Add to /etc/ssl/openssl.cnf (or a custom config file):
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
nxp = nxp_sect
[default_sect]
activate = 1
[nxp_sect]
module = /usr/local/lib/libsss_provider.so
activate = 1
The OpenSSL provider source is also available at: https://github.com/NXPPlugNTrust/se05x-openssl-provider
The following built-in examples in the MW package directly demonstrate these operations:
| Operation | Example Path |
|---|---|
| AES encrypt/decrypt | simw-top/sss/ex/symmetric/ex_sss_symmetric.c |
| RSA sign/verify | simw-top/sss/ex/rsa/ (Section 5.2.1.2 of AN13030) |
| ECC sign/verify | simw-top/sss/ex/ecc/ (Section 5.2.1.1 of AN13030) |
| PKCS#11 scripts | simw-top/sss/plugin/pkcs11/scripts/ |
| OpenSSL Provider RSA enc | simw-top/sss/plugin/openssl_provider/scripts/openssl_RsaEnc.py |
CFG_NXP_SE05X_CTR_DRV being enabled. User-space AES via PKCS#11 goes through the Access Manager and is separate from the OP-TEE crypto driver offload.RSA_CRT support added in PKCS11 v4.8). Use PKCS11_ENABLE_RSA_KEY_GEN_CRT cmake option to switch between CRT and plain RSA.ssscli delete .simw-top/hostlib/hostlib/accessManager. Build with -DSMCOM:STRING=JRCP_V1_AM.| Document | Description |
|---|---|
| AN13030 | Plug & Trust MW Documentation (primary reference) |
| AN12660 | IEC 62443 compliance with SE05x — includes SSS API example pointers |
simw-top/doc/ (local HTML) |
Full documentation for your installed version v04.08.01 |
simw-top/doc/plugins/pkcs11.html |
PKCS#11 Standalone Library documentation |
simw-top/doc/demos.html |
Complete list of available demo examples |
Hope that helps,
Have a great day,
Kan
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @Uc_S ,
When CFG_NXP_SE05X=y is set, OP-TEE takes exclusive ownership of the I2C bus to the SE051. The Linux DTS must disable that I2C controller (as described in the integration guide). This fundamentally changes how the Plug & Trust MW is used:
| Layer | Who Runs It | How It Reaches SE051 |
|---|---|---|
| OP-TEE Secure World | OP-TEE core | Native I2C driver (CFG_IMX_I2C=y) — direct, exclusive |
| Linux Userspace | Your application, ssscli, Access Manager | Cannot use T1oI2C — I2C is disabled in Linux DTS |
This means your existing cmake configuration with -DPTMW_SMCOM=T1oI2C applies only when Linux directly owns I2C. In the OP-TEE setup, it applies to two separate build scenarios described below.
CFG_NXP_SE05X_PLUG_AND_TRUST=)This is the most important case. The MW is compiled as a static library inside OP-TEE — you do not run cmake manually for this. OP-TEE's Makefile handles the integration automatically when you point CFG_NXP_SE05X_PLUG_AND_TRUST at your extracted MW directory:
CFG_NXP_SE05X_PLUG_AND_TRUST=$HOME/linux-factory/plug-and-trust
The SMCOM, Host, and Auth flags you listed are not applicable here. OP-TEE drives the SE051 via its own native I2C abstraction layer (CFG_IMX_I2C=y), bypassing the Linux MW communication stack entirely.
This is where your cmake flags do apply. When OP-TEE owns I2C, here is the flag-by-flag analysis of what must change:
| Flag | Your Current Value | Recommended Value for OP-TEE Setup | Reason |
|---|---|---|---|
-DPTMW_SMCOM |
T1oI2C |
JRCP_V1_AM (if using Access Manager) |
Linux cannot use I2C directly; Access Manager provides socket proxy |
-DPTMW_SE05X_Auth |
PlatfSCP03 |
None |
SCP03 channel is established by OP-TEE, not Linux userspace |
-DPTMW_SCP |
SCP03_SSS |
None |
Same reason — SCP03 is owned by OP-TEE secure world |
| Flag | Value | Reason |
|---|---|---|
-DPTMW_Applet |
SE05X_C |
Correct for your SE051C2 variant (OEF ID A8FA) |
-DPTMW_SE05X_Ver |
07_02 |
Matches applet version 7.2 seen in OP-TEE boot logs |
-DPTMW_Host |
iMXLinux |
Still running on i.MX Linux |
-DPTMW_HostCrypto |
OPENSSL |
Unchanged |
-DPTMW_RTOS |
Default |
Unchanged |
-DPTMW_OpenSSL |
3_0 |
Unchanged for OpenSSL 3.x |
-DPTMW_FIPS |
None |
Unchanged |
-DPTMW_SBL |
None |
Unchanged |
-DPTMW_mbedTLS_ALT |
None |
Unchanged |
-DPTMW_Log |
Silent |
Unchanged |
-DPTMW_SE_RESET_LOGIC |
1 |
Unchanged; new option added in v04.07.00 |
cd simw-top && mkdir build_optee_linux
cmake -S . -B ./build_optee_linux/ -DPTMW_Applet=SE05X_C -DPTMW_SE05X_Ver=07_02 -DPTMW_Host=iMXLinux -DPTMW_SMCOM=JRCP_V1_AM -DPTMW_HostCrypto=OPENSSL -DPTMW_RTOS=Default -DPTMW_mbedTLS_ALT=None -DPTMW_SCP=None -DPTMW_FIPS=None -DPTMW_SBL=None -DPTMW_SE05X_Auth=None -DPTMW_Log=Silent -DCMAKE_BUILD_TYPE=Release -DPTMW_OpenSSL=3_0 -DPTMW_SE_RESET_LOGIC=1
cd build_optee_linux && make -j8
Note:
JRCP_V1_AMrequires the Access Manager to be running as a daemon on the target. The Access Manager itself connects to the SE051 — but see the important caveat below.
The Access Manager (hostlib/hostLib/accessManager) is designed to serialize concurrent I2C access from multiple Linux processes. However:
When OP-TEE fully disables the I2C interface in Linux DTS (as required by
CFG_NXP_SE05X=y), the Access Manager itself cannot open I2C either.
This means you have two valid deployment choices:
OP-TEE owns I2C completely. Linux userspace uses only the OP-TEE PKCS#11 TA (libckteec.so) for crypto operations. The Plug & Trust MW ssscli and demos are not run from Linux in this mode.
Linux App → libckteec.so → OP-TEE PKCS#11 TA → SE051
This is the path described in the i.MX Linux User's Guide (UG10163) for OP-TEE-based SE05x use.
Use a Linux DTS that does not disable I2C from Linux (i.e., do NOT apply the lf-6.12.y-i2c-disabled-se050 DTS patch). In this configuration:
T1oI2C (your original flags)For this choice, revert SMCOM, SCP, and Auth flags to your original values and keep the original I2C DTS (do not disable it).
| Use Case | SMCOM | SCP | Auth | Notes |
|---|---|---|---|---|
| OP-TEE internal MW (static lib for OP-TEE build) | N/A | N/A | N/A | No cmake needed; handled by CFG_NXP_SE05X_PLUG_AND_TRUST= |
| Linux userspace, OP-TEE exclusive I2C | JRCP_V1_AM |
None |
None |
Requires Access Manager, but AM itself can't reach SE051 if I2C disabled |
| Linux userspace, co-existence (I2C shared) | T1oI2C |
SCP03_SSS |
PlatfSCP03 |
Your original flags — valid if Linux DTS still has I2C enabled |
| Linux userspace via PKCS#11 TA (OP-TEE exclusive) | N/A (no MW build) | N/A | N/A | Use pkcs11-tool / openssl with libckteec.so |
Have a great day,
Kan
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Thank you very much for the thorough and detailed response.
The breakdown of the three supported paths and the command examples are extremely helpful.
Regarding the OP-TEE environment, I have a follow-up question regarding the CMake build configuration for the Plug & Trust Middleware on the Linux rootfs.
Previously, when running the middleware directly on Linux (without OP-TEE routing), we used the following CMake configuration flags:
-DPTMW_Applet=SE05X_C
-DPTMW_SE05X_Ver=07_02
-DPTMW_Host=iMXLinux
-DPTMW_SMCOM=T1oI2C
-DPTMW_HostCrypto=OPENSSL
-DPTMW_RTOS=Default
-DPTMW_mbedTLS_ALT=None
-DPTMW_SCP=SCP03_SSS
-DPTMW_FIPS=None
-DPTMW_SBL=None
-DPTMW_SE05X_Auth=PlatfSCP03
-DPTMW_Log=Silent
-DCMAKE_BUILD_TYPE=Release
-DPTMW_OpenSSL=3_0
-DPTMW_SE_RESET_LOGIC=1Could you please advise which of the above settings should be changed and what their new recommended values should be for this OP-TEE setup?
Details:
Now that OP-TEE owns the direct I2C access to the SE051 (via CFG_NXP_SE05X=y), could you please clarify if any of these CMake flags need to be modified when building the Linux user-space middleware/tools (such as ssscli or Access Manager)?
Specifically, should options like -DPTMW_SMCOM (e.g., changing from T1oI2C to JRCP_V1_AM or socket interface) or -DPTMW_Host be updated for the Linux user-space side to properly route requests through OP-TEE?
Here are my environment details: