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 domodules.load
w miejscu docelowym.modules.load
zawiera listę modułów, które są wczytywane przezinit
podczas uruchamiania urządzenia.
Sprawdzanie integralności
Moduł jądra FIPS 140-3 oblicza skrót HMAC-SHA256 własnych sekcji .code
i .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.1
i android15-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) i 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.ko
moduł 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.
-
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. ↩