Condividi tramite


Che cos'è l'attestazione guest per le macchine virtuali riservate?

L'attestazione guest consente di verificare che l'ambiente della macchina virtuale riservata sia protetto da un ambiente di esecuzione attendibile (TEE) basato su hardware con funzionalità di sicurezza abilitate per l'isolamento e l'integrità.

È possibile usare l'attestazione guest per:

  • Assicurarsi che la macchina virtuale riservata venga eseguita sulla piattaforma hardware prevista
  • Controllare che sulla macchina virtuale riservata sia abilitato l'avvio protetto. Questa impostazione protegge i livelli inferiori della macchina virtuale (firmware, caricatore di avvio, kernel) da malware (rootkit, bootkit).
  • Ottenere prove per una relying party che la macchina virtuale riservata viene eseguita su hardware riservato

Nota

Per eseguire l'attestazione guest per le macchine virtuali DCesv5 ed ECesv5 supportate da Intel TDX, una guida pratica è disponibile qui. L'uso di Intel Trust Authority richiede la registrazione con Intel.

Scenari

I componenti e i servizi principali coinvolti nell'attestazione guest sono:

Diagramma dello scenario di attestazione guest per una macchina virtuale riservata.

Gli scenari operativi tipici incorporano la libreria client per effettuare richieste di attestazione come indicato di seguito.

Scenario: richiesta in un carico di lavoro separato

In questo scenario di esempio, le richieste di attestazione vengono effettuate in un carico di lavoro separato. Le richieste determinano se la macchina virtuale riservata viene eseguita nella piattaforma hardware corretta prima dell'avvio di un carico di lavoro.

Un carico di lavoro (Client di controllo della piattaforma nel diagramma) deve essere integrato con la libreria di attestazioni ed eseguito all'interno della macchina virtuale riservata per eseguire l'attestazione. Dopo che il programma effettua una richiesta alla libreria di attestazioni, il carico di lavoro analizza la risposta per determinare se la macchina virtuale viene eseguita nella piattaforma hardware corretta e/o nell'impostazione di avvio protetto prima di avviare il carico di lavoro sensibile.

Diagramma di una richiesta di attestazione eseguita in un carico di lavoro separato.

Questo scenario è simile allo scenario seguente. La differenza principale è il modo in cui ogni scenario raggiunge lo stesso obiettivo in base alla posizione della richiesta.

Scenario: richiesta dall'interno del carico di lavoro

In questo scenario di esempio, le richieste di attestazione vengono effettuate all'interno del carico di lavoro all'inizio del programma. Le richieste verificano se la macchina virtuale riservata viene eseguita nella piattaforma hardware corretta prima dell'avvio di un carico di lavoro.

Questo scenario è simile allo scenario precedente. La differenza principale è il modo in cui ogni scenario raggiunge lo stesso obiettivo in base alla posizione della richiesta.

Il carico di lavoro del cliente deve integrarsi con la libreria di attestazioni ed essere eseguito all'interno della macchina virtuale riservata. Dopo che il carico di lavoro del cliente effettua una richiesta alla libreria di attestazioni, il carico di lavoro del cliente analizza la risposta per determinare se la macchina virtuale viene eseguita nella piattaforma hardware corretta e/o nell'impostazione di avvio protetto prima di configurare completamente il carico di lavoro sensibile.

Diagramma di una richiesta di attestazione eseguita dall'interno di un carico di lavoro all'interno di una macchina virtuale riservata.

Scenario: handshake della relying party

In questo scenario di esempio, la macchina virtuale riservata deve dimostrare che viene eseguita su una piattaforma riservata prima che venga attivata una relying party. La macchina virtuale riservata presenta un token di attestazione alla relying party per avviare l'engagement.

Ecco alcuni esempi di engagement:

  • La macchina virtuale riservata vuole i segreti da un servizio di gestione dei segreti.
  • Un client vuole assicurarsi che la macchina virtuale riservata venga eseguita in una piattaforma riservata prima di rivelare i dati personali alla macchina virtuale riservata per l'elaborazione.

Il diagramma seguente illustra l'handshake tra una macchina virtuale riservata e la relying party.

Diagramma di una richiesta di attestazione effettuata in uno scenario relying party.

Il diagramma di sequenza seguente illustra ulteriormente lo scenario della relying party. La richiesta/risposta tra i sistemi coinvolti usa le API della libreria di attestazioni guest. La macchina virtuale riservata interagisce con il gestore dei segreti per eseguire il bootstrap usando i segreti ricevuti.

Diagramma della macchina virtuale relying party con un servizio di gestione dei segreti.

API

Microsoft fornisce la libreria di attestazioni guest con API per eseguire attestazioni e sia crittografare che decrittografare i dati. È anche disponibile un'API per recuperare memoria.

È possibile usare queste API per i diversi scenari descritti in precedenza.

