Sprzętowy magazyn kluczy

Dostępność środowiska Trusted Execution Environment (TEE) w systemie na chipie (SoC) daje urządzeniom z Androidem możliwość udostępniania usług bezpieczeństwa opartych na sprzęcie, które zapewniają wysoki poziom bezpieczeństwa systemu operacyjnego Android, usług platformy, a nawet aplikacji innych firm (w postaci rozszerzeń specyficznych dla Androida do standardowej architektury kryptograficznej Java, patrz KeyGenParameterSpec).

Słowniczek

Oto krótkie omówienie komponentów Keystore i ich relacji.

AndroidKeyStore
Interfejs API i komponent platformy Android używane przez aplikacje do uzyskiwania dostępu do funkcji Keystore. Jest to implementacja standardowych interfejsów API Java Cryptography Architecture, ale zawiera też rozszerzenia specyficzne dla Androida i składa się z kodu Java, który działa w przestrzeni procesów aplikacji. AndroidKeyStore realizuje żądania aplikacji dotyczące działania magazynu kluczy, przekazując je do demona magazynu kluczy.
demon magazynu kluczy
Demon systemu Android, który zapewnia dostęp do wszystkich funkcji Keystore za pomocą interfejsu API Binder. Ten proces odpowiada za przechowywanie kluczy utworzonych przez implementację KeyMint (lub Keymaster), które zawierają tajny klucz szyfrowania. Są one szyfrowane, aby Keystore mógł je przechowywać, ale nie mógł ich używać ani ujawniać.
Usługa KeyMint HAL
Serwer AIDL, który implementuje IKeyMintDevice HAL, zapewniając dostęp do bazowego środowiska TEE KeyMint.
Zaufana aplikacja KeyMint (TA)
Oprogramowanie działające w bezpiecznym kontekście, najczęściej w TrustZone na układzie SoC ARM, które zapewnia wszystkie bezpieczne operacje kryptograficzne. Ta aplikacja ma dostęp do surowego materiału klucza i sprawdza wszystkie warunki kontroli dostępu do kluczy, zanim zezwoli na ich użycie.
LockSettingsService
Komponent systemu Android odpowiedzialny za uwierzytelnianie użytkownika za pomocą hasła i odcisku palca. Nie jest to część Keystore, ale jest istotne, ponieważ Keystore obsługuje koncepcję kluczy powiązanych z uwierzytelnianiem, czyli kluczy, których można używać tylko wtedy, gdy użytkownik się uwierzytelnił. LockSettingsService wchodzi w interakcję z aplikacją Gatekeeper TA i aplikacją Fingerprint TA, aby uzyskać tokeny uwierzytelniania, które przekazuje do demona magazynu kluczy i które są wykorzystywane przez aplikację KeyMint TA.
Gatekeeper TA
Komponent działający w bezpiecznym środowisku, który odpowiada za uwierzytelnianie haseł użytkowników i generowanie tokenów uwierzytelniania używanych do potwierdzania zaufanemu środowisku wykonawczemu KeyMint, że uwierzytelnianie zostało przeprowadzone w przypadku konkretnego użytkownika w określonym momencie.
Fingerprint TA
Komponent działający w bezpiecznym środowisku, który odpowiada za uwierzytelnianie odcisków palców użytkownika i generowanie tokenów uwierzytelniania używanych do potwierdzania zaufanemu środowisku wykonawczemu KeyMint, że uwierzytelnianie zostało przeprowadzone dla konkretnego użytkownika w określonym momencie.

Architektura

Interfejs Android Keystore API i odpowiednia warstwa HAL KeyMint zapewniają podstawowy, ale wystarczający zestaw elementów kryptograficznych, które umożliwiają implementację protokołów korzystających z kluczy chronionych przez kontrolę dostępu i obsługiwanych przez sprzęt.

KeyMint HAL to usługa dostarczana przez producenta OEM, która jest używana przez usługę Keystore do udostępniania usług kryptograficznych opartych na sprzęcie. Aby zapewnić bezpieczeństwo materiałów klucza prywatnego, implementacje HAL nie wykonują żadnych operacji związanych z prywatnością w przestrzeni użytkownika ani nawet w przestrzeni jądra. Zamiast tego usługa KeyMint HAL działająca w Androidzie przekazuje wrażliwe operacje do zaufanej aplikacji działającej w jakimś bezpiecznym środowisku, zwykle przez przekształcanie żądań w określonym formacie i ich przywracanie.

