AWS CloudHSM
User Guide

Code Sample for Cavium CNG Provider

** Example code only - Not for production use **

This page includes example code that has not been fully tested. It is designed for test environments. Do not run this code in production.

The following sample shows how to enumerate the registered cryptographic providers on your system to find the Cavium CNG provider. The sample also shows how to create an asymmetric key pair and how to use the key pair to sign data.

Important

Before you run this example, you must set the n3fips_partition and n3fips_password environment variables. For details, see Windows AWS CloudHSM Prerequisites.

// CloudHsmCngExampleConsole.cpp : Console application that demonstrates CNG capabilities. // This example contains the following functions. // // VerifyProvider() - Enumerate the registered providers and retrieve Cavium KSP and CNG providers. // GenerateKeyPair() - Create an RSA key pair. // SignData() - Sign and verify data. // #include "stdafx.h" #include <Windows.h> #ifndef NT_SUCCESS #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #endif #define CAVIUM_CNG_PROVIDER L"Cavium CNG Provider" #define CAVIUM_KEYSTORE_PROVIDER L"Cavium Key Storage Provider" // Enumerate the registered providers and determine whether the Cavium CNG provider // and the Cavium KSP provider exist. // bool VerifyProvider() { NTSTATUS status; ULONG cbBuffer = 0; PCRYPT_PROVIDERS pBuffer = NULL; bool foundCng = false; bool foundKeystore = false; // Retrieve information about the registered providers. // cbBuffer - the size, in bytes, of the buffer pointed to by pBuffer. // pBuffer - pointer to a buffer that contains a CRYPT_PROVIDERS structure. status = BCryptEnumRegisteredProviders(&cbBuffer, &pBuffer); // If registered providers exist, enumerate them and determine whether the // Cavium CNG provider and Cavium KSP provider have been registered. if (NT_SUCCESS(status)) { if (pBuffer != NULL) { for (ULONG i = 0; i < pBuffer->cProviders; i++) { // Determine whether the Cavium CNG provider exists. if (wcscmp(CAVIUM_CNG_PROVIDER, pBuffer->rgpszProviders[i]) == 0) { printf("Found %S\n", CAVIUM_CNG_PROVIDER); foundCng = true; } // Determine whether the Cavium KSP provider exists. else if (wcscmp(CAVIUM_KEYSTORE_PROVIDER, pBuffer->rgpszProviders[i]) == 0) { printf("Found %S\n", CAVIUM_KEYSTORE_PROVIDER); foundKeystore = true; } } } } else { printf("BCryptEnumRegisteredProviders failed with error code 0x%08x\n", status); } // Free memory allocated for the CRYPT_PROVIDERS structure. if (NULL != pBuffer) { BCryptFreeBuffer(pBuffer); } return foundCng == foundKeystore == true; } // Generate an asymmetric key pair. As used here, this example generates an RSA key pair // and returns a handle. The handle is used in subsequent operations that use the key pair. // The key material is not available. // // The key pair is used in the SignData function. // NTSTATUS GenerateKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE *hKey) { NTSTATUS status; // Generate the key pair. status = BCryptGenerateKeyPair(hAlgorithm, hKey, 2048, 0); if (!NT_SUCCESS(status)) { printf("BCryptGenerateKeyPair failed with code 0x%08x\n", status); return status; } // Finalize the key pair. The public/private key pair cannot be used until this // function is called. status = BCryptFinalizeKeyPair(&hKey, 0); if (!NT_SUCCESS(status)) { printf("BCryptFinalizeKeyPair failed with code 0x%08x\n", status); return status; } return status; } // Sign and verify data using the RSA key pair. The data in this function is hardcoded // and is for example purposes only. // NTSTATUS SignData(BCRYPT_KEY_HANDLE hKey) { NTSTATUS status; PBYTE sig; ULONG sigLen; ULONG resLen; BCRYPT_PKCS1_PADDING_INFO pInfo; // Hardcode the data to be signed (for demonstration purposes only). PBYTE message = (PBYTE)"d83e7716bed8a20343d8dc6845e574477e4a9be63a80a0122f1fdcaa7a3c18c3"; ULONG messageLen = strlen((char*)message); // Retrieve the size of the buffer needed for the signature. status = BCryptSignHash(hKey, NULL, message, messageLen, NULL, 0, &sigLen, 0); if (!NT_SUCCESS(status)) { printf("BCryptSignHash failed with code 0x%08x\n", status); return status; } // Allocate a buffer for the signature. sig = (PBYTE)HeapAlloc(GetProcessHeap(), 0, sigLen); if (sig == NULL) { return -1; } // Use the SHA256 algorithm to create padding information. pInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; // Create a signature. status = BCryptSignHash(hKey, &pInfo, message, messageLen, sig, sigLen, &resLen, BCRYPT_PAD_PKCS1); if (!NT_SUCCESS(status)) { printf("BCryptSignHash failed with code 0x%08x\n", status); return status; } // Verify the signature. status = BCryptVerifySignature(hKey, &pInfo, message, messageLen, sig, sigLen, 0); if (!NT_SUCCESS(status)) { printf("BCryptVerifySignature failed with code 0x%08x\n", status); return status; } // Free the memory allocated for the signature. if (sig != NULL) { HeapFree(GetProcessHeap(), 0, sig); sig = NULL; } return 0; } // Main function. // int main() { NTSTATUS status; BCRYPT_ALG_HANDLE hRsaAlg; BCRYPT_KEY_HANDLE hKey = NULL; // Enumerate the registered providers. printf("Searching for Cavium providers...\n"); if (VerifyProvider() == false) { printf("Could not find the CNG and Keystore providers\n"); return 1; } // Get the RSA algorithm provider from the Cavium CNG provider. printf("Opening RSA algorithm\n"); status = BCryptOpenAlgorithmProvider(&hRsaAlg, BCRYPT_RSA_ALGORITHM, CAVIUM_CNG_PROVIDER, 0); if (!NT_SUCCESS(status)) { printf("BCryptOpenAlgorithmProvider RSA failed with code 0x%08x\n", status); return status; } // Generate an asymmetric key pair using the RSA algorithm. printf("Generating RSA Keypair\n"); GenerateKeyPair(hRsaAlg, &hKey); if (hKey == NULL) { printf("Invalid key handle returned\n"); return 0; } printf("Done!\n"); // Sign and verify [hardcoded] data using the RSA key pair. printf("Sign/Verify data with key\n"); SignData(hKey); printf("Done!\n"); // Remove the key handle from memory. status = BCryptDestroyKey(hKey); if (!NT_SUCCESS(status)) { printf("BCryptDestroyKey failed with code 0x%08x\n", status); return status; } // Close the RSA algorithm provider. status = BCryptCloseAlgorithmProvider(hRsaAlg, NULL); if (!NT_SUCCESS(status)) { printf("BCryptCloseAlgorithmProvider RSA failed with code 0x%08x\n", status); return status; } return 0; }