Magazyn kluczy wspierany sprzętowo

Dostępność zaufanego środowiska wykonawczego w systemie na chipie (SoC) umożliwia urządzeniom z Androidem świadczenie wspieranych sprzętowo, silnych usług bezpieczeństwa dla systemu operacyjnego Android, usług platformy, a nawet aplikacji innych firm. Deweloperzy poszukują rozszerzenia Android specyficzne powinien udać się do android.security.keystore .

Przed Androidem 6.0 system Android miał już prosty, wspierany sprzętowo interfejs API usług kryptograficznych, dostarczany przez wersje 0.2 i 0.3 warstwy abstrakcji sprzętu Keymaster (HAL). Magazyn kluczy zapewniał operacje podpisywania cyfrowego i weryfikacji, a także generowanie i importowanie asymetrycznych par kluczy podpisujących. Jest to już zaimplementowane na wielu urządzeniach, ale istnieje wiele celów bezpieczeństwa, których nie można łatwo osiągnąć za pomocą samego interfejsu API podpisu. Keystore w systemie Android 6.0 rozszerzył interfejs Keystore API, aby zapewnić szerszy zakres możliwości.

W Androidzie 6.0, dodaje kluczy symetrycznych operacji kryptograficznych , AES i HMAC oraz system kontroli dostępu do kluczy sprzętowych oparciem. Kontrole dostępu są określane podczas generowania klucza i wymuszane przez cały okres istnienia klucza. Klucze mogą zostać ograniczone do użytku dopiero po uwierzytelnieniu użytkownika i tylko do określonych celów lub z określonymi parametrami kryptograficznymi. Aby uzyskać więcej informacji, zobacz autoryzacji Tagi i Funkcje stron.

Oprócz rozszerzenia zakresu prymitywów kryptograficznych, Keystore w systemie Android 6.0 dodał:

  • Schemat kontroli użycia pozwalający na ograniczenie użycia klucza, aby złagodzić ryzyko naruszenia bezpieczeństwa z powodu niewłaściwego użycia kluczy
  • Schemat kontroli dostępu umożliwiający ograniczenie kluczy do określonych użytkowników, klientów i określonego przedziału czasowego

W systemie Android 7.0 Keymaster 2 dodał obsługę poświadczania kluczy i wiązania wersji. Klucz zaświadczenie zapewnia certyfikatów klucza publicznego, które zawierają szczegółowy opis klucza i jego kontroli dostępu, aby istnienie kluczyk w bezpiecznym sprzętu i jego konfiguracji zdalnego zweryfikowania.

Wiązanie wersja wiąże klucze do systemu operacyjnego i wersji łaty. Gwarantuje to, że atakujący, który 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. Gdy urządzenie jest uaktualniane, klawisze „zapadają się” do przodu wraz z urządzeniem, ale jakikolwiek powrót urządzenia do poprzedniej wersji powoduje, że klawisze stają się bezużyteczne.

W systemie Android 8.0 Keymaster 3 przeszedł ze starej warstwy abstrakcji sprzętu (HAL) o strukturze C do interfejsu C++ HAL wygenerowanego na podstawie definicji w nowym języku definicji interfejsu sprzętowego (HIDL). W ramach zmiany zmieniło się wiele typów argumentów, chociaż typy i metody mają korespondencję jeden do jednego ze starymi typami i metodami struktury HAL. Patrz Funkcje stronę po więcej szczegółów.

Oprócz tego interfejsu rewizji, Android 8.0 rozszerzyć funkcję atestacji keymaster 2 do wspierania ID zaświadczenia . Zaświadczanie identyfikatora zapewnia ograniczony i opcjonalny mechanizm silnego potwierdzania identyfikatorów sprzętowych, takich jak numer seryjny urządzenia, nazwa produktu i identyfikator telefonu (IMEI / MEID). Aby zaimplementować ten dodatek, system Android 8.0 zmienił schemat poświadczania ASN.1, aby dodać poświadczenie identyfikatora. Implementacje Keymaster muszą znaleźć bezpieczny sposób na pobieranie odpowiednich elementów danych, a także zdefiniować mechanizm bezpiecznego i trwałego wyłączania funkcji.

