O que é atestado de convidado para VMs confidenciais?

O atestado de convidado o ajuda a confirmar que o ambiente da sua VM confidencial esteja protegido por um Ambiente de Execução Confiável (TEE) com recursos de segurança habilitados para isolamento e integridade.

Você pode usar o atestado de convidado para:

  • Verifique se a VM confidencial é executada na plataforma de hardware esperada
  • Verifique se a VM confidencial está com a inicialização segura habilitada. Essa configuração protege camadas inferiores da VM (firmware, carregador de inicialização, kernel) contra malware (rootkits, bootkits).
  • Obter prova para uma terceira parte confiável de que a VM confidencial é executada em hardware confidencial

Observação

Para executar o atestado de convidado nas VMs DCesv5 e ECesv5 com suporte do Intel TDX, um guia de instruções está disponível aqui. Usar o Intel Trust Authority requer registro na Intel.

Cenários

Os principais componentes e serviços envolvidos no atestado de convidado são:

  • A carga de trabalho
  • A biblioteca de atestados de convidado
  • Hardware (para relatórios). Por exemplo, AMD-SEVSNP.
  • O serviço Atestado do Microsoft Azure
  • Resposta do token Web JSON

Diagrama do cenário de atestado de convidado para uma VM confidencial.

Os cenários operacionais típicos incorporam a biblioteca de clientes para fazer solicitações de atestado desta maneira.

Cenário: solicitação em carga de trabalho separada

Neste cenário de exemplo, as solicitações de atestado são feitas em uma carga de trabalho separada. As solicitações determinam se a VM confidencial é executada na plataforma de hardware correta antes de uma carga de trabalho ser iniciada.

Uma carga de trabalho (Cliente verificador da plataforma no diagrama) precisa se integrar à biblioteca de atestados e ser executada na VM confidencial para fazer o atestado. Depois que o programa faz uma solicitação à biblioteca de atestado, a carga de trabalho analisa a resposta para determinar se a VM é executada na plataforma de hardware correta e/ou na configuração de inicialização segura antes de iniciar a carga de trabalho confidencial.

Diagrama de uma solicitação de atestado feita em uma carga de trabalho separada.

Esse cenário é semelhante ao cenário a seguir. A principal diferença é como cada cenário atinge a mesma meta com base no local da solicitação.

Cenário: solicitação dentro da carga de trabalho

Neste cenário de exemplo, as solicitações de atestado são feitas dentro da carga de trabalho no início do programa. As solicitações verificam se a VM confidencial é executada na plataforma de hardware correta antes de uma carga de trabalho ser iniciada.

Esse cenário é semelhante ao cenário anterior. A principal diferença é como cada cenário atinge a mesma meta com base no local da solicitação.

A carga de trabalho do cliente precisa se integrar à biblioteca de atestados e ser executada dentro da VM confidencial. Depois que a carga de trabalho do cliente faz uma solicitação à biblioteca de atestado, a carga de trabalho do cliente analisa a resposta para determinar se a VM é executada na plataforma de hardware correta e/ou na configuração de inicialização segura antes de configurar a carga de trabalho confidencial por completo.

Diagrama de uma solicitação de atestado feita em uma carga de trabalho dentro de uma VM confidencial.

Cenário: handshake com terceira parte confiável

Neste cenário de exemplo, a VM confidencial deve provar que ela é executada em uma plataforma confidencial antes que uma terceira parte confiável se envolva. A VM confidencial apresenta um token de atestado à terceira parte confiável para iniciar a participação.

Alguns exemplos de participação são:

  • A VM confidencial quer segredos de um serviço de gerenciamento de segredos.
  • Um cliente deseja garantir que a VM confidencial será executada em uma plataforma confidencial antes de revelar dados pessoais para processamento pela VM confidencial.

O diagrama a seguir mostra o handshake entre uma VM confidencial e a terceira parte confiável.

Diagrama de uma solicitação de atestado feita em um cenário de terceira parte confiável.

O diagrama de sequência a seguir explica ainda mais o cenário de terceira parte confiável. A solicitação/resposta entre os sistemas envolvidos usa as APIs de biblioteca de atestados de convidado. A VM confidencial interage com o gerenciador de segredos para se inicializar usando os segredos recebidos.

Diagrama da VM da terceira parte confiável com um serviço de gerenciador de segredos.

APIs

A Microsoft fornece a biblioteca de atestados de convidado com APIs para fazer atestados, criptografar e descriptografar dados. Também há uma API para recuperar memória.

Você pode usar essas APIs nos vários cenários descritos anteriormente.

API de atestado

