Moduł kryptograficzny GKI z certyfikatem FIPS 140-3

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

W szczególności następujące wymagania FIPS 140-3 muszą być spełnione przed użyciem procedur kryptograficznych:

  • Moduł musi sprawdzić swoją integralność przed udostępnieniem algorytmów kryptograficznych.
  • Moduł musi przetestować i zweryfikować zatwierdzone algorytmy kryptograficzne za pomocą autotestów ze znaną odpowiedzią przed ich udostępnieniem.

Dlaczego osobny moduł jądra

Walidacja FIPS 140-3 opiera się na założeniu, że raz certyfikowany moduł programowy lub sprzętowy nigdy nie jest zmieniany. W przypadku zmiany należy dokonać ponownej certyfikacji. Nie odpowiada to łatwo stosowanym obecnie procesom tworzenia oprogramowania, a w wyniku tego wymogu moduły oprogramowania FIPS są generalnie projektowane tak, aby były jak najbardziej skoncentrowane na komponentach kryptograficznych, aby zapewnić, że zmiany niezwiązane z kryptografią nie nie wymagają ponownej oceny kryptografii.

Jądro GKI ma być regularnie aktualizowane przez cały obsługiwany okres eksploatacji. To sprawia, że ​​​​niemożliwe jest, aby całe jądro mieściło się w granicach modułu FIPS, ponieważ taki moduł musi być ponownie certyfikowany przy każdej aktualizacji jądra. Ponadto GKI jest kompilowany z włączonym LTO (Link Time Optimization), ponieważ LTO jest warunkiem wstępnym dla CFI , który jest ważną funkcją bezpieczeństwa. To sprawia, że ​​​​niewykonalne jest narysowanie granicy modułu FIPS tylko wokół kodu kryptograficznego jądra, ponieważ taki kod nie znajduje się w jasno określonym miejscu w wynikowym pliku binarnym. Aktualizacje jądra mogą również zmienić kod kryptograficzny.

Dlatego cały kod objęty wymaganiami FIPS 140-3 jest pakowany w oddzielny moduł jądra fips140.ko , który opiera się tylko na stabilnych interfejsach ujawnionych przez źródło jądra GKI, z którego został zbudowany. Gwarantuje to, że moduł może być używany z różnymi wersjami GKI tej samej generacji oraz że musi być aktualizowany i ponownie przesyłany do certyfikacji tylko wtedy, gdy jakiekolwiek problemy zostały naprawione w kodzie przenoszonym przez sam moduł.

Kiedy używać modułu

Samo jądro GKI zawiera kod zależny od procedur kryptograficznych, które są również spakowane w module jądra FIPS 140-3. Dlatego wbudowane procedury kryptograficzne nie są w rzeczywistości przenoszone z jądra GKI, ale raczej kopiowane do modułu. Gdy moduł jest ładowany, wbudowane procedury kryptograficzne są wyrejestrowywane z interfejsu Linux CryptoAPI i zastępowane przez te, które są dostępne w module.

Oznacza to, że moduł fips140.ko jest całkowicie opcjonalny i jego wdrożenie ma sens tylko wtedy, gdy wymagana jest certyfikacja FIPS 140-3. Poza tym moduł nie zapewnia żadnych dodatkowych funkcji, a niepotrzebne ładowanie może tylko wpłynąć na czas rozruchu, nie zapewniając żadnych korzyści.

Jak wdrożyć moduł

Moduł można włączyć do kompilacji Androida, wykonując następujące czynności:

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

Samokontrola integralności

Moduł jądra FIPS 140-3 pobiera skrót HMAC-SHA256 własnych .code i .rodata w czasie ładowania modułu i porównuje go ze skrótem zarejestrowanym w module. Ma to miejsce po tym, jak program ładujący moduł Linuksa dokonał już zwykłych modyfikacji, takich jak przetwarzanie relokacji ELF i łatanie alternatywnych errat procesora w tych sekcjach. Podejmowane są następujące dodatkowe kroki, aby zapewnić prawidłowe odtworzenie skrótu:

  • Relokacje ELF są zachowywane wewnątrz modułu, dzięki czemu można je zastosować w odwrotnej kolejności do danych wejściowych HMAC.
  • Wszystkie inne poprawki kodu są wyłączone dla modułu, w tym klucze statyczne, a zatem punkty śledzenia, a także punkty zaczepienia dostawcy.