W systemie Android 9 aktualizacje obejmowały:

  • Aktualizacja keymaster 4
  • Obsługa wbudowanych bezpiecznych elementów
  • Obsługa bezpiecznego importu kluczy
  • Obsługa szyfrowania 3DES
  • Zmiany w powiązaniu wersji, tak aby boot.img i system.img miały oddzielnie ustawione wersje, aby umożliwić niezależne aktualizacje

Słowniczek

Oto krótki przegląd komponentów Keystore i ich relacji.

AndroidKeystore jest API Framework Android i składnik używany przez aplikacje do dostępu funkcjonalności kluczy. Jest zaimplementowany jako rozszerzenie standardowych interfejsów API Java Cryptography Architecture i składa się z kodu Java działającego we własnej przestrzeni procesów aplikacji. AndroidKeystore spełnia żądań aplikacji dla zachowania magazynu kluczy przez przekazywanie ich do demona kluczy.

Demon kluczy jest demon systemu Android, który zapewnia dostęp do wszystkich funkcji za pośrednictwem magazynu kluczy Binder API . Odpowiada za przechowywanie „kluczowych obiektów blob”, które zawierają rzeczywisty materiał klucza tajnego, zaszyfrowany, aby Keystore mógł je przechowywać, ale nie mógł ich używać ani ujawniać.

keymasterd jest serwerem HIDL, który zapewnia dostęp do keymaster TA. (Ta nazwa nie jest znormalizowana i służy do celów koncepcyjnych.)

Keymaster TA (zaufanych aplikacji) to oprogramowanie działa w bezpiecznym kontekście, najczęściej w TrustZone na ARM SoC, który dostarcza wszystkich bezpiecznych operacji kluczy, ma dostęp do materiału kluczowego surowca, sprawdza wszystkie warunki kontroli dostępu na klucze itp.

LockSettingsService jest składnikiem systemu Android odpowiedzialny za uwierzytelnianie użytkowników, zarówno hasło i odcisków palców. Nie jest częścią magazynu kluczy, ale ma znaczenie, ponieważ wiele operacji na kluczach magazynu kluczy wymaga uwierzytelnienia użytkownika. LockSettingsService współdziała z Gatekeeper TA TA i palców, aby uzyskać tokenów uwierzytelniania, które przekazuje do demona kluczy, a które ostatecznie są spożywane przez aplikację keymaster TA.

Gatekeeper TA (zaufanych aplikacji) to kolejny składnik działa w bezpiecznym kontekście, który jest odpowiedzialny za uwierzytelnianie haseł użytkowników i generowania tokenów uwierzytelniania stosowanego udowodnić keymaster TA że uwierzytelnianie zostało wykonane dla konkretnego użytkownika w danym momencie.

Fingerprint TA (zaufanych aplikacji) to kolejny składnik działa w bezpiecznym kontekście, który jest odpowiedzialny za uwierzytelnianie użytkowników i generując odciski palców uwierzytelniania żetony używane udowodnić keymaster TA że uwierzytelnianie zostało wykonane dla konkretnego użytkownika w danym momencie.

Architektura

Interfejs API magazynu kluczy systemu Android i bazowa warstwa HAL Keymaster zapewniają podstawowy, ale odpowiedni zestaw prymitywów kryptograficznych, aby umożliwić implementację protokołów przy użyciu kluczy z kontrolą dostępu i sprzętem.

Keymaster HAL to dostarczona przez producenta OEM, dynamicznie ładowana biblioteka używana przez usługę Keystore do świadczenia usług kryptograficznych wspieranych sprzętowo. Aby zapewnić bezpieczeństwo, implementacje HAL nie wykonują żadnych wrażliwych operacji w przestrzeni użytkownika, a nawet w przestrzeni jądra. Poufne operacje są delegowane do bezpiecznego procesora, do którego dostęp uzyskuje się za pośrednictwem interfejsu jądra. Powstała architektura wygląda tak:

Dostęp do Keymaster