A API de atestado usa o objeto ClientParameters como entrada e retorna um token de atestado descriptografado. Por exemplo:

AttestationResult Attest([in] ClientParameters client_params,  

  				 [out] buffer jwt_token); 
Parâmetro Informações
ClientParameters (type: object) Objeto que usa a versão (type: uint32_t), o URI de locatário do atestado (type: unsigned character) e o conteúdo do cliente (type: unsigned character). O conteúdo do cliente é zero ou mais pares chave-valor de algum cliente ou metadados de cliente retornados no conteúdo de resposta. Os pares chave-valor precisam estar no formato de cadeia de caracteres JSON "{\"key1\":\"value1\",\"key2\":\"value2\"}". Por exemplo, a chave-valor de atualização de atestado pode ser parecida com {\”Nonce\”:\”011510062022\”} .
buffer Token Web JSON que contém informações de atestado.

A API de atestado retorna um AttestationResult (type: structure).

API de criptografia

A API de criptografia usa dados para criptografia e um token Web JSON como entrada. A API criptografa os dados usando a chave efêmera pública presente no token Web JSON. Por exemplo:

AttestationResult Encrypt(

  [enum] encryption_type, 

  [in] const unsigned char* jwt_token, 

  [in] const unsigned char* data, 

  [in] uint32_t data_size, 

  [out] unsigned char** encrypted_data, 

  [out] uint32_t* encrypted_data_size, 

  [out] unsigned char** encryption_metadata,  

  [out] uint32_t encryption_metadata_size); 
Parâmetro Explicação
encryption_type Nenhum.
const unsigned char* jwt_token Token Web JSON que contém informações de atestado.
const unsigned char* data Dados a serem criptografados
uint32_t data_size Tamanho dos dados a serem criptografados.
unsigned char** encrypted_data Dados criptografados.
uint32_t* encrypted_data_size Tamanho dos dados criptografados.
unsigned char** encryption_metadata Metadados de criptografia.
uint32_t encryption_metadata_size Tamanho dos metadados de criptografia.

A API de criptografia retorna um AttestationResult (type: structure).

API de descriptografia

A API de descriptografia usa dados criptografados como entrada e os descriptografa usando a chave efêmera privada selada para a o TPM (Trusted Platform Module). Por exemplo:

AttestationResult Decrypt([enum] encryption_type, 

  [in] const unsigned char* encrypted_data, 

  [in] uint32_t encrypted_data_size, 

  [in] const unsigned char* encryption_metadata, 

  [in] unit32_t encryption_metadata_size, 

  [out] unsigned char** decrypted_data,  

  [out] unit32_t decrypted_data_size); 
Parâmetro Explicação
encryption_type Nenhum.
const unsigned char* encrypted_data Dados a serem descriptografados.
uint32_t encrypted_data_size Tamanho dos dados a serem descriptografados.
const unsigned char* encryption_metadata Metadados de criptografia.
unit32_t encryption_metadata_size Tamanho dos metadados de criptografia.
unsigned char** decrypted_data Dados descriptografados.
unit32_t decrypted_data_size Tamanho dos dados descriptografados.

A API de descriptografia retorna um AttestationResult (type: structure).

API de liberação

A API de liberação recupera memória retida pelos dados. Por exemplo:

Free([in] buffer data); 
Parâmetro Explicação
data Recupera memória retida pelos dados.

A API de liberação não retorna nada.

Códigos do Erro

As APIs podem retornar os seguintes códigos de erro:

Código do erro Descrição
1 Erro ao inicializar a falha.
2 Erro ao analisar resposta.
3 Token Gerenciar identidades para recursos do Azure não encontrado.
4 A solicitação excedeu a quantidade de tentativas.
5 Falha na solicitação.
6 Falha no atestado.
7 Falha no envio de solicitação.
8 Parâmetro de entrada inválido.
9 Falha na validação dos parâmetros de atestado.
10 Falha na alocação de memória.
11 Falha ao obter informações do SO (sistema operacional).
12 Falha interna do TPM.
13 Falha na operação do TPM.
14 Falha na descriptografia do token Web JSON.
15 Erro de TPM de descriptografia do token Web JSON.
16 Resposta JSON inválida.
17 Certificado VCEK (Chave de Endosso de Chip com Versão Vazia).
18 Resposta vazia.
19 Corpo da solicitação vazio.
20 Falha na análise de relatórios.
21 Relatório vazio.
22 Erro ao extrair informações do token Web JSON.
23 Erro ao converter o token Web JSON em chave pública RSA.
24 Falha na inicialização da criptografia de EVP_PKEY.
25 Falha na criptografia de EVP_PKEY.
26 Erro de TPM de descriptografia de dados.
27 Erro ao analisar informações de DNS.

