NCryptVerifyClaim 函数 (ncrypt.h)

验证密钥证明声明。

语法

SECURITY_STATUS NCryptVerifyClaim(
  [in]           NCRYPT_KEY_HANDLE hSubjectKey,
  [in, optional] NCRYPT_KEY_HANDLE hAuthorityKey,
  [in]           DWORD             dwClaimType,
  [in, optional] NCryptBufferDesc  *pParameterList,
  [in]           PBYTE             pbClaimBlob,
  [in]           DWORD             cbClaimBlob,
  [out]          NCryptBufferDesc  *pOutput,
  [in]           DWORD             dwFlags
);

参数

[in] hSubjectKey

声明的主题密钥句柄。

[in, optional] hAuthorityKey

验证声明时要使用的颁发机构密钥句柄。 此参数是可选的,因为颁发机构密钥对于某些声明类型是自包含的。

[in] dwClaimType

声明的类型。

[in, optional] pParameterList

可选参数列表。

[in] pbClaimBlob

输入声明 Blob。

[in] cbClaimBlob

pbClaimBlob 缓冲区的大小(以字节为单位)。

[out] pOutput

输出 blob。

[in] dwFlags

NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG 是在验证 VBS 生成的声明期间设置的新标志。 有关详细信息,请参阅 备注 部分。

目前没有定义其他标志。 对于所有其他验证类型,应将 dwFlags 参数设置为 0

返回值

返回一个状态代码,指示函数的成功或失败。

以下是验证 VBS 密钥保护证明声明时可能从验证 API 返回的一些错误代码:

返回代码 意义
NTE_BAD_TYPE 声明类型输入参数不同于输入声明 blob 的类型。
STATUS_BAD_DATA 输入声明 blob 无效。
STATUS_NO_MEMORY 内存(声明验证所需的)分配失败。
STATUS_INVALID_PARAMETER 缺少必需的输入参数或其中一个参数具有非法值。
STATUS_FAIL_CHECK 输入 Blob 声明的检查失败。
NTE_BAD_VER 声明 Blob 版本与验证实现不匹配。
NTE_BAD_FLAGS 不支持 dwFlags 中提供的标志。

言论

使用基于虚拟化的安全性保护/证明私钥(VBS)

注意

有关 VBS 标志的信息与预发布产品有关,该产品在商业发布之前可能会进行大幅修改。 Microsoft对此处提供的信息不作任何明示或暗示的保证。

此 API 有助于基于 VBS 密钥保护(用于使用 VBS 保护和证明私钥的 Windows 模块)启用安全密钥的高级证明。 安全密钥的证明证明证明此密钥与定位密钥(即证明密钥)关联。 此功能可以通过限制使用上下文键来提高不同实体之间的通信安全级别。

API 定义新的标志,以支持基于 VBS 密钥保护中的证明密钥创建和验证证明声明。

以下是为 API 定义的 dwClaimType 类型

声明类型 描述
NCRYPT_CLAIM_VBS_ROOT 此类型指示生成的声明是由 VBS 根密钥生成的。
NCRYPT_CLAIM_VBS_IDENTITY 此类型指示生成的声明由 VBS 标识/证明生成。 这意味着声明是由使用证明标志 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG 提升的 VBS 密钥生成的(请参阅下文的详细信息)。

