Enclaves seguros

Como proteger código e dados mesmo de quem controla a máquina.

O problema

Normalmente, quem manda no computador vê tudo. O sistema operacional consegue ler a memória de qualquer processo, o hypervisor consegue ler a memória de qualquer máquina virtual, e quem administra o servidor (ou a nuvem) consegue ler tudo isso junto.

Sem enclaveCom enclaveSeu app + segredoSistema operacionallê o segredoHypervisorlê o segredoAdmin / nuvemlê o segredoEnclave + segredoSistema operacionalsó vê cifradoHypervisorsó vê cifradoAdmin / nuvemsó vê cifrado
As mesmas camadas existem nos dois casos. O que muda é quem consegue ler o segredo.

Isso é um problema quando você quer processar algo sensível, como uma chave privada, dados médicos ou o modelo de outra empresa, numa máquina que não é sua ou em que você não confia por completo.

A ideia em uma frase: um enclave seguro é uma área isolada, garantida pelo próprio hardware, onde o código roda e os dados ficam protegidos até do sistema operacional, do hypervisor e do dono da máquina.

Em quem você confia

O enclave inverte a pilha de confiança. Em vez de confiar em todas as camadas de software abaixo do seu programa, você confia só no processador e no código que está dentro do enclave. Esse conjunto mínimo de coisas confiáveis se chama TCB (Trusted Computing Base).

Aplicação (parte comum)Enclave: código + segredosSistema operacionalnão confiávelHypervisor / nuvemnão confiávelProcessador (hardware)
Só as partes tracejadas fazem parte da TCB. Tudo no meio pode estar comprometido.

As quatro peças

1. Isolamento de memória

O processador reserva uma região de memória para o enclave e bloqueia qualquer acesso vindo de fora dele, inclusive do kernel. Se o sistema operacional tentar ler esses endereços, recebe lixo ou um erro.

Esse isolamento pode ter tamanhos diferentes. Algumas tecnologias protegem só um pedaço de um processo; outras protegem uma máquina virtual inteira:

Enclave de processo (SGX)Sistema operacionalSeu processoEnclavesó a parte sensívelVM confidencial (TDX, SEV-SNP)Hypervisor da nuvemVM inteira protegidaSO convidadoseus apps
Proteger um processo deixa a TCB menor. Proteger a VM inteira facilita rodar software que já existe, sem reescrever nada.

2. Memória cifrada

Dentro do processador os dados ficam em claro, porque é lá que o código trabalha. Quando eles saem do chip e vão para a RAM, um motor de criptografia cifra tudo automaticamente com uma chave que nunca deixa o processador. Na volta, decifra. Assim, mesmo alguém com acesso físico aos pentes de memória só vê bytes embaralhados.

dentro do chipNúcleodados em clarosenha=hunter2Motor de criptoa chave nuncasai do chipRAM9f a2 7c 01e3 5b d8 44SO ou atacantesó lê bytes cifrados
Os dados só existem em claro dentro do processador.

3. Atestação remota

Como saber que o código rodando lá dentro é mesmo o que você espera, e que ele está num enclave de verdade e não num simulador? O processador calcula um hash (a medição) do código carregado no enclave e assina esse valor com uma chave que só um chip genuíno tem. Você confere a assinatura, compara o hash com o código que auditou e só então envia seus segredos.

Você (cliente)HostEnclaveFabricante1. pede atestação + nonce2. repassa o pedido3. CPU assina relatório:hash + nonce + chave pública4. relatório assinado5. essa assinatura é de um chip genuíno?6. sim, certificado válido7. compara o hash como código que auditou8. segredo cifrado p/ o enclaveo host repassa, mas só vê bytes cifrados
O nonce impede que um relatório antigo seja reaproveitado. A chave pública no relatório é o que permite cifrar o segredo só para aquele enclave.

4. Selagem (sealing)

