다음을 통해 공유


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 모듈인 VBS 키 보호를 기반으로 보안 키의 고급 증명을 사용하도록 설정하는 데 도움이 됩니다. 보안 키의 증명은 이 키와 고정된 키, 즉 증명 키의 연결을 증명합니다. 이 기능은 컨텍스트 외부 키의 사용을 제한하여 서로 다른 엔터티 간의 통신 보안 수준을 향상시킬 수 있습니다.

API는 VBS 키 보호의 증명 키를 기반으로 증명 클레임 생성 및 확인을 지원하는 새 플래그를 정의합니다.

다음은 API에 대해 정의된 dwClaimType 형식입니다.

클레임 유형 묘사
NCRYPT_CLAIM_VBS_ROOT 이 형식은 생성된 클레임이 VBS 루트 키에 의해 생성됨을 나타냅니다.
NCRYPT_CLAIM_VBS_IDENTITY 이 형식은 생성된 클레임이 VBS ID/증명에 의해 생성됨을 나타냅니다. 즉, 클레임은 증명 플래그 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG 상승된 VBS 키에 의해 생성됩니다(아래 세부 정보 참조).

다음은 증명 클레임을 확인할 때 pParameterList 버퍼에서 설정할 버퍼 형식입니다.

  • NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

    dwClaimTypeNCRYPT_CLAIM_VBS_ROOT설정하여 NCryptVerifyClaimNCryptBufferDesc 출력 매개 변수에 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS 형식의 NCryptBuffer 항목으로 설정할 새 구조체입니다. 구조 정의는 다음과 같습니다.

    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 – ID 키에 대해 설정된 NCRYPT_VBS_KEY_FLAG_* 값의 조합입니다.
    • ullTrustletId – 클레임을 만든 VBS Trustlet의 정책 메타데이터에 하드 코딩된 식별자 정수입니다.
    • ulTrustletSecurityVersion – 클레임을 만든 VBS Trustlet의 보안 버전 번호입니다. 이 버전은 보안 업데이트가 trustlet에 적용된 것을 반영하고 결과적으로 보안 수준을 의미합니다.
    • ulTrustletDebuggable – 클레임을 만든 VBS Trustlet을 디버깅할 수 있는지를 나타냅니다. 1 값은 트러스트렛이 디버깅 가능하고 0 디버깅할 수 없는 트러스트렛을 나타냅니다.

    나중에 추가 정보 항목이 필요한 경우 새 구조체와 해당 구조체 형식이 정의됩니다.

    메모

    이 출력 매개 변수는 더 이상 참조되지 않은 후에 해제해야 합니다.

  • NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

    dwClaimType이 NCRYPT_CLAIM_VBS_IDENTITY설정된 NCryptVerifyClaim NCryptBufferDesc 출력 매개 변수에 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 형식의 NCryptBuffer 항목으로 설정할 새 구조체입니다. 구조 정의는 다음과 같습니다.

    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 – ID 키에 대해 설정된 NCRYPT_VBS_KEY_FLAG_* 값의 조합입니다.
    • pszSignatureHashAlg - 클레임 서명 해시 알고리즘의 유니코드 문자열에 대한 포인터입니다.
    • ulPaddingScheme - BCryptSignHash클레임 생성을 통해 사용된 서명 알고리즘의 패딩 체계입니다.
    • pszPaddingHashAlg - BCryptSignHash클레임 생성을 통해 사용되는 클레임 패딩 해시 알고리즘의 유니코드 문자열에 대한 포인터입니다.
    • ulPaddingSalt - BCryptSignHash클레임 생성을 통해 사용된 서명 알고리즘의 패딩 솔트입니다.

    나중에 추가 정보 항목이 필요한 경우 새 구조체와 해당 구조체 형식이 정의됩니다.

    메모

    이 출력 매개 변수는 더 이상 참조되지 않은 후에 해제해야 합니다. 이 매개 변수를 해제하기 위한 샘플 코드는아래 코드 예제에 제공됩니다.

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS

    NCryptVerifyClaimNCryptBufferDesc*pOutput 매개 변수의 매개 변수 NCryptBuffer 설정할 새 버퍼 형식입니다. 이 형식은 NCryptBuffer 데이터 구조 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS포함했음을 나타냅니다.

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS

    NCryptVerifyClaimNCryptBufferDesc*pOutput 매개 변수의 매개 변수 NCryptBuffer 설정할 새 버퍼 형식입니다. 이 형식은 NCryptBuffer 데이터 구조 NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS포함되었음을 나타냅니다.

  • NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG

    VBS에서 생성된 클레임을 확인하는 동안 dwFlags 입력 매개 변수에 설정할 새 플래그입니다. NCryptVerifyClaim 이 플래그를 설정하면 내부 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS 또는 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 매개 변수 버퍼 형식의 NCryptBufferDesc 출력 매개 변수가 생성됩니다.

    다음 표에서는 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사용하여 생성된 증명 클레임을 확인하는 방법을 보여 줍니다.

확인 API는 로컬(클레임 Blob을 생성한 컴퓨터에서) 또는 원격으로 호출될 수 있습니다. 확인 절차에는 클레임 생성 키에 해당하는 다음 요소가 필요합니다.

  • 클레임 Blob
  • 공용 증명 키 Blob
  • 공용 토큰(범용) 키 Blob

확인 API는 입력 플래그 NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG 설정된 경우 출력 정보 구조 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS 또는 NCRYPT_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 앱]
대상 플랫폼 Windows
헤더 ncrypt.h
라이브러리 Ncrypt.lib
DLL Ncrypt.dll