Rysunek 1. Dostęp do Keymaster

W urządzeniu z systemem Android „klient” warstwy HAL Keymaster składa się z wielu warstw (np. aplikacji, struktury, demona Keystore), ale można to zignorować na potrzeby tego dokumentu. Oznacza to, że opisany interfejs API Keymaster HAL jest niskopoziomowy, używany przez składniki wewnętrzne platformy i nie jest udostępniany programistom aplikacji. Im wyższy poziom API jest opisany na Android Developer miejscu .

Celem Keymaster HAL nie jest implementacja algorytmów wrażliwych na bezpieczeństwo, ale tylko porządkowanie i rozbieranie żądań do bezpiecznego świata. Format przewodu jest zdefiniowany przez implementację.

Kompatybilność z poprzednimi wersjami

HAL Keymaster 1 jest całkowicie niekompatybilny z wcześniej wydanymi warstwami HAL, np. Keymaster 0.2 i 0.3. Aby ułatwić współdziałanie na urządzeniach z systemem Android 5.0 lub starszym, które zostały uruchomione ze starszymi warstwami HAL Keymaster, Keystore udostępnia adapter, który implementuje warstwę HAL Keymaster 1 z wywołaniami istniejącej biblioteki sprzętowej. Wynik nie może zapewnić pełnego zakresu funkcjonalności w Keymaster 1 HAL. W szczególności obsługuje tylko algorytmy RSA i ECDSA, a całe wymuszenie autoryzacji klucza jest wykonywane przez adapter w świecie niezabezpieczonym.

Keymaster 2 dodatkowo uproszczony interfejs HAL usuwając get_supported_* sposobów i pozwala na finish() sposób przyjąć wkład. Zmniejsza to liczbę podróży w obie strony do TEE w przypadkach, gdy dane wejściowe są dostępne jednocześnie, i upraszcza implementację deszyfrowania AEAD.

W systemie Android 8.0 Keymaster 3 przeszedł ze starej struktury C HAL do interfejsu HAL C++ wygenerowanego na podstawie definicji w nowym języku definicji interfejsu sprzętowego (HIDL). Implementacja HAL nowy styl jest tworzony przez instacji wygenerowany IKeymasterDevice klasę i wdrażania czystych metod wirtualnych. W ramach zmiany zmieniło się wiele typów argumentów, chociaż typy i metody mają korespondencję jeden do jednego ze starymi typami i metodami struktur HAL.

Przegląd HIDL

Język definicji interfejsu sprzętowego (HIDL) zapewnia niezależny od języka implementacji mechanizm określania interfejsów sprzętowych. Narzędzia HIDL obecnie obsługują generowanie interfejsów C++ i Java. Oczekuje się, że większość implementatorów Trusted Execution Environment (TEE) uzna narzędzia C++ za wygodniejsze, więc ten dokument omawia tylko reprezentację C++.

Interfejsy HIDL składają się z zestawu metod, wyrażonych jako:

  methodName(INPUT ARGUMENTS) generates (RESULT ARGUMENTS);

Istnieją różne wstępnie zdefiniowane typy, a warstwy HAL mogą definiować nowe typy wyliczeniowe i strukturalne. Więcej informacji na temat HIDL, patrz punkt odniesienia .

Przykładem metody z keymaster 3 IKeymasterDevice.hal jest:

generateKey(vec<KeyParameter> keyParams)
        generates(ErrorCode error, vec<uint8_t> keyBlob,
                  KeyCharacteristics keyCharacteristics);

Jest to odpowiednik następującego z HAL keymaster2:

keymaster_error_t (*generate_key)(
        const struct keymaster2_device* dev,
        const keymaster_key_param_set_t* params,
        keymaster_key_blob_t* key_blob,
        keymaster_key_characteristics_t* characteristics);

W wersji HIDL The dev argumentem jest usuwany, ponieważ jest niejawny. params argumentów nie jest struktura zawiera wskaźnik odsyłania tablicę key_parameter_t obiektów, ale vec (wektor) zawierający KeyParameter obiektów. Wartości zwracane są wymienione w „ generates ” klauzuli, w tym wektorem uint8_t wartości dla klucza blob.

