Sprzętowy magazyn kluczy

Dostępność zaufanego środowiska wykonywania w systemie na chipie (SoC) umożliwia urządzeniom z Androidem udostępnianie mocnych usług zabezpieczających opartych na sprzęcie systemowi operacyjnemu Android, usługom platformy, a nawet aplikacjom innych firm (w formie 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 Android Framework 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 procesu aplikacji. AndroidKeyStore obsługuje żądania aplikacji dotyczące zachowania magazynu kluczy, przekazując je do demona magazynu kluczy.
demon klucza kluczy
Dziedziczony demon systemu Androida, który zapewnia dostęp do wszystkich funkcji Keystore za pomocą interfejsu Binder API. Ten demon odpowiada za przechowywanie blobów kluczy utworzonych przez implementację KeyMint (lub Keymaster), które zawierają tajny materiał klucza. Są one zaszyfrowane, więc Keystore może je przechowywać, ale nie może ich używać ani ujawniać.
Usługa HAL KeyMint
Serwer AIDL, który implementuje interfejs HAL IKeyMintDevice, zapewniający dostęp do podstawowego interfejsu KeyMint TA.
Zaufana aplikacja KeyMint (TA)
Oprogramowanie działające w bezpiecznym kontekście, najczęściej w TrustZone na procesorze ARM SoC, które zapewnia wszystkie bezpieczne operacje kryptograficzne. Aplikacja ma dostęp do nieprzetworzonego klucza i weryfikuje wszystkie warunki kontroli dostępu dotyczące kluczy przed ich użyciem.
LockSettingsService
Składnik systemu Android odpowiedzialny za uwierzytelnianie użytkownika, zarówno za pomocą hasła, jak i odcisków palców. Nie jest to część Keystore, ale jest istotna, ponieważ Keystore obsługuje koncepcję kluczy powiązanych z uwierzytelnianiem: kluczy, których można używać tylko wtedy, gdy użytkownik został uwierzytelniony. LockSettingsService współpracuje z usługą gatekeepingową i usługą Fingerprint, aby uzyskać tokeny uwierzytelniania, które przekazuje demonowi klucza. Są one wykorzystywane przez usługę KeyMint.
Gatekeeper TA
Komponent działający w bezpiecznym środowisku, który odpowiada za uwierzytelnianie haseł użytkowników i generowanie tokenów uwierzytelniania służących do udowodnienia dostawcy kluczy KeyMint, że uwierzytelnianie zostało wykonane dla konkretnego użytkownika w określonym momencie.
TA odcisku palca
Komponent działający w bezpiecznym środowisku, który odpowiada za uwierzytelnianie odcisków palców użytkowników i generowanie tokenów uwierzytelniania służących do potwierdzania przed TA KeyMint, że w określonym momencie zostało przeprowadzone uwierzytelnianie konkretnego użytkownika.

Architektura

Interfejs API Keystore na Androida i podstawowy interfejs HAL KeyMint zapewniają podstawowy, ale wystarczający zestaw prymitywnych elementów kryptograficznych, umożliwiający implementację protokołów z kluczami kontrolowanymi przez dostęp i opartymi na sprzęcie.

KeyMint HAL to usługa OEM używana przez usługę Keystore do udostępniania usług kryptograficznych opartych na sprzęcie. Aby zapewnić bezpieczeństwo kluczy prywatnych, implementacje HAL nie wykonują żadnych operacji wrażliwych w przestrzeni użytkownika ani nawet w przestrzeni jądra. Zamiast tego usługa KeyMint HAL działająca w Androidzie deleguje operacje wrażliwe na usługę TA działającą w jakimś bezpiecznym środowisku, zwykle przez porządkowanie i odczytywanie żądań w jakimś formacie danych określonym przez implementację.

Wynikowa architektura wygląda tak:

Dostęp do KeyMint

Rysunek 1. Dostęp do KeyMint.

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

Kontrola dostępu

Keystore 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 systemowych. Dlatego dostęp do poszczególnych kluczy jest zwykle ograniczony do aplikacji lub komponentu systemu, które je utworzyły.

Domeny magazynu kluczy

Aby umożliwić 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 Keystore za pomocą standardowej architektury szyfrowania Java, która identyfikuje klucze za pomocą aliasu ciągu znaków. Ta metoda identyfikacji jest mapowana wewnętrznie do domeny Keystore APP. Dodawany jest też identyfikator UID wywołującego, aby rozróżniać klucze z różnych aplikacji i uniemożliwić jednej aplikacji dostęp do kluczy innej.

Wewnętrznie kod frameworka otrzymuje również unikalny numeryczny identyfikator klucza po załadowaniu klucza. Ten identyfikator liczbowy jest używany jako identyfikator opisów kluczy w domenie KEY_ID. Kontrola dostępu jest jednak nadal wykonywana: nawet jeśli jedna aplikacja wykryje identyfikator klucza dla klucza innej aplikacji, nie może go użyć w normalnych okolicznościach.

Aplikacja może jednak zezwolić na używanie klucza innej aplikacji (identyfikowanej za pomocą identyfikatora UID). Ta operacja przyznawania uprawnień zwraca unikalny identyfikator uprawnień, który jest używany jako identyfikator opisów kluczy w domenie GRANT. Ponownie, kontrola dostępu jest nadal wykonywana: nawet jeśli aplikacja innej firmy wykryje identyfikator grantu dla klucza beneficjenta, nie może go użyć.

Keystore obsługuje też 2 inne domeny opisów kluczy, które są używane w przypadku innych składników systemu i nie są dostępne w przypadku kluczy utworzonych przez aplikację:

  • Domena BLOB wskazuje, że w określniku klucza nie ma identyfikatora klucza. Zamiast tego opis klucza zawiera klucz bloba, a klient obsługuje magazyn klucza bloba. Jest on używany przez klientów (na przykład vold), którzy muszą uzyskać dostęp do Keystore przed zamontowaniem partycji danych.
  • Domena SELINUX umożliwia udostępnianie kluczy przez komponenty systemu. Dostęp jest regulowany przez identyfikator numeryczny odpowiadający etykiecie SELinux (patrz zasady SELinux dotyczące klucza keystore_key).

Zasada SELinux dla keystore_key

Wartości identyfikatorów używane w przypadku kluczy opisowych Domain::SELINUX są konfigurowane w pliku zasad SELinux keystore2_key_context. Każdy wiersz w tych plikach mapuje wartość liczbową 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ć odpowiednią zasadę SELinux. Aby na przykład umożliwić wpa_supplicant pobieranie i używanie tych kluczy, dodaj do pliku hal_wifi_supplicant.te ten wiersz:

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

Identyfikatory liczbowe kluczy Domain::SELINUX są podzielone na zakresy, aby umożliwić obsługę różnych partycji bez kolizji:

Partycja Zakres Pliki konfiguracji
System 0 ... 9999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Rozszerzony system 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. Tylko do testowania w wersjach userdebug i eng. Nie ma zastosowania w przypadku wersji użytkownika.
1 shell_key Nie dotyczy Przestrzeń nazw dostępna dla powłoki. Jest on używany głównie do testowania, ale można go też stosować w przypadku kompilacji użytkownika w wierszu 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żywany przez podsystem Wi-Fi Androida, w tym wpa_supplicant.
103 locksettings_key Nie dotyczy Używany 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 operacji, które 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 na poziomie klucza opisanych w zasadach SELinux dotyczących klucza keystore_key w tabeli poniżej znajdziesz inne uprawnienia SELinux wymagane do wykonywania różnych operacji systemowych i zabiegów konserwacyjnych:

Uprawnienia Znaczenie
add_auth Wymagane do dodawania tokenów uwierzytelniania do Keystore; używane przez dostawców uwierzytelniania, takich jak Gatekeeper lub BiometricManager.
clear_ns Wymagane do usunięcia wszystkich kluczy w konkretnej przestrzeni nazw; używane jako operacja konserwacyjna podczas odinstalowywania aplikacji.
list Wymagane 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. Użytkownicy wywołujący własne przestrzenie nazw nie potrzebują tego uprawnienia (jest ono objęte uprawnieniem get_info).
lock Wymagane do powiadomienia 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, przywracania dostępu do superkluczy, 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 operacyjnego Android.

Historia

W Androidzie 5 i starszych wersjach dostępne było proste interfejsy API usług kryptograficznych obsługiwane przez sprzęt, które zapewniały wersje 0.2 i 0.3 warstwy abstrakcji sprzętowej Keymaster (HAL). Magazyn kluczy zapewnia operacje podpisywania cyfrowego i weryfikacji oraz generowanie i importowanie par kluczy asymetrycznych. Jest to już zaimplementowane na wielu urządzeniach, ale jest wiele celów związanych z bezpieczeństwem, których nie da się łatwo osiągnąć tylko za pomocą interfejsu API podpisów. W Androidzie 6.0 rozszerzono interfejs Keystore API, aby zapewnić szerszy zakres funkcji.

Android 6.0

W Androidzie 6.0 Keymaster 1.0 zawiera symetryczne algorytmy kryptograficzne, AES i HMAC oraz system kontroli dostępu do kluczy sprzętowych. Uprawnienia dostępu są określane podczas generowania klucza i stosowane przez cały czas jego istnienia. Klucze mogą być ograniczone do użytku tylko po uwierzytelnieniu użytkownika i tylko do określonych celów lub z określonymi parametrami kryptograficznymi.

Oprócz rozszerzenia zakresu prymitywnych funkcji kryptograficznych Keystore w Androidzie 6.0 zawiera:

  • Schemat kontroli użycia, który umożliwia ograniczenie użycia kluczy w celu zminimalizowania ryzyka naruszenia bezpieczeństwa spowodowanego niewłaściwym użyciem 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 Keymaster 2 obsługuje potwierdzanie klucza i wiązanie wersji.

Weryfikacja klucza zapewnia certyfikaty kluczy publicznych zawierające szczegółowy opis klucza i jego kontroli dostępu, aby umożliwić zdalne sprawdzanie istnienia klucza na bezpiecznym sprzęcie oraz jego konfiguracji.

Powiązanie z wersją: klucze są powiązane z systemem operacyjnym i poziomem poprawek. Dzięki temu atakujący, który odkryje słabość w starszej wersji systemu lub oprogramowania TEE, nie będzie mógł przywrócić urządzenia do wersji podatnej na ataki i używać kluczy utworzonych w nowszej wersji. Dodatkowo, gdy klucz z danej wersji i poziomu poprawki jest używany na urządzeniu, które zostało uaktualnione do nowszej wersji lub poziomu poprawki, klucz jest uaktualniany przed użyciem, a poprzednia wersja klucza staje się nieważna. Gdy urządzenie jest aktualizowane, klucze są aktualizowane razem 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 opartego na C do interfejsu HAL w C++ wygenerowanego na podstawie definicji w nowym języku definiowania interfejsu sprzętowego (HIDL). W ramach tej zmiany wiele typów argumentów zostało zmienionych, ale typy i metody są zgodne ze starymi typami i metodami struktury HAL.

Oprócz tej wersji interfejsu w Androidzie 8.0 rozszerzono funkcję uwierzytelniania Keymastera 2, aby obsługiwała potwierdzenie tożsamości. Poświadczenie to ograniczony i opcjonalny mechanizm zapewniający silne uwierzytelnianie identyfikatorów sprzętowych, takich jak numer seryjny urządzenia, nazwa produktu i identyfikator telefonu (IMEI lub MEID). Aby wdrożyć tę funkcję, w Androidzie 8.0 zmieniono schemat uwierzytelniania ASN.1, aby dodać uwierzytelnianie tożsamości. Implementacje Keymaster muszą znaleźć bezpieczny sposób na pobranie odpowiednich elementów danych, a także zdefiniować mechanizm bezpiecznego i trwałego wyłączania funkcji.

Android 9

W Androidzie 9 aktualizacje obejmowały:

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

Android 10

Android 10 wprowadził wersję 4.1 interfejsu Keymaster HAL, która zawiera:

  • Obsługa kluczy, które można używać tylko wtedy, gdy urządzenie jest odblokowane
  • Obsługa kluczy, które można używać tylko na wczesnych etapach uruchamiania
  • Opcjonalna obsługa kluczy sprzętowych z miejscem na dane
  • Opcjonalna obsługa poświadczania urządzenia w StrongBox

Android 12

Android 12 wprowadził nowy komponent HAL KeyMint, który zastępuje komponent HAL Keymaster, ale zapewnia podobne funkcje. Oprócz wszystkich funkcji wymienionych powyżej interfejs HAL KeyMint zawiera też:

  • Obsługa uzgadniania kluczy ECDH
  • Obsługa kluczy uwierzytelniania określonych przez użytkownika
  • Obsługa kluczy z ograniczoną liczbą zastosowań

Android 12 zawiera też nową wersję demona systemu Keystore, napisanego w języku Rust i znanego jako keystore2

Android 13

W Androidzie 13 dodano wersję 2 interfejsu KeyMint HAL, która obsługuje krzywą krzywą Curve25519 zarówno do podpisywania, jak i do uzgodnienia klucza.