Retomar durante a reinicialização

No Android 11, as atualizações OTA podem ser aplicadas usando os mecanismos de atualização A/B ou atualização A/B virtual, combinados com os métodos da classe RecoverySystem (link em inglês). Depois que um dispositivo é reiniciado para aplicar uma atualização OTA, o recurso "Retomar na reinicialização" (RoR, na sigla em inglês) desbloqueia o armazenamento criptografado por credencial (CE, na sigla em inglês) do dispositivo.

Embora os parceiros possam combinar esse processo com um recurso do sistema OTA que aplica atualizações quando o dispositivo está inativo no Android 11, no Android 12, os parceiros não precisam de um recurso adicional do sistema OTA. O processo de RoR oferece mais segurança e conveniência aos usuários, porque as atualizações podem ser feitas durante os períodos de inatividade do dispositivo, enquanto as funcionalidades de atualização baseada em servidor e de múltiplos clientes do Android 12 juntas fornecem segurança aos dispositivos no nível do hardware.

Embora seja necessário fornecer permissão de dispositivo para que o recurso android.hardware.reboot_escrow ofereça suporte ao RoR no Android 11, isso não é necessário para ativar o RoR baseado em servidor no Android 12 e versões mais recentes, porque eles não usam a HAL.

Contexto

A partir do Android 7, o sistema operacional passou a oferecer suporte à inicialização direta, que permite que os apps em um dispositivo sejam iniciados antes que o armazenamento CE seja desbloqueado pelo usuário. A implementação do suporte à inicialização direta proporcionou aos usuários uma experiência melhor antes que o fator de conhecimento da tela de bloqueio (LSKF, na sigla em inglês) precisasse ser inserido após uma inicialização.

A RoR permite que o armazenamento de CE de todos os apps em um dispositivo seja desbloqueado, incluindo aqueles que não são compatíveis com a inicialização direta, quando uma reinicialização é iniciada após uma atualização OTA. Com esse recurso, os usuários recebem notificações de todos os apps instalados após a reinicialização.

Modelo de ameaça

Uma implementação de RoR precisa garantir que, quando um dispositivo cai nas mãos de um invasor, seja extremamente difícil para ele recuperar os dados criptografados por CE do usuário, mesmo que o dispositivo esteja ligado, o armazenamento de CE esteja desbloqueado e o dispositivo seja desbloqueado pelo usuário após receber uma atualização OTA. A resistência a ataques internos precisa ser eficaz mesmo que o invasor tenha acesso às chaves de assinatura criptográfica de transmissão.

Especificamente, o armazenamento de CE não pode ser lido por um invasor que tenha o dispositivo fisicamente e tenha estas capacidades e limitações:

Recursos

  • Pode usar a chave de assinatura de qualquer fornecedor ou empresa para assinar mensagens arbitrárias.
  • Pode fazer com que o dispositivo receba uma atualização OTA.
  • Pode modificar a operação de qualquer hardware (como um processador de aplicativos ou memória flash), exceto conforme detalhado em Limitações abaixo. No entanto, essa modificação envolve um atraso de pelo menos uma hora e um ciclo de energia que destrói o conteúdo da RAM.

Limitações

  • Não é possível modificar a operação de hardware resistente a violações (por exemplo, um Titan M).
  • Não é possível ler a RAM do dispositivo ativo.
  • Não pode adivinhar as credenciais do usuário (PIN, padrão, senha) nem fazer com que elas sejam inseridas.

Solução

O sistema de atualização RoR do Android 12 oferece segurança contra invasores muito sofisticados, e isso acontece enquanto as senhas e PINs do dispositivo permanecem nele. Eles nunca são enviados nem armazenados nos servidores do Google. Esta é uma visão geral do processo que garante que os níveis de segurança fornecidos sejam semelhantes a um sistema RoR baseado em hardware e no nível do dispositivo:

  • O Android aplica proteções criptográficas aos dados armazenados em um dispositivo.
  • Todos os dados são protegidos por chaves armazenadas no ambiente de execução confiável (TEE).
  • O TEE só libera as chaves se o sistema operacional em execução passar pela autenticação criptográfica (Inicialização verificada).
  • O serviço RoR executado nos servidores do Google protege os dados de CE armazenando um segredo que pode ser recuperado por um período limitado. Isso funciona em todo o ecossistema Android.
  • Uma chave criptográfica, protegida por um PIN do usuário, é usada para desbloquear o dispositivo e descriptografar o armazenamento CE.
    • Quando uma reinicialização noturna é programada, o Android pede que o usuário insira o PIN e calcula uma senha sintética (SP).
    • Em seguida, ele criptografa o SP duas vezes: uma com uma chave K_s armazenada na RAM e outra com uma chave K_k armazenada no TEE.
    • O SP com criptografia dupla é armazenado em disco, e o SP é apagado da RAM. As duas chaves são geradas recentemente e usadas apenas para uma reinicialização.
  • Quando é hora de reiniciar, o Android confia o K_s ao servidor. O recibo com K_k é criptografado antes de ser armazenado em disco.
  • Após a reinicialização, o Android usa K_k para descriptografar o recibo e o envia ao servidor para recuperar K_s.
    • K_k e K_s são usados para descriptografar o SP armazenado no disco.
    • O Android usa o SP para desbloquear o armazenamento de CE e permitir a inicialização normal do app.
    • K_k e K_s são descartados.