Wynikowa architektura wygląda tak:

Dostęp do KeyMint

Rysunek 1. Dostęp do KeyMint.

Interfejs KeyMint HAL API jest interfejsem niskiego poziomu używanym przez wewnętrzne komponenty platformy i nie jest udostępniany programistom aplikacji. Interfejs Java API wyższego poziomu dostępny dla aplikacji jest opisany na stronie dla deweloperów aplikacji na Androida.

Kontrola dostępu

Magazyn kluczy Androida to centralny komponent do przechowywania i używania kluczy kryptograficznych obsługiwanych przez sprzęt, zarówno w przypadku aplikacji, jak i innych komponentów systemu. Dlatego dostęp do poszczególnych kluczy jest zwykle ograniczony do aplikacji lub komponentu systemu, który je utworzył.

Domeny magazynu kluczy

Aby obsługiwać tę kontrolę dostępu, klucze są identyfikowane w Keystore za pomocą deskryptora klucza. Ten kluczowy deskryptor wskazuje domenę, do której należy deskryptor, oraz tożsamość w tej domenie.

Aplikacje na Androida uzyskują dostęp do magazynu kluczy za pomocą standardowej architektury Java Cryptography, która identyfikuje klucze za pomocą aliasu w postaci ciągu znaków. Ta metoda identyfikacji jest wewnętrznie mapowana na domenę APP Keystore. Zawiera też identyfikator UID wywołującego, aby odróżnić klucze z różnych aplikacji i uniemożliwić jednej aplikacji dostęp do kluczy innej aplikacji.

Wewnętrznie kod platformy otrzymuje też unikalny numeryczny identyfikator klucza po załadowaniu klucza. Ten identyfikator numeryczny jest używany jako identyfikator deskryptorów kluczy w domenie KEY_ID. Jednak kontrola dostępu jest nadal przeprowadzana: nawet jeśli jedna aplikacja wykryje identyfikator klucza innej aplikacji, w normalnych okolicznościach nie może go użyć.

Aplikacja może jednak przyznać innej aplikacji (zidentyfikowanej przez UID) prawo do używania klucza. Ta operacja przyznawania zwraca unikalny identyfikator przyznania, który jest używany jako identyfikator deskryptorów kluczy w domenie GRANT. Ponownie: kontrola dostępu jest nadal przeprowadzana. Nawet jeśli aplikacja innej firmy odkryje identyfikator uprawnień do klucza odbiorcy, nie będzie mogła go użyć.

Keystore obsługuje też 2 inne domeny deskryptorów kluczy, które są używane przez inne komponenty systemu i nie są dostępne w przypadku kluczy utworzonych przez aplikacje:

  • Domena BLOB wskazuje, że w deskryptorze klucza nie ma identyfikatora klucza. Zamiast tego deskryptor klucza zawiera sam klucz, a klient obsługuje jego przechowywanie. Jest on używany przez klientów (np. vold), którzy muszą uzyskać dostęp do Keystore przed zamontowaniem partycji danych.
  • Domena SELINUX umożliwia komponentom systemu udostępnianie kluczy, a dostęp jest regulowany przez identyfikator numeryczny odpowiadający etykiecie SELinux (patrz zasady SELinux dotyczące keystore_key).

Zasady SELinux dla keystore_key

Wartości identyfikatorów używane w przypadku deskryptorów kluczy Domain::SELINUX są konfigurowane w keystore2_key_context pliku zasad SELinux. Każdy wiersz w tych plikach mapuje liczbę na etykietę SELinux, np.:

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share Keystore keys.
102            u:object_r:wifi_key:s0

Komponent, który potrzebuje dostępu do klucza o identyfikatorze 102 w domenie SELINUX, musi mieć odpowiednie zasady SELinux. Aby na przykład zezwolić usłudze wpa_supplicant na uzyskiwanie i używanie tych kluczy, dodaj ten wiersz do pliku hal_wifi_supplicant.te:

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

Identyfikatory numeryczne kluczy Domain::SELINUX są podzielone na zakresy, aby obsługiwać różne partycje bez kolizji:

Partycja Zakres Pliki konfiguracji
System 0 ... 9999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
System rozszerzony 10 000–19 999 /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Produkt 20 000–29 999 /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Dostawca 30 000–39 999 /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Dla partycji systemowej zdefiniowano te wartości:

