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

O kernel 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. Esse módulo pode ser enviado para certificação FIPS se o produto que executa o kernel de GKI precisar dele.

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 testar 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 alterado, ele precisará ser certificado novamente. Isso não corresponde prontamente aos processos de desenvolvimento de software em uso atualmente e, como resultado desse requisito, os módulos de software FIPS geralmente são projetados para ter o máximo de foco possível nos componentes criptográficos, para garantir que as alterações não relacionadas à criptografia não exijam uma reavaliação da criptografia.

O kernel de GKI precisa ser atualizado regularmente durante toda a vida útil com suporte. Isso torna inviável que todo o kernel esteja dentro do limite de módulo do FIPS, já que esse módulo precisaria ser certificado novamente a 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 importante recurso de segurança.

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 origem do kernel de GKI de que foi criado. Isso garante que o módulo possa ser usado com diferentes versões de GKI da mesma geração e que ele precise ser atualizado e reenviado para certificação somente se algum problema for corrigido no código transferido pelo próprio módulo.

Quando usar o módulo

O próprio kernel de GKI carrega um código que depende das rotinas de criptografia que também estão empacotadas no módulo do kernel do FIPS 140-3. Portanto, as rotinas de criptografia integradas não são removidas do kernel de GKI, mas são copiadas para o módulo. Quando o módulo é carregado, o registro das rotinas de criptografia integradas é cancelado na CryptoAPI do Linux e substituídas pelas transferidas 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 fornece outras funcionalidades, e carregá-lo desnecessariamente só pode afetar o tempo de inicialização, sem oferecer 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 que são carregados por init quando o dispositivo é inicializado.

Autoverificação de integridade

O módulo do kernel do FIPS 140-3 usa o resumo HMAC-SHA256 das próprias seções .code e .rodata no tempo de carregamento do módulo e o compara com o resumo gravado 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 seguintes etapas extras são tomadas para garantir que o resumo possa ser reproduzido corretamente:

  • As realocações de 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 Dynamic Shadow Call Stack. 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.
  • Todas as outras correções de código são desativadas para o módulo, incluindo chaves estáticas e, portanto, tracepoints, bem como hooks de fornecedores.

Autotestes de resposta conhecida

Todos os algoritmos implementados que forem cobertos pelos requisitos do FIPS 140-3 precisam executar um autoteste de resposta conhecida antes de serem usados. De acordo com as Orientação de implementação 10.3.A do FIPS 140-3 (em inglês), um único vetor de teste por algoritmo que usa qualquer um dos comprimentos de chave com suporte é suficiente para criptografias, 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 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 baseada em prioridade seja desviada e que um algoritmo de menor prioridade 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 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 do 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. Além da implementação da biblioteca, todas as implementações 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 blocos finais 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 suportados. 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: no kernel versão 6.1 e anteriores, todos os tamanhos de chave AES são compatíveis; no kernel 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, chaves XTS com primeira e segunda metades iguais são rejeitadas.
gcm(aes) gcm (modelo), gcm-aes-ce Não1 AES-GCM: todos os tamanhos de chave AES são suportados. 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 de hash criptográfica SHA-224: o código é compartilhado com o SHA-256.
sha256 sha256-generic, sha256-arm64, sha256-ce, biblioteca SHA-256 Sim Função de hash criptográfica SHA-256: uma interface de biblioteca é fornecida ao SHA-256, além da interface tradicional da CryptoAPI. Esta interface de biblioteca usa uma implementação diferente.
sha384 sha384-generic, sha384-arm64, sha384-ce Sim Função de hash criptográfica SHA-384: o código é compartilhado com o SHA-512.
sha512 sha512-generic, sha512-arm64, sha512-ce Sim Função de hash criptográfico SHA-512
sha3-224 sha3-224-generic Sim Função hash criptográfica SHA3-224. Presente apenas no kernel versão 6.6 e superior.
sha3-256 sha3-256-generic Sim Igual ao anterior, mas com tamanho 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 tamanho 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 um 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 mensagem de hash com chave): o modelo hmac pode ser composto com qualquer implementação ou algoritmo 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 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. 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. Eles 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 no kernel versão 5.15 e mais recentes.
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 pela origem usando os comandos abaixo.

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

Orientação ao usuário final

Orientação para oficial de criptografia

Para operar o módulo do kernel, o sistema operacional precisa estar restrito a um único modo de operação de 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 do 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 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

No caso de uma falha no autoteste, o módulo do kernel entra em pânico e o dispositivo não continua a inicialização. Se a reinicialização do dispositivo não resolver o problema, ele precisará ser inicializado no modo de recuperação para corrigir o problema atualizando-o novamente.


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