As atualizações que mantêm seu smartphone seguro podem acontecer em um horário conveniente para você: enquanto você dorme.

Repetição de PIN do chip

Em determinadas condições, o código PIN de um chip é verificado em um cache, um processo chamado de repetição do PIN do chip.

Um chip com um PIN ativado também precisa passar por uma verificação de código PIN sem problemas (uma repetição do PIN do chip) após uma reinicialização autônoma para restaurar a conectividade celular (necessária para ligações, mensagens SMS e serviços de dados). O PIN do chip e as informações correspondentes (ICCID e número do slot do chip) são armazenados juntos de forma segura. O PIN armazenado só pode ser recuperado e usado para verificação após uma reinicialização autônoma bem-sucedida. Se o dispositivo estiver protegido, o PIN do SIM será armazenado com chaves protegidas pelo LSKF. Se o chip tiver o PIN ativado, a interação com o servidor RoR exigirá uma conexão Wi-Fi para a atualização OTA e o RoR baseado em servidor, o que garante a funcionalidade básica (com conectividade celular) após a reinicialização.

O PIN do chip é recriptografado e armazenado sempre que o usuário o ativa, verifica ou modifica. O PIN do SIM é descartado se uma das seguintes situações ocorrer:

  • O chip é removido ou redefinido.
  • O usuário desativa o PIN.
  • Ocorreu uma reinicialização não iniciada pelo RoR.

O PIN do chip armazenado só pode ser usado uma vez após a reinicialização iniciada pelo RoR e apenas por um período muito curto (20 segundos) se os detalhes do chip forem correspondentes. O PIN do SIM armazenado nunca sai do app TelephonyManager e não pode ser recuperado por módulos externos.

Diretrizes de implementação

No Android 12, as funções RoR baseadas em servidor e de vários clientes oferecem uma carga mais leve aos parceiros quando eles enviam atualizações OTA. As atualizações necessárias podem ocorrer durante períodos de inatividade convenientes do dispositivo, como horários de sono designados.

Para garantir que as atualizações OTA durante esses períodos não interrompam os usuários, use o modo escuro para reduzir as emissões de luz. Para isso, faça com que o carregador de inicialização do dispositivo pesquise a string reason unattended. Se unattended for true, coloque o dispositivo no modo escuro. É responsabilidade de cada OEM reduzir as emissões de som e luz.

Se você estiver fazendo upgrade para o Android 12 ou lançando dispositivos com essa versão, não precisa fazer nada para implementar a nova funcionalidade de RoR.

Há uma nova chamada no fluxo de vários clientes, isPreparedForUnattendedUpdate, mostrada abaixo:

@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
            android.Manifest.permission.REBOOT})
public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)

Não é necessário implementar isso, porque a HAL foi descontinuada a partir do Android 12.

TelephonyManager

O cliente OTA invoca a API do sistema TelephonyManager quando uma reinicialização é iminente no Android 12. Essa API move todos os códigos PIN armazenados em cache do estado AVAILABLE para o estado REBOOT_READY. A API TelephonyManager do sistema é protegida pela permissão REBOOT do manifesto.

 /**
    * The unattended reboot was prepared successfully.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_SUCCESS = 0;

   /**
    * The unattended reboot was prepared, but the user will need to manually
    * enter the PIN code of at least one SIM card present in the device.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1;

   /**
    * The unattended reboot was not prepared due to generic error.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_ERROR = 2;

   /** @hide */
   @Retention(RetentionPolicy.SOURCE)
   @IntDef(prefix = {"PREPARE_UNATTENDED_REBOOT_"},
           value = {
                   PREPARE_UNATTENDED_REBOOT_SUCCESS,
                   PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED,
                   PREPARE_UNATTENDED_REBOOT_ERROR
           })
   public @interface PrepareUnattendedRebootResult {}

   /**
    * Prepare TelephonyManager for an unattended reboot. The reboot is
    * required to be done shortly after the API is invoked.
    *
    * Requires system privileges.
    *
    * <p>Requires Permission:
    *   {@link android.Manifest.permission#REBOOT}
    *
    * @return {@link #PREPARE_UNATTENDED_REBOOT_SUCCESS} in case of success.
    * {@link #PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED} if the device contains
    * at least one SIM card for which the user needs to manually enter the PIN
    * code after the reboot. {@link #PREPARE_UNATTENDED_REBOOT_ERROR} in case
    * of error.
    * @hide
    */
   @SystemApi
   @RequiresPermission(android.Manifest.permission.REBOOT)
   @PrepareUnattendedRebootResult
   public int prepareForUnattendedReboot()

A API do sistema TelephonyManager é usada por APKs privilegiados.

