你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

什么是机密 VM 的来宾证明?

来宾证明可帮助你确认机密 VM 环境由真正的硬件支持的受信任执行环境 (TEE) 保护,并且已启用安全功能来实现隔离和完整性。

使用来宾证明可以:

  • 确保机密 VM 在预期的硬件平台上运行
  • 检查机密 VM 是否启用了安全启动。 此设置可以保护 VM 的较低层(固件、启动加载程序、内核)免受恶意软件(rootkit、bootkit)的侵害。
  • 为信赖方获取机密 VM 在机密硬件上运行的证据

注意

要为 Intel TDX 支持的 DCesv5 和 ECesv5 VM 执行来宾证明,可在此处获取操作指南。 使用 Intel 信任机构需要向 Intel 注册。

方案

来宾证明中涉及的主要组件和服务包括:

机密 VM 的来宾证明方案示意图。

典型的操作方案整合了发出证明请求的客户端库,如下所示。

方案:在单独的工作负载中发出请求

在此示例方案中,证明请求是在单独的工作负载中发出的。 在启动工作负载之前,请求将确定机密 VM 是否在正确的硬件平台上运行。

工作负载(图中的“平台检查器客户端”)必须与证明库集成并在机密 VM 中运行,这样才能进行证明。 在程序向证明库发出请求后,工作负载将分析响应,以确定 VM 是否在正确的硬件平台上运行和/或在启动敏感工作负载之前指定了安全启动设置。

在单独的工作负载中发出证明请求的示意图。

此方案类似于下一个方案。 主要差别在于每个方案如何根据请求位置实现相同的目标。

方案:从工作负载内部发出请求

在此示例方案中,证明请求是在程序启动时从工作负载内部发出的。 在启动工作负载之前,请求将检查机密 VM 是否在正确的硬件平台上运行。

此方案类似于上一个方案。 主要差别在于每个方案如何根据请求位置实现相同的目标。

客户工作负载必须与证明库集成并在机密 VM 内部运行。 在客户工作负载向证明库发出请求后,客户工作负载将分析响应,以确定 VM 是否在正确的硬件平台上运行和/或完全设置敏感工作负载之前指定了安全启动设置。

从机密 VM 中的工作负载内部发出证明请求的示意图。

方案:信赖方握手

在此示例方案中,机密 VM 必须证明它在机密平台上运行,然后信赖方才会参与进来。 机密 VM 向信赖方提供证明令牌以开始参与。

下面是一些参与示例:

  • 机密 VM 需要机密管理服务提供的机密。
  • 客户端在将个人数据透露给机密 VM 进行处理之前,需要确保机密 VM 在机密平台上运行。

下图显示了机密 VM 与信赖方之间的握手。

在信赖方方案中发出证明请求的示意图。

以下序列图进一步解释了信赖方方案。 相关系统之间的请求/响应使用来宾证明库 API。 机密 VM 与机密管理器交互,以使用接收的机密启动自身。

包含机密管理器服务的信赖方 VM 的示意图。

API

Microsoft 为来宾证明库提供了 API 用于执行证明,以及加密解密数据。 还有一个用于回收内存的 API。

可将这些 API 用于前面所述的不同方案

证明 API

证明 API 将 ClientParameters 对象用作输入并返回解密的证明令牌。 例如:

AttestationResult Attest([in] ClientParameters client_params,  

  				 [out] buffer jwt_token); 
参数 信息
ClientParameters(类型:对象) 采用版本(类型:uint32_t)、证明租户 URI(类型:无符号字符)和客户端有效负载(类型:无符号字符)的对象。 客户端有效负载是响应有效负载中返回的任何客户端或客户元数据的零个或多个键值对。 键值对必须采用 JSON 字符串格式 "{\"key1\":\"value1\",\"key2\":\"value2\"}"。 例如,证明新鲜度键值可能类似于 {\”Nonce\”:\”011510062022\”}
buffer 包含证明信息的 JSON Web 令牌

证明 API 返回一个 AttestationResult(类型:结构)

加密 API

加密 API 将要加密的数据和 JSON Web 令牌用作输入。 该 API 使用 JSON Web 令牌中提供的公共临时密钥加密数据。 例如:

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); 
参数 解释
encryption_type 无。
const unsigned char* jwt_token 包含证明信息的 JSON Web 令牌
const unsigned char* data 要加密的数据
uint32_t data_size 要加密的数据大小。
unsigned char** encrypted_data 已加密的数据。
uint32_t* encrypted_data_size 已加密数据的大小。
unsigned char** encryption_metadata 加密元数据。
uint32_t encryption_metadata_size 加密元数据的大小。

加密 API 返回一个 AttestationResult(类型:结构)

解密 API

解密 API 将加密的数据用作输入,并使用密封在受信任平台模块 (TPM) 中的专用临时密钥来解密数据。 例如:

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); 
参数 解释
encryption_type 无。
const unsigned char* encrypted_data 要解密的数据。
uint32_t encrypted_data_size 要解密的数据大小。
const unsigned char* encryption_metadata 加密元数据。
unit32_t encryption_metadata_size 加密元数据的大小。
unsigned char** decrypted_data 已解密的数据。
unit32_t decrypted_data_size 已解密数据的大小。

解密 API 返回一个 AttestationResult(类型:结构)

释放 API

释放 API 回收数据占用的内存。 例如:

Free([in] buffer data); 
参数 解释
data 回收数据占用的内存。

释放 API 不返回任何信息

错误代码

API 可能返回以下错误代码:

错误代码 说明
1 初始化失败时出错。
2 分析响应时出错。
3 找不到 Azure 资源的托管标识令牌。
4 请求超过重试次数。
5 请求失败。
6 证明失败。
7 发送请求失败。
8 输入参数无效。
9 证明参数验证失败。
10 内存分配失败。
11 无法获取操作系统 (OS) 信息。
12 TPM 内部故障。
13 TPM 操作失败。
14 JSON Web 令牌解密失败。
15 JSON Web 令牌解密 TPM 错误。
16 JSON 响应无效。
17 版本受控的芯片认可密钥 (VCEK) 证书为空。
18 响应为空。
19 请求正文为空。
20 报告分析失败。
21 报告为空。
22 提取 JSON Web 令牌信息时出错。
23 将 JSON Web 令牌转换为 RSA 公钥时出错。
24 EVP_PKEY 加密初始化失败
25 EVP_PKEY 加密失败
26 数据解密 TPM 错误。
27 分析 DNS 信息时出错。

JSON Web 令牌

对于前面所述的不同 API 方案,可以提取 JSON Web 令牌的不同部分。 下面是来宾证明功能的重要字段:

声明 属性 示例值
- x-ms-azurevm-vmid 2DEDC52A-6832-46CE-9910-E8C9980BF5A7
AMD SEV-SNP 硬件 x-ms-isolation-tee sevsnpvm
AMD SEV-SNP 硬件 x-ms-compliance-status(在 x-ms-isolation-tee 下) azure-compliant-cvm
安全启动 secure-boot(在 x-ms-runtime>vm-configuration 下) true
虚拟 TPM tpm-enabled(在 x-ms-runtime>vm-configuration 下) true
虚拟 TPM kid(在 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"
}

后续步骤