Identyfikator przestrzeni nazw Etykieta SEPolicy UID Opis
0 su_key Nie dotyczy Klucz superużytkownika. Używane tylko do testowania w wersjach userdebug i eng. Nie ma znaczenia w przypadku kompilacji użytkownika.
1 shell_key Nie dotyczy Przestrzeń nazw dostępna dla powłoki. Używane głównie do testowania, ale można ich też używać w wersjach użytkownika z poziomu wiersza poleceń.
100 vold_key Nie dotyczy Przeznaczony do użytku przez vold.
101 odsign_key Nie dotyczy Używany przez demona podpisywania na urządzeniu.
102 wifi_key AID_WIFI(1010) Używane przez podsystem Wi-Fi Androida, w tym wpa_supplicant.
103 locksettings_key Nie dotyczy Używane przez LockSettingsService
120 resume_on_reboot_key AID_SYSTEM(1000) Używany przez serwer systemowy Androida do obsługi wznawiania po ponownym uruchomieniu.

Wektory dostępu

Keystore umożliwia kontrolowanie, jakie operacje można wykonywać na kluczu, a także kontrolowanie ogólnego dostępu do klucza. Uprawnienia keystore2_key są opisane w pliku KeyPermission.aidl.

Uprawnienia systemowe

Oprócz kontroli dostępu do poszczególnych kluczy opisanych w sekcji Zasady SELinux dla keystore_key poniższa tabela zawiera inne uprawnienia SELinux wymagane do wykonywania różnych operacji systemowych i konserwacyjnych:

Uprawnienia Znaczenie
add_auth Wymagane do dodawania tokenów uwierzytelniania do magazynu kluczy; używane przez dostawców uwierzytelniania, takich jak Gatekeeper lub BiometricManager.
clear_ns Wymagane do usunięcia wszystkich kluczy w określonej przestrzeni nazw. Używane jako operacja konserwacyjna podczas odinstalowywania aplikacji.
list Wymagany przez system do wyliczania kluczy według różnych właściwości, takich jak własność lub to, czy są one powiązane z uwierzytelnianiem. To uprawnienie nie jest wymagane w przypadku wywołujących, którzy wyliczają własne przestrzenie nazw (objęte uprawnieniem get_info).
lock Wymagane do powiadamiania magazynu kluczy o zablokowaniu urządzenia, co z kolei powoduje usunięcie superkluczy, aby klucze powiązane z uwierzytelnianiem były niedostępne.
unlock Wymagane do powiadomienia magazynu kluczy o odblokowaniu urządzenia i przywrócenia dostępu do kluczy nadrzędnych, które chronią klucze powiązane z uwierzytelnianiem.
reset Wymagane do zresetowania Keystore do ustawień fabrycznych i usunięcia wszystkich kluczy, które nie są niezbędne do działania systemu Android.

Historia

W Androidzie 5 i starszych wersjach dostępny był prosty interfejs API usług kryptograficznych oparty na sprzęcie, udostępniany przez warstwę abstrakcji sprzętu (HAL) Keymaster w wersjach 0.2 i 0.3. Magazyn kluczy udostępniał operacje podpisywania i weryfikacji cyfrowej, a także generowanie i importowanie par kluczy podpisywania asymetrycznego. Jest to już zaimplementowane na wielu urządzeniach, ale istnieje wiele celów związanych z bezpieczeństwem, których nie można łatwo osiągnąć za pomocą samego interfejsu API podpisu. Android 6.0 rozszerzył interfejs Keystore API, aby zapewnić szerszy zakres funkcji.

Android 6.0

W Androidzie 6.0 w Keymasterze 1.0 dodano symetryczne elementy kryptograficzne, AES i HMAC oraz system kontroli dostępu do kluczy obsługiwanych przez sprzęt. Kontrola dostępu jest określana podczas generowania klucza i obowiązuje przez cały okres jego ważności. Klucze można ograniczyć tak, aby można było ich używać tylko po uwierzytelnieniu użytkownika i tylko do określonych celów lub z określonymi parametrami kryptograficznymi.

Oprócz rozszerzenia zakresu podstawowych funkcji kryptograficznych w Androidzie 6.0 dodano te funkcje:

  • system kontroli użycia, który umożliwia ograniczenie użycia klucza w celu zmniejszenia ryzyka naruszenia bezpieczeństwa z powodu niewłaściwego użycia kluczy;
  • Schemat kontroli dostępu umożliwiający ograniczenie kluczy do określonych użytkowników, klientów i zdefiniowanego zakresu czasu.

