Strażnik dostępu

Podsystem Gatekeeper przeprowadza uwierzytelnianie za pomocą wzorów lub haseł w zaufanym środowisku wykonawczym (TEE). Bramka rejestruje i weryfikuje hasła za pomocą tajnego klucza obsługiwanego sprzętowo. Dodatkowo Gatekeeper ogranicza liczbę kolejnych nieudanych prób weryfikacji i musi odrzucać żądania na podstawie określonego limitu czasu i określonej liczby kolejnych nieudanych prób.

Gdy użytkownicy weryfikują hasła, Gatekeeper emituje token uwierzytelniania podpisany za pomocą klucza HMAC na potrzeby rozruchu, który jest dostępny tylko dla bezpiecznych komponentów. Token jest wysyłany do magazynu kluczy obsługiwanego przez sprzęt. Oznacza to, że token uwierzytelniania Gatekeepera informuje Keystore, że aplikacje mogą używać kluczy powiązanych z uwierzytelnianiem (np. kluczy utworzonych przez aplikacje).

Architektura

Gatekeeper składa się z 3 głównych komponentów:

  • gatekeeperd (demon Gatekeeper) – usługa Binder w języku C++ na Androidzie, która zawiera logikę niezależną od platformy implementującą interfejs AIDL (IGateKeeperService) na podstawie implementacji IGatekeeper specyficznej dla danego dostawcy.
  • Usługa warstwy abstrakcji sprzętowej (HAL) bramki – implementacja interfejsu AIDL IGatekeeper charakterystyczna dla danego dostawcy. Ta usługa HAL działa w Androidzie, ale główna funkcjonalność Gatekeepera musi działać w bezpiecznym środowisku, więc zwykle komunikuje się z interfejsem TA Gatekeepera.
  • Zatwierdzona aplikacja bramki (TA) – implementacja specyficzna dla danego dostawcy, która działa w środowisku TEE i wykonuje rzeczywistą weryfikację hasła lub wzorca.

LockSettingsService wysyła żądanie (za pomocą Bindera), które dociera do demona gatekeeperd w systemie operacyjnym Android. Demon gatekeeperd wysyła następnie żądanie do usługi IGatekeeper HAL, która z kolei przesyła je do swojego odpowiednika w TEE, czyli do Gatekeepera TA:

Procedura dla pracownika recepcji

Rysunek 1. Ogólny przepływ danych w ramach uwierzytelniania przez GateKeeper.

Demon gatekeeperd udostępnia interfejsom API platformy Android dostęp do HAL i uczestniczy w raportowaniu autoryzacji urządzenia do Keystore. Demon gatekeeperd działa w ramach własnego procesu i jest oddzielony od serwera systemowego.

Implementacja HAL

Demon gatekeeperd używa interfejsu IGatekeeper HAL do interakcji z podstawową usługą Gatekeeper TA w celu uwierzytelniania za pomocą hasła. Implementacja bramki TA musi umożliwiać podpisywanie (rejestrowanie) i weryfikowanie blobów. Wszystkie implementacje powinny być zgodne ze standardowym formatem tokena uwierzytelniania (HardwareAuthToken), który jest generowany po każdej pomyślnej weryfikacji hasła. Szczegółowe informacje o treściach i semantyce HardwareAuthToken znajdziesz w definicji HardwareAuthToken.aidl.

Implementacje IGatekeeper HAL przez dostawców muszą zawierać funkcje enrollverify:

  • Metoda enroll przyjmuje ciąg znaków hasła, podpisuje go i zwraca podpis jako identyfikator. Zwrócony blob (z wywołania metody enroll) musi mieć strukturę pokazaną na rysunku system/gatekeeper/include/gatekeeper/password_handle.h.
  • Funkcja verify musi porównać podpis wygenerowany przez podane hasło i sprawdzić, czy jest on zgodny z identyfikatorem zarejestrowanego hasła.

Klucz używany do rejestracji i weryfikacji nie może się nigdy zmienić i powinien być możliwy do ponownego wyprowadzenia przy każdym uruchomieniu urządzenia.

Trusty i inne implementacje

System operacyjny Trusty to zaufany system operacyjny Google oparty na technologii open source przeznaczony do środowisk TEE. Zawiera zatwierdzone wdrożenie Gatekeeper. Jednak każdy system operacyjny TEE może wdrażać Gatekeepera, o ile ma dostęp do trwałego klucza obsługiwanego sprzętowo i bezpiecznego, monotonicznego zegara działającego w trybie zawieszenia.

Trusty używa wewnętrznego systemu IPC do przekazywania informacji poufnych bezpośrednio między KeyMint a implementacją Trusty w Gatekeeper (Trusty Gatekeeper). Ten udostępniony klucz tajny służy do podpisywania tokenów uwierzytelniania wysyłanych do Keystore w celu zapewnienia atestacji weryfikacji hasła. Usługa Trusty Gatekeeper prosi o klucz z KeyMint przy każdym użyciu i nie przechowuje ani nie przechowuje w pamięci podręcznej 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 tworzony i przechowywany wyłącznie w Gatekeeper.

