Engenharia Reversa do fTPM
Engenharia Reversa de Driver UEFI SMM para Firmware TPM (fTPM)
Sumário
- Contexto Técnico e Inicialização
- Fluxo de Execução Integrado
- Variáveis Globais e Estruturas Críticas
- Handlers SW-SMI e Interação com o Sistema Operacional
- Observações Técnicas
Contexto Técnico e Inicialização
Recentemente conduzi a análise de um driver UEFI SMM que integra um Firmware TPM (fTPM) baseado em ARM TrustZone. O repositório é privado, pois inclui processos internos, handlers e buffers críticos, mas o estudo permite compreender em detalhes a comunicação entre firmware, SMRAM e TPM.
Este driver atua como uma ponte entre o firmware UEFI e uma Trusted Application no TrustZone. Ele não implementa a lógica interna do TPM, mas garante que todas as operações críticas requisitadas pelo Sistema Operacional sejam processadas de forma segura e confiável.
O driver executa no System Management Mode (SMM), o nível mais privilegiado da CPU, operando de forma invisível ao sistema operacional. A inicialização ocorre em duas fases:
- DXE Phase:
InitializeSmmBasesalva handles globais essenciais, localiza protocolos necessários e verifica a existência de hardware fTPM via MMIO no endereço0xE00D0000. - SMM Phase:
FtpmSmmInitregistra os handlers de Software System Management Interrupts (SW-SMI), instala a tabela ACPI TPM2 e configura os buffers de comando/resposta (CRB).
A persistência do driver é mantida através de setjmp e longjmp, permitindo residir em memória mesmo diante de falhas internas.
Fluxo de Execução Integrado
[DXE Phase] InitializeSmmBase
│
├─> Salva handles globais (ImageHandle, SystemTable, Boot Services)
├─> Localiza protocolo EFI_SMM_BASE2 → gSmmBase2
├─> Consulta tamanho do fTPM e aloca buffer SMM
└─> Verifica hardware fTPM via MMIO
[SMM Phase] FtpmSmmInit
│
├─> CheckFtpmHardware — aborta se hardware ausente
│
├─> SetupAcpiTable
│ ├─> Recupera blob de capacidades do fTPM
│ ├─> Aloca gFtpmData (39 bytes na SMRAM)
│ ├─> Corrige ponteiros na estrutura ACPI ("TNVF")
│ └─> Instala tabela ACPI TPM2 (52 bytes)
│
├─> Registra Handlers SW-SMI
│ ├─> PhysicalPresenceSmiHandler — manipula TrEEPhysicalPresence
│ └─> MemoryOverwriteSmiHandler — manipula MemoryOverwriteRequestControl
│
└─> InstallTpmProtocol
├─> Preenche CRB (48 bytes)
├─> Define CommandAddress / ResponseAddress = CRB_base + 0x80
└─> Instala tabela ACPI final
Variáveis Globais e Estruturas Críticas
| Variável | Tipo | Descrição |
|---|---|---|
gImageHandle |
EFI_HANDLE |
Handle da imagem do driver |
gSystemTable |
EFI_SYSTEM_TABLE* |
Ponteiro para a tabela central do sistema |
gBS_local |
EFI_BOOT_SERVICES* |
Boot services de escopo local |
gSmst |
EFI_SMM_SYSTEM_TABLE2* |
Ponteiro para a Tabela SMM |
gSmmBase2 |
EFI_SMM_BASE2_PROTOCOL* |
Protocolo base da infraestrutura SMM |
gSmmVariable |
EFI_SMM_VARIABLE_PROTOCOL* |
Protocolo para acesso e controle de variáveis SMM |
gInSmm |
BOOLEAN |
Flag indicando se a execução está dentro da SMRAM |
gAllocatedPool |
VOID* |
Buffer de memória pré-alocado dedicado ao fTPM |
gFtpmDeviceFamily |
UINT32 |
Identificador numérico da família do dispositivo fTPM |
gFtpmData |
FTPM_GLOBAL_DATA* |
Dados compartilhados para controle de PP/MOR |
gFtpmCrbSnapshot |
TPM2_CRB_CONTROL_AREA |
Snapshot do estado do CRB |
gTpm2AcpiTable |
TPM2_ACPI_TABLE |
Tabela ACPI TPM2 com tamanho fixo de 52 bytes |
gDriverStatus |
EFI_STATUS |
Status e código de retorno interno do driver |
gJmpBuf |
jmp_buf |
Armazena contexto CPU para setjmp/longjmp |
FTPM_GLOBAL_DATA (39 bytes, SMRAM)
#pragma pack(1)
typedef struct {
UINT8 PpSwSmiValue;
UINT32 PpRequest;
UINT32 PpRequestParameter;
UINT32 PpLastRequest;
UINT32 PpPendingResponseFlags;
UINT32 PpOperationResponse;
UINT8 MorSwSmiValue;
UINT32 MorOperation;
UINT8 MorSavedByte;
UINT8 Reserved[3];
UINT32 MorStatus;
} FTPM_GLOBAL_DATA;
#pragma pack()
TPM2_CRB_CONTROL_AREA (48 bytes)
#pragma pack(1)
typedef struct {
UINT32 ReqCancel;
UINT32 ReqComplete;
UINT32 Status;
UINT32 Reserved;
UINT64 CommandSize;
UINT64 CommandAddress;
UINT64 ResponseSize;
UINT64 ResponseAddress;
} TPM2_CRB_CONTROL_AREA;
#pragma pack()
TPM2_ACPI_TABLE (52 bytes)
A tabela ACPI TPM2 é instalada em dois estágios: placeholder e final, com AddressOfControlArea preenchido dinamicamente apontando para o CRB.
Handlers SW-SMI e Interação com o Sistema Operacional
O SO interage com SMM via variáveis controladas na NVRAM, acionando Software SMIs. Os handlers principais são:
| Handler | Variável em NVRAM | Operações Mapeadas |
|---|---|---|
PhysicalPresenceSmiHandler |
TrEEPhysicalPresence |
PP_REQUEST_CLEAR_ACTIVATE, PP_REQUEST_DEACTIVATE_DISABLE, PP_REQUEST_SPECIAL |
MemoryOverwriteSmiHandler |
MemoryOverwriteRequestControl (MOR) |
MOR_OP_DISABLE, MOR_OP_CLEAR |
Fluxo dinâmico durante comunicação:
[SO] envia comando → escreve na variável gFtpmData
│
v
[SMM] dispara SW-SMI
│
├─> PhysicalPresenceSmiHandler → atualiza TrEEPhysicalPresence
│
├─> MemoryOverwriteSmiHandler → atualiza MemoryOverwriteRequestControl
│
v
[Tabela ACPI TPM2] → referencia CRB_base
│
v
[CRB Buffer] → operação de comando/resposta compartilhada
Observações Técnicas
- Limitações de Endereçamento: gFtpmData é truncado para 32 bits na ACPI.
- Controle Irrestrito: execução em SMM permite controle total da memória física do sistema.
- Segurança e Mitigações: buffers pequenos validados mitigam ausência de stack canaries.
- Sigilo de Informação: código e processos internos permanecem privados, incluindo despacho de handlers e formatos de buffers críticos.