Moduł kryptograficzny GKI z certyfikatem FIPS 140-3

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 elementu modules.load w docelowym elemencie. modules.load zawiera listę modułów wczytywanych przez init 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.1android15-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)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.koz 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.


  1. 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.