W Keymaster 1 wszystkie klucze keymastera były kryptograficznie powiązane z Root of Trust urządzenia lub kluczem Verified Boot. W Keymaster 2 i 3 wszystkie klucze są również powiązane z systemem operacyjnym i poziomem poprawek obrazu systemu. Gwarantuje to, że osoba atakująca, która wykryje słabość w starej wersji systemu lub oprogramowania TEE, nie może przywrócić urządzenia do wersji zawierającej lukę i użyć kluczy utworzonych w nowszej wersji. Ponadto, gdy klucz z daną wersją i poziomem poprawki jest używany na urządzeniu, które zostało zaktualizowane do nowszej wersji lub poziomu poprawki, klucz jest aktualizowany, zanim będzie mógł zostać użyty, a poprzednia wersja klucza unieważniona. W ten sposób, wraz z aktualizacją urządzenia, klawisze będą „zaskakiwać” do przodu wraz z urządzeniem, ale każde przywrócenie poprzedniej wersji urządzenia spowoduje, że klawisze staną się bezużyteczne.
Aby wesprzeć modułową strukturę Treble i przełamać wiązanie system.img z boot.img, Keymaster 4 zmienił model wiązania wersji klucza, aby mieć oddzielne poziomy poprawek dla każdej partycji. Dzięki temu każda partycja może być aktualizowana niezależnie, przy jednoczesnym zapewnieniu ochrony przed wycofaniem.
W systemie Android 9 partycje boot
, system
i vendor
mają swój własny poziom poprawek.
- Urządzenia z Android Verified Boot (AVB) mogą umieścić wszystkie poziomy poprawek i wersję systemu w vbmeta, aby bootloader mógł je dostarczyć do Keymastera. W przypadku partycji połączonych informacje o wersji partycji będą znajdować się w powiązanej vbmeta. Ogólnie informacje o wersji powinny znajdować się w
vbmeta struct
, która zawiera dane weryfikacyjne (hash lub hashtree) dla danej partycji. - Na urządzeniach bez AVB:
- Implementacje Verified Boot muszą dostarczać skrót metadanych wersji do bootloadera, aby bootloader mógł dostarczyć skrót do Keymastera.
-
boot.img
może kontynuować przechowywanie poziomu poprawek w nagłówku -
system.img
może kontynuować przechowywanie poziomu poprawek i wersji systemu operacyjnego we właściwościach tylko do odczytu -
vendor.img
przechowuje poziom poprawek we właściwości tylko do odczyturo.vendor.build.version.security_patch
. - Bootloader może dostarczyć hash wszystkich danych zweryfikowanych przez zweryfikowany rozruch do keymastera.
- W systemie Android 9 użyj następujących tagów, aby podać informacje o wersji dla następujących partycji:
-
VENDOR_PATCH_LEVEL
: partycjavendor
-
BOOT_PATCH_LEVEL
: partycjaboot
-
OS_PATCH_LEVEL
iOS_VERSION
: partycjasystem
. (OS_VERSION
jest usuwany z nagłówkaboot.img
.
-
- Implementacje Keymaster powinny traktować wszystkie poziomy poprawek niezależnie. Klucze są użyteczne, jeśli wszystkie informacje o wersji są zgodne z wartościami powiązanymi z kluczem, a
IKeymaster::upgradeDevice()
w razie potrzeby przechodzi na wyższy poziom poprawki.
Zmiany HAL
Aby obsługiwać powiązanie wersji i zaświadczanie wersji, system Android 7.1 dodał tagi Tag::OS_VERSION
i Tag::OS_PATCHLEVEL
oraz metody configure
i upgradeKey
. Tagi wersji są automatycznie dodawane przez implementacje Keymaster 2+ do wszystkich nowo wygenerowanych (lub zaktualizowanych) kluczy. Ponadto każda próba użycia klucza, który nie ma wersji systemu operacyjnego lub poziomu poprawki pasującej odpowiednio do bieżącej wersji systemu operacyjnego lub poziomu poprawki, jest odrzucana za pomocą ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
to wartość UINT
, która reprezentuje główne, podrzędne i podrzędne części wersji systemu Android jako MMmmss, gdzie MM to wersja główna, mm to podrzędna wersja, a ss to podrzędna wersja. Na przykład 6.1.2 będzie reprezentowane jako 060102.
Tag::OS_PATCHLEVEL
to wartość UINT
, która reprezentuje rok i miesiąc ostatniej aktualizacji systemu jako RRRRMM, gdzie RRRR to rok czterocyfrowy, a MM to miesiąc dwucyfrowy. Na przykład marzec 2016 będzie reprezentowany jako 201603.
UpgradeKey
Aby umożliwić aktualizację kluczy do nowej wersji systemu operacyjnego i poziomu poprawek obrazu systemu, system Android 7.1 dodał metodę upgradeKey
do warstwy HAL:
Keymaster 3
upgradeKey(vec keyBlobToUpgrade, vec upgradeParams) generates(ErrorCode error, vec upgradedKeyBlob);
Keymaster 2
keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key);
-
dev
to struktura urządzenia -
keyBlobToUpgrade
to klucz, który należy zaktualizować -
upgradeParams
to parametry potrzebne do uaktualnienia klucza. Należą do nichTag::APPLICATION_ID
iTag::APPLICATION_DATA
, które są niezbędne do odszyfrowania obiektu BLOB klucza, jeśli zostały podane podczas generowania. -
upgradedKeyBlob
jest parametrem wyjściowym używanym do zwracania nowego kluczowego obiektu BLOB.
Jeśli upgradeKey
jest wywoływany z obiektem BLOB klucza, którego nie można przeanalizować lub jest w inny sposób nieprawidłowy, zwraca ErrorCode::INVALID_KEY_BLOB
. Jeśli zostanie wywołany z kluczem, którego poziom poprawki jest większy niż bieżąca wartość systemowa, zwraca ErrorCode::INVALID_ARGUMENT
. Jeśli zostanie wywołany z kluczem, którego wersja systemu operacyjnego jest większa niż bieżąca wartość systemowa, a wartość systemowa jest niezerowa, zwraca ErrorCode::INVALID_ARGUMENT
. Dozwolone są aktualizacje wersji systemu operacyjnego z wartości niezerowej do zera. W przypadku błędów komunikacji z bezpiecznym światem zwraca odpowiednią wartość błędu (np. ErrorCode::SECURE_HW_ACCESS_DENIED
, ErrorCode::SECURE_HW_BUSY
). W przeciwnym razie zwraca ErrorCode::OK
i zwraca nowy kluczowy obiekt blob w upgradedKeyBlob
.
keyBlobToUpgrade
zachowuje ważność po wywołaniu upgradeKey
i teoretycznie może być ponownie użyty, jeśli urządzenie zostało obniżone. W praktyce magazyn kluczy zazwyczaj wywołuje deleteKey
w obiekcie blob keyBlobToUpgrade
krótko po wywołaniu upgradeKey
. Jeśli keyBlobToUpgrade
miał tag Tag::ROLLBACK_RESISTANT
, to upgradedKeyBlob
również powinien go mieć (i powinien być odporny na wycofywanie).
Bezpieczna konfiguracja
Aby zaimplementować wiązanie wersji, keymaster TA potrzebuje sposobu na bezpieczne odbieranie bieżącej wersji systemu operacyjnego i poziomu poprawek (informacje o wersji) oraz zapewnienie, że otrzymywane informacje są zgodne z informacjami o uruchomionym systemie.
Aby zapewnić bezpieczne dostarczanie informacji o wersji do TA, do nagłówka obrazu rozruchowego dodano pole OS_VERSION
. Skrypt budowania obrazu rozruchowego automatycznie wypełnia to pole. Producenci OEM i realizatorzy TA Keymaster muszą współpracować, aby zmodyfikować programy ładujące urządzenia, aby wyodrębnić informacje o wersji z obrazu rozruchowego i przekazać je do TA przed uruchomieniem niezabezpieczonego systemu. Gwarantuje to, że osoby atakujące nie mogą ingerować w dostarczanie informacji o wersji do TA.
Konieczne jest również upewnienie się, że obraz systemu zawiera te same informacje o wersji, co obraz rozruchowy. W tym celu do keymastera HAL dodano metodę configure:
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
Argument params
zawiera Tag::OS_VERSION
i Tag::OS_PATCHLEVEL
. Ta metoda jest wywoływana przez klientów keymaster2 po otwarciu warstwy HAL, ale przed wywołaniem jakichkolwiek innych metod. Jeśli przed konfiguracją zostanie wywołana jakakolwiek inna metoda, TA zwróci ErrorCode::KEYMASTER_NOT_CONFIGURED
.
Gdy configure
jest wywoływany po raz pierwszy po uruchomieniu urządzenia, powinno ono zweryfikować, czy podana informacja o wersji jest zgodna z tym, co zostało dostarczone przez bootloader. Jeśli informacje o wersji nie są zgodne, configure
zwraca ErrorCode::INVALID_ARGUMENT
, a wszystkie inne metody keymastera nadal zwracają ErrorCode::KEYMASTER_NOT_CONFIGURED
. Jeśli informacje są zgodne, configure
zwraca ErrorCode::OK
, a inne metody keymastera zaczynają działać normalnie.
Kolejne wywołania configure
zwracają tę samą wartość zwróconą przez pierwsze wywołanie i nie zmieniają stanu keymastera. Zauważ, że ten proces WYMAGA, aby wszystkie OTA aktualizowały zarówno obrazy systemu, jak i obrazy rozruchowe; nie można ich aktualizować osobno, aby zachować synchronizację informacji o wersji.
Ponieważ configure
zostanie wywołana przez system, którego zawartość ma sprawdzić poprawność, osoba atakująca może złamać obraz systemu i zmusić go do podania informacji o wersji, które pasują do obrazu rozruchowego, ale które nie są rzeczywistymi wersja systemu. Połączenie weryfikacji obrazu rozruchowego, walidacji dm-verity zawartości obrazu systemu oraz fakt, że configure
jest wywoływana na bardzo wczesnym etapie rozruchu systemu, powinno utrudnić wykorzystanie tego okna możliwości.