Módulo de criptografia GKI certificável para FIPS 140-3

O kernel GKI inclui um módulo do kernel do Linux chamado fips140.ko que atende aos requisitos do FIPS 140-3 para módulos de software criptográficos. Esse módulo pode ser enviado para certificação FIPS se o produto que executa o kernel 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 se baseia na ideia de que, depois que um módulo de software ou hardware é certificado, ele nunca é alterado. Se ele for alterado, será necessário passar por uma nova certificação. Isso não corresponde facilmente aos processos de desenvolvimento de software em uso hoje. Como resultado desse requisito, os módulos de software FIPS são geralmente projetados para serem o mais focados possível nos componentes criptográficos para garantir que as mudanças não relacionadas à criptografia não exijam uma reavaliação da criptografia.

O kernel GKI foi projetado para ser atualizado regularmente durante todo o ciclo de vida com suporte. Isso torna inviável que todo o kernel esteja dentro do limite do módulo FIPS, já que um módulo assim precisaria ser recertificado a cada atualização do kernel. Definir o "módulo FIPS" como um subconjunto da imagem do kernel mitigaria 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 do que o necessário.

Antes da versão 6.1 do kernel, outra consideração era que o GKI era compilado com a LTO (Link Time Optimization) ativada, já que ela era um pré-requisito para a Integridade do fluxo de controle, 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 separado fips140.ko, que depende apenas de interfaces estáveis expostas pela fonte do kernel GKI de 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 apenas se algum problema for corrigido no código contido no próprio módulo.

Quando usar o módulo

O próprio kernel GKI tem um código que depende das rotinas de criptografia também incluídas no módulo do kernel FIPS 140-3. Portanto, as rotinas criptográficas integradas não são movidas para fora do kernel da GKI, mas copiadas para o módulo. Quando o módulo é carregado, as rotinas criptográficas integradas são desregistradas da CryptoAPI do Linux e substituídas pelas rotinas do 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 só vai afetar o tempo de inicialização, sem trazer 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 a modules.load no destino. modules.load contém a lista de módulos carregados por init quando o dispositivo é inicializado.

A autoverificação de integridade

O módulo de 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 acontece depois que o carregador de módulos do Linux já fez as modificações usuais, como o processamento de realocação ELF e a correção de alternativas para erratas de CPU nessas seções. As seguintes etapas adicionais são realizadas para garantir que o resumo possa ser reproduzido corretamente:

  • As relocações ELF são preservadas dentro do módulo para que possam ser aplicadas em reverso à entrada do HMAC.
  • O módulo reverte todos os patches de código feitos pelo kernel para a pilha de chamadas dinâmicas. Especificamente, o módulo substitui todas as instruções que enviam ou extraem da pilha de chamadas de sombra com as instruções do Código de Autenticação de Ponteiro (PAC) que estavam presentes originalmente.
  • Todo o restante do patch de código é desativado para o módulo, incluindo chaves estáticas e, portanto, pontos de rastreamento e hooks do fornecedor.

Os autotestes de resposta conhecida

Todos os algoritmos implementados que são cobertos pelos requisitos da FIPS 140-3 precisam realizar um autoteste de resposta conhecida antes de serem usados. De acordo com o FIPS 140-3 Implementation Guidance 10.3.A, um único vetor de teste por algoritmo usando qualquer um dos comprimentos de chave compatíveis é suficiente para cifras, desde que a criptografia e a descriptografia sejam testadas.

A CryptoAPI do Linux tem uma noção de prioridades de algoritmo, em que várias implementações (como uma que usa instruções criptográficas especiais e um fallback para CPUs que não implementam essas instruções) do mesmo algoritmo podem coexistir. Portanto, é necessário testar todas as implementações do mesmo algoritmo. Isso é necessário porque a CryptoAPI do Linux permite que a seleção baseada em 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 estão listados abaixo. Isso se aplica às ramificações do kernel android12-5.10, android13-5.10, android13-5.15, android14-5.15, android14-6.1 e android15-6.6, mas as diferenças entre as versões do kernel são 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 compatíveis. 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 compatíveis. 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 compatíveis. 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 últimos blocos de texto criptografado são trocados incondicionalmente. Todos os tamanhos de chave AES são compatíveis. 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 compatíveis. 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 fazem a verificação de chaves fracas exigida pelo FIPS. Ou seja, chaves XTS cujas primeira e segunda metades são iguais são rejeitadas.
gcm(aes) gcm (modelo), gcm-aes-ce Não1 AES-GCM: todos os tamanhos de chave AES são compatíveis. Somente IVs de 96 bits são compatíveis. Assim 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 CryptoAPI padrão. Essa 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 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 Igual ao 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 HMAC (código de autenticação de mensagens de hash com chave): 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 de hash nomeada e com a resistência à previsão ativada: as verificações de integridade estão incluídas. Os usuários dessa interface recebem as próprias instâncias de DRBG.
stdrng drbg_nopr_hmac_sha1, drbg_nopr_hmac_sha256, drbg_nopr_hmac_sha384, drbg_nopr_hmac_sha512 Sim Igual aos algoritmos drbg_pr_*, mas com a resistência à previsão desativada. O código é compartilhado com a variante resistente a previsões. Na versão 5.10 do kernel, o DRBG de maior prioridade é drbg_nopr_hmac_sha256. Na versão 5.15 e mais recentes do kernel, é drbg_pr_hmac_sha512.
jitterentropy_rng jitterentropy_rng Não O Jitter RNG, versão 2.2.0 (kernel 6.1 e versões anteriores) ou 3.4.0 (kernel 6.6 e versões mais recentes). Os usuários dessa interface recebem as próprias instâncias de RNG de Jitter. 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 da origem

No Android 14 e versões mais recentes (incluindo android-mainline), crie o módulo fips140.ko da origem usando os comandos a seguir.

  • Crie 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 realizam um build completo, incluindo o kernel e o módulo fips140.ko com o conteúdo do resumo HMAC-SHA256 incorporado.

Orientações para usuários finais

Orientações para o oficial de criptografia

Para operar o módulo do kernel, o sistema operacional precisa ser restrito a um único modo de operação do operador. 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 Crypto Officer pode fazer com que os autotestes sejam executados a qualquer momento reiniciando o dispositivo.

Orientação ao 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 parâmetros além do tempo necessário para realizar uma operação criptográfica.

O uso dos algoritmos para fins de compliance com o FIPS é limitado aos algoritmos aprovados. Para atender ao requisito de "indicador de serviço" da FIPS 140-3, o módulo fornece uma função fips140_is_approved_service que indica se um algoritmo foi aprovado.

Erros do autoteste

Em caso de falha no autoteste, o módulo do kernel faz com que o kernel entre em pânico e o dispositivo não continue a inicialização. Se a reinicialização não resolver o problema, o dispositivo precisará ser inicializado no modo de recuperação para corrigir o problema com uma nova atualização.


  1. Espera-se que as implementações AES-GCM do módulo sejam "algoritmo aprovado", mas não "módulo aprovado". Eles podem ser validados, mas o AES-GCM não pode ser considerado um algoritmo aprovado do ponto de vista de um módulo FIPS. Isso ocorre porque os requisitos do módulo FIPS para GCM são incompatíveis com implementações do GCM que não geram os próprios IVs.