|
| 1 | +# OPTEE on RK3566 |
| 2 | + |
| 3 | +OPTEE is a software stack with security purposes that contains following |
| 4 | +elements: |
| 5 | +* OPTEE OS; |
| 6 | +* OPTEE TAs; |
| 7 | +* tee-supplicant; |
| 8 | +* Various Linux userspace libraries. |
| 9 | + |
| 10 | +OPTEE OS and OPTEE TAs, could be launched standalone or under hypervisor. |
| 11 | + |
| 12 | +In case of latest 64-bit ARM architectures, there is an additional layer EL3 |
| 13 | +where secure monitor resides. This secure monitor is a part of ARM TrustZone |
| 14 | +(aka. ATZ) future and is responsible for deviding execution environment into two |
| 15 | +parts: trusted (aka. TEE) and rich (aka. REE). |
| 16 | + |
| 17 | +The common software stack configuration for embedded ARM devices with ATZ |
| 18 | +present is when Linux is running inside REE, but TEE launches some other, |
| 19 | +smaller software, that is responsible only for security-related features (e.g., |
| 20 | +secure storage, cryptography). In such cases OPTEE OS could be used inside TEE, |
| 21 | +utilizing its well-known and community-supported architecture and good |
| 22 | +security-related feature list. |
| 23 | + |
| 24 | +## OPTEE and ATZ on Rockchip SoCs |
| 25 | + |
| 26 | +Rockchip is known for not sharing some of their SoCs security features, |
| 27 | +therefore porting OPTEE or ATZ might not be possible. As an alternative Rockchip |
| 28 | +gives a repository with binaries for OPTEE OS and ATZ. But these binaries are |
| 29 | +known to not boot or work properly. In this guide booting and verification of |
| 30 | +the Rockchips bianries for RK3566 will be presented. At the end, there will be |
| 31 | +dev notes on how the results were achieved. |
| 32 | + |
| 33 | +### Building Zarhus with ATZ and OPTEE on RK3566 |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +### Tests and verification |
| 38 | + |
| 39 | +OPTEE `xtest` tool results: |
| 40 | + |
| 41 | +```bash |
| 42 | + |
| 43 | +``` |
| 44 | + |
| 45 | +Encryption/decryption workflow: |
| 46 | + |
| 47 | +```bash |
| 48 | +root@quartz64-a:~# alias p11="pkcs11-tool --module /usr/lib/libckteec.so" |
| 49 | +root@quartz64-a:~# p11 --show-info |
| 50 | +Cryptoki version 2.40 |
| 51 | +Manufacturer Linaro |
| 52 | +Library OP-TEE PKCS11 Cryptoki library (ver 0.1) |
| 53 | +Using slot 0 with a present token (0x0) |
| 54 | +root@quartz64-a:~# p11 --list-slots |
| 55 | +Available slots: |
| 56 | +Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 57 | + token state: uninitialized |
| 58 | +Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 59 | + token state: uninitialized |
| 60 | +Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 61 | + token state: uninitialized |
| 62 | +root@quartz64-a:~# p11 --init-token --label mytoken --so-pin 1234567890 |
| 63 | +Using slot 0 with a present token (0x0) |
| 64 | +Token successfully initialized |
| 65 | +root@quartz64-a:~# p11 --label mytoken --login --so-pin 1234567890 --init-pin --pin 12345 |
| 66 | +Using slot 0 with a present token (0x0) |
| 67 | +User PIN successfully initialized |
| 68 | +root@quartz64-a:~# p11 --list-slots |
| 69 | +Available slots: |
| 70 | +Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 71 | + token label : mytoken |
| 72 | + token manufacturer : Linaro |
| 73 | + token model : OP-TEE TA |
| 74 | + token flags : login required, rng, token initialized, PIN initialized, other flags=0x200 |
| 75 | + hardware version : 0.0 |
| 76 | + firmware version : 0.1 |
| 77 | + serial num : 0000000000000000 |
| 78 | + pin min/max : 4/128 |
| 79 | +Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 80 | + token state: uninitialized |
| 81 | +Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 82 | + token state: uninitialized |
| 83 | +root@quartz64-a:~# p11 --list-slots |
| 84 | +Available slots: |
| 85 | +Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 86 | + token label : mytoken |
| 87 | + token manufacturer : Linaro |
| 88 | + token model : OP-TEE TA |
| 89 | + token flags : login required, rng, token initialized, PIN initialized, other flags=0x200 |
| 90 | + hardware version : 0.0 |
| 91 | + firmware version : 0.1 |
| 92 | + serial num : 0000000000000000 |
| 93 | + pin min/max : 4/128 |
| 94 | +Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 95 | + token state: uninitialized |
| 96 | +Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 08b2092e-806a-5e0e-9817-f515c8ff3171 |
| 97 | + token state: uninitialized |
| 98 | +root@quartz64-a:~# p11 --list-mechanisms |
| 99 | +Using slot 0 with a present token (0x0) |
| 100 | +Supported mechanisms: |
| 101 | + SHA512-HMAC, keySize={32,128}, sign, verify |
| 102 | + SHA384-HMAC, keySize={32,128}, sign, verify |
| 103 | + SHA256-HMAC, keySize={24,128}, sign, verify |
| 104 | + SHA224-HMAC, keySize={14,64}, sign, verify |
| 105 | + SHA-1-HMAC, keySize={10,64}, sign, verify |
| 106 | + MD5-HMAC, keySize={8,64}, sign, verify |
| 107 | + SHA512, digest |
| 108 | + SHA384, digest |
| 109 | + SHA256, digest |
| 110 | + SHA224, digest |
| 111 | + SHA-1, digest |
| 112 | + MD5, digest |
| 113 | + GENERIC-SECRET-KEY-GEN, keySize={1,4096}, generate |
| 114 | + AES-KEY-GEN, keySize={16,32}, generate |
| 115 | + AES-CBC-ENCRYPT-DATA, derive |
| 116 | + AES-ECB-ENCRYPT-DATA, derive |
| 117 | + mechtype-0x1089, keySize={16,32}, encrypt, decrypt |
| 118 | + AES-CTR, keySize={16,32}, encrypt, decrypt |
| 119 | + AES-CBC-PAD, keySize={16,32}, encrypt, decrypt |
| 120 | + AES-CBC, keySize={16,32}, encrypt, decrypt |
| 121 | + AES-ECB, keySize={16,32}, encrypt, decrypt |
| 122 | +root@quartz64-a:~# p11 -l --pin 12345 --keygen --key-type aes:32 --label mykey --id 1234 |
| 123 | +Using slot 0 with a present token (0x0) |
| 124 | +Key generated: |
| 125 | +Secret Key Object; AES length 32 |
| 126 | +warning: PKCS11 function C_GetAttributeValue(VALUE) failed: rv = CKR_ATTRIBUTE_SENSITIVE (0x11) |
| 127 | + label: mykey |
| 128 | + ID: 1234 |
| 129 | +warning: PKCS11 function C_GetAttributeValue(VERIFY_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) |
| 130 | + Usage: encrypt, decrypt |
| 131 | + Access: never extractable, local |
| 132 | +root@quartz64-a:~# p11 --login --pin 12345 --id 1234 --list-objects --type secrkey |
| 133 | +Using slot 0 with a present token (0x0) |
| 134 | +Secret Key Object; AES length 16 |
| 135 | +warning: PKCS11 function C_GetAttributeValue(VALUE) failed: rv = CKR_ATTRIBUTE_SENSITIVE (0x11) |
| 136 | + label: mykey |
| 137 | + ID: 1234 |
| 138 | +warning: PKCS11 function C_GetAttributeValue(VERIFY_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) |
| 139 | + Usage: encrypt, decrypt |
| 140 | + Access: never extractable, local |
| 141 | +root@quartz64-a:~# dd if=/dev/random bs=32 count=1 of=somefile |
| 142 | +1+0 records in |
| 143 | +1+0 records out |
| 144 | +32 bytes copied, 0.000401625 s, 79.7 kB/s |
| 145 | +root@quartz64-a:~# cat somefile |
| 146 | +p_�8�q����Jy�(�i��c��Ƹ��X�k��r |
| 147 | +root@quartz64-a:~# p11 --login --pin 12345 --encrypt --id 1234 -m AES-ECB -i somefile -o somefile.enc |
| 148 | +Using slot 0 with a present token (0x0) |
| 149 | +Using encrypt algorithm AES-ECB |
| 150 | +root@quartz64-a:~# diff somefile somefile.enc |
| 151 | +1c1 |
| 152 | +< p_�8�q����Jy�(�i��c��Ƹ��X�k�� |
| 153 | +\ No newline at end of file |
| 154 | +--- |
| 155 | +> ��R'��n|��wd�<*�3�(���H���\^O� |
| 156 | +\ No newline at end of file |
| 157 | +root@quartz64-a:~# p11 --login --pin 12345 --decrypt --id 1234 -m AES-ECB -i somefile.enc -o somefile.dec |
| 158 | +Using slot 0 with a present token (0x0) |
| 159 | +Using decrypt algorithm AES-ECB |
| 160 | +root@quartz64-a:~# diff somefile somefile.dec |
| 161 | +root@quartz64-a:~# |
| 162 | +``` |
| 163 | +
|
| 164 | +### Dev notes |
| 165 | +
|
| 166 | +#### Linking Rockchips ATZ and OPTEE binaries to U-Boot image |
| 167 | +
|
| 168 | +Here is `do_prepare_elf` task from `rockchip-rkbin` package: |
| 169 | +
|
| 170 | +```bash |
| 171 | +do_prepare_elf() { |
| 172 | + install -d ${KEYS_DIRECTORY} |
| 173 | + # Generate key: |
| 174 | + openssl genrsa -out ${KEYS_DIRECTORY}/rsa2048.pem 2048 |
| 175 | + openssl rsa -in ${KEYS_DIRECTORY}/rsa2048.pem -pubout -out ${KEYS_DIRECTORY}/rsa2048_pub.pem |
| 176 | +
|
| 177 | + # Embed key into OPTEE OS binary: |
| 178 | + install ${S}/bin/rk35/rk3568_bl32_v*.bin ${WORKDIR}/ |
| 179 | + change_puk --teebin ${WORKDIR}/rk3568_bl32_v*.bin --key ${KEYS_DIRECTORY}/rsa2048_pub.pem |
| 180 | +
|
| 181 | + # Create final .elf file: |
| 182 | + cp ${WORKDIR}/rk3568_bl32_v*.bin ${WORKDIR}/tee-rk3566.bin |
| 183 | + aarch64-zarhus-linux-objcopy -B aarch64 -I binary -O elf64-littleaarch64 ${WORKDIR}/tee-rk3566.bin ${WORKDIR}/tee-rk3566.o |
| 184 | + # The 0x08400000 is from here: |
| 185 | + # https://github.com/rockchip-linux/rkbin/blob/0f8ac860f0479da56a1decae207ddc99e289f2e2/RKTRUST/RK3566TRUST_ULTRA.ini#L13 |
| 186 | + aarch64-zarhus-linux-ld --entry=0x08400000 ${WORKDIR}/tee-rk3566.o -T ${WORKDIR}/optee.ld -o ${WORKDIR}/tee-rk3566.elf |
| 187 | +} |
| 188 | +``` |
| 189 | +
|
| 190 | +The purpose of this function is to link an ELF file from the Rockchips OPTEE OS |
| 191 | +binary, because U-Boot expects it in this format. Here **is important** to use |
| 192 | +proper entry address. The address from the code above (`--entry=0x08400000`) is |
| 193 | +from [Rockchips |
| 194 | +`rkbin`](https://github.com/rockchip-linux/rkbin/blob/f43a462e7a1429a9d407ae52b4745033034a6cf9/RKTRUST/RK3566TRUST_ULTRA.ini#L13) |
| 195 | +repository. There are addresses for other SoCs too. |
| 196 | +
|
| 197 | +Content of the `optee.ld`: |
| 198 | +
|
| 199 | +```ld |
| 200 | +ENTRY(_binary_tee_rk3566_bin_start); |
| 201 | +
|
| 202 | +SECTIONS |
| 203 | +{ |
| 204 | + . = 0x08400000; |
| 205 | + .data : { |
| 206 | + *(.data) |
| 207 | + } |
| 208 | +} |
| 209 | +``` |
| 210 | +
|
| 211 | +#### Linux devicetree integration |
| 212 | +
|
| 213 | +For OPTEE OS to work without issues alongise Linux, Linux should know about its |
| 214 | +location (`optee_tzdram` from code below) and any kind of shared resources |
| 215 | +(`optee_shmem` from code below). These should be declared in Linux devicetree, |
| 216 | +here is an example for RK3566: |
| 217 | +
|
| 218 | +```dts |
| 219 | +/ { |
| 220 | + compatible = "rockchip,rk3566"; |
| 221 | +
|
| 222 | + reserved-memory { |
| 223 | + #address-cells = <2>; |
| 224 | + #size-cells = <2>; |
| 225 | + ranges; |
| 226 | +
|
| 227 | + // Memory for OP-TEE OS use only: |
| 228 | + optee_tzdram: optee-tzdram@8400000 { |
| 229 | + reg = <0x0 0x08400000 0x0 0x00E00000>; |
| 230 | + no-map; |
| 231 | + }; |
| 232 | +
|
| 233 | + // Memory shared between TEE and REE: |
| 234 | + optee_shmem: optee-shmem@9400000 { |
| 235 | + reg = <0x0 0x09200000 0x0 0x00200000>; |
| 236 | + }; |
| 237 | + }; |
| 238 | +
|
| 239 | + firmware { |
| 240 | + optee: optee { |
| 241 | + compatible = "linaro,optee-tz"; |
| 242 | + method = "smc"; |
| 243 | + shm = <&optee_shmem>; |
| 244 | + }; |
| 245 | + }; |
| 246 | +}; |
| 247 | +``` |
| 248 | +
|
| 249 | +The probelm is, that Rockchip, while providing the OPTEE OS binary, does not |
| 250 | +provide information needed for Linux devicetree configuration and it seems that |
| 251 | +the only way to get the inf. is to contact them or try to get it via analysing |
| 252 | +the bianries and dumping the shared memory addresses via TA. |
| 253 | +
|
| 254 | +#### Adjusting OPTEE Linux stack version |
| 255 | +
|
| 256 | +As was mentioned above, OPTEE contains not only the OS and the TAs, but |
| 257 | +`tee-supplicant` and libraries too. It is **important**, that those components |
| 258 | +are compatible with each other. Rockchips OPTEE binaries are not regularily |
| 259 | +updated, therefore some of them may have version that is one or two years back |
| 260 | +to actual OPTEE releases. The version could be checked after the binaries were |
| 261 | +linked and booted. Here is U-Boot logs for RK3566 stating OPTEE OS version: |
| 262 | +
|
| 263 | +```bash |
| 264 | +(...) |
| 265 | +INFO: BL31: Initializing runtime services |
| 266 | +INFO: BL31: Initializing BL32 |
| 267 | +I/TC: |
| 268 | +I/TC: OP-TEE version: 3.13.0-723-gdcfdd61d0 #hisping.lin (gcc version 10.2.1 20201103 (GNU Toolchain for the A-profil4 |
| 269 | +I/TC: Primary CPU initializing |
| 270 | +I/TC: Primary CPU switching to normal world boot |
| 271 | +INFO: BL31: Preparing for EL3 exit to normal world |
| 272 | +(...) |
| 273 | +``` |
| 274 | +
|
| 275 | +So, it is `3.13.0` then. |
| 276 | +
|
| 277 | +The OPTEE Linux userspace software stack should be downgraded to `3.13.0` too. |
| 278 | +
|
| 279 | +!!! warning |
| 280 | +
|
| 281 | + It was noted, that version `3.18.0` is compatible with the `3.13.0` too, |
| 282 | + but newer versions did not work without issues. |
0 commit comments