Testy ze znaną odpowiedzią

Wszelkie zaimplementowane algorytmy, które są objęte wymaganiami FIPS 140-3, muszą przed użyciem wykonać autotest ze znaną odpowiedzią. Zgodnie z FIPS 140-3 Implementation Guidance 10.3.A , pojedynczy wektor testowy na algorytm używający dowolnej obsługiwanej długości klucza jest wystarczający dla szyfrów, o ile testowane jest zarówno szyfrowanie, jak i deszyfrowanie.

Linux CryptoAPI ma pojęcie priorytetów algorytmów, w których może współistnieć kilka implementacji (takich jak jedna używająca specjalnych instrukcji kryptograficznych i rezerwa dla procesorów, które nie implementują tych instrukcji) tego samego algorytmu. Istnieje więc potrzeba przetestowania wszystkich implementacji tego samego algorytmu. Jest to konieczne, ponieważ Linux CryptoAPI pozwala na ominięcie wyboru opartego na priorytecie i zamiast tego wybranie algorytmu o niższym priorytecie.

Algorytmy zawarte w module

Wszystkie algorytmy, które są zawarte w module FIPS 140-3, gdy są zbudowane ze źródeł Android13-5.10, są wymienione poniżej.

Algorytm Implementacje Zatwierdzone Definicja
aes aes-generic , aes-arm64 , aes-ce , biblioteka AES TAk Zwykły 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 biblioteczna mogą być złożone z trybem działania poprzez szablon.
cmac(aes) cmac (szablon), cmac-aes-neon , cmac-aes-ce TAk AES-CMAC: Obsługiwane są wszystkie rozmiary kluczy AES. Szablon cmac można skomponować z dowolną implementacją aes przy użyciu 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 skomponować z dowolną implementacją aes przy użyciu ecb(<aes-impl>) . Pozostałe implementacje są samodzielne.
cbc(aes) cbc (szablon), cbc-aes-neon , cbc-aes-neonbs , cbc cbc-aes-ce TAk AES-CBC: Obsługiwane są wszystkie rozmiary kluczy AES. Szablon cbc można skomponować z dowolną implementacją aes przy użyciu 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 kradzieżą tekstu zaszyfrowanego: stosowana konwencja to CS3 ; ostatnie dwa bloki tekstu zaszyfrowanego są wymieniane bezwarunkowo. Obsługiwane są wszystkie rozmiary kluczy AES. Szablon cts można skomponować z dowolną implementacją cbc przy użyciu 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 skomponować z dowolną implementacją aes przy użyciu ctr(<aes-impl>) . Pozostałe implementacje są samodzielne.
xts(aes) xts (szablon), xts-aes-neon , xts-aes-neonbs , xts-aes-ce TAk AES-XTS: Obsługiwane są wszystkie rozmiary kluczy AES. Szablon xts można skomponować z dowolną implementacją ecb(aes) przy użyciu xts(<ecb(aes)-impl>) . Pozostałe implementacje są samodzielne. Wszystkie implementacje implementują kontrolę słabego klucza wymaganą przez FIPS; to znaczy klucze XTS, których pierwsza i druga połowa są równe, są odrzucane.
gcm(aes) gcm (szablon), gcm-aes-ce nr 1 AES-GCM: Obsługiwane są wszystkie rozmiary kluczy AES. Obsługiwane są tylko 96-bitowe pliki IV. Podobnie jak w przypadku wszystkich innych trybów AES w tym module, osoba dzwoniąca jest odpowiedzialna za dostarczenie IV. Szablon gcm można skomponować z dowolnymi implementacjami ctr(aes) i ghash przy użyciu gcm_base(<ctr(aes)-impl>,<ghash-impl>) . Pozostałe implementacje są samodzielne.
sha1 sha1-generic , sha1-ce TAk Kryptograficzna funkcja skrótu SHA-1
sha224 sha224-generic , sha224-arm64 , sha224-ce TAk Kryptograficzna funkcja skrótu SHA-224: kod jest współdzielony z SHA-256.
sha256 sha256-generic , sha256-arm64 , sha256-ce , biblioteka SHA-256 TAk Kryptograficzna funkcja skrótu SHA-256: oprócz tradycyjnego interfejsu CryptoAPI do SHA-256 dodano interfejs biblioteki. Ten interfejs biblioteki używa innej implementacji.
sha384 sha384-generic , sha384-arm64 , sha384-ce TAk Kryptograficzna funkcja skrótu SHA-384: kod jest współdzielony z SHA-512.
sha512 sha512-generic , sha512-arm64 , sha512-ce TAk Kryptograficzna funkcja skrótu SHA-512
hmac hmac (szablon) TAk HMAC (Keyed-Hash Message Authentication Code): szablon hmac można skomponować z dowolnym algorytmem SHA lub implementacją przy użyciu 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 Utworzono instancję HMAC_DRBG z nazwaną funkcją skrótu i ​​z włączoną odpornością na predykcję: uwzględniono kontrole kondycji. 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 Tak samo jak algorytmy drbg_pr_* , ale z wyłączoną odpornością na predykcję. Kod jest współdzielony z wariantem odpornym na przewidywania. DRBG o najwyższym priorytecie to drbg_nopr_hmac_sha256 .
jitterentropy_rng jitterentropy_rng Nie Wersja 2.2.0 Jitter RNG : 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
cbcmac(aes) cbcmac-aes-neon , cbcmac-aes-ce Nie
essiv(cbc(aes),sha256) essiv-cbc-aes-sha256-neon , essiv-cbc-aes-sha256-ce Nie

