Compartilhar via


Função NCryptCreateClaim (ncrypt.h)

Cria uma declaração de atestado de chave.

Sintaxe

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

Parâmetros

[in] hSubjectKey

O identificador de chave de assunto para o qual a declaração é criada.

[in, optional] hAuthorityKey

O identificador de chave de autoridade no qual a declaração se baseia.

[in] dwClaimType

O tipo de declaração.

[in, optional] pParameterList

Uma lista de parâmetros opcional.

[out] pbClaimBlob

Saída do blob de declaração criado.

[in] cbClaimBlob

O tamanho, em bytes, do buffer de pbClaimBlob.

[out] pcbResult

A saída do blob de declaração criado.

[in] dwFlags

No momento, não há nenhum sinalizador definido. O parâmetro dwFlags deve ser definido como .

Valor de retorno

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

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/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 em buffer de pParameterList ao criar uma declaração de atestado:

Tipo de buffer Descrição
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH Um tipo de buffer a ser definido em um buffer de parâmetro ao criar uma declaração de atestado no NCryptCreateClaim. Esse é um tipo de parâmetro obrigatório para declarações NCRYPT_CLAIM_VBS_IDENTITY.

Esse parâmetro configura o tipo de função de hash a ser usado por meio da criação da declaração de atestado. Os valores para esse parâmetro são definidos em ncrypt.h (como as constantes em identificadores de algoritmo CNG):

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME Um tipo de buffer a ser definido em um buffer de parâmetro ao criar uma declaração de atestado no NCryptCreateClaim. Esse é um parâmetro obrigatório caso a chave de atestado na declaração de NCRYPT_CLAIM_VBS_IDENTITY criada seja uma chave RSA.

Esse parâmetro configura o esquema de preenchimento para o tipo de função de assinatura a ser usado por meio da criação da declaração de atestado. Os valores opcionais para esse parâmetro são definidos em (como as constantes dwFlags em NCryptSignHash ):

#define BCRYPT_PAD_PSS 0x00000008
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO Um novo tipo de buffer a ser definido em um buffer de parâmetro ao criar uma declaração de atestado no NCryptCreateClaim. Esse é um parâmetro obrigatório caso a chave de atestado na declaração de NCRYPT_CLAIM_VBS_IDENTITY criada seja uma chave RSA. O parâmetro é um ponteiro para uma cadeia de caracteres Unicode terminada em nulo que identifica o algoritmo criptográfico a ser usado para criar o preenchimento. Esse algoritmo deve ser um algoritmo de hash. Os valores para esse parâmetro são definidos em ncrypt.h (como as constantes em identificadores de algoritmo CNG):

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE Um novo tipo de buffer a ser definido em um buffer de parâmetro ao criar uma declaração de atestado no NCryptCreateClaim. Esse é um parâmetro obrigatório caso a chave de atestado na declaração de NCRYPT_CLAIM_VBS_IDENTITY criada seja uma chave RSA.

O parâmetro representa um tamanho, em bytes, do sal aleatório a ser usado para o preenchimento.
NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE Um tipo de buffer a ser definido em um buffer de parâmetro ao criar uma declaração de atestado em NCryptCreateClaim. Esse parâmetro é um alias para NCRYPTBUFFER_CLAIM_KEYATTESTATION_NONCE.

Exemplos

Este exemplo ilustra o uso do novo sinalizador de API NCRYPT_ALLOW_KEY_ATTESTATION_FLAG. Além disso, o valor de nonce para a criação da declaração é definido pelo tipo de parâmetro NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE.

O exemplo consiste nestas etapas principais:

  1. Uma nova chave de atestado é criada. A chave é especializada usando a função de API NCryptSetProperty. A geração de um atestado baseia-se em uma chave de assinatura.
  2. Uma declaração é criada para atestado adicional. A declaração está associada à chave de atestado e a uma chave VBS interna. A declaração pode ser verificada em NCryptVerifyClaim fornecendo a chave de atestado.
  3. O objeto de chave de atestado é liberado para evitar perda de memória.
// Create an attestation/identity key. This function is invoked in the main code flow below.
NCRYPT_KEY_HANDLE CreateAttestationKey(NCRYPT_PROV_HANDLE provider)
{

    NCRYPT_KEY_HANDLE attestationKey = NULL;
    HRESULT hr;

    if (FAILED(hr = NCryptCreatePersistedKey(
                    provider,
                    &attestationKey,
                    BCRYPT_RSA_ALGORITHM,
                    L"AttestationKey", // a unique name for the attestation key in the key store
                    0, //dwLegacyKeySpec, not used
                    NCRYPT_REQUIRE_VBS_FLAG/*This flag targets VBS */)))
    {
        wprintf(L"Error creating an Attestation Identity Key with NCryptCreatePersistedKey(): 0x%X\n", hr);
        goto cleanup;
    }

    // This is a new flag. It’s used to enable the capability in an attestation key.
    DWORD keyUsagePolicy = NCRYPT_ALLOW_KEY_ATTESTATION_FLAG;
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_KEY_USAGE_PROPERTY,
                    (PUCHAR)&keyUsagePolicy,
                    sizeof(keyUsagePolicy),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }

    DWORD keySizeBits = 2048; // minimum allowed RSA key size
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_LENGTH_PROPERTY,
                    (PUCHAR)&keySizeBits,
                    sizeof(keySizeBits),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }
    
    if (FAILED(hr = NCryptFinalizeKey(attestationKey, 0 /*dwFlags*/)))
    {
        wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
        goto cleanup;
    }

    return attestationKey;
cleanup:
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }

    return NULL;
}

