OP-TEE Trusted Apps: Wybór sprzętu i budowanie Linuxa | STM32MP2
OP-TEE Trusted Apps: Wybór sprzętu i budowanie Linuxa | STM32MP2

W dzisiejszym artykule pokażę, jak wejść na bardzo niski poziom bezpieczeństwa i zacząć pisać własne Trusted Applications (TA). To aplikacje kluczowe dla kryptografii i bezpieczeństwa, wykorzystywane w operacjach takich jak szyfrowanie Secure Storage czy Digital Rights Management (DRM).
Trusted Applications są wszędzie. W telefonie z Androidem klucze kryptograficzne do szyfrowania i odszyfrowywania danych przechowuje właśnie TA o nazwie Android KeyMaster. Jeśli interesuje Cię teoria i architektura, zapraszam do poprzedniego artykułu. Dziś skupimy się na praktyce.
Ten artykuł jest materiałem uzupełniającym dla video na YT:
Wybór Frameworka: OP-TEE
Istnieje wiele frameworków do pisania TA, ale większość jest zamkniętym oprogramowaniem. Na szczęście, mamy OP-TEE – popularny i open-source’owy framework, oficjalnie wspierany przez ARM Trusted Firmware. To właśnie za jego pomocą będziemy tworzyć własne aplikacje i zgłębiać działanie zabezpieczonego systemu operacyjnego. Pamiętajmy, że mówimy o warstwie programowej, bo warstwa sprzętowa opiera się na ARM TrustZone, wbudowanym w architekturę procesorów ARM.
Dokumentacja OP-TEE: https://optee.readthedocs.io/en/latest/general/about.html
Wybór Sprzętu
Do naszych celów emulatory, takie jak QEMU, nie sprawdzą się zbyt dobrze. Będziemy korzystać bezpośrednio z niskopoziomowych funkcji architektury procesora, co w symulacjach często sprawia więcej problemów niż daje korzyści.
Na stronie OP-TEE znajdziesz listę wspieranych platform sprzętowych. Jest tam wiele pozycji: NXP (i.MX), Raspberry Pi 3, Rockchip.
Jednak dokumentacja bywa nieaktualna. Na przykład, nie ma tam STM32MP2, choć platforma jest wspierana.
Jak to sprawdzić? Najlepiej zajrzeć do kodu.
W repozytorium OP-TEE OS na GitHubie, w pliku maintainers, znajdziesz osoby i firmy odpowiedzialne za wsparcie konkretnych platform. Tam potwierdzisz, że STM32MP2 jest wspierane.
Link do repozytorium: https://github.com/OP-TEE/optee_os
Do programowania Trusted Applications wybrałem Discovery Kit dla platformy STM32MP2. To potężna platforma z dwoma procesorami: ARM Cortex-A (dla Linuxa) i ARM Cortex-M (do zastosowań real-time). Posiada sporo pamięci DRAM i eMMC, WiFi, Bluetooth. Cena to około 100$, co jest nieco więcej niż Raspberry Pi, ale możliwości są znacznie większe. Oczywiście, możesz użyć innych platform, takich jak Rockchip, Raspberry Pi czy STM32MP1.
Budowanie Systemu z Yocto Project
Mając sprzęt, musimy zbudować na niego system operacyjny z OP-TEE. Skorzystamy z pakietu dystrybucyjnego od ST, który zawiera cały niezbędny software. Wszystko zbudujemy za pomocą Yocto Project. To standard w tworzeniu nowoczesnych systemów Linux dla urządzeń wbudowanych.