Metoda wirtualna C++ generowana przez kompilator HIDL to:

Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
                         generateKey_cb _hidl_cb) override;

Gdzie generate_cb jest wskaźnikiem funkcja zdefiniowana jako:

std::function<void(ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
                   const KeyCharacteristics& keyCharacteristics)>

Oznacza to, że generate_cb jest funkcją, która przyjmuje wartości powrotne wymienione w pkt wytworzenia. Klasa realizacja HAL nadpisuje ten generateKey sposób i wywołuje generate_cb wskaźnik funkcja zwraca wynik operacji do rozmówcy. Uwaga wywołanie wskaźnik funkcja jest synchroniczny. Rozmówca zwraca generateKey i generateKey wzywa dostarczonego wskaźnik funkcji, które wykonuje do końca, zwracając sterowanie do generateKey realizacji, który następnie powraca do rozmówcy.

Szczegółowy przykład zobaczyć realizację domyślną hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp . Domyślna implementacja zapewnia kompatybilność wsteczną dla urządzeń ze starym stylem keymaster0, keymaster1 lub keymaster2 HALS.

Kontrola dostępu

Najbardziej podstawową zasadą kontroli dostępu do magazynu kluczy jest to, że każda aplikacja ma własną przestrzeń nazw. Ale dla każdej reguły jest wyjątek. Magazyn kluczy ma kilka map zakodowanych na sztywno, które umożliwiają niektórym składnikom systemu dostęp do niektórych innych przestrzeni nazw. Jest to bardzo tępy instrument, ponieważ daje jednemu komponentowi pełną kontrolę nad inną przestrzenią nazw. I jeszcze kwestia komponentów dostawcy jako klientów Keystore. Obecnie nie mamy możliwości ustanowienia przestrzeni nazw dla komponentów dostawcy, na przykład suplikanta WPA.

Aby dostosować się do komponentów dostawców i uogólnić kontrolę dostępu bez zakodowanych na stałe wyjątków, Keystore 2.0 wprowadza domeny i przestrzenie nazw SELinux.

Domeny magazynu kluczy

Dzięki domenom Keystore możemy oddzielić przestrzenie nazw od identyfikatorów UID. Klienci uzyskujący dostęp do klucza w magazynie kluczy muszą określić domenę, przestrzeń nazw i alias, do których chcą uzyskać dostęp. Na podstawie tej krotki i tożsamości dzwoniącego możemy określić, do którego klucza dzwoniący chce uzyskać dostęp i czy ma odpowiednie uprawnienia.