Android udostępnia ogólną implementację Gatekeepera w C++, która wymaga tylko dodania rutyn związanych z konkretnym urządzeniem. Na tym opiera się implementacja Trusty. Aby zaimplementować TEE Gatekeeper z kodem TEE dla konkretnego urządzenia, zapoznaj się z funkcjami i komentarzami w system/gatekeeper/include/gatekeeper/gatekeeper.h. Główne obowiązki związane z wdrożeniem zgodnym z wymaganiami to:

  • przestrzeganie zasad IGatekeeper HAL;
  • Zwracane tokeny uwierzytelniania muszą mieć format zgodny ze specyfikacją HardwareAuthToken (opisaną w HardwareAuthToken.aidl).
  • Bramka TEE musi mieć możliwość udostępnienia klucza HMAC usłudze KeyMint za pomocą jednej z tych metod:
    • Ugoda dotycząca wspólnego klucza tajnego: bramka może uczestniczyć w negocjacjach klucza HMAC podczas uruchamiania, wdrażając interfejs ISharedSecretHAL. Wymaga to, aby zarówno Gatekeeper, jak i KeyMint miały dostęp do wspólnego, udostępnionego wcześniej tajnego klucza.
    • Dostęp bezpośredni: Gatekeeper może pobrać klucz HMAC z KeyMint, korzystając z wewnętrznego mechanizmu komunikacji międzyprocesowej TEE, albo na żądanie, albo przy pierwszym użyciu (później jest przechowywany w pamięci podręcznej).

Bezpieczne identyfikatory użytkowników (SID)

Identyfikator SID użytkownika to reprezentacja użytkownika w ujęciu TEE (bez ścisłego powiązania z identyfikatorem użytkownika Androida). SID jest generowany za pomocą kryptograficznego generatora liczb pseudolosowych (PRNG) za każdym razem, gdy użytkownik rejestruje nowe hasło bez podania poprzedniego. Jest to tzw. niewiarygodne ponowne rejestrowanie. Zwykle ma to miejsce tylko wtedy, gdy użytkownik po raz pierwszy ustawia hasło lub wzór.

Zaufane ponowne rejestrowanie następuje, gdy użytkownik poda aktualne hasło, np. podczas zmiany hasła. W takim przypadku identyfikator SID użytkownika jest przenoszony do nowego identyfikatora hasła, zachowując klucze, które były z nim powiązane.

Identyfikator SID użytkownika jest uwzględniany w uwierzytelnianiu HMAC wraz z hasłem w uchwycie hasła, gdy hasło jest zarejestrowane.

Identyfikatory SID użytkowników są uwzględniane w HardwareAuthToken zwracanym przez funkcję verify() i powiązane ze wszystkimi kluczami Keystore powiązanymi z uwierzytelnianiem (szczegółowe informacje o formatach HardwareAuthToken i Keystore znajdziesz w artykule Uwierzytelnianie).

Pamiętaj, że wywołanie funkcji enroll() bez zaufania zmienia identyfikator SID użytkownika, przez co klucze powiązane z tym hasłem stają się bezużyteczne. Jeśli atakujący przejmą kontrolę nad systemem Android, mogą zmienić hasło do urządzenia, ale w trakcie tego procesu niszczą wrażliwe klucze chronione przez roota.

Ograniczanie żądań

Bramka musi umożliwiać bezpieczne ograniczanie prób włamania się do danych logowania użytkownika. Jak widać w GatekeeperVerifyResponse.aidl, HAL zwraca czas oczekiwania w milisekundach. Limit czasu informuje klienta, że nie powinien ponownie wywoływać interfejsu Gatekeeper, dopóki nie upłynie limit czasu. Bramka nie powinna obsługiwać żądań, jeśli czas oczekiwania na odpowiedź jeszcze nie upłynął.

Bramka musi zapisać licznik niepowodzeń przed weryfikacją hasła użytkownika. Jeśli weryfikacja hasła się powiedzie, należy wyczyścić licznik niepowodzeń. Zapobiega to atakom, które uniemożliwiają ograniczanie przepustowości, przez wyłączenie wbudowanego MMC (eMMC) po wywołaniu funkcji verify. Funkcja enroll weryfikuje też hasło użytkownika (jeśli zostało podane) i musi być ograniczana w taki sam sposób.

Jeśli urządzenie obsługuje tę funkcję, zdecydowanie zalecamy zapisanie licznika błędów w bezpiecznym miejscu. Jeśli urządzenie nie obsługuje szyfrowania plików lub jeśli bezpieczna pamięć masowa jest zbyt wolna, implementacje mogą bezpośrednio używać bloku pamięci chronionej przed odtwarzaniem (Replay Protected Memory Block, RPMB).