Budowanie modułu ze źródła

Moduł fips140.ko można zbudować ze źródeł jądra GKI za pomocą następującego polecenia:

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

Wykonuje to pełną kompilację z jądrem i modułem fips140.ko , z osadzonym poprawnym skrótem HMAC-SHA256 jego zawartości.

W systemie Android 14 (eksperymentalny AOSP) i nowszych zbuduj z Bazel zamiast build/build.sh za pomocą następującego polecenia:

tools/bazel run //common:fips140_dist

Wskazówki dla użytkownika końcowego

Wskazówki dotyczące oficera ds. kryptografii

Aby obsługiwać moduł jądra, system operacyjny musi być ograniczony do trybu pracy jednego operatora. Jest to obsługiwane automatycznie przez system Android przy użyciu sprzętu do zarządzania pamięcią w procesorze.

Moduł jądra nie może być zainstalowany oddzielnie; jest dołączony jako część oprogramowania układowego urządzenia i ładowany automatycznie podczas rozruchu. Działa tylko w zatwierdzonym trybie pracy.

Crypto Officer może w dowolnym momencie uruchomić autotesty poprzez ponowne uruchomienie urządzenia.

Wskazówki dla użytkownika

Użytkownikiem 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 korzystaniu z algorytmów i nie przechowuje żadnych parametrów poza czasem potrzebnym do wykonania operacji kryptograficznej.

Korzystanie z algorytmów w celu zapewnienia zgodności ze standardem FIPS jest ograniczone do zatwierdzonych algorytmów. Aby spełnić wymagania FIPS 140-3 dotyczące „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 i urządzenie nie kontynuuje uruchamiania. Jeśli ponowne uruchomienie urządzenia nie rozwiąże problemu, urządzenie musi uruchomić się w trybie odzyskiwania, aby rozwiązać problem przez ponowne flashowanie urządzenia.


  1. Oczekuje się, że implementacje modułu AES-GCM mogą być „zatwierdzone przez algorytm”, ale nie „zatwierdzone przez moduł”. Można je zweryfikować, ale algorytmu AES-GCM nie można uznać za zatwierdzony z punktu widzenia modułu FIPS. Wynika to z faktu, że wymagania modułu FIPS dla GCM są niezgodne z implementacjami GCM, które nie generują własnych IV.