O enclave precisa guardar coisas entre reinicializações, mas o disco é controlado pelo sistema operacional. A solução é cifrar os dados com uma chave derivada de dois ingredientes: uma chave secreta gravada no chip e a medição do próprio enclave.

Chave raiz do chipMedição do enclavesegredoSelar (cifrar)blob no discomesmo códigoe mesmo chipabre o segredocódigo alteradoou outro chipnão abre
Mudou um byte do código, a medição muda, a chave muda e o blob vira lixo.

A vida de um enclave

  1. Criar. A aplicação pede ao processador uma região protegida de memória.
  2. Carregar e medir. O código do enclave é copiado para dentro, página por página, e o processador vai calculando o hash de tudo que entra.
  3. Inicializar. A medição é congelada. A partir daqui ninguém de fora pode mudar o código.
  4. Atestar. Quem precisa confiar no enclave pede o relatório assinado e confere a medição.
  5. Executar. A aplicação chama funções do enclave, que processa os segredos lá dentro.
  6. Destruir. O processador apaga a região. Só o que foi selado sobrevive.

Durante a execução, o código cruza a fronteira do enclave por portas bem definidas. Entrar no enclave é uma ECALL; quando o enclave precisa de algo que só o sistema operacional faz, como ler um arquivo ou usar a rede, ele sai por uma OCALL.

Aplicação comumnão confiávelfala com o SO, rede,discoEnclaveconfiávelvalida tudo queentra pela fronteirafronteiraECALL: entraOCALL: pede ao SO
Tudo que volta de uma OCALL veio de fora e pode ser mentira. O enclave precisa checar.

Um exemplo concreto

Imagine um serviço de assinatura de transações que guarda uma chave privada num servidor alugado:

  1. O serviço sobe o enclave com o código de assinatura, que é open source.
  2. O dono da chave pede a atestação, confere que o hash bate com a versão publicada do código e só então envia a chave privada, cifrada para o enclave.
  3. O enclave sela a chave e guarda o blob no disco.
  4. A aplicação comum envia transações por ECALL; o enclave devolve assinaturas.
  5. Se o servidor reiniciar, o enclave abre o blob selado e continua. A chave nunca aparece em claro fora dele, nem para o administrador do servidor.

Implementações que você vai encontrar

TecnologiaIsola o quêOnde aparece
Intel SGXUm pedaço de um processoServidores Intel, Azure
Intel TDXUma máquina virtual inteiraNuvens com Xeon recentes
AMD SEV-SNPUma máquina virtual inteiraAWS, Azure, GCP
Arm TrustZone / CCAUm "mundo seguro" separadoCelulares, dispositivos embarcados
Apple Secure EnclaveUm coprocessador dedicadoiPhone, Mac (Face ID, chaves)
AWS Nitro EnclavesUma VM isolada sem rede nem discoAWS EC2

O nome guarda-chuva para tudo isso é TEE (Trusted Execution Environment), e quando o uso é em nuvem costuma aparecer como confidential computing.

O que enclaves não resolvem

Glossário rápido

TCB (Trusted Computing Base)
Tudo em que você precisa confiar para o sistema ser seguro. Enclaves existem para encolher a TCB.
Medição
Hash do código e da configuração carregados no enclave.
Atestação
Prova assinada pelo hardware de que uma medição específica está rodando num enclave genuíno.
Nonce
Número aleatório usado uma vez só, para provar que a resposta é nova e não uma gravação.
Selagem
Cifrar dados para que só o mesmo enclave, no mesmo chip, consiga decifrá-los depois.
ECALL / OCALL
Chamadas que entram no enclave e que saem dele, respectivamente.

Próxima parte: um policy engine dentro de um enclave →

A ideia

Um policy engine é o pedaço do sistema que responde a uma pergunta só: "quem está pedindo pode fazer isso com esse recurso?". Ele recebe o pedido, olha as regras escritas por quem é dono dos dados e devolve permite ou nega.

