Podsystem Gatekeeper uwierzytelnia wzór lub hasło urządzenia w zaufanym środowisku wykonawczym (TEE). Gatekeeper rejestruje i weryfikuje hasła przy użyciu klucza tajnego wspieranego sprzętowo. Dodatkowo Gatekeeper ogranicza kolejne nieudane próby weryfikacji i musi odrzucać zapytania o usługę na podstawie określonego limitu czasu i określonej liczby kolejnych nieudanych prób.
Gdy użytkownicy zweryfikują swoje hasła, Gatekeeper wysyła token uwierzytelniania podpisany kluczem HMAC dla każdego uruchomienia, który jest dostępny tylko dla bezpiecznych komponentów. Ten token jest wysyłany do magazynu kluczy obsługiwanego sprzętowo. Oznacza to, że token uwierzytelniania Gatekeeper powiadamia Keystore, że klucze powiązane z uwierzytelnianiem (np. klucze utworzone przez aplikacje) mogą być używane przez aplikacje.
Architektura
Gatekeeper składa się z 3 głównych elementów:
gatekeeperd(demon Gatekeeper) – usługa Binder w języku C++ na Androidzie, która zawiera niezależną od platformy logikę implementującą interfejs AIDLIGateKeeperServicena podstawie implementacjiIGatekeeperdostawcy.- Usługa warstwy abstrakcji sprzętowej (HAL) Gatekeeper – implementacja interfejsu AIDL
IGatekeeperdostarczana przez dostawcę. Ta usługa HAL działa na Androidzie, ale podstawowe funkcje Gatekeepera muszą działać w bezpiecznym środowisku, więc zwykle komunikuje się ona z aplikacją zaufaną Gatekeepera. - Zaufana aplikacja Gatekeeper (TA) – implementacja dostawcy, która działa w TEE i przeprowadza rzeczywistą weryfikację hasła lub wzoru.
LockSettingsService wysyła żądanie (przez Binder), które dociera do demona gatekeeperd w systemie operacyjnym Android. Następnie demon gatekeeperd wysyła żądanie do usługi HAL IGatekeeper, która z kolei dociera do swojego odpowiednika Gatekeeper TA w TEE:
Rysunek 1. Ogólny przepływ danych na potrzeby uwierzytelniania przez GateKeepera.
Daemon gatekeeperd zapewnia interfejsom API platformy Android dostęp do HAL i uczestniczy w raportowaniu uwierzytelnień urządzenia do magazynu kluczy.
Demon gatekeeperd działa we własnym procesie i jest oddzielony od serwera systemowego.
Implementacja HAL
Daemon gatekeeperd używa HAL IGatekeeper do interakcji z podstawową aplikacją zaufaną Gatekeeper w celu uwierzytelniania hasłem. Implementacja TA Gatekeepera musi umożliwiać podpisywanie (rejestrowanie) i weryfikowanie obiektów blob. Wszystkie implementacje powinny być zgodne ze standardowym formatem tokena uwierzytelniania (HardwareAuthToken) generowanego po każdej udanej weryfikacji hasła. Szczegółowe informacje o zawartości i semantyce HardwareAuthToken znajdziesz w definicji HardwareAuthToken.aidl.
Implementacje HAL IGatekeeper dostawcy muszą implementować funkcje enroll i verify:
- Metoda
enrollpobiera obiekt blob hasła, podpisuje go i zwraca podpis jako uchwyt. Zwrócony obiekt blob (z wywołaniaenroll) musi mieć strukturę pokazaną wsystem/gatekeeper/include/gatekeeper/password_handle.h. - Funkcja
verifymusi porównać podpis wygenerowany przez podane hasło i upewnić się, że pasuje on do zarejestrowanego uchwytu hasła.
Klucz używany do rejestracji i weryfikacji nie może się nigdy zmieniać i powinien być możliwy do ponownego wygenerowania przy każdym uruchomieniu urządzenia.
Trusty i inne implementacje
System operacyjny Trusty to opracowany przez Google zaufany system operacyjny open source dla środowisk TEE, który zawiera zatwierdzoną implementację Gatekeepera. Jednak każdy system operacyjny TEE może implementować Gatekeepera, o ile TEE ma dostęp do trwałego klucza wspieranego sprzętowo i bezpiecznego zegara monotonicznego, który działa w trybie uśpienia.
Trusty używa wewnętrznego systemu IPC do przekazywania wspólnego klucza tajnego bezpośrednio między KeyMint (wcześniej Keymaster) a implementacją Gatekeepera w Trusty (Trusty Gatekeeper). Ten udostępniony klucz tajny służy do podpisywania tokenów uwierzytelniania wysyłanych do magazynu kluczy w celu potwierdzenia weryfikacji hasła. Trusty Gatekeeper żąda klucza od KeyMint przy każdym użyciu i nie przechowuje ani nie zapisuje w pamięci podręcznej jego wartości. Implementacje mogą udostępniać ten obiekt tajny w dowolny sposób, który nie narusza bezpieczeństwa.
Klucz HMAC używany do rejestrowania i weryfikowania haseł jest generowany i przechowywany wyłącznie w usłudze Gatekeeper.
Android udostępnia ogólną implementację Gatekeepera w języku C++, która wymaga jedynie dodania procedur związanych z urządzeniem. Implementacja Trusty jest oparta na tym rozwiązaniu. Aby zaimplementować Gatekeepera TEE z kodem dla TEE na konkretnym urządzeniu, zapoznaj się z funkcjami i komentarzami w pliku system/gatekeeper/include/gatekeeper/gatekeeper.h. Główne obowiązki związane z wdrożeniem zgodnym z zasadami obejmują:
- Zgodność z warstwą HAL
IGatekeeper. - Zwracane tokeny uwierzytelniania muszą być sformatowane zgodnie ze specyfikacją
HardwareAuthToken(opisaną wHardwareAuthToken.aidl). - Gatekeeper TEE musi mieć możliwość udostępniania klucza HMAC usłudze KeyMint za pomocą jednej z tych metod:
- Umowa dotycząca wspólnego klucza tajnego: Gatekeeper może uczestniczyć w negocjacjach klucza HMAC przy każdym uruchomieniu, implementując interfejs HAL
ISharedSecret. Wymaga to, aby Gatekeeper i KeyMint miały dostęp do wspólnego klucza PSK. - Dostęp bezpośredni: Gatekeeper może pobrać klucz HMAC z KeyMint za pomocą mechanizmu komunikacji między procesami w TEE, na żądanie lub przy pierwszym użyciu (później jest on przechowywany w pamięci podręcznej).
- Umowa dotycząca wspólnego klucza tajnego: Gatekeeper może uczestniczyć w negocjacjach klucza HMAC przy każdym uruchomieniu, implementując interfejs HAL
Identyfikatory zabezpieczeń użytkowników (SID)
Identyfikator SID użytkownika to reprezentacja użytkownika w TEE (bez silnego powiązania z identyfikatorem użytkownika Androida). Identyfikator SID jest generowany za pomocą kryptograficznego generatora liczb pseudolosowych (PRNG), gdy użytkownik rejestruje nowe hasło bez podawania poprzedniego. Jest to tzw. niezaufana ponowna rejestracja, która zwykle ma miejsce tylko wtedy, gdy użytkownik po raz pierwszy ustawia hasło lub wzór.
Zaufana ponowna rejestracja ma miejsce, gdy użytkownik podaje prawidłowe, poprzednie hasło, na przykład podczas zmiany hasła. W takim przypadku identyfikator SID użytkownika jest przenoszony do nowego uchwytu hasła, co pozwala zachować powiązane z nim klucze.
Identyfikator SID użytkownika jest uwzględniany w uwierzytelnianiu HMAC wraz z hasłem w uchwycie hasła podczas rejestrowania hasła.
Identyfikatory SID użytkowników są uwzględniane w obiekcie HardwareAuthToken zwracanym przez funkcję verify() i powiązane ze wszystkimi kluczami Keystore powiązanymi z uwierzytelnianiem (szczegółowe informacje o formacie HardwareAuthToken i Keystore znajdziesz w sekcji Uwierzytelnianie).
Pamiętaj, że niezaufane wywołanie funkcji enroll() zmienia identyfikator SID użytkownika, przez co klucze powiązane z tym hasłem stają się bezużyteczne. Atakujący mogą zmienić hasło do urządzenia, jeśli kontrolują system operacyjny Android, ale w tym procesie niszczą chronione przez roota klucze poufne.
Ograniczanie żądań
Gatekeeper musi być w stanie bezpiecznie ograniczać próby złamania danych logowania użytkownika metodą brute-force. Jak pokazano w GatekeeperVerifyResponse.aidl, HAL umożliwia zwrócenie limitu czasu w milisekundach. Limit czasu informuje klienta, aby nie dzwonił ponownie do Gatekeepera, dopóki nie upłynie limit czasu.
Gatekeeper nie powinien obsługiwać żądań, jeśli oczekuje na upłynięcie limitu czasu.
Gatekeeper musi zapisać licznik niepowodzeń przed zweryfikowaniem hasła użytkownika. Jeśli weryfikacja hasła się powiedzie, licznik nieudanych prób powinien zostać wyzerowany. Zapobiega to atakom, które uniemożliwiają ograniczanie przepustowości przez wyłączenie wbudowanej karty MMC (eMMC) po wywołaniu verify. Funkcja enroll również weryfikuje hasło użytkownika (jeśli zostało podane) i musi być ograniczana w ten sam sposób.
Jeśli urządzenie obsługuje tę funkcję, zdecydowanie zalecamy zapisywanie licznika nieudanych prób w bezpiecznej pamięci. Jeśli urządzenie nie obsługuje szyfrowania opartego na plikach lub bezpieczna pamięć jest zbyt wolna, implementacje mogą bezpośrednio używać pamięci RPMB (Replay Protected Memory Block).