Ejemplo de código para proveedor de GNC

Descubra cómo indexar los proveedores criptográficos registrados en Dedicated KMS para encontrar el proveedor de GNV instalado con el instalador del cliente de Windows mediante el código de ejemplo proporcionado.

El siguiente código de ejemplo muestra cómo indexar los proveedores criptográficos registrados para encontrar el proveedor de GNC instalado con el instalador del cliente de Windows. El código también muestra cómo crear un par de claves asimétricas y cómo utilizar el par de claves para firmar datos.

Nota

Antes de ejecutar este ejemplo, debe configurar las credenciales de HSM. Para obtener más información, consulte Setting up the HSM Cluster Client in Windows.

#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>


int testReturnStatus = 0;

BCRYPT_KEY_HANDLE GenerateKeyPair(
	BCRYPT_ALG_HANDLE   hAlg,
	ULONG				keyLen)
{
	NTSTATUS            status = -1;
	BCRYPT_KEY_HANDLE	keyHandle = NULL;

	print_debug("Generating Key Pair of size: %lu\n", keyLen);
	status = BCryptGenerateKeyPair(hAlg, &keyHandle, keyLen, 0);
	if (status)
	{
		ReportErrorStatus(status, "\t\t\t\t\t\t\t FAIL BCryptGenerateKeyPair");
		goto cleanup;
	}
	/* Finalize RSA keys generated */
	status = BCryptFinalizeKeyPair(keyHandle, 0);
	if (status)
	{
		ReportErrorStatus(status, "\t\t\t\t\t\t\t FAIL BCryptFinalizeKeyPair");
		goto cleanup;
	}
	print_debug("Keypair Gen Success\n");
	ReportErrorStatus(status, "\t\t PASS\n");
	return keyHandle;
cleanup:
	if (keyHandle) {
		status = BCryptDestroyKey(keyHandle);
		keyHandle = NULL;
		if (status)
			ReportErrorStatus(status, "BCryptDestroyKey");
	}

	return keyHandle;
}


static NTSTATUS testSignVerify(
	PBYTE				test,
	BCRYPT_KEY_HANDLE	signKey,
	BCRYPT_KEY_HANDLE	verifyKey,
	ULONG				keyLen,
	VOID				*pPaddingInfo)
{
	NTSTATUS			status = -1;
	BYTE                inbuf[CHUNK_SIZE];
	BYTE				hash[CHUNK_SIZE];
	DWORD				hash_size;
	PBYTE				sign = NULL;
	DWORD				i;
	DWORD               insize;
	DWORD				pcbResult = 0;
	ULONG				dwFlags = 0;

	if (signKey == NULL || verifyKey == NULL) {
		status = STATUS_INVALID_HANDLE;
		goto cleanup;
	}

	printf("%s", test);

	/* Fill input data; Alternatively can read from file */
	for (i = 0; i < CHUNK_SIZE; i++)
		inbuf[i] = (BYTE)i + 1;
	insize = i;/* Length of inbuf */
	if (pPaddingInfo)
		dwFlags = BCRYPT_PAD_PKCS1;
	// calculate the size of sign data needed
	status = BCryptSignHash(signKey,
		pPaddingInfo,
		hash,
		CHUNK_SIZE,
		NULL,
		0,
		&pcbResult,
		dwFlags
		);
	if (status)
	{
		ReportErrorStatus(status, "\t\t FAIL BCryptSignHash get-size");
		goto cleanup;
	}
	print_debug("required sign data size: %lu\n", pcbResult);

	status = CreateHash(BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, inbuf, insize, hash, &hash_size, NULL, 0, 0);
	if (status)
		goto cleanup;

	sign = (PBYTE)HEAPALLOC(pcbResult);
	if (sign == NULL) {
		status = STATUS_UNSUCCESSFUL;
		goto cleanup;
	}
	status = BCryptSignHash(signKey,
		pPaddingInfo,
		hash,
		hash_size,
		sign,
		pcbResult,
		&pcbResult,
		dwFlags
		);
	if (status)
	{
		ReportErrorStatus(status, "\t\t FAIL BCryptSignHash");
		goto cleanup;
	}
	print_debug("signed data size: %lu\n", pcbResult);
	print_debug("Created Signature from Hash using MS Key Success\n");

	/* Verify Signature with Cavium key*/
	status = BCryptVerifySignature(verifyKey,
		pPaddingInfo,
		hash,
		hash_size,
		sign,
		pcbResult,
		dwFlags);
	if (status)
	{
		ReportErrorStatus(status, "\t\t FAIL BCryptVerifySignature");
		goto cleanup;
	}
	print_debug("Verifying Signature SUCCESS\n");
	ReportErrorStatus(status, "\t\t PASS\n");
cleanup:
	if (sign)
		HeapFree(GetProcessHeap(), 0, sign);
	return status;
}


static void testRSA()
{
	NTSTATUS            status = STATUS_UNSUCCESSFUL;
	LPCWSTR				pszAlgId = NULL;
	BCRYPT_ALG_HANDLE   caviumAlg = NULL;
	BCRYPT_ALG_HANDLE   msAlg = NULL;
	EncDecPriv			priv = { 0 };
	ULONG				keyLen = 2048;
	

	pszAlgId = BCRYPT_RSA_ALGORITHM;

	//open Cavium CNG Provider
	caviumAlg = OpenAlgorithmProvider(pszAlgId, CAVIUM_PROVIDER_NAME, 0);
	if (caviumAlg == NULL)
		goto cleanup;
	//open Microsoft Primitive Provider
	msAlg = OpenAlgorithmProvider(pszAlgId, MS_PRIMITIVE_PROVIDER, 0);
	if (msAlg == NULL)
		goto cleanup;

	// fill priv structure
	priv.alg = RSA;
	priv.blockSize = 1;

	printf("\n\n############################# %ls Unit Testing ########################################\n\n", pszAlgId);
	printf("KeyLen\t   Test\t\t      Info\t\t\t Result\n");
	printf("=======================================================================================\n");
	for (keyLen = 2048; keyLen <= 4096; keyLen = keyLen + 256) {
		printf("\n%lu\n", keyLen);
		priv.keyLen = keyLen;
		status = testRSACommon(caviumAlg, msAlg, &priv);
#ifdef RUN_MINIMAL_TEST
		/* To test functionality with RSA 2048 key size only, break now. */
		break; /* This will be suitable if we are running these tests in PR checker kind of build.*/
#endif
	}

cleanup:
	if (caviumAlg)
		CloseAlgorithmProvider(caviumAlg, 0);
	if (msAlg)
		CloseAlgorithmProvider(msAlg, 0);
	return;
}