Moduł kryptograficzny GKI z certyfikatem FIPS 140-3

Jądro GKI zawiera moduł jądra Linuxa o nazwie fips140.ko, który jest zgodny z wymaganiami FIPS 140-3 dotyczącymi modułów oprogramowania kryptograficznego. Ten moduł można przesłać do certyfikacji FIPS, jeśli wymaga tego produkt z jądrem GKI.

Zanim będzie można używać procedur kryptograficznych, należy spełnić w szczególności te wymagania FIPS 140-3:

  • Przed udostępnieniem algorytmów kryptograficznych moduł musi sprawdzić własną integralność.
  • Zanim moduł udostępni zatwierdzone algorytmy kryptograficzne, musi je przetestować i zweryfikować za pomocą testów własnych z użyciem znanych odpowiedzi.

Dlaczego osobny moduł jądra

Walidacja FIPS 140-3 opiera się na założeniu, że po certyfikacji modułu oprogramowania lub sprzętu nigdy nie jest on zmieniany. Jeśli zostanie zmieniony, musi zostać ponownie certyfikowany. Nie jest to zgodne z obecnie stosowanymi procesami tworzenia oprogramowania. W rezultacie tego wymagania moduły oprogramowania FIPS są zwykle projektowane tak, aby jak najbardziej skupiać się na komponentach kryptograficznych. Dzięki temu zmiany niezwiązane z kryptografią nie wymagają ponownej oceny kryptografii.

Jądro GKI ma być regularnie aktualizowane przez cały okres obsługi. Sprawia to, że umieszczenie całego jądra w granicach modułu FIPS jest niemożliwe, ponieważ taki moduł musiałby być ponownie certyfikowany po każdej aktualizacji jądra. Zdefiniowanie „modułu FIPS” jako podzbioru obrazu jądra złagodziłoby ten problem, ale go nie rozwiązało, ponieważ zawartość binarna „modułu FIPS” nadal zmieniałaby się znacznie częściej niż jest to konieczne.

Przed wersją jądra 6.1 należało też pamiętać, że GKI było kompilowane z włączoną optymalizacją czasu łączenia (LTO), ponieważ LTO było warunkiem wstępnym dla integralności przepływu sterowania, która jest ważną funkcją zabezpieczeń.

Dlatego cały kod objęty wymaganiami FIPS 140-3 jest pakowany w osobny moduł jądra fips140.ko, który korzysta tylko ze stabilnych interfejsów udostępnianych przez źródło jądra GKI, z którego został utworzony. Oznacza to, że moduł może być używany z różnymi wersjami GKI tej samej generacji i musi być aktualizowany i ponownie przesyłany do certyfikacji tylko wtedy, gdy w kodzie zawartym w samym module zostaną naprawione jakieś problemy.

Kiedy używać modułu

Sam kernel GKI zawiera kod, który zależy od procedur kryptograficznych, które są również spakowane w module kernela FIPS 140-3. Wbudowane procedury kryptograficzne nie są więc przenoszone z jądra GKI, ale kopiowane do modułu. Po załadowaniu modułu wbudowane procedury kryptograficzne są wyrejestrowywane z interfejsu Linux CryptoAPI i zastępowane przez procedury zawarte w module.

Oznacza to, że moduł fips140.ko jest całkowicie opcjonalny i warto go wdrożyć tylko wtedy, gdy wymagana jest certyfikacja FIPS 140-3. Poza tym moduł nie zapewnia żadnych dodatkowych funkcji, a jego niepotrzebne wczytywanie może jedynie wpłynąć na czas rozruchu bez żadnych korzyści.

Jak wdrożyć moduł

Moduł można włączyć do kompilacji Androida, wykonując te czynności:

  • Dodaj nazwę modułu do BOARD_VENDOR_RAMDISK_KERNEL_MODULES. Spowoduje to skopiowanie modułu do dysku RAM dostawcy.
  • Dodaj nazwę modułu do BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD. Powoduje to dodanie nazwy modułu do modules.load w miejscu docelowym. modules.load zawiera listę modułów, które są wczytywane przez init podczas uruchamiania urządzenia.

Sprawdzanie integralności