Teste

Para testar a nova API, execute este comando:

    adb shell cmd phone unattended-reboot

Esse comando só funciona quando o shell está sendo executado como raiz (adb root).

Somente Android 11

O restante desta página se aplica ao Android 11.

Em julho de 2020, as implementações do HAL do RoR se enquadravam em duas categorias:

  1. Se o hardware do SoC for compatível com a persistência de RAM em reinicializações, os OEMs poderão usar a implementação padrão no AOSP (Default RAM Escrow).
  2. Se o hardware do dispositivo ou o SoC for compatível com um enclave de hardware seguro (um coprocessador de segurança discreto com RAM e ROM próprias), ele também precisará fazer o seguinte:
    • Ser capaz de detectar uma reinicialização da CPU principal.
    • Ter uma fonte de timer de hardware que persista nas reinicializações. Ou seja, o enclave precisa detectar a reinicialização e expirar um timer definido antes dela.
    • Oferecer suporte ao armazenamento de uma chave em depósito na RAM/ROM do enclave para que ela não possa ser recuperada com ataques off-line. Ele precisa armazenar a chave RoR de forma que seja impossível para pessoas de dentro ou invasores recuperá-la.

Escrow de RAM padrão

O AOSP tem uma implementação da HAL RoR usando a persistência de RAM. Para que isso funcione, os OEMs precisam garantir que os SoCs ofereçam suporte à persistência de RAM em reinicializações. Alguns SoCs não conseguem manter o conteúdo da RAM durante uma reinicialização. Por isso, recomendamos que os OEMs consultem os parceiros de SoC antes de ativar esse HAL padrão. A referência canônica para isso na seção a seguir.

Fluxo de atualização OTA usando RoR

O app cliente OTA no smartphone precisa ter as permissões Manifest.permission.REBOOT e Manifest.permission.RECOVERY para chamar os métodos necessários para implementar o RoR. Com esse pré-requisito, o fluxo de uma atualização segue estas etapas:

  1. O app cliente OTA faz o download da atualização.
  2. O app cliente OTA faz chamadas para RecoverySystem#prepareForUnattendedUpdate, o que faz com que o usuário seja solicitado a inserir o PIN, o padrão ou a senha na tela de bloqueio durante o próximo desbloqueio.
  3. O usuário desbloqueia o dispositivo na tela de bloqueio, e ele fica pronto para receber a atualização.
  4. O app cliente OTA chama RecoverySystem#rebootAndApply, que imediatamente aciona uma reinicialização.

No final desse fluxo, o dispositivo é reinicializado, e o mecanismo de RoR desbloqueia o armazenamento criptografado por credencial (CE). Para os apps, isso aparece como um desbloqueio normal do usuário. Assim, eles recebem todos os indicadores, como ACTION_LOCKED_BOOT_COMPLETED e ACTION_BOOT_COMPLETED que normalmente recebem.

Modificar configurações de produtos

Um produto marcado como compatível com o recurso RoR no Android 11 precisa incluir uma implementação da HAL RebootEscrow e o arquivo XML de marcador de recurso. A implementação padrão funciona bem em dispositivos que usam reinicialização a quente (quando a energia da DRAM permanece ligada durante a reinicialização).

Marcador de recurso de reinicialização de escrow

O marcador de recurso também precisa estar presente:

PRODUCT_COPY_FILES += \
    frameworks/native/data/etc/android.hardware.reboot_escrow.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.reboot_escrow.xml

Implementação padrão da HAL de escrow de reinicialização

Para usar a implementação padrão, reserve 65.536 (0x10000) bytes. Nunca grave esses bytes em um armazenamento não volátil para garantir que as propriedades de segurança persistam.

Mudanças na árvore de dispositivos do kernel do Linux

Na árvore de dispositivos do kernel do Linux, é necessário reservar memória para uma região pmem. O exemplo a seguir mostra 0x50000000 sendo reservado:

  reserved-memory {
    my_reservation@0x50000000 {
      no-map;
      reg = <0x50000000 0x10000>;
    }
  }

  reboot_escrow@0 {
    compatible = "pmem-region";
    reg = <0x50000000 0x10000>;
  };

Verifique se você tem um novo dispositivo no diretório de blocos com um nome como /dev/block/pmem0 (por exemplo, pmem1 ou pmem2).

Mudanças no Device.mk

Supondo que o novo dispositivo da etapa anterior seja chamado pmem0, verifique se as seguintes novas entradas foram adicionadas a vendor/<oem>/<product>/device.mk:

# Resume on Reboot support
PRODUCT_PROPERTY_OVERRIDES += \
    ro.rebootescrow.device=/dev/block/pmem0
PRODUCT_PACKAGES += \
    android.hardware.rebootescrow-service.default
Regras do SELinux

Adicione estas novas entradas ao file_contexts do dispositivo:

/dev/block/pmem0  u:object_r:rebootescrow_device:s0
/vendor/bin/hw/android\.hardware\.rebootescrow-service\.default  u:object_r:hal_rebootescrow_default_exec:s0