Przedstawiamy pięć parametrów domeny, które regulują sposób dostępu do kluczy. Kontrolują semantykę parametru przestrzeni nazw deskryptora klucza i sposób wykonywania kontroli dostępu.

  • DOMAIN_APP : Domena aplikacja obejmuje zachowanie dziedzictwa. Interfejs SPI Java Keystore używa domyślnie tej domeny. Gdy ta domena jest używana, argument przestrzeni nazw jest ignorowany i zamiast tego używany jest identyfikator UID wywołującego. Dostęp do tej domeny jest kontrolowana przez wytwórnię magazynu kluczy do klasy keystore_key w polityce SELinux.
  • DOMAIN_SELINUX : Ta domena wskazuje, że obszar nazw ma etykietę w polityce SELinux. Parametr nazw jest wzrok i języku kontekście docelowego i sprawdzenie uprawnienie jest wykonywane dla wywołującego kontekście SELinux dla keystore_key klasie. Po ustanowieniu uprawnienia dla danej operacji do wyszukiwania klucza używana jest pełna krotka.
  • DOMAIN_GRANT : Domena grant wskazuje, że parametr nazw jest identyfikatorem grant. Parametr alias jest ignorowany. Testy SELinux są wykonywane podczas tworzenia grantu. Dalsza kontrola dostępu sprawdza tylko, czy UID wywołującego jest zgodny z UID beneficjenta żądanego przydziału.
  • DOMAIN_KEY_ID : Ta domena wskazuje, że parametr nazw to unikatowy identyfikator, klucz. Sam klucz może zostały stworzone z DOMAIN_APP lub DOMAIN_SELINUX . Czek uprawnienie jest wykonywane po domain i namespace zostały załadowane z kluczowych danych w taki sam sposób, jak gdyby blob został załadowany przez domeny, nazw i alias krotki. Uzasadnieniem dla domeny id klucza jest ciągłość. Podczas uzyskiwania dostępu do klucza przez alias, kolejne wywołania mogą działać na różnych kluczach, ponieważ nowy klucz mógł zostać wygenerowany lub zaimportowany i powiązany z tym aliasem. Kluczowy identyfikator jednak nigdy się nie zmienia. Zatem używając klucza według identyfikatora klucza po jego jednokrotnym załadowaniu z bazy danych Keystore przy użyciu aliasu, można być pewnym, że jest to ten sam klucz, o ile identyfikator klucza nadal istnieje. Ta funkcja nie jest dostępna dla twórców aplikacji. Zamiast tego jest używany w interfejsie SPI Android Keystore, aby zapewnić bardziej spójne środowisko, nawet jeśli jest używany jednocześnie w niebezpieczny sposób.
  • DOMAIN_BLOB : Domena blob wskazuje, że rozmówca zarządza blob sama. Jest to używane w przypadku klientów, którzy muszą uzyskać dostęp do magazynu kluczy przed zamontowaniem partycji danych. Kluczem blob jest wliczone w blob dziedzinie kluczowych deskryptora.

Korzystając z domeny SELinux, możemy dać komponentom dostawcy dostęp do bardzo specyficznych przestrzeni nazw Keystore, które mogą być współdzielone przez komponenty systemu, takie jak okno dialogowe ustawień.

Polityka SELinux dla keystore_key

Etykiety przestrzeni nazw są konfigurowane za pomocą keystore2_key_context pliku.
Każdy wiersz w tych plikach odwzorowuje numeryczny identyfikator przestrzeni nazw na etykietę SELinux. Na przykład,

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share keystore keys.
102            u:object_r:wifi_key:s0

Po skonfigurowaniu w ten sposób nowej przestrzeni nazw kluczy, możemy dać do niej dostęp, dodając odpowiednią politykę. Na przykład, aby umożliwić wpa_supplicant dostać i za pomocą przycisków w nowej przestrzeni nazw chcemy dodać następującą linię do hal_wifi_supplicant.te :

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

Po skonfigurowaniu nowej przestrzeni nazw AndroidKeyStore może być używany prawie jak zwykle. Jedyna różnica polega na tym, że należy określić identyfikator przestrzeni nazw. Do załadunku i importowania kluczy i do magazynu kluczy id nazw jest określona za pomocą AndroidKeyStoreLoadStoreParameter . Na przykład,

import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
import java.security.KeyStore;

KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
keystore.load(new AndroidKeyStoreLoadStoreParameter(102));

Aby wygenerować klucz w danej przestrzeni nazw, identyfikator nazw musi być podawana przy KeyGenParameterSpec.Builder#setNamespace():

import android.security.keystore.KeyGenParameterSpec;
KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder();
specBuilder.setNamespace(102);

Poniższe pliki kontekstowe mogą służyć do konfigurowania przestrzeni nazw Keystore 2.0 SELinux. Każda partycja ma inny zarezerwowany zakres 10 000 identyfikatorów przestrzeni nazw, aby uniknąć kolizji.

Przegroda Zasięg Pliki konfiguracyjne
System 0 ... 9999
/system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Rozszerzony system 10 000 ... 19 999
/system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Produkt 20 000 ... 29 999
/product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Sprzedawca 30 000 ... 39 999
/vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Klient żąda klucza o udostępnienie domeny SELinux i żądaną nazw wirtualnych, w tym przypadku "wifi_key" , przez jej numerycznym identyfikatorem.

Powyżej zdefiniowano następujące przestrzenie nazw. Jeśli zastępują zasady specjalne, poniższa tabela wskazuje UID, któremu odpowiadały.

