Partilhar via


Função NCryptVerifyClaim (ncrypt.h)

Verifica uma declaração de atestado de chave.

Sintaxe

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
);

Parâmetros

[in] hSubjectKey

O identificador de chave do assunto para a declaração.

[in, optional] hAuthorityKey

O identificador de chave de autoridade a ser usado ao verificar a declaração. Esse parâmetro é opcional porque a chave de autoridade é independente para determinados tipos de declaração.

[in] dwClaimType

O tipo de declaração.

[in, optional] pParameterList

Uma lista de parâmetros opcional.

[in] pbClaimBlob

O blob de declaração de entrada.

[in] cbClaimBlob

O tamanho, em bytes, do buffer de pbClaimBlob.

[out] pOutput

O blob de saída.

[in] dwFlags

NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG é um novo sinalizador a ser definido durante a verificação de uma declaração gerada por VBS. Consulte a seção comentários para obter mais informações.

No momento, não há outros sinalizadores definidos. O parâmetro dwFlags deve ser definido como para todos os outros tipos de verificação.

Valor de retorno

Retorna um código de status que indica o êxito ou a falha da função.

Veja a seguir alguns dos códigos de erro que podem ser retornados da API de verificação ao verificar declarações de atestado de proteção de chave VBS:

Código de retorno Significado
NTE_BAD_TYPE O parâmetro de entrada do tipo de declaração é diferente do tipo do blob de declaração de entrada.
STATUS_BAD_DATA O blob de declaração de entrada é inválido.
STATUS_NO_MEMORY Falha na alocação de memória (necessária para verificação de declaração).
STATUS_INVALID_PARAMETER Falta um parâmetro de entrada obrigatório ou um dos parâmetros tem um valor ilegal.
STATUS_FAIL_CHECK As verificações da declaração de blob de entrada falharam.
NTE_BAD_VER A versão do blob de declaração não corresponde à implementação de verificação.
NTE_BAD_FLAGS Não há suporte para os sinalizadores fornecidos em dwFlags.

Observações

Protegendo/atestando chaves privadas usando a VBS (Virtualization Based Security)

Nota

Informações sobre sinalizadores VBS referem-se ao produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.

Essa API ajuda a habilitar um atestado avançado de chaves de segurança com base na proteção de chave VBS, um módulo do Windows para proteger e atestar chaves privadas usando VBS. O atestado de uma chave de segurança prova a associação dessa chave a uma chave ancorada, também conhecida como uma chave de atestado. Essa funcionalidade pode aprimorar o nível de segurança de comunicação entre diferentes entidades restringindo o uso de chaves fora de contexto.

A API define novos sinalizadores para dar suporte à criação e verificação de declarações de atestado com base em chaves de atestado na proteção de chave VBS.

Veja a seguir tipos de dwClaimType definidos para a API:

Tipo de declaração Descrição
NCRYPT_CLAIM_VBS_ROOT Esse tipo indica que a declaração gerada é produzida pela chave raiz do VBS.
NCRYPT_CLAIM_VBS_IDENTITY Esse tipo indica que a declaração gerada é produzida por uma identidade/atestado de VBS. Isso significa que a declaração é produzida por uma chave VBS que é elevada com o sinalizador de atestado NCRYPT_ALLOW_KEY_ATTESTATION_FLAG (consulte os detalhes abaixo).