以下是在验证证明声明时在 pParameterList 缓冲区 中设置的缓冲区类型:

  • NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

    NCryptBufferDesc NCryptVerifyClaim dwClaimType 设置为 NCRYPT_CLAIM_VBS_ROOTnCryptBufferDesc 类型 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS 项的新结构。 结构定义为:

    typedef struct _NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS
    {
        ULONG ulKeyFlags;
        ULONGLONG ullTrustletId;
        ULONG ulTrustletSecurityVersion;
        ULONG ulTrustletDebuggable;
    } NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS, *PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS;
    

    该结构包括以下项:

    • ulKeyFlags – 为标识密钥设置的 NCRYPT_VBS_KEY_FLAG_* 值的组合。
    • ullTrustletId – 创建声明的 VBS Trustlet 的策略元数据中的硬编码标识符整数。
    • ulTrustletSecurityVersion – 创建声明的 VBS Trustlet 的安全版本号。 此版本反映哪些安全更新已应用于 trustlet,因此意味着其安全性级别。
    • ulTrustletDebuggable – 指示创建声明的 VBS Trustlet 是否可调试。 1 值指示 trustlet 可调试,0 指示不可调试的 trustlet

    如果将来需要进一步的信息性项,则将定义一个新结构和相应的结构类型。

    注意

    在不再引用此输出参数后,必须释放该参数。

  • NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

    NCryptBufferDesc NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS NCryptBufferDesc NCryptVerifyClaimdwClaimType 设置为 NCRYPT_CLAIM_VBS_IDENTITYNCryptBuffer 项的新结构。 结构定义为:

    typedef struct _NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS
    {
        ULONG ulKeyFlags;
        LPCWSTR pszSignatureHashAlg;
        ULONG ulPaddingScheme;
        LPCWSTR pszPaddingHashAlg;
        ULONG ulPaddingSalt;
    } NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS, *PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS;
    

    该结构包括以下项:

    • ulKeyFlags – 为标识密钥设置的 NCRYPT_VBS_KEY_FLAG_* 值的组合。
    • pszSignatureHashAlg - 指向声明签名哈希算法的 Unicode 字符串的指针。
    • ulPaddingScheme - 通过 BCryptSignHash中创建声明使用的签名算法的填充方案。
    • pszPaddingHashAlg - 指向通过 BCryptSignHash中创建声明时使用的声明填充哈希算法的 Unicode 字符串的指针。
    • ulPaddingSalt - 通过 BCryptSignHash中创建声明使用的签名算法的填充盐。

    如果将来需要进一步的信息性项,则将定义一个新结构和相应的结构类型。

    注意

    在不再引用此输出参数后,必须释放该参数。 下面的代码示例 提供了用于发布此参数的示例代码。

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS

    NCryptBufferDesc*pOutputNCryptVerifyClaim的参数 NCryptBuffer 中设置的新缓冲区类型。 此类型指示 NCryptBuffer 包括数据结构 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS

    NCryptBufferDesc*pOutputNCryptVerifyClaim的参数 NCryptBuffer 中设置的新缓冲区类型。 此类型指示 NCryptBuffer 包括数据结构 NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

  • NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG

    这是在验证 VBS 生成的声明期间在 dwFlags 输入参数中设置的新标志。 当 NCryptVerifyClaim 设置此标志时,NCryptBufferDesc 输出参数具有内部 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILSNCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 参数缓冲区类型。

    下表描述了输入和输出数据结构类型之间的关系,在成功的情况下使用 NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG

    输入 输出
    dwClaimType = NCRYPT_CLAIM_VBS_ROOT 具有内部 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS 信息结构的 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS 缓冲区类型。
    dwClaimType = NCRYPT_CLAIM_VBS_IDENTITY 具有内部 NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS 信息结构的 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 缓冲区类型。

例子

此示例演示了现有 API 的用法,以验证在 NCryptCreateClaim中生成的证明声明。

可以在本地(在生成声明 Blob 的计算机上)或远程调用验证 API。 验证过程需要这些元素,这些元素对应于声明生成密钥:

  • 声明 blob
  • 公共证明密钥 Blob
  • 公共令牌(常规用途)密钥 Blob

如果设置了输入标志 NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG,验证 API 将生成 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILSNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS 输出信息结构之一。 这些结构的内存在代码流的末尾释放,以避免内存泄漏。