API Attest

L'API Attest accetta l'oggetto ClientParameters come input e restituisce un token di attestazione decrittografato. Ad esempio:

AttestationResult Attest([in] ClientParameters client_params,  

  				 [out] buffer jwt_token); 
Parametro Informazioni
ClientParameters (tipo: oggetto) Oggetto che accetta la versione (tipo: uint32_t), l'URI del tenant di attestazione (tipo: carattere senza segno) e il payload del client (tipo: carattere senza segno). Il payload del client è pari a zero o più coppie chiave-valore per qualsiasi metadato client o cliente restituito nel payload della risposta. Le coppie chiave-valore devono essere in formato stringa JSON "{\"key1\":\"value1\",\"key2\":\"value2\"}". Ad esempio, il valore chiave di aggiornamento dell'attestazione potrebbe essere simile a {\”Nonce\”:\”011510062022\”} .
buffer Token Web JSON che contiene informazioni di attestazione.

L'API Attest restituisce un AttestationResult (tipo: struttura).

API Encrypt

L'API Encrypt accetta i dati da crittografare e un token Web JSON come input. L'API crittografa i dati usando la chiave temporanea pubblica presente nel token Web JSON. Ad esempio:

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); 
Parametro Spiegazione
encryption_type Nessuno.
const unsigned char* jwt_token Token Web JSON che contiene informazioni di attestazione.
const unsigned char* data Dati da crittografare
uint32_t data_size Dimensioni dei dati da crittografare.
unsigned char** encrypted_data Dati crittografati.
uint32_t* encrypted_data_size Dimensioni dei dati crittografati.
unsigned char** encryption_metadata Metadati di crittografia.
uint32_t encryption_metadata_size Dimensioni dei metadati di crittografia.

L'API Encrypt restituisce un AttestationResult (tipo: struttura).

API Decrypt

L'API Decrypt accetta i dati crittografati come input e decrittografa i dati usando la chiave temporanea privata sealed al modulo TPM (Trusted Platform Module). Ad esempio:

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); 
Parametro Spiegazione
encryption_type Nessuno.
const unsigned char* encrypted_data Dati da decrittografare.
uint32_t encrypted_data_size Dimensioni dei dati da decrittografare.
const unsigned char* encryption_metadata Metadati di crittografia.
unit32_t encryption_metadata_size Dimensioni dei metadati di crittografia.
unsigned char** decrypted_data Dati decrittografati.
unit32_t decrypted_data_size Dimensioni dei dati decrittografati.

L'API Decrypt restituisce un AttestationResult (tipo: struttura).

API Free

L'API Free recupera la memoria contenuta nei dati. Ad esempio:

Free([in] buffer data); 
Parametro Spiegazione
data Recuperare la memoria contenuta nei dati.

L'API Free non restituisce nulla.

Codici di errore

Le API possono restituire i codici di errore seguenti:

Codice di errore Descrizione
1 Errore durante l'inizializzazione dell'errore.
2 Errore durante l'analisi della risposta.
3 Token Identità gestite per le risorse di Azure non trovato.
4 La richiesta ha superato il numero di tentativi.
5 Richiesta non riuscita.
6 Attestazione non riuscita.
7 Richiesta di invio non riuscita.
8 Parametro di input non valido.
9 Convalida dei parametri di attestazione non riuscita.
10 L'allocazione di memoria ha avuto esito negativo.
11 Impossibile ottenere informazioni sul sistema operativo (OS).
12 Errore interno TPM.
13 Operazione TPM non riuscita.
14 Decrittografia del token Web JSON non riuscita.
15 Errore TPM di decrittografia del token Web JSON.
16 Risposta JSON non valida.
17 Certificato VCEK (Versioned Chip Endorsement Key) vuoto.
18 Risposta vuota.
19 Corpo della richiesta vuoto.
20 Errore di analisi del report.
21 Report vuoto.
22 Errore durante l'estrazione delle informazioni sul token Web JSON.
23 Errore durante la conversione del token Web JSON in chiave pubblica RSA.
24 Inizializzazione della crittografia di EVP_PKEY non riuscita.
25 Crittografia di EVP_PKEY non riuscita.
26 Errore TPM di decrittografia dei dati.
27 Errore durante l'analisi delle informazioni sul DNS.

Token JSON Web

È possibile estrarre parti diverse del token Web JSON per i diversi scenari di API descritti in precedenza. Di seguito sono riportati i campi importanti per la funzionalità di attestazione guest:

Richiesta di rimborso Attributo Valore di esempio
- 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 (in x-ms-isolation-tee) azure-compliant-cvm
Avvio protetto secure-boot (in x-ms-runtime>vm-configuration) true
TPM virtuale tpm-enabled (in x-ms-runtime>vm-configuration) true
TPM virtuale kid (in 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"
}

Passaggi successivi