Code Example for CNG Provider
Learn how to index the registered cryptographic providers in Dedicated KMS to find the CNG provider installed with the Windows client installer using the provided example code.
The following example code shows how to index the registered cryptographic providers to find the CNG provider installed with the Windows client installer. The code also shows how to create an asymmetric key pair and how to use the key pair to sign data.
Note
Before you run this example, you must set up the HSM credentials. For more information, see 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;
}