How to perform Key Gen, Enc/Dec, and Sign/Verify with SE051 via OP-TEE on Linux? 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. SE050 Re: How to perform Key Gen, Enc/Dec, and Sign/Verify with SE051 via OP-TEE on Linux? 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.
Operation 1: Generate an AES Key and Store It in 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 0x20000001 is a 32-bit object identifier stored persistently in SE051 NVM.
Operation 2: Generate an RSA Key Pair and Store It in SE051
Option A — Using 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"
Option B — Using ssscli
ssscli 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.
Operation 3: Encrypt a File Using the AES Key in SE051
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).
Operation 4: Decrypt a File Using the AES Key in SE051
./se05x_symmetric_aes_cbc_decrypt --keyid 0x20000001 --input ciphertext.bin --output decrypted.bin --iv 00000000000000000000000000000000
The SSS API uses kMode_SSS_Decrypt mode with sss_cipher_one_go() for one-shot decryption, or the multi-step sss_cipher_init() / sss_cipher_update() / sss_cipher_finish() sequence for streaming.
Operation 5: Sign Data Using the RSA Private Key in SE051
Using 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-PKCS
RSA-PKCS-PSS (PSS padding)
Using OpenSSL Provider (v3.x)
# 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
Operation 6: Verify Signature Using the RSA Public Key in SE051
Step 1 — Export public key from SE051
# 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
Step 2 — Verify (host-side, no SE051 required)
openssl dgst -keyform PEM -verify pubkey.pem -sha256 -signature signature.der in.txt
# Expected output: Verified OK
Operation 7: Encrypt Data Using the RSA Public Key in SE051
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.txt
AN13030 Section 3.3.5.6 lists supported algorithms including kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256 and kAlgorithm_SSS_RSAES_PKCS1_V1_5 .
Operation 8: Decrypt Data Using the RSA Private Key in SE051
The RSA private key decryption is performed entirely inside SE051. The private key never leaves the secure element.
Using pkcs11-tool
pkcs11-tool --module $PKCS11_MODULE --decrypt --label sss:10101010 --slot 1 -i crypt.txt -o decrypt.txt
cat decrypt.txt
Using OpenSSL Provider (v3.x)
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).
Key ID Label Convention
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_ID attribute ( --id ) is now treated as a byte array to avoid byte swapping. Pass the ID without changing endianness.
PKCS#11 Token Initialization (First-Time Setup)
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
OpenSSL 3.x Provider Configuration
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
Source Code Examples (in simw-top)
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
Known Limitations in OP-TEE Context
AES offload to SE051 from OP-TEE kernel side depends on 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 key generation in SE051 is CRT format by default in v04.07.01 ( RSA_CRT support added in PKCS11 v4.8). Use PKCS11_ENABLE_RSA_KEY_GEN_CRT cmake option to switch between CRT and plain RSA.
SE051 NVM is limited. Many RSA key pair generations may exhaust persistent storage — delete unused objects with ssscli delete .
For concurrent multi-process access (e.g., multiple user-space apps), use the Access Manager at simw-top/hostlib/hostlib/accessManager . Build with -DSMCOM:STRING=JRCP_V1_AM .
Reference Documents
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. ------------------------------------------------------------------------------- Re: How to perform Key Gen, Enc/Dec, and Sign/Verify with SE051 via OP-TEE on Linux? 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.
Scenario 1: MW Build Fed into OP-TEE ( 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.
Scenario 2: Linux Userspace Tools (ssscli / Access Manager / Demos)
This is where your cmake flags do apply. When OP-TEE owns I2C, here is the flag-by-flag analysis of what must change:
Flags That 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
Flags That Stay the Same
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
Recommended cmake Command for Linux Userspace Tools in OP-TEE Setup
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_AM requires 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.
Critical Caveat: The Access Manager I2C Conflict
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:
Choice A: OP-TEE Exclusive (Recommended for Production)
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.
Choice B: Co-existence (Testing / Provisioning)
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:
OP-TEE uses SE051 for crypto offload (RSA/ECC)
Linux userspace can still run ssscli / Access Manager using T1oI2C (your original flags)
Risk: concurrent I2C access from both OP-TEE and Linux requires careful arbitration
For this choice, revert SMCOM, SCP, and Auth flags to your original values and keep the original I2C DTS (do not disable it).
Summary Table
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
Additional Reference
AN13030 Rev. 2.4 — Section 4.4 (i.MX Linux Build), Section 8.9 (PKCS#11 Standalone Library), Access Manager documentation
UG10163 i.MX Linux User's Guide — OP-TEE PKCS#11 command examples using libckteec.so (Sections 10.4.7 & 10.4.8, pages 110–114); Note: these examples use OP-TEE internal secure storage as the key backend, not SE05x directly — the command syntax is the same when SE051 is configured as the OP-TEE crypto backend via CFG_NXP_SE05X=y
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. ------------------------------------------------------------------------------- Re: How to perform Key Gen, Enc/Dec, and Sign/Verify with SE051 via OP-TEE on Linux? @Kan_Li 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=1 Could 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: Board: MCIMX8M-WEVK and OM-SE051ARD Plug and Trust MW Version: v04.07.01 OP-TEE OS Version: 3.19.0 Linux Kernel: 6.1.151 Re: How to perform Key Gen, Enc/Dec, and Sign/Verify with SE051 via OP-TEE on Linux? Thank you very much for this exceptionally detailed and clear explanation. The flag-by-flag breakdown, the build command example, and especially the critical caveat regarding the I2C conflict and the choice between Choice A (OP-TEE Exclusive via libckteec.so) and Choice B (Co-existence) have clarified our setup options. This information was exactly what we needed to determine our architecture moving forward.
查看全文