Moduł jądra FIPS 140-3 oblicza skrót HMAC-SHA256 własnych sekcji .code.rodata w momencie wczytywania modułu i porównuje go ze skrótem zapisanym w module. Dzieje się to po tym, jak moduł ładujący systemu Linux wprowadzi już zwykłe modyfikacje, takie jak przetwarzanie relokacji ELF i łatki alternatywne dotyczące błędów procesora. Aby mieć pewność, że streszczenie można prawidłowo odtworzyć, wykonujemy te dodatkowe czynności:

  • Relokacje ELF są zachowywane w module, aby można je było zastosować w odwrotnej kolejności do danych wejściowych funkcji HMAC.
  • Moduł cofa wszelkie poprawki kodu wprowadzone przez jądro na potrzeby dynamicznego stosu wywołań w cieniu. W szczególności moduł zastępuje wszystkie instrukcje, które umieszczają lub zdejmują elementy ze stosu wywołań cienia, instrukcjami kodu uwierzytelniania wskaźnika (PAC), które były obecne pierwotnie.
  • W przypadku modułu wyłączone jest stosowanie wszystkich innych poprawek kodu, w tym kluczy statycznych, a co za tym idzie – punktów śledzenia i haków dostawcy.

Testy własne z odpowiedzią

Wszystkie wdrożone algorytmy, które podlegają wymaganiom FIPS 140-3, muszą przed użyciem przeprowadzić test własny z odpowiedzią znaną z góry. Zgodnie z wytycznymi dotyczącymi wdrażania standardu FIPS 140-3 10.3.A w przypadku szyfrów wystarczy jeden wektor testowy na algorytm z użyciem dowolnej obsługiwanej długości klucza, o ile przetestowane zostaną zarówno szyfrowanie, jak i odszyfrowywanie.

Interfejs Linux CryptoAPI ma pojęcie priorytetów algorytmów, w którym może współistnieć kilka implementacji tego samego algorytmu (np. jedna korzystająca ze specjalnych instrukcji kryptograficznych i druga, która jest rezerwowa w przypadku procesorów, które nie implementują tych instrukcji). Dlatego konieczne jest przetestowanie wszystkich implementacji tego samego algorytmu. Jest to konieczne, ponieważ interfejs Linux CryptoAPI umożliwia pominięcie wyboru na podstawie priorytetu i zamiast tego wybranie algorytmu o niższym priorytecie.

Algorytmy uwzględnione w module

Wszystkie algorytmy zawarte w module FIPS 140-3 są wymienione poniżej. Dotyczy to gałęzi jądra android12-5.10, android13-5.10, android13-5.15, android14-5.15, android14-6.1android15-6.6, chociaż w odpowiednich miejscach wskazujemy różnice między wersjami jądra.

