Rdzeń GKI zawiera moduł jądra systemu Linux 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 można używać procedur szyfrowania, należy spełnić te wymagania FIPS 140-3:
- Zanim udostępni algorytmy szyfrowania, moduł musi sprawdzić własną integralność.
- Zanim udostępnisz zatwierdzone algorytmy kryptograficzne, musisz je przetestować i sprawdzać za pomocą testów samokontroli z znanymi odpowiedziami.
Dlaczego oddzielny moduł jądra
Weryfikacja FIPS 140-3 opiera się na założeniu, że raz certyfikowany moduł oparty na oprogramowaniu lub sprzęcie nigdy nie ulega zmianie. Jeśli zmienisz dane, musisz je ponownie zatwierdzić. Nie jest to zgodne z obecnie stosowanymi procesami rozwoju oprogramowania. W rezultacie moduły oprogramowania FIPS są zazwyczaj tak zaprojektowane, aby jak najściślej skupiały się na komponentach kryptograficznych, co zapewnia, że zmiany niezwiązane z kryptografia nie wymagają ponownej oceny kryptografii.
Rdzenie GKI mają być regularnie aktualizowane przez cały okres obsługi. Z tego powodu nie jest możliwe, aby cały kernel mieścił się w ramach modułu FIPS, ponieważ taki moduł musiałby być ponownie certyfikowany po każdej aktualizacji jądra. Zdefiniowanie „modułu FIPS” jako podzbioru obrazu jądra ograniczyłoby ten problem, ale nie rozwiązałoby go, ponieważ zawartość binarna „modułu FIPS” nadal zmieniałaby się znacznie częściej niż to konieczne.
Przed wersją jądra 6.1 brano pod uwagę również to, że GKI został skompilowany z włączoną optymalizacją w czasie łączenia (LTO), ponieważ LTO było warunkiem wstępnym dla kontroli integralności przepływu, która jest ważną funkcją zabezpieczeń.
Dlatego cały kod objęty wymaganiami FIPS 140-3 jest pakowany w oddzielny moduł jądra fips140.ko
, który korzysta tylko ze stabilnych interfejsów udostępnionych przez źródło jądra GKI, z którego został skompilowany. Oznacza to, że moduł może być używany z różnymi wersjami GKI tej samej generacji i że musi zostać zaktualizowany i ponownie przesłany do certyfikacji tylko wtedy, gdy w kodzie, który jest zawarty w samym module, zostały poprawione jakieś problemy.
Kiedy używać modułu
Kernel GKI zawiera kod, który zależy od procedur szyfrowania, które są również spakowane w moduł jądra FIPS 140-3. Wbudowane procedury szyfrowania nie są więc przenoszone z rdzenia GKI, tylko kopiowane do modułu. Gdy moduł zostanie załadowany, wbudowane procedury szyfrowania zostaną usunięte z CryptoAPI Linux i zastąpione przez te, które są zawarte w module.
Oznacza to, że moduł fips140.ko
jest całkowicie opcjonalny i należy go wdrożyć tylko wtedy, gdy certyfikat FIPS 140-3 jest wymagany. Poza tym moduł nie zapewnia żadnych dodatkowych funkcji, a jego niepotrzebne wczytywanie może wpłynąć na czas uruchamiania bez żadnej korzyści.
Jak wdrożyć moduł
Aby włączyć moduł w kompilacji Androida, wykonaj te czynności:
- Dodaj nazwę modułu do
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
. Spowoduje to skopiowanie modułu na dysk RAM dostawcy. - Dodaj nazwę modułu do
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
. W efekcie nazwa modułu zostanie dodana do elementumodules.load
w docelowym elemencie.modules.load
zawiera listę modułów wczytywanych przezinit
podczas uruchamiania urządzenia.
Sprawdzanie integralności
Moduł jądra FIPS 140-3 pobiera podczas wczytywania modułu skrót HMAC-SHA256 własnych sekcji .code
i .rodata
, a następnie porównuje go ze skrótem zapisanym w module. Dzieje się tak po tym, jak ładowarka modułów Linuxa wprowadziła już typowe modyfikacje, takie jak przetwarzanie przeniesienia ELF i łatki alternatywne dla poprawek procesora w tych sekcjach. Aby zapewnić prawidłowe odtworzenie podsumowania, należy wykonać te dodatkowe czynności:
- Przekierowania ELF są zachowane w module, aby można było zastosować je w odwrotnej kolejności do danych wejściowych funkcji HMAC.
- Moduł odwraca wszystkie poprawki kodu wprowadzone przez jądro dla dynamicznego stosu wywołań cienia. W szczególności moduł zastępuje wszystkie instrukcje, które wpycha lub wypycha z cienia stosu wywołań, instrukcjami kodu uwierzytelniania wskaźnika (PAC), które były obecne pierwotnie.
- W przypadku modułu wyłączone jest wszelkie inne poprawianie kodu, w tym klucze statyczne i punkty śledzenia, a także elementy dostawcy.
testy samodzielne z znanymi odpowiedziami.
Wdrożone algorytmy, które podlegają wymaganiom FIPS 140-3, muszą przed użyciem wykonać test samokontroli z znanymi odpowiedziami. Zgodnie z FIPS 140-3 Wskazówki dotyczące implementacji 10.3.A, jeden wektor testowy na algorytm, który używa dowolnej obsługiwanej długości klucza, wystarcza do szyfrowania, o ile testowane jest zarówno szyfrowanie, jak i odszyfrowywanie.
Interfejs CryptoAPI w Linuxie zawiera algorytmy o różnych priorytetach, w ramach których może współistnieć kilka implementacji tego samego algorytmu (np. jedna z użyciem specjalnych instrukcji szyfrowania i awaryjne dla procesorów, które nie obsługują tych instrukcji). Dlatego trzeba przetestować wszystkie implementacje tego samego algorytmu. Jest to konieczne, ponieważ interfejs CryptoAPI systemu Linux 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:
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
, ale w stosownych przypadkach są też podane różnice między wersjami jądra.
Algorytm | Implementacje | zatwierdzone, | 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, 192 i 256 bitów). Wszystkie implementacje inne niż implementacja biblioteki można tworzyć 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że być komponowany z dowolną implementacją aes za pomocą cmac(<aes-impl>) . Inne 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że być komponowany z dowolną implementacją aes za pomocą ecb(<aes-impl>) . Inne 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że być komponowany z dowolną implementacją aes za pomocą ctr(<aes-impl>) . Inne implementacje są samodzielne. |
cts(cbc(aes)) |
cts (szablon), cts-cbc-aes-neon , cts-cbc-aes-ce |
Tak | AES-CBC-CTS lub AES-CBC z kradzieżą tekstu zaszyfrowanego: użyta konwencja to CS3 ; 2 końcowe bloki tekstu zaszyfrowanego są zamieniane bezwarunkowo. Obsługiwane są wszystkie rozmiary kluczy AES. Szablon cts można tworzyć z dowolną implementacją cbc za pomocą cts(<cbc(aes)-impl>) . Inne 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że być komponowany z dowolną implementacją aes za pomocą ctr(<aes-impl>) . Inne implementacje są samodzielne. |
xts(aes) |
xts (szablon), xts-aes-neon , xts-aes-neonbs , xts-aes-ce |
Tak | AES-XTS: w jądrze w wersji 6.1 i starszych obsługiwane są wszystkie rozmiary klucza AES; w jądrze w wersji 6.6 i nowszych obsługiwane są tylko AES-128 i AES-256. Szablon xts może być komponowany z dowolną implementacją ecb(aes) za pomocą xts(<ecb(aes)-impl>) . Inne implementacje są samodzielne. Wszystkie implementacje implementują 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 klucza AES. Obsługiwane są tylko 96-bitowe tablice haseł. Podobnie jak w przypadku wszystkich innych trybów AES w tym module, wywołujący jest odpowiedzialny za podanie IV. Szablon gcm może być łączony z dowolnymi implementacjami interfejsów ctr(aes) i ghash za pomocą gcm_base(<ctr(aes)-impl>,<ghash-impl>) . Inne implementacje są samodzielne. |
sha1 |
sha1-generic , sha1-ce |
Tak | Funkcja kryptograficzna SHA-1 |
sha224 |
sha224-generic , sha224-arm64 , sha224-ce |
Tak | Funkcja kryptograficznego szyfrowania SHA-224: kod jest taki sam jak w przypadku SHA-256. |
sha256 |
sha256-generic , sha256-arm64 , sha256-ce , biblioteka SHA-256 |
Tak | Funkcja kryptograficznego szyfrowania SHA-256: oprócz standardowego interfejsu CryptoAPI udostępniamy interfejs biblioteki do SHA-256. Ten interfejs biblioteki korzysta z innej implementacji. |
sha384 |
sha384-generic , sha384-arm64 , sha384-ce |
Tak | Funkcja szyfrowania SHA-384: kod jest taki sam jak w przypadku SHA-512. |
sha512 |
sha512-generic , sha512-arm64 , sha512-ce |
Tak | Funkcja kryptograficzna SHA-512 |
sha3-224 |
sha3-224-generic |
Tak | Funkcja kryptograficzna SHA3-224. Dostępne tylko w jądrze w wersji 6.6 i nowszej. |
sha3-256 |
sha3-256-generic |
Tak | To samo co poprzednie, ale z 256-bitową długością skrótu (SHA3-256). Wszystkie długości skrótów używają tego samego algorytmu Keccak. |
sha3-384 |
sha3-384-generic |
Tak | To samo co poprzednie, ale z 384-bitową długością wynikowego ciągu znaków (SHA3-384). Wszystkie długości skrótów używają tego samego algorytmu Keccak. |
sha3-512 |
sha3-512-generic |
Tak | To samo co poprzednie, ale z 512-bitową długością cząstki (SHA3-512). Wszystkie długości skrótów używają tego samego algorytmu Keccak. |
hmac |
hmac (szablon) |
Tak | HMAC (kluczowy kod uwierzytelniania wiadomości oparty na wartościach hash): szablon hmac może być skompilowany z dowolnym algorytmem SHA lub jego implementacją za pomocą 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 | HMAC_DRBG instancjalizowany za pomocą nazwanej funkcji szyfrowania i z włączoną odpornością na przewidywanie: uwzględniono sprawdzanie 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 | To samo co algorytmy drbg_pr_* , ale z wyłączoną odpornością na prognozowanie. Kod jest udostępniany z wariantem odpornym na przewidywanie. W jądrze w wersji 5.10 DRBG o najwyższym priorytecie to drbg_nopr_hmac_sha256 . W wersji jądra 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 lub starszej) lub 3.4.0 (jądro w wersji 6.6 lub nowszej). Użytkownicy tego interfejsu otrzymują własne instancje Jitter RNG. Nie używają ponownie instancji używanych przez DRBG. |
xcbc(aes) |
xcbc-aes-neon , xcbc-aes-ce |
Nie | |
xctr(aes) |
xctr-aes-neon , xctr-aes-ce |
Nie | Jest dostępny 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 na podstawie kodu źródłowego
W przypadku Androida 14 lub nowszego (w tym android-mainline
) skompiluj moduł fips140.ko
ze źródła, używając tych poleceń.
Tworzenie za pomocą Bazel:
tools/bazel run //common:fips140_dist
Tworzenie za pomocą
build.sh
(starsza wersja):BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
Te polecenia wykonują pełne kompilowanie, w tym jądro i moduł fips140.ko
z zawartą w nich zawartością treści HMAC-SHA256.
Wskazówki dla użytkowników
Wskazówki dla oficera ds. kryptowalut
Aby moduł jądra mógł działać, system operacyjny musi być ograniczony do trybu pojedynczego operatora. Android automatycznie zarządza tym za pomocą sprzętu do zarządzania pamięcią w procesorze.
Moduł jądra nie może być instalowany osobno. Jest on częścią oprogramowania urządzenia i ładowany automatycznie podczas uruchamiania. Działa tylko w zatwierdzonych trybach działania.
Osoba odpowiedzialna za bezpieczeństwo kryptowalut może w każdej chwili uruchomić autotesty, ponownie uruchamiając urządzenie.
Wskazówki dla użytkowników
Użytkownikami modułu jądra są inne komponenty jądra, które muszą używać algorytmów kryptograficznych. Moduł jądra nie zapewnia dodatkowej logiki w użyciu algorytmów i nie przechowuje żadnych parametrów poza czasem potrzebnym do wykonania operacji kryptograficznej.
Korzystanie z algorytmów na potrzeby zgodności z FIPS jest ograniczone do zatwierdzonych algorytmów. Aby spełnić wymóg FIPS 140-3 dotyczący „wskaźnika usługi”, moduł udostępnia funkcję fips140_is_approved_service
, która wskazuje, czy algorytm został zatwierdzony.
Błędy autotestu
W przypadku niepowodzenia autotestu moduł jądra powoduje panikę jądra, a urządzenie nie uruchamia się. Jeśli ponowne uruchomienie urządzenia nie rozwiąże problemu, konieczne jest uruchomienie urządzenia w trybie odzyskiwania, aby rozwiązać problem przez ponowne zaflashowanie urządzenia.
-
Oczekuje się, że implementacje AES-GCM modułu mogą być „zatwierdzone przez algorytm”, ale nie „zatwierdzone przez moduł”. Można je weryfikować, ale AES-GCM nie jest uznawany za zatwierdzony algorytm z poziomu modułu FIPS. Dzieje się tak, ponieważ wymagania dotyczące modułu FIPS dla GCM są niezgodne z wdrożeniami GCM, które nie generują własnych IV. ↩