W ramach Yocto zbudujemy:
- Jądro Linuxa
- Trusted Firmware-A
- OP-TEE
- Oprogramowanie dla Cortex-M
- Bootloader (U-Boot)
Yocto Project to zestaw narzędzi do budowania dedykowanych dystrybucji Linuxa. Pomimo złożoności, zadanie ułatwi nam manifest przygotowany przez ST. Manifest to zbiór repozytoriów, ich wersji i linków, używanych do budowy oprogramowania.
Krok po Kroku: Proces Budowania
- Inicjalizacja repozytoriów:
Używamyrepo initirepo sync, podając link do manifestu i referencję do konkretnego wydania. - Przygotowanie środowiska Docker:
Najlepszym sposobem na budowanie w Yocto jest użycie Dockera, ponieważ rozwiązuje to problemy z zależnościami. Upewnij się, że Docker jest uruchomiony. (Jeśli potrzebujesz pomocy z konfiguracją Dockera, link do materiału znajdziesz w filmie na YT.) - Inicjalizacja środowiska budowania:
Wywołujemy komendę:
DISTRO=openstlinux-weston MACHINE=stm32mp25-disco source layers/meta-st/scripts/envsetup.sh
Definiujemy dystrybucję (OpenSTLinux Weston, z GUI) i maszynę (STM32MP25 Discovery Kit). Akceptujemy EULA.
- Konfiguracja Git:
Ustaw swoje dane Gitowe w kontenerze Dockera, aby uniknąć błędów podczas budowania. - Budowanie systemu:
bitbake st-image-weston
Teraz czas na kawę lub herbatę – to potrwa! Na koniec otrzymamy gotowy obraz Linuxa ze wszystkimi komponentami.
Anatomia Trusted Applications: Przykłady i Recepty
Mamy zbudowanego Linuxa. Teraz zobaczmy przykłady TA i recepty odpowiedzialne za ich budowanie. Dokumentacja ST jest dobrym punktem startowym. Prowadzi nas do repozytorium OP-TEE Examples na GitHubie, gdzie znajdziesz programy takie jak Hello World czy szyfrowanie AES.
Recepty Yocto dla komponentów OP-TEE znajdują się w katalogu recipes-security. Nas interesuje optee-examples_3.19.bb. Zawiera ona linki do źródeł, wersje oraz parametry kompilacji. To cenne źródło informacji, jeśli będziesz pisać własne programy poza przykładami.
Naprawiamy Wersję Przykładów
Niestety, domyślna wersja 3.19 z manifestu nie kompiluje się poprawnie. Rozwiązaniem jest stworzenie własnej recepty dla nowszej wersji – 4.0. Wystarczy skopiować optee-examples_3.19.bb, nazwać ją optee-examples_4.0.bb i zmienić w niej SRC_URI (numer rewizji przykładów) oraz PV (wersję na 4.0).
Następnie musimy zmodyfikować plik local.conf. Zmieniamy wersję recepty na 4.0 i dodajemy przykłady do paczek do zbudowania, używając IMAGE_INSTALL_append. Pamiętaj o spacji przed optee-examples.
Ponownie uruchamiamy bitbake st-image-weston, aby zbudować system z nowymi przykładami.
Architektura Trusted Applications
Przyjrzyjmy się budowie TA na przykładzie Hello World. Mamy tu pliki CMakeLists.txt i Android.mk do budowania aplikacji na różne systemy (np. Android).
Aplikacja składa się z dwóch części:
- Część kliencka (Host): Działa w normalnym świecie (Normal World), w przestrzeni użytkownika Linuxa.
- Trusted Application (TA): Działa w zabezpieczonym świecie (Secure World).
Klient wysyła żądania (komendy) do TA, która je obsługuje i odsyła odpowiedź. Obie części są niezbędne. TA samo w sobie nie ma nawet funkcji main()! Odpala się dopiero, gdy żądanie przychodzi z hosta.
Aby całość zadziałała, musimy zaimplementować kilka kluczowych metod po obu stronach.
- Host:
initialize_context()-> TA:create_entry_point() - Host:
open_session()-> TA:open_session_entry_point() - Host:
invoke_command()-> TA:invoke_command_entry_point()(tutaj dzieje się główna logika: host wysyła komendę, TA ją parsuje, wykonuje działanie i odsyła odpowiedź). - Host:
close_session()-> TA:close_session_entry_point() - Host:
finalize_context()-> TA:destroy_entry_point()

Kod – przykłady
Przykłady kodu wykonującego wcześniej przedstawione funkcje możesz zobaczyć dokładnie w materiale na YouTube (link na górze artykułu).
Źródła
https://optee.readthedocs.io/en/latest/general/about.html
https://github.com/OP-TEE/optee_os
https://www.st.com/en/embedded-softwa…