Algorytm Implementacje Możliwość zatwierdzenia Definicja
aes aes-generic, aes-arm64, aes-ce, biblioteka AES Tak Szyfr blokowy AES bez trybu działania: obsługiwane są wszystkie rozmiary kluczy (128 bitów, 192 bity i 256 bitów). Wszystkie implementacje inne niż implementacja biblioteki można tworzyć w trybie działania za pomocą szablonu.
cmac(aes) cmac (szablon), cmac-aes-neon, cmac-aes-ce Tak AES-CMAC: obsługiwane są wszystkie rozmiary kluczy AES. Szablon cmac można utworzyć z dowolną implementacją aes za pomocą cmac(<aes-impl>). Pozostałe implementacje są samodzielne.
ecb(aes) ecb (szablon), ecb-aes-neon, ecb-aes-neonbs, ecb-aes-ce Tak AES-ECB: obsługiwane są wszystkie rozmiary kluczy AES. Szablon ecb można utworzyć z dowolną implementacją aes za pomocą ecb(<aes-impl>). Pozostałe implementacje są samodzielne.
cbc(aes) cbc (szablon), cbc-aes-neon, cbc-aes-neonbs, cbc-aes-ce Tak AES-CBC: obsługiwane są wszystkie rozmiary kluczy AES. Szablon cbc można utworzyć z dowolną implementacją aes za pomocą ctr(<aes-impl>). Pozostałe implementacje są samodzielne.
cts(cbc(aes)) cts (szablon), cts-cbc-aes-neon, cts-cbc-aes-ce Tak AES-CBC-CTS lub AES-CBC z przechwytywaniem tekstu zaszyfrowanego: używana konwencja to CS3; ostatnie 2 bloki tekstu zaszyfrowanego są zamieniane bezwarunkowo. Obsługiwane są wszystkie rozmiary kluczy AES. Szablon cts można utworzyć z dowolną implementacją cbc za pomocą cts(<cbc(aes)-impl>). Pozostałe implementacje są samodzielne.
ctr(aes) ctr (szablon), ctr-aes-neon, ctr-aes-neonbs, ctr-aes-ce Tak AES-CTR: obsługiwane są wszystkie rozmiary kluczy AES. Szablon ctr można utworzyć z dowolną implementacją aes za pomocą ctr(<aes-impl>). Pozostałe implementacje są samodzielne.
xts(aes) xts (szablon), xts-aes-neon, xts-aes-neonbs, xts-aes-ce Tak AES-XTS: w wersji jądra 6.1 i starszych obsługiwane są wszystkie rozmiary kluczy AES, a w wersji 6.6 i nowszych obsługiwane są tylko AES-128 i AES-256. Szablon xts można utworzyć z dowolną implementacją ecb(aes) za pomocą xts(<ecb(aes)-impl>). Pozostałe implementacje są samodzielne. Wszystkie implementacje przeprowadzają sprawdzanie słabych kluczy wymagane przez FIPS, czyli odrzucają klucze XTS, których pierwsza i druga połowa są równe.
gcm(aes) gcm (szablon), gcm-aes-ce Nie1 AES-GCM: obsługiwane są wszystkie rozmiary kluczy AES. Obsługiwane są tylko 96-bitowe wektory inicjujące. Podobnie jak w przypadku wszystkich innych trybów AES w tym module, wywołujący odpowiada za podanie wektorów inicjujących. Szablon gcm można tworzyć z dowolnych implementacji ctr(aes)ghash za pomocą gcm_base(<ctr(aes)-impl>,<ghash-impl>). Pozostałe implementacje są samodzielne.
sha1 sha1-generic, sha1-ce Tak funkcja skrótu SHA-1,
sha224 sha224-generic, sha224-arm64, sha224-ce Tak Funkcja szyfrowania SHA-224: kod jest udostępniany w ramach SHA-256.
sha256 sha256-generic, sha256-arm64, sha256-ce, biblioteka SHA-256 Tak Funkcja szyfrowania SHA-256: oprócz standardowego interfejsu CryptoAPI udostępniany jest interfejs biblioteki SHA-256. Ten interfejs biblioteki korzysta z innej implementacji.
sha384 sha384-generic, sha384-arm64, sha384-ce Tak Funkcja kryptograficzna SHA-384: kod jest udostępniany z SHA-512.
sha512 sha512-generic, sha512-arm64, sha512-ce Tak funkcja skrótu SHA-512,
sha3-224 sha3-224-generic Tak funkcja skrótu SHA3-224, Dostępne tylko w jądrze w wersji 6.6 i nowszej.
sha3-256 sha3-256-generic Tak Podobnie jak wyżej, ale z 256-bitową długością skrótu (SHA3-256). Wszystkie długości skrótu korzystają z tej samej implementacji Keccak.
sha3-384 sha3-384-generic Tak Podobnie jak poprzednia, ale z długością skrótu 384 bity (SHA3-384). Wszystkie długości skrótu korzystają z tej samej implementacji Keccak.
sha3-512 sha3-512-generic Tak Podobnie jak poprzednio, ale z długością skrótu 512 bitów (SHA3-512). Wszystkie długości skrótu korzystają z tej samej implementacji Keccak.
hmac hmac (szablon) Tak HMAC (Keyed-Hash Message Authentication Code): szablon hmac można utworzyć za pomocą dowolnego algorytmu SHA lub implementacji z użyciem hmac(<sha-alg>) lub hmac(<sha-impl>).
stdrng drbg_pr_hmac_sha1, drbg_pr_hmac_sha256, drbg_pr_hmac_sha384, drbg_pr_hmac_sha512 Tak Algorytm HMAC_DRBG utworzony z funkcją skrótu o podanej nazwie i z włączoną odpornością na przewidywanie: obejmuje testy stanu. Użytkownicy tego interfejsu otrzymują własne instancje DRBG.
stdrng drbg_nopr_hmac_sha1, drbg_nopr_hmac_sha256, drbg_nopr_hmac_sha384, drbg_nopr_hmac_sha512 Tak Takie same jak algorytmy drbg_pr_*, ale z wyłączoną odpornością na przewidywanie. Kod jest udostępniany w wersji odpornej na prognozowanie. W jądrze w wersji 5.10 DRBG o najwyższym priorytecie to drbg_nopr_hmac_sha256. W jądrze w wersji 5.15 i nowszych jest to drbg_pr_hmac_sha512.
jitterentropy_rng jitterentropy_rng Nie Jitter RNG w wersji 2.2.0 (jądro w wersji 6.1 i starszej) lub 3.4.0 (jądro w wersji 6.6 i nowszej). Użytkownicy tego interfejsu otrzymują własne instancje Jitter RNG. Nie używają ponownie instancji, z których korzystają DRBG.
xcbc(aes) xcbc-aes-neon, xcbc-aes-ce Nie
xctr(aes) xctr-aes-neon, xctr-aes-ce Nie Dostępne tylko w jądrze w wersji 5.15 i nowszych.
cbcmac(aes) cbcmac-aes-neon, cbcmac-aes-ce Nie
essiv(cbc(aes),sha256) essiv-cbc-aes-sha256-neon, essiv-cbc-aes-sha256-ce Nie

