Поделиться через


Функция NCryptCreateClaim (ncrypt.h)

Создает утверждение аттестации ключей.

Синтаксис

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

Параметры

[in] hSubjectKey

Дескриптор ключа субъекта, для которому создается утверждение.

[in, optional] hAuthorityKey

Ключ центра обрабатывает утверждение на основе утверждения.

[in] dwClaimType

Тип утверждения.

[in, optional] pParameterList

Необязательный список параметров.

[out] pbClaimBlob

Выходные данные созданного большого двоичного объекта утверждения.

[in] cbClaimBlob

Размер в байтах буфера pbClaimBlob.

[out] pcbResult

Выходные данные созданного большого двоичного объекта утверждения.

[in] dwFlags

В настоящее время нет определенных флагов. Параметр dwFlags должен иметь значение .

Возвращаемое значение

Возвращает код состояния, указывающий на успешность или сбой функции.

Замечания

Защита и подтверждение закрытых ключей с помощью безопасности на основе виртуализации (VBS)

Заметка

Сведения о флагах VBS относятся к предварительному выпуску продукта, который может быть существенно изменен до выпуска. Корпорация Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых в отношении информации, предоставленной здесь.

Этот API позволяет включить расширенную аттестацию ключей безопасности на основе защиты ключей VBS, модуля Windows для защиты и проверки закрытых ключей с помощью VBS. Аттестация ключа безопасности подтверждает связь этого ключа с привязанным ключом и ключом аттестации. Эта возможность может повысить уровень безопасности взаимодействия между различными сущностями, ограничив использование ключей вне контекста.

API определяет новые флаги для поддержки создания и проверки утверждений аттестации на основе ключей аттестации в защите ключей VBS.

Ниже приведены типы dwClaimType, определенные для API:

Тип утверждения Описание
NCRYPT_CLAIM_VBS_ROOT Этот тип указывает, что созданное утверждение создается корневым ключом VBS.
NCRYPT_CLAIM_VBS_IDENTITY Этот тип указывает, что созданное утверждение создается удостоверением или аттестацией VBS. Это означает, что утверждение создается ключом VBS, который повышен с помощью флага аттестации NCRYPT_ALLOW_KEY_ATTESTATION_FLAG (см. подробные сведения ниже).

Ниже приведены типы буферов, которые необходимо задать в буфере pParameterList при создании утверждения аттестации:

Тип буфера Описание
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH Тип буфера, который необходимо задать в буфере параметров при создании утверждения аттестации в NCryptCreateClaim. Это обязательный тип параметра для утверждений NCRYPT_CLAIM_VBS_IDENTITY.

Этот параметр настраивает тип хэш-функции для использования с помощью создания утверждения аттестации. Значения этого параметра определяются в ncrypt.h (например, константы в идентификаторы алгоритма 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 Тип буфера, который необходимо задать в буфере параметров при создании утверждения аттестации в NCryptCreateClaim. Это обязательный параметр, если ключ аттестации в созданном утверждении NCRYPT_CLAIM_VBS_IDENTITY является ключом RSA.

Этот параметр настраивает схему заполнения для типа функции подписи для использования с помощью создания утверждения аттестации. Необязательные значения этого параметра определены в (например, константы dwFlags dwFlags в NCryptSignHash):

#define BCRYPT_PAD_PSS 0x00000008
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO Новый тип буфера, который необходимо задать в буфере параметров при создании утверждения аттестации в NCryptCreateClaim. Это обязательный параметр, если ключ аттестации в созданном утверждении NCRYPT_CLAIM_VBS_IDENTITY является ключом RSA. Параметр — это указатель на строку Юникода, завершающую значение NULL, которая идентифицирует алгоритм шифрования, используемый для создания заполнения. Этот алгоритм должен быть хэш-алгоритмом. Значения этого параметра определяются в ncrypt.h (например, константы в идентификаторы алгоритма 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 Новый тип буфера, который необходимо задать в буфере параметров при создании утверждения аттестации в NCryptCreateClaim. Это обязательный параметр, если ключ аттестации в созданном утверждении NCRYPT_CLAIM_VBS_IDENTITY является ключом RSA.

Параметр представляет размер в байтах случайной соли, используемой для заполнения.
NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE Тип буфера, который необходимо задать в буфере параметров при создании утверждения аттестации в NCryptCreateClaim. Этот параметр является псевдонимом для NCRYPTBUFFER_CLAIM_KEYATTESTATION_NONCE.

Примеры

В этом примере показано использование нового флага API NCRYPT_ALLOW_KEY_ATTESTATION_FLAG. Кроме того, значение nonce для создания утверждения задается типом параметра NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE.

Пример состоит из следующих основных шагов:

  1. Создается новый ключ аттестации. Ключ специализирован с помощью функции API NCryptSetProperty. Создание аттестации основано на ключе подписывания.
  2. Утверждение создается для дальнейшей аттестации. Утверждение связано с ключом аттестации и встроенным ключом VBS. Утверждение может быть проверено в NCryptVerifyClaim, предоставив ключ аттестации.
  3. Объект ключа аттестации освобождается, чтобы избежать утечки памяти.
// 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;
}

В следующем примере показано использование новых параметров API для создания криптографического ключа общего назначения и связанного утверждения аттестации. Этот ключ общего назначения используется для создания утверждения аттестации.

Хэш-алгоритм и заполнение для создания утверждений задаются в параметрах NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH и NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_[SCHEME/ALGO/SALT_SIZE] соответственно.

Обратите внимание, что:

  • Параметр NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH является обязательным только для NCRYPT_CLAIM_VBS_IDENTITY утверждений и без смысла в других типах утверждений.
  • Параметр NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING является обязательным только для утверждений NCRYPT_CLAIM_VBS_IDENTITY в случае ключа аттестации RSA. В других типах утверждений это бессмысленно.

Утверждение позволяет проверить, связан ли ключ общего назначения с ключом аттестации.

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

Требования

Требование Ценность
минимальные поддерживаемые клиентские Windows 10 [классические приложения | Приложения UWP]
минимальный поддерживаемый сервер Windows Server 2016 [классические приложения | Приложения UWP]
целевая платформа Виндоус
заголовка ncrypt.h
библиотеки Ncrypt.lib
DLL Ncrypt.dll