Veja a seguir os tipos de buffer a serem definidos no buffer de pParameterList ao verificar uma declaração de atestado:

  • NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

    Uma nova estrutura a ser definida como um item de NCryptBuffer do tipo NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS no parâmetro de saída NCryptBufferDesc NCryptVerifyClaim com dwClaimType definido como NCRYPT_CLAIM_VBS_ROOT. A definição da estrutura é:

    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;
    

    A estrutura inclui estes itens:

    • ulKeyFlags – uma combinação de valores NCRYPT_VBS_KEY_FLAG_* que foram definidos para a chave de identidade.
    • ullTrustletId – um inteiro de identificador codificado em código nos metadados de política do VBS Trustlet que criou a declaração.
    • ulTrustletSecurityVersion – o número de versão de segurança do VBS Trustlet que criou a declaração. Esta versão reflete quais atualizações de segurança foram aplicadas ao trustlet e, consequentemente, implica o nível de sua segurança.
    • ulTrustletDebuggable – uma indicação se o Trustlet VBS que criou a declaração for depurável. Um valor 1 indica que o trustlet é depurável e um 0 indica um trustlet não depurável

    Se mais itens informativos forem necessários no futuro, uma nova estrutura e um tipo de estrutura correspondente serão definidos.

    Nota

    Esse parâmetro de saída deve ser liberado depois de não ser mais referenciado.

  • NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

    Uma nova estrutura a ser definida como um nCryptBuffer item do tipo NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS no parâmetro de saída NCryptBufferDesc NCryptVerifyClaim com dwClaimType definido como NCRYPT_CLAIM_VBS_IDENTITY. A definição da estrutura é:

    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;
    

    A estrutura inclui estes itens:

    • ulKeyFlags – uma combinação de valores NCRYPT_VBS_KEY_FLAG_* que foram definidos para a chave de identidade.
    • pszSignatureHashAlg – um ponteiro para uma cadeia de caracteres Unicode do algoritmo de hash de assinatura de declaração.
    • ulPaddingScheme – Esquema de preenchimento do algoritmo de assinatura que foi usado por meio da criação de declarações em BCryptSignHash.
    • pszPaddingHashAlg – um ponteiro para uma cadeia de caracteres Unicode do algoritmo de hash de preenchimento de declaração usado por meio da criação de declaração em BCryptSignHash.
    • ulPaddingSalt – Sal de preenchimento do algoritmo de assinatura que foi usado por meio da criação de declarações em BCryptSignHash.

    Se mais itens informativos forem necessários no futuro, uma nova estrutura e um tipo de estrutura correspondente serão definidos.

    Nota

    Esse parâmetro de saída deve ser liberado depois de não ser mais referenciado. O código de exemplo para liberar esse parâmetro é dado no exemplo de código abaixo.

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS

    Um novo tipo de buffer a ser definido em um parâmetro NCryptBuffer no parâmetro NCryptBufferDesc*pOutput de NCryptVerifyClaim. Esse tipo indica que o NCryptBuffer inclui a estrutura de dados NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS.

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS

    Um novo tipo de buffer a ser definido em um parâmetro NCryptBuffer no parâmetro NCryptBufferDesc*pOutput de NCryptVerifyClaim. Esse tipo indica que o NCryptBuffer inclui a estrutura de dados NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS.

  • NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG

    Esse é um novo sinalizador a ser definido no parâmetro de entrada dwFlags durante a verificação de uma declaração gerada por VBS. Quando esse sinalizador é definido NCryptVerifyClaim produz o parâmetro de saída NCryptBufferDesc com um tipo de buffer de parâmetro NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS ou NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS interno.

    A tabela a seguir descreve a relação entre os tipos de estrutura de dados de entrada e saída, em um cenário bem-sucedido com NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG:

    Entrada Saída
    dwClaimType = NCRYPT_CLAIM_VBS_ROOT NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS tipo de buffer com estrutura informativa NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS interna.
    dwClaimType = NCRYPT_CLAIM_VBS_IDENTITY NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS tipo de buffer com estrutura informativa NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS interna.

Exemplos

Este exemplo ilustra o uso da API existente para verificar as declarações de atestado que foram geradas com NCryptCreateClaim.

A API de verificação pode ser invocada localmente (no computador que gerou o blob de declaração) ou remotamente. O procedimento de verificação requer esses elementos, correspondentes às chaves de geração de declaração:

  • Blob de declaração
  • Blob de chave de atestado público
  • Blob de chave de token público (uso geral)

A API de verificação produzirá uma das estruturas informativas de saída NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS ou NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS se o sinalizador de entrada NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG estiver definido. A memória dessas estruturas é liberada no final do fluxo de código para evitar vazamentos de memória.

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;
}

Requisitos

Requisito Valor
de cliente com suporte mínimo Windows 10 [aplicativos da área de trabalho | Aplicativos UWP]
servidor com suporte mínimo Windows Server 2016 [aplicativos da área de trabalho | Aplicativos UWP]
da Plataforma de Destino Windows
cabeçalho ncrypt.h
biblioteca Ncrypt.lib
de DLL Ncrypt.dll