Expert OP-TEE and PKCS#11 Support for Secure and Reliable Embedded Systems
Are you looking for a reliable and secure solution for your embedded platform like STM32MP1 or i.MX? Look no further! Our team of experts specializes in setting up and customizing secure bootchains with TF-A, OP-TEE, U-Boot, Linux, and more. We understand the importance of ensuring that only authorized software runs on your device and that secure connections are established to your cloud backend through OP-TEE. We have extensive experience working with all different kinds of embedded systems and have successfully set up security-enhanced trusted systems with Secure-Boot and network TEE-Apps.
Our services are tailored to meet the specific needs of our clients. We understand the significance of maintaining the authenticity of your embedded systems to ensure that connected entities can confidently communicate with only authorized devices, preventing cloning and unauthorized data transmission.
It is the importance of keeping private keys for SSL connections secure within OP-TEE.
Contact us today to learn more about our OP-TEE and PKCS#11 support services.
Exemplary use of OP-TEE (including PKCS#11) on a STM32MP1
To further illustrate the capabilities of OP-TEE (including PKCS#11) on a STM32MP1, we have provided the following examples and explanations of their implementation.
OP-TEE Function testing
To ensure that OP-TEE functions as intended, xtest is a useful tool for verification.
$ xtest -t pkcs11
Result of testsuite pkcs11:
3535 subtests of which 0 failed
25 test cases of which 0 failed
0 test cases were skipped
TEE test application done!
Supported OP-TEE mechanisms
$ alias p11='pkcs11-tool --module /usr/lib/libckteec.so.0'
$ p11 -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
SHA224-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
SHA224-RSA-PKCS, keySize={256,4096}, sign, verify
SHA512-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
SHA384-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
SHA256-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
SHA512-RSA-PKCS, keySize={256,4096}, sign, verify
SHA384-RSA-PKCS, keySize={256,4096}, sign, verify
SHA256-RSA-PKCS, keySize={256,4096}, sign, verify
SHA1-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
RSA-PKCS-OAEP, keySize={256,4096}, encrypt, decrypt
SHA1-RSA-PKCS, keySize={256,4096}, sign, verify
MD5-RSA-PKCS, keySize={256,4096}, sign, verify
RSA-PKCS-PSS, sign, verify
RSA-PKCS, keySize={256,4096}, encrypt, decrypt, sign, verify
RSA-PKCS-KEY-PAIR-GEN, keySize={256,4096}, generate_key_pair
ECDSA-SHA512, keySize={160,521}, sign, verify
ECDSA-SHA384, keySize={160,521}, sign, verify
ECDSA-SHA256, keySize={160,521}, sign, verify
ECDSA-SHA224, keySize={160,521}, sign, verify
ECDSA-SHA1, keySize={160,521}, sign, verify
ECDSA, keySize={160,521}, sign, verify
ECDSA-KEY-PAIR-GEN, keySize={160,521}, generate_key_pair
mechtype-0x272, keySize={32,128}, sign, verify
mechtype-0x262, keySize={32,128}, sign, verify
mechtype-0x252, keySize={24,128}, sign, verify
mechtype-0x257, keySize={14,64}, sign, verify
SHA-1-HMAC-GENERAL, keySize={10,64}, sign, verify
MD5-HMAC-GENERAL, keySize={8,64}, sign, verify
SHA512-HMAC, keySize={32,128}, sign, verify
SHA384-HMAC, keySize={32,128}, sign, verify
SHA256-HMAC, keySize={24,128}, sign, verify
SHA224-HMAC, keySize={14,64}, sign, verify
SHA-1-HMAC, keySize={10,64}, sign, verify
MD5-HMAC, keySize={8,64}, sign, verify
SHA512, digest
SHA384, digest
SHA256, digest
SHA224, digest
SHA-1, digest
MD5, digest
GENERIC-SECRET-KEY-GEN, keySize={1,4096}, generate
AES-KEY-GEN, keySize={16,32}, generate
AES-CBC-ENCRYPT-DATA, derive
AES-ECB-ENCRYPT-DATA, derive
mechtype-0x108B, keySize={16,32}, sign, verify
AES-CMAC, keySize={16,32}, sign, verify
mechtype-0x1089, keySize={16,32}, encrypt, decrypt
AES-CTR, keySize={16,32}, encrypt, decrypt
AES-CBC-PAD, keySize={16,32}, encrypt, decrypt
AES-CBC, keySize={16,32}, encrypt, decrypt, wrap, unwrap
AES-ECB, keySize={16,32}, encrypt, decrypt, wrap, unwrap
List available PKCS11 slots
$ p11 -L
Available slots:
Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token state: uninitialized
Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token state: uninitialized
Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token state: uninitialized
Initialize a token
$ p11 --init-token --label test-token --so-pin 1234
Using slot 0 with a present token (0x0)
I/TA: PKCS11 token 0: initialized
Token successfully initialized
$ p11 -L
Available slots:
Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token label : test-token
token manufacturer : Linaro
token model : OP-TEE TA
token flags : login required, rng, token initialized
hardware version : 0.0
firmware version : 0.1
serial num : 0000000000000000
pin min/max : 4/128
Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token state: uninitialized
Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 12dc11df-2674-561e-8f49-8afb3a4121df
token state: uninitialize
Create a keypair for SSH on OP-TEE its PKCS#11
$ p11 --label test-token --login --so-pin 1234 --init-pin --pin ABCD
Using slot 0 with a present token (0x0)
I/TA: PKCS11 session 1: login
I/TA: PKCS11 session 1: init PIN
User PIN successfully initialized
$ p11 --label test-token --pin ABCD --keypairgen --key-type EC:prime256v1 --id 2 --label ssh-key
Using slot 0 with a present token (0x0)
I/TA: PKCS11 session 1: login
Key pair generated:
Private Key Object; EC
label: ssh-key
ID: 02
Usage: sign, derive
Access: sensitive, always sensitive, never extractable, local
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 044104302867f8c7ecdc99abb62746[snip]
EC_PARAMS: 06082a8648ce3d030107
label: ssh-key
ID: 02
Usage: verify, derive
Access: local
Export public key stored in OP-TEE HSM for OpenSSH:
$ ssh-keygen -D libckteec.so.0 -e
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHA[snip]
One can put this public-key on a ssh-server (.ssh/authorized_keys) and start a login (private key never leaves OP-TEE 'never extractable'):
$ ssh -I libckteec.so.0 username@172.16.21.1 Enter PIN for 'test-token': I/TA: PKCS11 session 1: login Last login: Tue Jul 12 11:26:39 2022 from 192.168.0.22 username@linuxbox:~$
Create different keys
$ p11 --token-label test-token --pin ABCD --keypairgen --key-type RSA:2048 --id 0123 --label rsa-test-key
I/TA: PKCS11 session 1: login
Key pair generated:
Private Key Object; RSA
label: rsa-test-key
ID: 0123
Usage: decrypt, sign
Access: sensitive, always sensitive, never extractable, local
Public Key Object; RSA 2048 bits
label: rsa-test-key
ID: 0123
Usage: encrypt, verify
Access: local
$ p11 --token-label test-token --pin ABCD --keypairgen --key-type EC:secp384r1 --id 3 --label ecc-key1
I/TA: PKCS11 session 1: login
Key pair generated:
Private Key Object; EC
label: ecc-key1
ID: 03
Usage: sign, derive
Access: sensitive, always sensitive, never extractable, local
Public Key Object; EC EC_POINT 384 bits
EC_POINT: 0461043661b1e98e2e525144bda215d[snip]
EC_PARAMS: 06052b81040022
label: ecc-key1
ID: 03
Usage: verify, derive
Access: local
$ p11 --token-label test-token --keygen --key-type AES:32 --label aes-test-key --id 5
Key generated:
Secret Key Object; AES length 32
warning: PKCS11 function C_GetAttributeValue(VALUE) failed: rv = CKR_ATTRIBUTE_SENSITIVE (0x11)
label: aes-test-key
ID: 05
Usage: encrypt, decrypt, wrap, unwrap
Access: never extractable, local
Show all the different keys
$ p11 --list-objects
Using slot 0 with a present token (0x0)
Secret Key Object; AES length 32
warning: PKCS11 function C_GetAttributeValue(VALUE) failed: rv = CKR_ATTRIBUTE_SENSITIVE (0x11)
label: aes-test-key
ID: 05
Usage: encrypt, decrypt, wrap, unwrap
Access: never extractable, local
Public Key Object; EC EC_POINT 384 bits
EC_POINT: 0461043661b1e98e2e525144bda215d9bca6[snip]
EC_PARAMS: 06052b81040022
label: ecc-key1
ID: 03
Usage: verify, derive
Access: local
Public Key Object; RSA 2048 bits
label: rsa-test-key
ID: 0123
Usage: encrypt, verify
Access: local
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 0441040ff7ccda64398c865af82c0ff76b8622763f4b[snip]
EC_PARAMS: 06082a8648ce3d030107
label: ssh-key
ID: 02
Usage: verify, derive
Access: local
OpenSSL usage example (sign and verify)
$ dd if=/dev/random bs=512 count=2 of=in.dat
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00639621 s, 160 kB/s
$ p11 --sign -m SHA384-RSA-PKCS-PSS --id 0123 -i in.dat -o out.dat.sig-pss --pin ABCD
Using slot 0 with a present token (0x0)
I/TA: PKCS11 session 1: login
Using signature algorithm SHA384-RSA-PKCS-PSS
PSS parameters: hashAlg=SHA384, mgf=MGF1-SHA384, salt_len=48 B
$ openssl dgst -engine pkcs11 -keyform engine -verify "pkcs11:token=test-token;id=%01%23;type=public" \
-signature out.dat.sig-pss -sigopt rsa_padding_mode:pss -sha384 in.dat
Engine "pkcs11" set.
Verified OK
OpenSSL create certificate request
$ openssl req -new -subj '/CN=test/' -sha256 -engine pkcs11 -keyform engine -key "pkcs11:token=test-token;id=%03"
Engine "pkcs11" set.
Enter PKCS#11 token PIN for test-token:
I/TA: PKCS11 session 1: login
-----BEGIN CERTIFICATE REQUEST-----
MIIBBjCBjgIBADAPMQ0wCwYDVQQDDAR0ZXN0MHYwEAYHKoZIzj0CAQYFK4EEACID
YgAENmGx6Y4uUlFEvaIV2bymDoCMBBftWGyehbeIoo/uhJf+OHUXuCbnlCBsLz+D
40wxGIVe7CmdmfKF53otwdPpMT9xac0FV/7W+NZeuBfJg07opnwd/zAq3OFFCVUG
I3lXoAAwCgYIKoZIzj0EAwIDZwAwZAIwGtRMvWctVsafGy7ncs2csjz/fETHmKZj
2U3GIh0bIcVjtnwzKyYwGaoD0OcuD2IXAjBcV1awCTe0dqLTexJHbONKLriRAkvB
XksvAVEeF1Pb5DAgm/MMxsd12YwsNKS83To=
-----END CERTIFICATE REQUEST-----
OpenSSL generic SSL/TLS server example with PKCS#11 on OP-TEE
$ openssl req -x509 -newkey rsa:1024 -keyout key.pem -out cert.pem -days 365
...................................++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.....++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Test Certificate
Email Address []:
$ p11 --token-label test-token --pin ABCD -w key.pem -y privkey --id 9 --label importkey
I/TA: PKCS11 session 1: login
Enter PEM pass phrase:
Created private key:
Private Key Object; RSA
label: importkey
ID: 09
Usage: none
Access: sensitive
$ openssl s_server -engine pkcs11 -keyform engine -key "pkcs11:token=test-token;id=%09" -cert cert.pem
Engine "pkcs11" set.
Enter PKCS#11 token PIN for test-token:
I/TA: PKCS11 session 1: login
Using default temp DH parameters
ACCEPT
OpenSSL certificate creation
$ p11 --token-label test-token --pin ABCD --keypairgen --key-type EC:prime256v1 --id 7 --label ecc-key2
I/TA: PKCS11 session 1: login
Key pair generated:
Private Key Object; EC
label: ecc-key2
ID: 07
Usage: sign, derive
Access: sensitive, always sensitive, never extractable, local
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 04410436d9d802f525f8edeba3609c4eaeb4282b812c1191dc553[snip]
EC_PARAMS: 06082a8648ce3d030107
label: ecc-key2
ID: 07
Usage: verify, derive
Access: local
$ openssl req -subj /CN=ectest -new -x509 -key "pkcs11:token=test-token;id=%07;type=public;pin-value=ABCD" \
-engine pkcs11 -keyform engine -out /tmp/cert.pem
Engine "pkcs11" set.
I/TC: got HUK
I/TC: got HUK
I/TC: got HUK
Enter PKCS#11 token PIN for test-token:
I/TA: PKCS11 session 1: login
$ openssl x509 -in /tmp/cert.pem -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0b:82:84:b6:5c:2d:5e:34:e1:6d:41:ab:97:98:20:d0:b7:1f:24:6c
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN = ectest
Validity
Not Before: Mar 11 14:14:23 2022 GMT
Not After : Apr 10 14:14:23 2022 GMT
Subject: CN = ectest
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:36:d9:d8:02:f5:25:f8:ed:eb:a3:60:9c:4e:ae:
b4:28:2b:81:2c:11:91:dc:55:3a:78:18:02:c8:5e:
cc:bb:03:88:14:6e:88:a3:92:de:5d:f8:1c:93:1c:
1f:02:f0:cb:0c:37:53:61:bd:17:fc:c8:86:4b:a4:
33:e6:32:e7:36
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Key Identifier:
23:83:E4:10:7E:4D:0D:F4:C8:74:31:BE:F5:FD:C9:78:E2:55:13:5D
X509v3 Authority Key Identifier:
23:83:E4:10:7E:4D:0D:F4:C8:74:31:BE:F5:FD:C9:78:E2:55:13:5D
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:20:0e:1d:35:40:de:7a:09:45:a9:04:7f:b7:a9:1e:
2a:15:ef:4a:16:ca:34:17:b8:9f:57:a6:bb:5f:84:83:d2:50:
02:21:00:93:7a:f3:7b:1d:6d:5d:d8:88:4d:0b:47:00:4f:ec:
65:f3:03:4b:87:63:90:1b:00:dd:e9:6d:30:24:f5:3e:68
-----BEGIN CERTIFICATE-----
MIIBdzCCAR2gAwIBAgIUC4KEtlwtXjThbUGrl5gg0LcfJGwwCgYIKoZIzj0EAwIw
ETEPMA0GA1UEAwwGZWN0ZXN0MB4XDTIyMDMxMTE0MTQyM1oXDTIyMDQxMDE0MTQy
M1owETEPMA0GA1UEAwwGZWN0ZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
NtnYAvUl+O3ro2CcTq60KCuBLBGR3FU6eBgCyF7MuwOIFG6Io5LeXfgckxwfAvDL
DDdTYb0X/MiGS6Qz5jLnNqNTMFEwHQYDVR0OBBYEFCOD5BB+TQ30yHQxvvX9yXji
VRNdMB8GA1UdIwQYMBaAFCOD5BB+TQ30yHQxvvX9yXjiVRNdMA8GA1UdEwEB/wQF
MAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgDh01QN56CUWpBH+3qR4qFe9KFso0F7if
V6a7X4SD0lACIQCTevN7HW1d2IhNC0cAT+xl8wNLh2OQGwDd6W0wJPU+aA==
-----END CERTIFICATE-----
OpenSSL cURL usage example
$ openssl req -subj /CN=mytest -new -x509 -nodes -newkey ec:<(openssl ecparam -name prime256v1) \
-keyout /tmp/key2.key -out /tmp/cert2.key -days 365
$ p11 --token-label test-token --pin ABCD -w /tmp/key2.key -y privkey --id 4 --label my_importkey \
--key-type EC:prime256v1 --usage-sign --usage-derive
$ p11 --token-label test-token --pin ABCD -w /tmp/cert2.key -y cert --id 4 --label my_importkey \
--key-type EC:prime256v1 --usage-sign --usage-derive
$ curl -E "pkcs11:token=test-token;id=%04;type=public;pin-value=ABCD" \
--key "pkcs11:token=test-token;id=%04;pin-value=ABCD"