O problema é o mesmo da primeira parte. Se o policy engine roda num servidor que outra pessoa controla, essa pessoa pode trocar as regras, forjar um "permite" ou apagar o registro do que aconteceu. Colocando o policy engine dentro de um enclave, quem opera o servidor continua rodando o serviço, mas perde o poder de mexer nas decisões.

A divisão de papéis: o gateway fica fora do enclave e só aplica decisões (é o PEP, Policy Enforcement Point). O policy engine fica dentro e só decide (é o PDP, Policy Decision Point). Quem tem o dado confia no enclave, não no gateway.

Quem fala com quem

servidor alugado (não confiável)Gateway (PEP)só aplica a decisãoEnclave: policy engine (PDP)decide e assina a decisãopolíticas seladas no disco2. ECALL3. decisãoassinadaAgenteou app1. pedidoRecurso4. pedido+ decisão5. confere aassinatura doenclaveQuem escreve as políticas0. atesta o enclave e envia as políticas cifradas
O gateway carrega a decisão, mas não consegue fabricar uma: ele não tem a chave que o recurso espera ver na assinatura.

Antes do primeiro pedido

A preparação usa exatamente as peças da primeira parte:

  1. Atestação. Quem escreve as políticas pede o relatório do enclave e confere que a medição bate com a versão auditada do policy engine. O relatório traz a chave pública de assinatura que o enclave gerou lá dentro.
  2. Envio das políticas. O pacote de políticas vai assinado pelo autor e cifrado para o enclave. O host repassa, mas não lê nem altera.
  3. Selagem. O enclave confere a assinatura do autor, guarda o pacote selado no disco e anota a versão dele.
  4. Publicação da chave. Os recursos protegidos passam a aceitar só decisões assinadas pela chave que apareceu no relatório atestado.

As regras

Para o exemplo, um pacote pequeno com três regras. Negação sempre ganha de permissão, e o que nenhuma regra permite fica proibido.

nega nunca-exportar-pii:
  ação = "exportar" e recurso tem a etiqueta "pii"

permite ler-do-proprio-time:
  ação = "ler" e recurso.time = quem_pede.time

padrão: nega

O fluxo de cada pedido

Escolha um pedido para ver o caminho que ele faz dentro do enclave:

Nenhum pedido escolhido: o fluxograma mostra todos os caminhos.

Pedido entra por ECALLFormato válido?nãoNega: malformadosimAssinatura de quempede confere?nãoNega: identidade falsasimAbre as políticas seladasAlguma regra denegação casa?simNega: regra de negaçãonãoAlguma regra depermissão casa?nãoNega por padrãosimPermiteAssina: decisão + hash do pedido + versão das políticasGrava no log encadeado e devolve pela fronteira
Tudo que aparece aqui acontece dentro do enclave. Todo caminho termina numa decisão assinada, inclusive as negações.

O que vai na decisão

A resposta não é só "sim" ou "não". Ela amarra a decisão ao pedido e às regras usadas, para ninguém reaproveitar um "permite" antigo em outro pedido:

decisão:       permite
regra:         ler-do-proprio-time
pedido:        sha256(ana · ler · relatorio-q3.pdf · nonce)
políticas:     versão 12 (sha256 do pacote)
log anterior:  sha256 da entrada 4.311
assinatura:    chave do enclave (a mesma do relatório atestado)

O que o enclave garante aqui

O que ainda fica com você

Glossário desta parte

Policy engine
Componente que avalia regras e decide se um pedido é permitido.
PDP (Policy Decision Point)
Quem decide. Aqui, o policy engine dentro do enclave.
PEP (Policy Enforcement Point)
Quem aplica a decisão no caminho do pedido. Aqui, o gateway.
Negação por padrão
O que nenhuma regra permite explicitamente é proibido.
Log encadeado
Registro em que cada entrada inclui o hash da anterior, então qualquer alteração no meio aparece.

← Voltar para o conceito