Funkcje KeyMint

Ta strona zawiera dodatkowe informacje i wytyczne, które ułatwią implementowanie warstwy abstrakcji sprzętowej KeyMint (HAL). Podstawową dokumentacją HAL jest specyfikacja interfejsu AIDL.

Niewłaściwe użycie interfejsu API

Użytkownicy mogą tworzyć klucze KeyMint z autoryzacjami, które są prawidłowe jako parametry interfejsu API, ale powodują, że powstałe klucze są niepewne lub nieużyteczne. W takich przypadkach implementacje KeyMint nie muszą się nie powieść ani nie muszą generować raportu diagnostycznego. Implementacje nie powinny diagnozować korzystania z za małych kluczy, określania nieistotnych parametrów wejściowych, ponownego używania IV lub nonce, generowania kluczy bez celu (czyli bezużytecznych) itp.

Odpowiedzialność za to, aby wywołania modułów KeyMint były sensowne i przydatne, spoczywa na aplikacjach, frameworku i Keystore na Androida.

Punkt wejścia addRngEntropy

Punkt wejścia addRngEntropy dodaje dostarczoną przez wywołującego entropię do puli używanej przez implementację KeyMint do generowania losowych liczb dla kluczy i IV.

Implementacje KeyMint muszą bezpiecznie mieszać dostarczoną entropię w swojej puli, która musi też zawierać entropię wygenerowaną wewnętrznie przez sprzętowy generator liczb losowych. Mieszanie powinno być przeprowadzane w taki sposób, aby atakujący, który ma pełną kontrolę nad bitami dostarczonymi przez addRngEntropy lub bitami wygenerowanymi przez sprzęt (ale nie obiema), nie miał znaczącej przewagi w przewidywaniu bitów wygenerowanych z puli entropii.

Najważniejsze cechy

Każdy z mechanizmów (generateKey, importKey, i importWrappedKey), które tworzą klucze KeyMint, zwraca właściwości nowo utworzonego klucza, podzielone odpowiednio na poziomy zabezpieczeń, które narzucają każdą z tych właściwości. Zwracane cechy obejmują wszystkie parametry określone podczas tworzenia klucza, z wyjątkiem Tag::APPLICATION_IDTag::APPLICATION_DATA. Jeśli te tagi są uwzględnione w parametrach klucza, są usuwane z zwracanych właściwości, aby nie można było znaleźć ich wartości przez zbadanie zwróconego klucza. Są one jednak powiązane kryptograficznie z kluczem blob, więc jeśli podczas używania klucza nie zostaną podane prawidłowe wartości, użycie klucza zakończy się niepowodzeniem. Podobnie Tag::ROOT_OF_TRUST jest powiązany z kluczem za pomocą szyfrowania, ale nie można go określić podczas tworzenia lub importowania klucza i nigdy nie jest zwracany.

Oprócz podanych tagów implementacja KeyMint dodaje też tag Tag::ORIGIN, który wskazuje sposób utworzenia klucza (KeyOrigin::GENERATED, KeyOrigin::IMPORTED lub KeyOrigin::SECURELY_IMPORTED).

Ochrona przed przywróceniem starszych kluczy

Ochrona przed przywracaniem jest oznaczona symbolem Tag::ROLLBACK_RESISTANCE. Oznacza to, że po usunięciu klucza za pomocą polecenia deleteKey lub deleteAllKeys nie będzie można go już nigdy użyć.

Implementacje KeyMint zwracają wygenerowany lub zaimportowany materiał klucza do wywołującego jako kluczblob, czyli zaszyfrowany i uwierzytelniony formularz. Gdy Keystore usunie kluczblob, klucz zniknie, ale atakujący, który wcześniej odzyskał materiał klucza, może go przywrócić na urządzenie.

Klucz jest chroniony przed cofnięciem, jeśli sprzęt zabezpieczający zapewnia, że usunięte klucze nie mogą zostać przywrócone później. Zwykle polega to na przechowywaniu dodatkowych metadanych klucza w zaufanej lokalizacji, którą atakujący nie może zmodyfikować. Na urządzeniach mobilnych mechanizm używany do tego celu to zwykle bloki pamięci chronione przed ponownym odtwarzaniem (RPMB). Ponieważ liczba kluczy, które można utworzyć, jest w istocie nieograniczona, a zaufane miejsce na dane używane do zabezpieczenia przed cofnięciem może być ograniczone pod względem rozmiaru, implementacja może nie wykonać żądań tworzenia kluczy odpornych na cofnięcie, gdy miejsce na dane jest pełne.

zacznij

Punkt wejścia begin() rozpoczyna operację kryptograficzną przy użyciu określonego klucza, w określonym celu i z określonymi parametrami (w odpowiednich przypadkach). Zwraca nowy obiekt IKeyMintOperation Binder, który jest używany do wykonania operacji. Dodatkowo zwracana jest wartość wyzwania, która jest używana jako część tokena uwierzytelniania w operacjach uwierzytelnionych.

Implementacja KeyMint obsługuje co najmniej 16 jednoczesnych operacji. Keystore używa maksymalnie 15 kluczy, a jeden z nich jest używany do szyfrowania haseł.vold Gdy Keystore ma 15 działających operacji (wywołano begin(), ale finish lub abort nie zostały wywołane) i otrzyma prośbę o rozpoczęcie 16 operacji, wywołuje abort() w ramach operacji, która była używana najwcześniej, aby zmniejszyć liczbę aktywnych operacji do 14 i potem wywołać begin() w celu rozpoczęcia operacji, o której zgłoszono nowe żądanie.

Jeśli podczas generowania lub importowania klucza zostały określone tagi Tag::APPLICATION_ID lub Tag::APPLICATION_DATA, wywołania metody begin() muszą zawierać te tagi z wartościami określonymi pierwotnie w argumencie params tej metody.

Obsługa błędów

Jeśli metoda obiektu IKeyMintOperation zwraca kod błędu inny niż ErrorCode::OK, operacja jest przerywana, a obiekt Binder traci ważność. Wszelkie przyszłe użycie obiektu zwraca ErrorCode::INVALID_OPERATION_HANDLE.

Egzekwowanie autoryzacji

Egzekwowanie autoryzacji klucza jest wykonywane głównie w begin(). Wyjątkiem jest sytuacja, gdy klucz ma co najmniej 1 wartość Tag::USER_SECURE_ID i nie ma wartości Tag::AUTH_TIMEOUT.

W tym przypadku klucz wymaga autoryzacji na potrzeby każdej operacji, a metody update() lub finish() otrzymują token autoryzacji w argumencie authToken. Aby mieć pewność, że token jest prawidłowy, implementacja KeyMint:

  • Weryfikuje podpis HMAC w tokenie uwierzytelniania.
  • Sprawdza, czy token zawiera bezpieczny identyfikator użytkownika, który jest zgodny z kluczem.
  • Sprawdza, czy typ autoryzacji tokena jest zgodny z Tag::USER_AUTH_TYPE klucza.
  • Sprawdza, czy token zawiera wartość wyzwania dla bieżącej operacji w polu wyzwanie.

Jeśli te warunki nie są spełnione, KeyMint zwraca ErrorCode::KEY_USER_NOT_AUTHENTICATED.

Użytkownik przekazuje token uwierzytelniający w przypadku każdego wywołania do update()finish(). Implementacja może zweryfikować token tylko raz.