Bramkarz

Podsystem Gatekeeper przeprowadza uwierzytelnianie za pomocą wzoru lub hasła w zaufanym środowisku wykonawczym (TEE). Bramka rejestruje i weryfikuje hasła za pomocą funkcji HMAC z kluczem tajnym obsługiwanym 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 używa udostępnionego sekretu wygenerowanego przez TEE do podpisania oświadczenia uwierzytelniającego, które wysyła do magazynu kluczy z obsługą sprzętową. Oznacza to, że uwierzytelnianie Gatekeepera informuje Keystore, że klucze powiązane z uwierzytelnianiem (np. klucze utworzone przez aplikacje) mogą zostać udostępnione do użycia przez aplikacje.

Architektura

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

  • gatekeeperd (demon Gatekeeper). Usługa binder w C++, zawierająca logikę niezależną od platformy i odpowiadającą interfejsowi JavaGateKeeperService.
  • warstwa abstrakcji sprzętowej (HAL) w ramach usługi Gatekeeper. interfejs HAL w hardware/libhardware/include/hardware/gatekeeper.h oraz moduł implementacji,
  • Asystent (TEE). Odpowiednik TEE dla gatekeeperd. Implementacja Gatekeepera oparta na TEE.

Gatekeeper wymaga implementacji interfejsu HAL Gatekeepera (szczególnie funkcji w hardware/libhardware/include/hardware/gatekeeper.h) oraz elementu Gatekeepera dla TEE (opartego częściowo na pliku nagłówka system/gatekeeper/include/gatekeeper/gatekeeper.h, który zawiera czyste funkcje wirtualne do tworzenia i uzyskiwania dostępu do kluczy oraz obliczania podpisów).

LockSettingsService wysyła żądanie (za pomocą Bindera), które dociera do demona gatekeeperd w systemie operacyjnym Android. Demon gatekeeperd wysyła żądanie do swojego odpowiednika (Gatekeeper) w TEE:

Procedura dla pracownika recepcji
Rysunek 1. Ogólny przepływ danych do uwierzytelniania za pomocą GateKeepera

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 HAL do interakcji z odpowiednikiem demona gatekeeperd w układzie TEE do uwierzytelniania za pomocą hasła. Implementacja HAL musi umożliwiać podpisywanie (rejestrowanie) i weryfikowanie blobów. Wszystkie implementacje muszą być zgodne ze standardowym formatem tokena uwierzytelniania (AuthToken) generowanego po każdej pomyślnej weryfikacji hasła. Szczegółowe informacje o zawartości i semantyce AuthToken znajdziesz w artykule Format AuthToken.

Implementacje pliku nagłówka hardware/libhardware/include/hardware/gatekeeper.h muszą implementować funkcje enrollverify:

  • Funkcja enroll przyjmuje blob hasła, podpisuje go i zwraca podpis jako identyfikator. Zwrócony blob (z wywołania metody enroll) musi mieć strukturę pokazaną na 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 typu open source od Google przeznaczony do środowisk TEE. Zawiera zatwierdzoną implementację GateKeeper. Możesz jednak zaimplementować Gatekeepera za pomocą dowolnego systemu operacyjnego TEE, o ile TEE ma dostęp do klucza opartego na sprzęcie oraz bezpiecznego, monotonicznego zegara działającego w trybie zawieszenia.

Trusty używa wewnętrznego systemu IPC do przesyłania udostępnionego klucza bezpośrednio między Keymasterem a implementacją Trusty w Gatekeeperze (Trusty Gatekeeper). Ten udostępniony klucz tajny służy do podpisywania tokenów uwierzytelniających wysyłanych do Keystore w celu zapewnienia atestacji weryfikacji hasła. Usługa Trusty Gatekeeper prosi o klucz od Keymastera 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ę GateKeeper w C++, która wymaga tylko dodania rutyn związanych z konkretnym urządzeniem. Aby zaimplementować TEE Gatekeeper z kodem TEE dla konkretnego urządzenia, zapoznaj się z funkcjami i komentarzami w pliku system/gatekeeper/include/gatekeeper/gatekeeper.h. W przypadku TEE GateKeeper do głównych obowiązków związanych z wdrożeniem zgodnym z wymaganiami należą:

  • przestrzeganie zasad HAL firmy Gatekeeper;
  • Zwrócone tokeny uwierzytelniające muszą być sformatowane zgodnie ze specyfikacją tokenów uwierzytelniających (opisaną w sekcji Uwierzytelnianie).
  • TEE Gatekeeper musi mieć możliwość udostępnienia klucza HMAC aplikacji Keymaster, prosząc o klucz za pomocą interfejsu TEE IPC na żądanie lub utrzymując zawsze prawidłową pamięć podręczną z wartością.

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). Identyfikator 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 tak zwane nieuczciwe ponowne rejestrowanie i nie jest dozwolone przez platformę Androida w normalnych okolicznościach. Zaufane ponowne rejestrowanie następuje, gdy użytkownik poda prawidłowe, poprzednie hasło. W tym przypadku identyfikator SID użytkownika jest przenoszony do nowego identyfikatora hasła, zachowując powiązane z nim klucze.

Gdy hasło jest rejestrowane, identyfikator SID użytkownika jest szyfrowany za pomocą funkcji HMAC razem z hasłem w obiekcie hasła.

Identyfikatory SID użytkowników są zapisywane w AuthToken zwracanym przez funkcję verify i kojarzone ze wszystkimi kluczami Keystore powiązanymi z uwierzytelnianiem (szczegółowe informacje o formacie AuthToken i Keystore znajdziesz w artykule Uwierzytelnianie). Niezaufane wywołanie funkcji enroll spowoduje zmianę identyfikatora SID użytkownika, przez co wywołanie spowoduje, że klucze powiązane z tym hasłem staną się bezużyteczne. Jeśli atakujący przejmą kontrolę nad systemem Android, mogą zmienić hasło do urządzenia, ale w ten sposób zniszczą wrażliwe klucze chronione przez roota.

Ograniczanie żądań

GateKeeper musi umożliwiać bezpieczne ograniczanie prób siłowego złamania hasła użytkownika. Jak widać w hardware/libhardware/include/hardware/gatekeeper.h, interfejs HAL umożliwia zwracanie limitu czasu w milisekundach. Czas oczekiwania informuje klienta, że nie powinien ponownie wywoływać usługi GateKeeper, dopóki nie upłynie czas oczekiwania. GateKeeper nie powinien obsługiwać żądań, jeśli trwa czas oczekiwania.

Zanim GateKeeper zweryfikuje hasło użytkownika, musi zapisać licznik niepowodzeń. 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 chronionego przed odtwarzaniem (Replay Protected Memory Block, RPMB).