blob: 5be4fa13c8893bfb567a33cd214c47349b41c262 [file] [log] [blame]
Johannes Bauer57ec2062023-03-22 21:39:48 +01001.. _userland_integration:
2
3##########################
4Linux userland integration
5##########################
6
7This document gives pointers on how particular features of OP-TEE may be used
8from the Linux userland in typical application scenarios.
9
10PKCS#11 driver
11**************
12
13A common use-case is the integration of OP-TEE to securely store asymmetric
14keys inside the secure enclave. For example, when using TLS with client
15certificates, the corresponding private keys would reside securely within
16OP-TEE. If this client certificate is then used from within userspace, the
17corresponding cryptographic primitives are relayed to OP-TEE which establishes
18the connection using the requested client certificate on behalf of the
19application. However, the key itself never leaves secure storage (this is where
20it is created and resides).
21
22The way this is done is via PKCS#11 (aka Cryptoki API). PKCS#11 specifies a
23number of standard calls to relay cryptographic requests (such as a signing
24operation) to a third party module. Such a module may be a smart card or, in
25the case of OP-TEE, it is a software PKCS#11 trusted application that appears
26to the userland as one. This trusted application is accessed using a shared
27object (dynamic library) which serves as the "glue" to translate cryptographic
28requests into OP-TEE calls. This shared object is ``libckteec.so`` which is
29part of the `OP-TEE client tools <https://github.com/OP-TEE/optee_client>`_.
30
31Once OP-TEE has been compiled with the PKCS#11 TA, the client tools shared
32object has been built and the OP-TEE supplicant has been started, we can use
33``pkcs11-tool`` of the `OpenSC project <https://github.com/OpenSC/OpenSC>`_ to
34initiate first communication with the emulated smart card. In the following,
35we assume that ``libckteec.so`` has been installed in
36``/usr/lib/libckteec.so``. For simplicity reasons, we define an alias to call
37pkcs11-tool using the appropriate PKCS#11 module.
38
39.. code-block:: none
40
41 # alias p11="pkcs11-tool --module /usr/lib/libckteec.so"
42 # p11 --show-info
43 Cryptoki version 2.40
44 Manufacturer Linaro
45 Library OP-TEE PKCS11 Cryptoki library (ver 0.1)
46 Using slot 0 with a present token (0x0)
47
48.. hint::
49
50 When testing OP-TEE under QEMU, OpenSC should be built by default as well
51 and the ``pkcs11-tool`` should be available without modifications to the
52 configuration. It can be explicitly requested by using the
53
54 .. code-block:: bash
55
56 make BR2_PACKAGE_OPENSC=y
57
58 build parameter when compiling OP-TEE.
59
60This tells us the library code is already working. We can now display the
61different "slots". You can think of them as different "card readers" for
62virtual smart cards. In a typical use case, only one slot is used for a single
63smart card.
64
65.. code-block:: none
66
67 # p11 --list-slots
68 Available slots:
69 Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
70 token state: uninitialized
71 Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
72 token state: uninitialized
73 Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
74 token state: uninitialized
75
76Observe that the connection to the TA is also successfully working and it is
77showing three inserted (but "empty", uninitialized) smart cards/tokens. Before
78we are able to create keys on these tokens, we need to initialize them with a
79SO-PIN and PIN. The SO-PIN is the "super pin", while the PIN is the "user
80pin". The concept is likely familiar to you from the SIM card of your phone,
81where the PUK acts as the "super pin".
82
83First, we initialize the SO-PIN of slot 0 and name our token "mytoken":
84
85.. code-block:: none
86
87 # p11 --init-token --label mytoken --so-pin 1234567890
88 Using slot 0 with a present token (0x0)
89 Token successfully initialized
90
91We have successfully initialized the SO-PIN to "1234567890". Now we "log in"
92into the token using that SO-PIN and, using the SO-PIN authorization,
93initialize the PIN of the token to "12345":
94
95.. code-block:: none
96
97 # p11 --label mytoken --login --so-pin 1234567890 --init-pin --pin 12345
98 Using slot 0 with a present token (0x0)
99 User PIN successfully initialized
100
101We can now verify that the token has been successfully initialized:
102
103.. code-block:: none
104
105 # p11 --list-slots
106 Available slots:
107 Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
108 token label : mytoken
109 token manufacturer : Linaro
110 token model : OP-TEE TA
111 token flags : login required, rng, token initialized, PIN initialized
112 hardware version : 0.0
113 firmware version : 0.1
114 serial num : 0000000000000000
115 pin min/max : 4/128
116 Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
117 token state: uninitialized
118 Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 94e9ab89-4c43-56ea-8b35-45dc07226830
119 token state: uninitialized
120
121Now we have a fully initialized token but it still contains no keys. To list
122what cryptographic primitives the particular OP-TEE version offers, you can
123query the supported mechanisms:
124
125.. code-block:: none
126
127 # p11 --list-mechanisms
128 Using slot 0 with a present token (0x0)
129 Supported mechanisms:
130 SHA224-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
131 SHA224-RSA-PKCS, keySize={256,4096}, sign, verify
132 SHA512-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
133 SHA384-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
134 SHA256-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
135 SHA512-RSA-PKCS, keySize={256,4096}, sign, verify
136 SHA384-RSA-PKCS, keySize={256,4096}, sign, verify
137 SHA256-RSA-PKCS, keySize={256,4096}, sign, verify
138 SHA1-RSA-PKCS-PSS, keySize={256,4096}, sign, verify
139 RSA-PKCS-OAEP, keySize={256,4096}, encrypt, decrypt
140 SHA1-RSA-PKCS, keySize={256,4096}, sign, verify
141 MD5-RSA-PKCS, keySize={256,4096}, sign, verify
142 RSA-PKCS-PSS, sign, verify
143 RSA-PKCS, keySize={256,4096}, encrypt, decrypt, sign, verify
144 RSA-PKCS-KEY-PAIR-GEN, keySize={256,4096}, generate_key_pair
145 ECDSA-SHA512, keySize={160,521}, sign, verify
146 ECDSA-SHA384, keySize={160,521}, sign, verify
147 ECDSA-SHA256, keySize={160,521}, sign, verify
148 ECDSA-SHA224, keySize={160,521}, sign, verify
149 ECDSA-SHA1, keySize={160,521}, sign, verify
150 ECDSA, keySize={160,521}, sign, verify
151 ECDSA-KEY-PAIR-GEN, keySize={160,521}, generate_key_pair
152 mechtype-0x272, keySize={32,128}, sign, verify
153 mechtype-0x262, keySize={32,128}, sign, verify
154 mechtype-0x252, keySize={24,128}, sign, verify
155 mechtype-0x257, keySize={14,64}, sign, verify
156 SHA-1-HMAC-GENERAL, keySize={10,64}, sign, verify
157 MD5-HMAC-GENERAL, keySize={8,64}, sign, verify
158 SHA512-HMAC, keySize={32,128}, sign, verify
159 SHA384-HMAC, keySize={32,128}, sign, verify
160 SHA256-HMAC, keySize={24,128}, sign, verify
161 SHA224-HMAC, keySize={14,64}, sign, verify
162 SHA-1-HMAC, keySize={10,64}, sign, verify
163 MD5-HMAC, keySize={8,64}, sign, verify
164 SHA512, digest
165 SHA384, digest
166 SHA256, digest
167 SHA224, digest
168 SHA-1, digest
169 MD5, digest
170 GENERIC-SECRET-KEY-GEN, keySize={1,4096}, generate
171 AES-KEY-GEN, keySize={16,32}, generate
172 AES-CBC-ENCRYPT-DATA, derive
173 AES-ECB-ENCRYPT-DATA, derive
174 mechtype-0x108B, keySize={16,32}, sign, verify
175 AES-CMAC, keySize={16,32}, sign, verify
176 mechtype-0x1089, keySize={16,32}, encrypt, decrypt
177 AES-CTR, keySize={16,32}, encrypt, decrypt
178 AES-CBC-PAD, keySize={16,32}, encrypt, decrypt
179 AES-CBC, keySize={16,32}, encrypt, decrypt, wrap, unwrap
180 AES-ECB, keySize={16,32}, encrypt, decrypt, wrap, unwrap
181
182In our case, we would want to create an elliptic curve keypair on P-256 (aka
183secp256r1 or prime256v1). As you can see, this is supported ("ECDSA-KEY-PAIR-GEN" supports
184between 160 and 521 bit curves).
185
186.. code-block:: none
187
188 # p11 -l --pin 12345 --keypairgen --key-type EC:prime256v1 --label mykey
189 Using slot 0 with a present token (0x0)
190 Key pair generated:
191 Private Key Object; EC
192 label: mykey
193 Usage: sign, derive
194 Access: sensitive, always sensitive, never extractable, local
195 Public Key Object; EC EC_POINT 256 bits
196 EC_POINT: 044104e3f89bd32ac8101ba675815fbaf34c4f34bb7bb2d233589983bad934cfa09795d56811747778d22b94e245028d3af6aff9e6abbbdb3a75fe1433182c605868c7
197 EC_PARAMS: 06082a8648ce3d030107
198 label: mykey
199 Usage: verify, derive
200 Access: local
201
202You can see the public key, which is a point on the elliptic curve. The byte
203``04`` at byte offset 2 indicates that this point is represented in
204uncompressed affine representation, i.e., X and Y coordinates follow that byte
205directly. This format is not ideal to interface common libraries, however.
206Especially when using PKI with X.509 certificates, we typically want a
207PEM-formatted CSR to be able to create a certificate from.
208
209For this, we create a small configuration file for OpenSSL and call it
210``optee_hsm.conf``. It references a library of `libp11
211<https://github.com/OpenSC/libp11>`_ which acts as a driver that enables
212OpenSSL to interface with a PKCS#11 library.
213
214.. code-block::
215
216 openssl_conf = openssl_conf
217
218 [openssl_conf]
219 engines = engine_section
220
221 [engine_section]
222 pkcs11 = pkcs11_section
223
224 [pkcs11_section]
225 engine_id = pkcs11
226 dynamic_path = /usr/lib/engines-1.1/libpkcs11.so
227 MODULE_PATH = /usr/lib/libckteec.so
228 PIN = 12345
229
230 [req]
231 distinguished_name = req_distinguished_name
232
233 [req_distinguished_name]
234
235.. hint::
236
237 When testing OP-TEE under QEMU, libp11 is not compiled by default. For easy
238 access to this library, you can build OP-TEE using the command
239
240 .. code-block:: none
241
242 make BR2_PACKAGE_OPENSC=y BR2_PACKAGE_LIBOPENSSL=y BR2_PACKAGE_LIBOPENSSL_BIN=y BR2_PACKAGE_LIBP11=y
243
244 This will ensure that OpenSC (for the command line utility ``pkcs11-tool``),
245 OpenSSL, and libp11 are all built and installed in the QEMU environment.
246 Note that in that environment, ``libpkcs11.so`` will reside at
247 ``/usr/lib/engines-1.1/libpkcs11.so``.
248
249Then, we can ask OpenSSL to create a CSR from the key we have previously created:
250
251.. code-block:: none
252
253 # OPENSSL_CONF=optee_hsm.conf openssl req -new -engine pkcs11 -keyform engine -key label_mykey -subj "/CN=My CSR" -out mykey_csr.pem
254 engine "pkcs11" set.
255
256We can then inspect said CSR:
257
258.. code-block:: none
259
260 $ openssl req -in mykey_csr.pem -text
261 Certificate Request:
262 Data:
263 Version: 1 (0x0)
264 Subject: CN = My CSR
265 Subject Public Key Info:
266 Public Key Algorithm: id-ecPublicKey
267 Public-Key: (256 bit)
268 pub:
269 04:e3:f8:9b:d3:2a:c8:10:1b:a6:75:81:5f:ba:f3:
270 4c:4f:34:bb:7b:b2:d2:33:58:99:83:ba:d9:34:cf:
271 a0:97:95:d5:68:11:74:77:78:d2:2b:94:e2:45:02:
272 8d:3a:f6:af:f9:e6:ab:bb:db:3a:75:fe:14:33:18:
273 2c:60:58:68:c7
274 ASN1 OID: prime256v1
275 NIST CURVE: P-256
276 Attributes:
277 a0:00
278 Signature Algorithm: ecdsa-with-SHA256
279 30:45:02:20:61:7e:05:30:cf:4d:d0:93:22:78:9e:45:cf:af:
280 3c:83:bb:04:c4:f0:81:f6:9a:5c:97:cd:ac:1e:94:cd:17:1b:
281 02:21:00:e7:7f:88:1d:4f:56:b8:e2:87:be:76:de:28:b3:92:
282 68:a7:16:3a:56:af:79:2f:98:bd:fd:6d:b3:82:e1:15:6c
283
284Note that the public key matches exactly that which we have previously created
285(``04 e3 f8...``). This CSR could then be signed by a CA. For simplicity
286purposes, we can also use a self-signed certificate and sign with our own
287OP-TEE contained key:
288
289.. code-block:: none
290
291 # OPENSSL_CONF=optee_hsm.conf openssl req -new -engine pkcs11 -keyform engine -key label_mykey -subj "/CN=My CSR" -x509 -out mykey_selfsigned_cert.pem
292 engine "pkcs11" set.
293
294Again we can review this self-signed certificate:
295
296.. code-block:: none
297
298 $ openssl x509 -in mykey_selfsigned_cert.pem -text
299 Certificate:
300 Data:
301 Version: 1 (0x0)
302 Serial Number:
303 3f:8f:c8:c0:de:a8:75:ca:9d:62:79:31:c2:6c:48:f4:fd:50:22:1d
304 Signature Algorithm: ecdsa-with-SHA256
305 Issuer: CN = My CSR
306 Validity
307 Not Before: Mar 22 20:19:15 2023 GMT
308 Not After : Apr 21 20:19:15 2023 GMT
309 Subject: CN = My CSR
310 Subject Public Key Info:
311 Public Key Algorithm: id-ecPublicKey
312 Public-Key: (256 bit)
313 pub:
314 04:e3:f8:9b:d3:2a:c8:10:1b:a6:75:81:5f:ba:f3:
315 4c:4f:34:bb:7b:b2:d2:33:58:99:83:ba:d9:34:cf:
316 a0:97:95:d5:68:11:74:77:78:d2:2b:94:e2:45:02:
317 8d:3a:f6:af:f9:e6:ab:bb:db:3a:75:fe:14:33:18:
318 2c:60:58:68:c7
319 ASN1 OID: prime256v1
320 NIST CURVE: P-256
321 Signature Algorithm: ecdsa-with-SHA256
322 30:45:02:20:4a:9d:63:f2:e0:12:4b:46:eb:eb:62:34:9e:86:
323 3d:d4:c8:cf:5f:c0:44:fe:8b:71:a0:b8:fa:41:d9:0b:60:3a:
324 02:21:00:fb:c2:b3:0a:7b:54:e9:bb:66:7b:8e:f7:11:52:81:
325 69:81:a6:cc:d0:bf:a2:7c:f7:2a:67:db:ab:f1:f3:2c:9f
326 -----BEGIN CERTIFICATE-----
327 MIIBHDCBwwIUP4/IwN6odcqdYnkxwmxI9P1QIh0wCgYIKoZIzj0EAwIwETEPMA0G
328 A1UEAwwGTXkgQ1NSMB4XDTIzMDMyMjIwMTkxNVoXDTIzMDQyMTIwMTkxNVowETEP
329 MA0GA1UEAwwGTXkgQ1NSMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4/ib0yrI
330 EBumdYFfuvNMTzS7e7LSM1iZg7rZNM+gl5XVaBF0d3jSK5TiRQKNOvav+earu9s6
331 df4UMxgsYFhoxzAKBggqhkjOPQQDAgNIADBFAiBKnWPy4BJLRuvrYjSehj3UyM9f
332 wET+i3GguPpB2QtgOgIhAPvCswp7VOm7ZnuO9xFSgWmBpszQv6J89ypn26vx8yyf
333 -----END CERTIFICATE-----
334
335To test our self-signed certificate as a client certificate, we first need to
336initialize a TLS server. This can either be done on a remote machine or
337locally. For the server we will again use a self-signed certificate (but simply
338store the corresponding private key in a file).
339
340.. code-block:: none
341
342 $ openssl ecparam -genkey -name prime256v1 -out server_key.pem
343 $ openssl req -new -x509 -key server_key.pem -subj '/CN=Server' -out server_cert.pem
344 $ openssl s_server -accept 9876 -cert server_cert.pem -key server_key.pem -www -Verify 1
345 verify depth is 1, must return a certificate
346 Using default temp DH parameters
347 ACCEPT
348
349This starts a HTTPS server which listens at port 9876 and requires a TLS client
350certificate. We can validate that the connection to the server is refused if no
351client certificate is provided. Assume that ``192.168.178.34`` is the IPv4
352address of the server:
353
354.. code-block:: none
355
356 $ curl -k https://192.168.178.34:9876
357 curl: (56) OpenSSL SSL_read: error:0A00045C:SSL routines::tlsv13 alert certificate required, errno 0
358
359Now on our OP-TEE device we can use OpenSSL to establish a connection using our
360OP-TEE stored client certificate:
361
362.. code-block:: none
363
364 # OPENSSL_CONF=optee_hsm.conf openssl s_client -engine pkcs11 -connect 192.168.178.34:9876 -cert mykey_selfsigned_cert.pem -keyform engine -key label_mykey
365 engine "pkcs11" set.
366 CONNECTED(00000004)
367 Can't use SSL_get_servername
368 depth=0 CN = Server
369 verify error:num=18:self signed certificate
370 verify return:1
371 depth=0 CN = Server
372 verify return:1
373 ---
374 Certificate chain
375 0 s:CN = Server
376 i:CN = Server
377 ---
378 Server certificate
379 -----BEGIN CERTIFICATE-----
380 MIIBeDCCAR2gAwIBAgIUDnUzOcNS9AgeJhvVmp73wF5DwxQwCgYIKoZIzj0EAwIw
381 ETEPMA0GA1UEAwwGU2VydmVyMB4XDTIzMDMyMjIwMjMwMloXDTIzMDQyMTIwMjMw
382 MlowETEPMA0GA1UEAwwGU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
383 qnCvLjLa1XWBtY1OQjaHa60re5vnZ2WY555XSsFCe2RoF7wGBDDrdXKkQz9Vy0t4
384 d5OC6VMcFhia967nGa5zPqNTMFEwHQYDVR0OBBYEFBKTMLG057a/a2exmeF7dHVH
385 85D0MB8GA1UdIwQYMBaAFBKTMLG057a/a2exmeF7dHVH85D0MA8GA1UdEwEB/wQF
386 MAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAIeKwlghSkhA8zvpXsl9y6WSCXo9fRzt
387 DSl6myUsgac/AiEAhipKSjVQAvJAqXIecmMylqjY79XVzrbxKWYjsL1XdLw=
388 -----END CERTIFICATE-----
389 subject=CN = Server
390
391 issuer=CN = Server
392
393 ---
394 No client certificate CA names sent
395 Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
396 Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
397 Peer signing digest: SHA256
398 Peer signature type: ECDSA
399 Server Temp Key: X25519, 253 bits
400 ---
401 SSL handshake has read 817 bytes and written 797 bytes
402 Verification error: self signed certificate
403 ---
404 New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
405 Server public key is 256 bit
406 Secure Renegotiation IS NOT supported
407 Compression: NONE
408 Expansion: NONE
409 No ALPN negotiated
410 Early data was not sent
411 Verify return code: 18 (self signed certificate)
412 [...]
413
414When connected, you can type "GET /" and press return to get a HTML response
415back from the HTTPS server, which will echo your client certificate inside a
416HTML page.