HRESULT VerifyClaim(
       BCRYPT_RSAKEY_BLOB *pAttestPublicKeyBlob,
       BCRYPT_RSAKEY_BLOB *pTokenPublicKeyBlob,
       PBYTE pRootClaim,
       DWORD rootClaimSize,
       PBYTE pIdentityClaim,
       DWORD identityClaimSize)
{

    HRESULT hr = S_OK;
    DWORD bytesWritten = 0;

    NCRYPT_PROV_HANDLE provider = NULL;

    if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
    {
        wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
        goto cleanup;
    }

    NCRYPT_KEY_HANDLE attestPublicKey = NULL;

    if (FAILED(hr = NCryptImportKey(
                       provider,
                       NULL,
                       BCRYPT_RSAPUBLIC_BLOB,
                       NULL,
                       &attestPublicKey,
                       (PBYTE)pAttestPublicKeyBlob,
                       GetRsaPublicKeyBlobSize(pAttestPublicKeyBlob),
                       0)))
    {
        wprintf(L"Unable to create a key handle for attestation public key blob with NCryptImportKey(): 0x%X\n", hr);
        goto cleanup;
    }

    NCRYPT_KEY_HANDLE tokenPublicKey = NULL;

    if (FAILED(hr = NCryptImportKey(
                       provider,
                       NULL,
                       BCRYPT_RSAPUBLIC_BLOB,
                       NULL,
                       &tokenPublicKey,
                       (PBYTE)pTokenPublicKeyBlob,
                       GetRsaPublicKeyBlobSize(pTokenPublicKeyBlob),
                       0)))
    {
        wprintf(L"Unable to create a key handle for token public key blob with NCryptImportKey(): 0x%X\n", hr);
        goto cleanup;
    }

    NCryptBufferDesc rootOutput{};

    // Verify the VBS root claim using the attestation/identity public key
    if (FAILED(hr = NCryptVerifyClaim(
                       attestPublicKey,
                       NULL,
                       NCRYPT_CLAIM_VBS_ROOT, // Created claim by IDKS (VBS root signing key)
                       NULL, // parameters
                       pRootClaim,
                       rootClaimSize,
                       &rootOutput,
                       NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG /*dwFlags*/)))
    {
        switch (hr)
        {
            case STATUS_OBJECT_TYPE_MISMATCH:
                wprintf(L"The dwClaimType parameter’s value is different than the claim’s type.\n-----\n", hr);
                break;
            case STATUS_BAD_DATA:
                wprintf(L"Something wrong in one of the data structures. E.g. Magic value mismatch\n-----\n", hr);
                break;
            case STATUS_NO_MEMORY:
                wprintf(L"Memory allocation failed\n-----\n", hr);
                break;
            case STATUS_INVALID_PARAMETER:
                wprintf(L"Missing mandatory parameter or one of the parameters has a bad value.\n-----\n", hr);
                break;
            case STATUS_FAIL_CHECK:
                wprintf(L"One of the claim checks has failed.\n-----\n", hr);
                break;
            default:
                wprintf(L"Unable to verify VBS root claim from NCryptVerifyClaim(): 0x%X\n-----\n", hr);
        }
        goto cleanup;
    }

    PNCryptBuffer pRootOutBuffer;
    DWORD count;

    // Look into the retrieved VBS root claim details
    for (count = 0; count < rootOutput.cBuffers; ++count)
    {
        pRootOutBuffer = rootOutput.pBuffers[count];
        if (pRootOutBuffer->BufferType == NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS)
        {
            PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS pDetails =
            (PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS) pRootOutBuffer->pvBuffer;
            wprintf(L"The claim trustlet id is: %lu\n-----\n", pDetails->ullTrustletId);
            wprintf(L"The claim trustlet Security Version number is: %llu\n-----\n", pDetails->ulTrustletSecurityVersion);
        }
    }

    NCryptBufferDesc identityOutput{};

    // Verify the identity claim using the attestation/identity and token public keys
    if (FAILED(hr = NCryptVerifyClaim(
                        tokenPublicKey,
                        attestPublicKey,
                        NCRYPT_CLAIM_VBS_IDENTITY, // Claim created by an attestation/identity key
                        NULL, // parameters
                        pIdentityClaim,
                        identityClaimSize,
                        &identityOutput,
                        NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG /*dwFlags*/)))
    {
        wprintf(L"Unable to verify identity claim from NCryptVerifyClaim(): 0x%X\n-----\n", hr);
        goto cleanup;
    }

    PNCryptBuffer pIdentityOutBuffer;

    // Look into the retrieved identity claim details
    for (count = 0; count < identityOutput.cBuffers; ++count)
    {
        pIdentityOutBuffer = identityOutput.pBuffers[count];
        if (pIdentityOutBuffer->BufferType == NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS)
        {
            PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS pDetails =
            (PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS) pIdentityOutBuffer->pvBuffer;
            wprintf(L"The claim hash algorithm is: %S\n-----\n", pDetails-> pszSignatureHashAlg);
            wprintf(L"The claim padding scheme is: %lu\n-----\n", pDetails->ulPaddingScheme);
        }
    }

    wprintf(L"Verify claim for root and identity types passed successfully\n");

    cleanup:

    if (provider != NULL)
    {
        NCryptFreeObject(provider);
    }
    if (attestPublicKey != NULL)
    {
        CryptDestroyKey(attestPublicKey);
    }
    if (tokenPub != NULL)
    {
        CryptDestroyKey(tokenPublicKey);
    }
    if (rootOutput.pBuffers != NULL)
    {
        for (count = 0; count < rootOutput.cBuffers; ++count)
        {
            NCryptFreeBuffer(rootOutput.pBuffers[count].pvBuffer);
        }
        NCryptFreeBuffer(rootOutput.pBuffers);
    }

    if (identityOutput.pBuffers != NULL)
    {
        for (count = 0; count < identityOutput.cBuffers; ++count)
        {
            NCryptFreeBuffer(identityOutput.pBuffers[count].pvBuffer);
        }
        NCryptFreeBuffer(identityOutput.pBuffers);
    }

    return hr;
}

DWORD GetRsaPublicKeyBlobSize(BCRYPT_RSAKEY_BLOB* publicKeyBlob)
{
    return sizeof(BCRYPT_RSAKEY_BLOB) +
                publicKeyBlob->cbModulus +
                publicKeyBlob->cbPublicExp;
}

要求

要求 价值
最低支持的客户端 Windows 10 [桌面应用 |UWP 应用]
支持的最低服务器 Windows Server 2016 [桌面应用 |UWP 应用]
目标平台 窗户
标头 ncrypt.h
Ncrypt.lib
DLL Ncrypt.dll