Compartir a través de


Función NCryptCreateClaim (ncrypt.h)

Crea una notificación de atestación de clave.

Sintaxis

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

Identificador de clave de asunto para el que se crea la notificación.

[in, optional] hAuthorityKey

La clave de autoridad controla que la notificación se basa.

[in] dwClaimType

Tipo de notificación.

[in, optional] pParameterList

Una lista de parámetros opcional.

[out] pbClaimBlob

Salida del blob de notificación creado.

[in] cbClaimBlob

Tamaño, en bytes, del búfer de pbClaimBlob.

[out] pcbResult

Salida del blob de notificación creado.

[in] dwFlags

Actualmente no hay marcas definidas. El parámetro dwFlags debe establecerse en .

Valor devuelto

Devuelve un código de estado que indica el éxito o error de la función.

Observaciones

Protección o atestación de claves privadas mediante la seguridad basada en virtualización (VBS)

Nota

La información relacionada con las marcas vbS está relacionada con el producto de versión preliminar que puede modificarse sustancialmente antes de su publicación comercial. Microsoft no ofrece ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Esta API ayuda a habilitar una atestación avanzada de claves de seguridad basadas en la protección de claves VBS, un módulo de Windows para proteger o atestiguar claves privadas mediante VBS. La atestación de una clave de seguridad demuestra la asociación de esta clave a una clave anclada, también conocida como clave de atestación. Esta funcionalidad puede mejorar el nivel de seguridad de la comunicación entre diferentes entidades al restringir el uso de claves fuera del contexto.

La API define nuevas marcas para admitir la creación y comprobación de notificaciones de atestación basadas en claves de atestación en la protección de claves de VBS.

A continuación se muestran dwClaimType tipos definidos para la API:

Tipo de notificación Descripción
NCRYPT_CLAIM_VBS_ROOT Este tipo indica que la notificación generada se genera mediante la clave raíz de VBS.
NCRYPT_CLAIM_VBS_IDENTITY Este tipo indica que la notificación generada se genera mediante una identidad o atestación de VBS. Esto significa que la notificación se genera mediante una clave VBS con privilegios elevados con la marca de atestación NCRYPT_ALLOW_KEY_ATTESTATION_FLAG (consulte los detalles a continuación).

A continuación se muestran los tipos de búfer que se establecerán en pParameterList búfer al crear una notificación de atestación:

Tipo de búfer Descripción
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH Tipo de búfer que se va a establecer en un búfer de parámetros al crear una notificación de atestación en NCryptCreateClaim. Este es un tipo de parámetro obligatorio para NCRYPT_CLAIM_VBS_IDENTITY notificaciones.

Este parámetro configura el tipo de función hash que se usará a través de la creación de notificaciones de atestación. Los valores de este parámetro se definen en ncrypt.h (como las constantes de identificadores de algoritmo de 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 Tipo de búfer que se va a establecer en un búfer de parámetros al crear una notificación de atestación en NCryptCreateClaim. Este es un parámetro obligatorio en caso de que la clave de atestación en la notificación de NCRYPT_CLAIM_VBS_IDENTITY creada sea una clave RSA.

Este parámetro configura el esquema de relleno para el tipo de función de firma que se usará a través de la creación de notificaciones de atestación. Los valores opcionales de este parámetro se definen en bcrypt.h (como las constantes de dwFlags en NCryptSignHash):

#define BCRYPT_PAD_PSS 0x00000008
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO Nuevo tipo de búfer que se va a establecer en un búfer de parámetros al crear una notificación de atestación en NCryptCreateClaim. Este es un parámetro obligatorio en caso de que la clave de atestación en la notificación de NCRYPT_CLAIM_VBS_IDENTITY creada sea una clave RSA. El parámetro es un puntero a una cadena Unicode terminada en null que identifica el algoritmo criptográfico que se va a usar para crear el relleno. Este algoritmo debe ser un algoritmo hash. Los valores de este parámetro se definen en ncrypt.h (como las constantes de identificadores de algoritmo de 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 Nuevo tipo de búfer que se va a establecer en un búfer de parámetros al crear una notificación de atestación en NCryptCreateClaim. Este es un parámetro obligatorio en caso de que la clave de atestación en la notificación de NCRYPT_CLAIM_VBS_IDENTITY creada sea una clave RSA.

El parámetro representa un tamaño, en bytes, de la sal aleatoria que se va a usar para el relleno.
NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE Tipo de búfer que se va a establecer en un búfer de parámetros al crear una notificación de atestación en NCryptCreateClaim. Este parámetro es un alias para NCRYPTBUFFER_CLAIM_KEYATTESTATION_NONCE.

Ejemplos

En este ejemplo se muestra el uso de la nueva marca de API NCRYPT_ALLOW_KEY_ATTESTATION_FLAG. Además, el tipo de parámetro NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE establece el valor nonce para la creación de la notificación.

El ejemplo consta de estos pasos principales:

  1. Se crea una nueva clave de atestación. La clave se especializa mediante la función de API NCryptSetProperty. La generación de una atestación se basa en una clave de firma.
  2. Se crea una notificación para una atestación adicional. La notificación está asociada a la clave de atestación y a una clave VBS integrada. La notificación se puede comprobar en NCryptVerifyClaim proporcionando la clave de atestación.
  3. El objeto de clave de atestación se libera para evitar la pérdida de memoria.
// 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;
}

En este ejemplo siguiente se muestra el uso de nuevos parámetros de API para crear una clave criptográfica de uso general y una notificación de atestación asociada. Esta clave de uso general se usa para generar una notificación de atestación.

El tipo de algoritmo hash y el relleno para la creación de notificaciones se establecen en los parámetros NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH y NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_[SCHEME/ALGO/SALT_SIZE] respectivamente.

Tenga en cuenta que:

  • El parámetro NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH solo es obligatorio para las notificaciones de NCRYPT_CLAIM_VBS_IDENTITY y sin sentido en otros tipos de notificaciones.
  • El parámetro NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING solo es obligatorio para las notificaciones de NCRYPT_CLAIM_VBS_IDENTITY en caso de una clave de atestación RSA. En otros tipos de notificaciones, no tiene sentido.

La notificación nos permite comprobar que la clave de uso general está asociada a la clave de atestación.

//
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
cliente mínimo admitido Windows 10 [aplicaciones de escritorio | Aplicaciones para UWP]
servidor mínimo admitido Windows Server 2016 [aplicaciones de escritorio | Aplicaciones para UWP]
de la plataforma de destino de Windows
encabezado de ncrypt.h
biblioteca de Ncrypt.lib
DLL de Ncrypt.dll