Identyfikator przestrzeni nazw Etykieta zasad SE UID Opis
0 su_key Nie dotyczy Klucz superużytkownika. Używany tylko do testowania kompilacji userdebug i eng. Nie dotyczy kompilacji użytkownika.
1 klucz_powłoki Nie dotyczy Przestrzeń nazw dostępna dla powłoki. Używany głównie do testowania, ale można go również używać w kompilacjach użytkownika z wiersza poleceń.
100 vold_key Nie dotyczy Przeznaczony do użytku przez vold.
101 odsing_key Nie dotyczy Używany przez demona podpisującego na urządzeniu.
102 klucz_wifi AID_WIFI(1010) Używany przez sybsystem Wifi Androida, w tym wpa_supplicant.
120 resume_on_reboot_key AID_SYSTEM(1000) Używany przez serwer systemu Android do obsługi wznawiania po ponownym uruchomieniu.

Dostęp do wektorów

Klasa SELinux keystore_key postarzał się trochę, a niektóre z uprawnień, takich jak verify czy sign straciły znaczenie. Oto nowy zestaw uprawnień, keystore2_key , że kluczy 2,0 wymusi.

Pozwolenie Oznaczający
delete Zaznaczone podczas usuwania kluczy z Keystore.
get_info Sprawdzane, gdy wymagane są metadane klucza.
grant Obiekt wywołujący potrzebuje tego uprawnienia, aby utworzyć przydział do klucza w kontekście docelowym.
manage_blob Dzwoniący może używać DOMAIN_BLOB na danym obszarze nazw SELinux, a tym samym zarządzanie plamy sama. Jest to szczególnie przydatne dla volda.
rebind To uprawnienie kontroluje, czy alias może być ponownie powiązany z nowym kluczem. Jest to wymagane do wstawiania i oznacza, że ​​poprzednio powiązany klucz zostanie usunięty. Jest to w zasadzie uprawnienie do wstawiania, ale lepiej oddaje semantykę magazynu kluczy.
req_forced_op Klienci z tym uprawnieniem mogą tworzyć operacje, których nie można oczyścić, a tworzenie operacji nigdy nie kończy się niepowodzeniem, chyba że wszystkie miejsca operacji są zajęte przez operacje, których nie można oczyścić.
update Wymagany do aktualizacji podkomponentu klucza.
use Zaznaczone podczas tworzenia operacji Keymint, która wykorzystuje materiał klucza, np. do podpisywania, szyfrowania/odszyfrowywania.
use_dev_id Wymagane podczas generowania informacji identyfikujących urządzenie, takich jak poświadczenie identyfikatora urządzenia.

Dodatkowo, możemy podzielić na szereg kluczowych uprawnień Niespecyficzne kluczy w klasie bezpieczeństwa SELinux keystore2 :

Pozwolenie Oznaczający
add_auth Wymagane przez dostawcę uwierzytelniania, takiego jak Gatekeeper lub BiometricsManager, do dodawania tokenów uwierzytelniania.
clear_ns Dawniej clear_uid to uprawnienie umożliwia osobie niebędącej właścicielem przestrzeni nazw usunięcie wszystkich kluczy w tej przestrzeni nazw.
list Wymagane przez system do wyliczania kluczy według różnych właściwości, takich jak własność lub ograniczenia uwierzytelniania. To uprawnienie nie jest wymagane przez wywołujące wyliczanie własnych przestrzeni nazw. To jest objęte get_info zgody.
lock Uprawnienie to pozwala na zablokowanie Keystore, czyli wyrzucenie klucza głównego, tak aby klucze powiązane z uwierzytelnianiem stały się bezużyteczne i niemożliwe do utworzenia.
reset To uprawnienie pozwala zresetować Keystore do ustawień fabrycznych, usuwając wszystkie klucze, które nie są niezbędne do funkcjonowania systemu operacyjnego Android.
unlock To uprawnienie jest wymagane do próby odblokowania klucza głównego dla kluczy powiązanych z uwierzytelnianiem.