Android 7.0

W Androidzie 7.0 w Keymasterze 2 dodano obsługę atestowania kluczy i powiązania z wersją.

Atestowanie kluczy zapewnia certyfikaty kluczy publicznych, które zawierają szczegółowy opis klucza i jego kontroli dostępu, dzięki czemu można zdalnie zweryfikować, czy klucz znajduje się w bezpiecznym sprzęcie i czy jest prawidłowo skonfigurowany.

Powiązanie z wersją powiązuje klucze z wersją systemu operacyjnego i poziomem poprawek. Dzięki temu atakujący, który odkryje słaby punkt w starszej wersji systemu lub oprogramowania TEE, nie będzie mógł przywrócić urządzenia do podatnej na ataki wersji i użyć kluczy utworzonych w nowszej wersji. Dodatkowo, gdy klucz o danej wersji i poziomie poprawki jest używany na urządzeniu, które zostało uaktualnione do nowszej wersji lub poziomu poprawki, klucz jest uaktualniany, zanim będzie można go użyć, a poprzednia wersja klucza jest unieważniana. Podczas aktualizacji urządzenia klucze są przenoszone wraz z nim, ale przywrócenie urządzenia do poprzedniej wersji powoduje, że klucze stają się bezużyteczne.

Android 8.0

W Androidzie 8.0 Keymaster 3 przeszedł ze starego interfejsu HAL w stylu C na interfejs HAL w C++ wygenerowany na podstawie definicji w nowym języku definiowania interfejsu sprzętowego (HIDL). W ramach tej zmiany wiele typów argumentów uległo zmianie, chociaż typy i metody mają bezpośrednie powiązanie ze starymi typami i metodami struktury HAL.

Oprócz zmiany interfejsu Android 8.0 rozszerzył funkcję atestowania Keymaster 2, aby obsługiwać atestowanie tożsamości. Potwierdzanie tożsamości zapewnia ograniczony i opcjonalny mechanizm silnego potwierdzania identyfikatorów sprzętu, takich jak numer seryjny urządzenia, nazwa produktu i identyfikator telefonu (IMEI lub MEID). Aby wprowadzić tę zmianę, w Androidzie 8.0 zmieniono schemat atestu ASN.1, aby dodać atest identyfikatora. Implementacje Keymastera muszą znaleźć bezpieczny sposób pobierania odpowiednich elementów danych, a także zdefiniować mechanizm bezpiecznego i trwałego wyłączania tej funkcji.

Android 9

W Androidzie 9 aktualizacje obejmowały:

  • Aktualizacja do Keymastera 4
  • Obsługa wbudowanych elementów zabezpieczających
  • Obsługa importowania bezpiecznego klucza
  • Obsługa szyfrowania 3DES
  • Zmiany w powiązaniu wersji, dzięki którym boot.imgsystem.img mają oddzielnie ustawione wersje, co umożliwia niezależne aktualizacje.

Android 10

W Androidzie 10 wprowadzono wersję 4.1 interfejsu HAL Keymaster, która zawiera:

  • Obsługa kluczy, których można używać tylko wtedy, gdy urządzenie jest odblokowane
  • Obsługa kluczy, których można używać tylko na wczesnych etapach rozruchu
  • Opcjonalna obsługa kluczy pamięci chronionych sprzętowo
  • Opcjonalna obsługa poświadczania unikalnego dla urządzenia w StrongBox

Android 12

W Androidzie 12 wprowadziliśmy nowy komponent HAL KeyMint, który zastępuje komponent HAL Keymaster, ale zapewnia podobną funkcjonalność. Oprócz wszystkich wymienionych wyżej funkcji interfejs HAL KeyMint obejmuje też:

  • Obsługa uzgadniania kluczy ECDH
  • Obsługa kluczy atestu określonych przez użytkownika
  • Obsługa kluczy o ograniczonej liczbie użyć

Android 12 zawiera też nową wersję demona systemu magazynu kluczy,keystore2 napisaną w języku Rust i znaną jako

Android 13

W Androidzie 13 dodano wersję 2 interfejsu HAL KeyMint, która obsługuje algorytm Curve25519 do podpisywania i uzgadniania kluczy.