Token Web JSON

Você pode extrair várias partes do token Web JSON para os diferentes cenários de API descritos anteriormente. Veja abaixo campos importantes para o recurso de atestado de convidado:

Declaração Atributo Valor de exemplo
- x-ms-azurevm-vmid 2DEDC52A-6832-46CE-9910-E8C9980BF5A7
Hardware AMD SEV-SNP x-ms-isolation-tee sevsnpvm
Hardware AMD SEV-SNP x-ms-compliance-status (em x-ms-isolation-tee) azure-compliant-cvm
Inicialização Segura secure-boot (em x-ms-runtime>vm-configuration) true
TPM Virtual tpm-enabled (em x-ms-runtime>vm-configuration) true
TPM Virtual kid (em x-ms-runtime>keys) TpmEphemeralEncryptionKey
{
  "exp": 1653021894,
  "iat": 1652993094,
  "iss": "https://sharedeus.eus.test.attest.azure.net",
  "jti": "<value>",
  "nbf": 1652993094,
  "secureboot": true,
  "x-ms-attestation-type": "azurevm",
  "x-ms-azurevm-attestation-protocol-ver": "2.0",
  "x-ms-azurevm-attested-pcrs": [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    11,
    12,
    13
  ],
  "x-ms-azurevm-bootdebug-enabled": false,
  "x-ms-azurevm-dbvalidated": true,
  "x-ms-azurevm-dbxvalidated": true,
  "x-ms-azurevm-debuggersdisabled": true,
  "x-ms-azurevm-default-securebootkeysvalidated": true,
  "x-ms-azurevm-elam-enabled": true,
  "x-ms-azurevm-flightsigning-enabled": false,
  "x-ms-azurevm-hvci-policy": 0,
  "x-ms-azurevm-hypervisordebug-enabled": false,
  "x-ms-azurevm-is-windows": true,
  "x-ms-azurevm-kerneldebug-enabled": false,
  "x-ms-azurevm-osbuild": "NotApplicable",
  "x-ms-azurevm-osdistro": "Microsoft",
  "x-ms-azurevm-ostype": "Windows",
  "x-ms-azurevm-osversion-major": 10,
  "x-ms-azurevm-osversion-minor": 0,
  "x-ms-azurevm-signingdisabled": true,
  "x-ms-azurevm-testsigning-enabled": false,
  "x-ms-azurevm-vmid": "<value>",
  "x-ms-isolation-tee": {
    "x-ms-attestation-type": "sevsnpvm",
    "x-ms-compliance-status": "azure-compliant-cvm",
    "x-ms-runtime": {
      "keys": [
        {
          "e": "AQAB",
          "key_ops": [
            "encrypt"
          ],
          "kid": "HCLAkPub",
          "kty": "RSA",
          "n": "<value>"
        }
      ],
      "vm-configuration": {
        "console-enabled": true,
        "current-time": 1652993091,
        "secure-boot": true,
        "tpm-enabled": true,
        "vmUniqueId": "<value>"
      }
    },
    "x-ms-sevsnpvm-authorkeydigest": "<value>",
    "x-ms-sevsnpvm-bootloader-svn": 2,
    "x-ms-sevsnpvm-familyId": "<value>",
    "x-ms-sevsnpvm-guestsvn": 1,
    "x-ms-sevsnpvm-hostdata": "<value>",
    "x-ms-sevsnpvm-idkeydigest": "<value>",
    "x-ms-sevsnpvm-imageId": "<value>",
    "x-ms-sevsnpvm-is-debuggable": false,
    "x-ms-sevsnpvm-launchmeasurement": "<value>",
    "x-ms-sevsnpvm-microcode-svn": 55,
    "x-ms-sevsnpvm-migration-allowed": false,
    "x-ms-sevsnpvm-reportdata": "<value>",
    "x-ms-sevsnpvm-reportid": "<value>",
    "x-ms-sevsnpvm-smt-allowed": true,
    "x-ms-sevsnpvm-snpfw-svn": 2,
    "x-ms-sevsnpvm-tee-svn": 0,
    "x-ms-sevsnpvm-vmpl": 0
  },
  "x-ms-policy-hash": "<value>",
  "x-ms-runtime": {
    "keys": [
      {
        "e": "AQAB",
        "key_ops": [
          "encrypt"
        ],
        "kid": "TpmEphemeralEncryptionKey",
        "kty": "RSA",
        "n": "<value>"
      }
    ]
  },
  "x-ms-ver": "1.0"
}

Próximas etapas