HRESULT CreateAttestation()
{
    HRESULT hr = S_OK;
    NCRYPT_PROV_HANDLE provider = NULL;
    
    BYTE nonce[] = "TheSuperSecretNonce";
    // This way of setting parameters is an existent pattern for NCrypt APIs
    NCryptBuffer paramBuffers[] =
    {
        { sizeof(nonce), NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE, (PBYTE)&nonce },
    };
    NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };
    
    if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
    {
        wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
        goto cleanup;
    }
    
    // Create a VBS attestation key
    NCRYPT_KEY_HANDLE attestationKey = CreateAttestationKey(provider);
    if (attestationKey == NULL)
    {
        hr = E_ABORT;
        goto cleanup;
    }
    
    DWORD bytesWritten = 0;
    
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, // implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest a key with IDKS (VBS root signing key).
                    &params, // parameters list
                    NULL, // getting the size
                    0, // getting the size
                    &bytesWritten,
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    DWORD claimBufferSize = bytesWritten;
    
    PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
    if (NULL == claimBuffer)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
        goto cleanup;
    }
    
    bytesWritten = 0;
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, //implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest with IDKS (VBS root signing key).
                    &params, // parameters list
                    claimBuffer,
                    claimBufferSize,
                    &bytesWritten,
                    0)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
        NCryptFreeObject(provider);
    }
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }
    if (claimBuffer)
    {
        HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
    return hr;
}

Este próximo exemplo ilustra o uso de novos parâmetros de API para criar uma chave criptográfica de uso geral e uma declaração de atestado associada. Essa chave de uso geral é usada para gerar uma declaração de atestado.

O tipo de algoritmo de hash e o preenchimento para a criação da declaração são definidos nos parâmetros NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH e NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_[SCHEME/ALGO/SALT_SIZE], respectivamente.

Observe que:

  • O parâmetro NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH é obrigatório apenas para declarações NCRYPT_CLAIM_VBS_IDENTITY e sem sentido em outros tipos de declarações.
  • O parâmetro NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING é obrigatório apenas para declarações NCRYPT_CLAIM_VBS_IDENTITY no caso de uma chave de atestado RSA. Em outros tipos de declarações, não tem sentido.

A declaração nos permite verificar se a chave de uso geral está associada à chave de atestado.

//
HRESULT hr = S_OK;
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 attestationKey = NULL;

// Open the attestation key, created in CreateAttestationKey(), see previous example
if (FAILED(hr = NCryptOpenKey(
                provider,
                &attestationKey,
                L"AttestationKey",
                0, //dwLegacyKeySpec, not used
                0 ,/* dwFlags */)))
{
    wprintf(L"Error openning the attestation key with NCryptOpenKey (): 0x%X\n", hr);
    goto cleanup;
}

NCRYPT_KEY_HANDLE tokenKey = NULL; // Token key that is bound to the security token

// Create VBS token (general purpose) key
if (FAILED(hr = NCryptCreatePersistedKey(
                provider,
                &tokenKey,
                BCRYPT_RSA_ALGORITHM,
                L"TokenKey",
                0, //dwLegacyKeySpec, not used
                NCRYPT_REQUIRE_VBS_FLAG /*This flag targets VBS*/)))
{
    wprintf(L"Error creating an token key with NCryptCreatePersistedKey(): 0x%X\n", hr);
    goto cleanup;
}

DWORD keySizeBits = 2048;
if (FAILED(hr = NCryptSetProperty(
                tokenKey,
                NCRYPT_LENGTH_PROPERTY,
                (PUCHAR)&keySizeBits,
                sizeof(keySizeBits),
                0 /*dwFlags*/)))
{
    wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
    goto cleanup;
}

if (FAILED(hr = NCryptFinalizeKey(tokenKey, 0 /*dwFlags*/)))
{
    wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
    goto cleanup;
}

DWORD bytesWritten = 0;

DWORD hashAlgoType; // This is a new flag. It’s used to set type of hash algorithm of the claim// Set specific hash function type to produce the claim
wchar_t pHashAlgo[] = NCRYPT_SHA512_ALGORITHM;
// Set specific padding scheme for hash function to produce the claim
ULONG paddingScheme = BCRYPT_PAD_PSS;
wchar_t pPaddingAlgo[] = NCRYPT_SHA256_ALGORITHM;
ULONG paddingSalt = 345;

// This way of setting parameters is an existent pattern for NCrypt APIs
NCryptBuffer paramBuffers[] =
{
    { sizeof(NCRYPT_SHA512_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH, (PBYTE)&pHashAlgo },
    { sizeof(paddingScheme), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME , (PBYTE)&paddingScheme },
    { sizeof(NCRYPT_SHA256_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO, (PBYTE)&pPaddingAlgo },
    { sizeof(paddingSalt, NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE, (PBYTE)&paddingSalt }
};
NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey,
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key.
                &params, // parameters list
                NULL, // getting the size
                0, // getting the size
                &bytesWritten,
                0 /*dwFlags*/)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

DWORD claimBufferSize = bytesWritten;

PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
if (NULL == claimBuffer)
{
    hr = HRESULT_FROM_WIN32(GetLastError());
    wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
    goto cleanup;
}
bytesWritten = 0;

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey, // we assume that it is already initialized
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key
                &params,
                claimBuffer,
                claimBufferSize,
                &bytesWritten,
                0)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
    NCryptFreeObject(provider);
    }
    if (tokenKey != NULL)
    {
    NCryptFreeObject(tokenKey);
    }
    if (attestationKey != NULL)
    {
    NCryptDeleteKey(attestationKey);
    }
    if (claimBuffer)
    {
    HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
return hr;

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