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"
    

References

For further information and resources, please refer to the following links: