O kernel do GKI inclui um
módulo do kernel do Linux chamado fips140.ko
, que está em conformidade com os
requisitos do FIPS 140-3
para módulos de software criptográfico. Este módulo pode ser enviado para a certificação
FIPS se o produto que executa o kernel do GKI exigir isso.
Os seguintes requisitos do FIPS 140-3 precisam ser atendidos antes que as rotinas de criptografia possam ser usadas:
- O módulo precisa verificar a própria integridade antes de disponibilizar algoritmos criptográficos.
- O módulo precisa exercitar e verificar os algoritmos criptográficos aprovados usando autotestes de resposta conhecida antes de disponibilizá-los.
Por que um módulo de kernel separado
A validação FIPS 140-3 baseia-se na ideia de que, depois que um módulo baseado em software ou hardware é certificado, ele nunca é alterado. Se for alterado, ele precisará ser recertificado. Isso não corresponde aos processos de desenvolvimento de software em uso atualmente. Como resultado desse requisito, os módulos de software FIPS são geralmente projetados para se concentrarem o máximo possível nos componentes criptográficos, para garantir que as mudanças que não estão relacionadas à criptografia não exijam uma reavaliação dela.
O kernel do GKI é atualizado regularmente durante toda a vida útil de suporte. Isso torna inviável que todo o kernel esteja dentro do limite do módulo FIPS, já que esse módulo precisaria ser recertificado em cada atualização do kernel. Definir o "módulo FIPS" como um subconjunto da imagem do kernel atenuaria esse problema, mas não o resolveria, já que o conteúdo binário do "módulo FIPS" ainda mudaria com muito mais frequência que o necessário.
Antes da versão 6.1 do kernel, outra consideração era que a GKI era compilada com a otimização de tempo de vinculação (LTO, na sigla em inglês) ativada, já que a LTO era um pré-requisito da Integridade do fluxo de controle, que é um recurso de segurança importante.
Portanto, todo o código coberto pelos requisitos do FIPS 140-3 é empacotado
em um módulo de kernel fips140.ko
separado, que depende apenas de interfaces estáveis
exibidas pela fonte do kernel da GKI em que foi criado. Isso
significa que o módulo pode ser usado com diferentes versões do GKI da mesma
geração e que ele precisa ser atualizado e reenviado para certificação somente
se algum problema foi corrigido no código que é transmitido pelo próprio módulo.
Quando usar o módulo
O kernel do GKI carrega um código que depende das rotinas de criptografia que também são empacotadas no módulo do kernel FIPS 140-3. Portanto, as rotinas criptográficas integradas não são movidas para fora do kernel do GKI, mas são copiadas para o módulo. Quando o módulo é carregado, as rotinas criptográficas integradas são desregistradas da Linux CryptoAPI e substituídas pelas que são transmitidas pelo módulo.
Isso significa que o módulo fips140.ko
é totalmente opcional e só faz
sentido implantá-lo se a certificação FIPS 140-3 for um requisito. Além disso,
o módulo não oferece recursos adicionais, e carregá-lo desnecessariamente
pode afetar o tempo de inicialização, sem nenhum benefício.
Como implantar o módulo
O módulo pode ser incorporado ao build do Android seguindo estas etapas:
- Adicione o nome do módulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
. Isso faz com que o módulo seja copiado para o ramdisk do fornecedor. - Adicione o nome do módulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
. Isso faz com que o nome do módulo seja adicionado amodules.load
no destino.modules.load
contém a lista de módulos que são carregados porinit
quando o dispositivo é inicializado.
Autoverificação de integridade
O módulo do kernel FIPS 140-3 usa o resumo HMAC-SHA256 das próprias seções .code
e .rodata
no momento do carregamento do módulo e o compara com o resumo
registrado no módulo. Isso ocorre depois que o carregador de módulos do Linux
já fez as modificações usuais, como processamento de realocação de ELF e
patches alternativos para errata da CPU nessas seções. As etapas a seguir
são tomadas para garantir que o resumo possa ser reproduzido
corretamente:
- As relocalizações ELF são preservadas dentro do módulo para que possam ser aplicadas de forma inversa à entrada do HMAC.
- O módulo reverte todos os patches de código feitos pelo kernel para a pilha de chamadas de sombra dinâmica. Especificamente, o módulo substitui todas as instruções enviadas ou destacadas da pilha de chamadas paralelas pelas instruções do código de autenticação do ponteiro (PAC, na sigla em inglês) que estavam presentes originalmente.
- Todos os outros ajustes de código são desativados para o módulo, incluindo chaves estáticas e tracepoints, além de hooks de fornecedores.
Autotestes de resposta conhecida
Todos os algoritmos implementados que são cobertos pelos requisitos do FIPS 140-3 precisam realizar um autoteste de resposta conhecida antes de serem usados. De acordo com a orientação de implementação 10.3.A do FIPS 140-3, um único vetor de teste por algoritmo usando qualquer uma das chaves de tamanhos compatíveis é suficiente para cifras, desde que a criptografia e a descriptografia sejam testadas.
A Linux CryptoAPI tem uma noção de prioridades de algoritmo, em que várias implementações do mesmo algoritmo podem coexistir, como uma que usa instruções de criptografia especiais e um substituto para CPUs que não implementam essas instruções. Portanto, é necessário testar todas as implementações do mesmo algoritmo. Isso é necessário porque a Linux CryptoAPI permite que a seleção com base na prioridade seja ignorada e que um algoritmo de prioridade mais baixa seja selecionado.
Algoritmos incluídos no módulo
Todos os algoritmos incluídos no módulo FIPS 140-3 são listados da seguinte maneira.
Isso se aplica às ramificações de kernel android12-5.10
, android13-5.10
, android13-5.15
,
android14-5.15
, android14-6.1
e android15-6.6
, embora
as diferenças entre as versões do kernel sejam observadas quando apropriado.
Algoritmo | Implementações | Aprovável | Definição |
---|---|---|---|
aes |
aes-generic , aes-arm64 , aes-ce , biblioteca AES |
Sim | Criptografia de bloco AES simples, sem modo de operação: todos os tamanhos de chave (128 bits, 192 bits e 256 bits) são compatíveis. Todas as implementações, exceto a da biblioteca, podem ser compostas com um modo de operação usando um modelo. |
cmac(aes) |
cmac (modelo), cmac-aes-neon , cmac-aes-ce |
Sim | AES-CMAC: todos os tamanhos de chave AES são aceitos. O modelo cmac pode ser composto com qualquer implementação de aes usando cmac(<aes-impl>) . As outras implementações são independentes. |
ecb(aes) |
ecb (modelo), ecb-aes-neon , ecb-aes-neonbs , ecb-aes-ce |
Sim | AES-ECB: todos os tamanhos de chave AES são aceitos. O modelo ecb pode ser composto com qualquer implementação de aes usando ecb(<aes-impl>) . As outras implementações são independentes. |
cbc(aes) |
cbc (modelo), cbc-aes-neon , cbc-aes-neonbs , cbc-aes-ce |
Sim | AES-CBC: todos os tamanhos de chave AES são aceitos. O modelo cbc pode ser composto com qualquer implementação de aes usando ctr(<aes-impl>) . As outras implementações são independentes. |
cts(cbc(aes)) |
cts (modelo), cts-cbc-aes-neon , cts-cbc-aes-ce |
Sim | AES-CBC-CTS ou AES-CBC com roubo de texto criptografado: a convenção usada é CS3 . Os dois blocos finais de texto criptografado são trocados incondicionalmente. Todos os tamanhos de chave AES são aceitos. O modelo cts pode ser composto com qualquer implementação de cbc usando cts(<cbc(aes)-impl>) .As outras implementações são independentes. |
ctr(aes) |
ctr (modelo), ctr-aes-neon , ctr-aes-neonbs , ctr-aes-ce |
Sim | AES-CTR: todos os tamanhos de chave AES são aceitos. O modelo ctr pode ser composto com qualquer implementação de aes usando ctr(<aes-impl>) . As outras implementações são independentes. |
xts(aes) |
xts (modelo), xts-aes-neon , xts-aes-neonbs , xts-aes-ce |
Sim | AES-XTS: na versão 6.1 e anteriores do kernel, todos os tamanhos de chave AES são compatíveis. Na versão 6.6 e mais recentes, apenas AES-128 e AES-256 são compatíveis. O modelo xts pode ser composto com qualquer implementação de ecb(aes) usando xts(<ecb(aes)-impl>) . As outras implementações são independentes. Todas as implementações implementam a verificação de chave fraca exigida pelo FIPS. Ou seja, as chaves XTS com a primeira e a segunda metade iguais são rejeitadas. |
gcm(aes) |
gcm (modelo), gcm-aes-ce |
Não1 | AES-GCM: todos os tamanhos de chave AES são aceitos. Somente IVs de 96 bits são aceitos. Como em todos os outros modos AES neste módulo, o autor da chamada é responsável por fornecer os IVs. O modelo gcm pode ser composto com qualquer implementação de ctr(aes) e ghash usando gcm_base(<ctr(aes)-impl>,<ghash-impl>) . As outras implementações são independentes. |
sha1 |
sha1-generic , sha1-ce |
Sim | Função hash criptográfica SHA-1 |
sha224 |
sha224-generic , sha224-arm64 , sha224-ce |
Sim | Função hash criptográfica SHA-224: o código é compartilhado com SHA-256. |
sha256 |
sha256-generic , sha256-arm64 , sha256-ce , biblioteca SHA-256 |
Sim | Função hash criptográfica SHA-256: uma interface de biblioteca é fornecida para SHA-256, além da interface padrão da CryptoAPI. Esta interface de biblioteca usa uma implementação diferente. |
sha384 |
sha384-generic , sha384-arm64 , sha384-ce |
Sim | Função hash criptográfica SHA-384: o código é compartilhado com o SHA-512. |
sha512 |
sha512-generic , sha512-arm64 , sha512-ce |
Sim | Função hash criptográfica SHA-512 |
sha3-224 |
sha3-224-generic |
Sim | Função hash criptográfica SHA3-224. Presente apenas na versão 6.6 e mais recentes do kernel. |
sha3-256 |
sha3-256-generic |
Sim | Igual ao anterior, mas com comprimento de resumo de 256 bits (SHA3-256). Todos os tamanhos de resumo usam a mesma implementação do Keccak. |
sha3-384 |
sha3-384-generic |
Sim | Mesma que a anterior, mas com comprimento de resumo de 384 bits (SHA3-384). Todos os tamanhos de resumo usam a mesma implementação do Keccak. |
sha3-512 |
sha3-512-generic |
Sim | Igual ao anterior, mas com comprimento de resumo de 512 bits (SHA3-512). Todos os tamanhos de resumo usam a mesma implementação do Keccak. |
hmac |
hmac (modelo) |
Sim | Código de autenticação de mensagens de hash com chave (HMAC): o modelo hmac pode ser composto com qualquer algoritmo ou implementação SHA usando hmac(<sha-alg>) ou hmac(<sha-impl>) . |
stdrng |
drbg_pr_hmac_sha1 , drbg_pr_hmac_sha256 , drbg_pr_hmac_sha384 , drbg_pr_hmac_sha512 |
Sim | HMAC_DRBG instanciado com a função hash nomeada e com resistência à previsão ativada: as verificações de integridade são incluídas. Os usuários dessa interface recebem as próprias instâncias do DRBG. |
stdrng |
drbg_nopr_hmac_sha1 , drbg_nopr_hmac_sha256 , drbg_nopr_hmac_sha384 , drbg_nopr_hmac_sha512 |
Sim | O mesmo que os algoritmos drbg_pr_* , mas com a resistência à previsão desativada. O código é compartilhado com a variante resistente à previsão. Na versão 5.10 do kernel, o DRBG de maior prioridade é drbg_nopr_hmac_sha256 . No kernel versão 5.15 e mais recentes, ele é drbg_pr_hmac_sha512 . |
jitterentropy_rng |
jitterentropy_rng |
Não | O Jitter RNG, a versão 2.2.0 (kernel versão 6.1 e anteriores) ou 3.4.0 (kernel versão 6.6 e mais recentes). Os usuários dessa interface recebem as próprias instâncias de RNG de instabilidade. Elas não reutilizam as instâncias usadas pelos DRBGs. |
xcbc(aes) |
xcbc-aes-neon , xcbc-aes-ce |
Não | |
xctr(aes) |
xctr-aes-neon , xctr-aes-ce |
Não | Presente apenas na versão 5.15 e mais recentes do kernel. |
cbcmac(aes) |
cbcmac-aes-neon , cbcmac-aes-ce |
Não | |
essiv(cbc(aes),sha256) |
essiv-cbc-aes-sha256-neon , essiv-cbc-aes-sha256-ce |
Não |
Criar o módulo a partir da origem
Para o Android 14 e versões mais recentes (incluindo
android-mainline
), crie o módulo fips140.ko
da origem usando os
seguintes comandos.
Criar com o Bazel:
tools/bazel run //common:fips140_dist
Criar com
build.sh
(legado):BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
Esses comandos executam um build completo, incluindo o kernel e o módulo fips140.ko
com o conteúdo do resumo HMAC-SHA256 incorporado.
Orientações para o usuário final
Orientações do oficial de criptografia
Para operar o módulo do kernel, o sistema operacional precisa ser restrito a um modo de operação de operador único. Isso é processado automaticamente pelo Android usando hardware de gerenciamento de memória no processador.
O módulo do kernel não pode ser instalado separadamente. Ele é incluído como parte do firmware do dispositivo e carregado automaticamente na inicialização. Ele só opera em um modo de operação aprovado.
O oficial de criptografia pode reiniciar o dispositivo a qualquer momento para que os autotestes sejam executados.
Orientações para o usuário
O usuário do módulo do kernel são outros componentes do kernel que precisam usar algoritmos criptográficos. O módulo do kernel não fornece lógica adicional no uso dos algoritmos e não armazena nenhum parâmetro além do tempo necessário para executar uma operação criptográfica.
O uso dos algoritmos para fins de conformidade com o FIPS é limitado a algoritmos
aprovados. Para atender ao requisito de "indicador de serviço" do FIPS 140-3, o
módulo fornece uma função fips140_is_approved_service
que indica se
um algoritmo foi aprovado.
Erros de autoteste
Em caso de falha no autoteste, o módulo do kernel causa pânico no kernel e o dispositivo não continua a inicialização. Se uma reinicialização do dispositivo não resolver o problema, ele precisará ser inicializado no modo de recuperação para corrigir o problema com uma nova atualização.
-
Espera-se que as implementações AES-GCM do módulo possam ser "aprovadas pelo algoritmo", mas não "aprovadas pelo módulo". Eles podem ser validados, mas o AES-GCM não pode ser considerado um algoritmo aprovado do ponto de vista do módulo FIPS. Isso ocorre porque os requisitos de módulo do FIPS para o GCM são incompatíveis com implementações do GCM que não geram os próprios IVs. ↩