Kompilowanie modułu ze źródła

W przypadku Androida 14 i nowszych wersji (w tym android-mainline) skompiluj moduł fips140.ko ze źródeł, używając tych poleceń:

  • Tworzenie za pomocą Bazel:

    tools/bazel run //common:fips140_dist
  • Utwórz za pomocą build.sh (starsza wersja):

    BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh

Te polecenia wykonują pełną kompilację, w tym jądro i fips140.komoduł z osadzonymi w nim treściami skrótu HMAC-SHA256.

Wskazówki dla użytkowników

Wskazówki dla Crypto Officer

Aby moduł jądra działał, system operacyjny musi być ograniczony do trybu pracy z jednym operatorem. Android obsługuje to automatycznie za pomocą sprzętu do zarządzania pamięcią w procesorze.

Modułu jądra nie można zainstalować osobno. Jest on częścią oprogramowania urządzenia i jest ładowany automatycznie podczas uruchamiania. Działa tylko w zatwierdzonym trybie pracy.

Funkcjonariusz ds. kryptografii może w dowolnym momencie uruchomić autotesty, ponownie uruchamiając urządzenie.

Wytyczne dla użytkowników

Użytkownikami modułu jądra są inne komponenty jądra, które muszą korzystać z algorytmów kryptograficznych. Moduł jądra nie zapewnia dodatkowej logiki w zakresie korzystania z algorytmów i nie przechowuje żadnych parametrów poza czasem potrzebnym do wykonania operacji kryptograficznej.

Używanie algorytmów na potrzeby zgodności z FIPS jest ograniczone do zatwierdzonych algorytmów. Aby spełnić wymaganie „wskaźnika usługi” określone w standardzie FIPS 140-3, moduł udostępnia funkcję fips140_is_approved_service, która wskazuje, czy algorytm jest zatwierdzony.

Błędy autotestu

W przypadku niepowodzenia autotestu moduł jądra powoduje panikę jądra, a urządzenie nie kontynuuje rozruchu. Jeśli ponowne uruchomienie urządzenia nie rozwiąże problemu, należy uruchomić urządzenie w trybie odzyskiwania, aby naprawić problem przez ponowne wgranie oprogramowania.


  1. Oczekuje się, że implementacje AES-GCM w module mogą być „zatwierdzone pod względem algorytmu”, ale nie „zatwierdzone pod względem modułu”. Można je zweryfikować, ale z punktu widzenia modułu FIPS algorytmu AES-GCM nie można uznać za zatwierdzony. Dzieje się tak, ponieważ wymagania modułu FIPS dotyczące GCM są niezgodne z implementacjami GCM, które nie generują własnych wektorów inicjujących.