Last active
October 31, 2018 13:25
-
-
Save johnallers/ead0d1e4e7dd47f2b0af2c53455e81ec to your computer and use it in GitHub Desktop.
Test basic CNG API methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <Windows.h> | |
#include <ncrypt.h> | |
#ifndef NT_SUCCESS | |
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) | |
#endif | |
#define CAVIUM_KEYSTORE_PROVIDER L"Cavium Key Storage Provider" | |
#define MS_KEY_STORAGE_PROVIDER L"Microsoft Software Key Storage Provider" | |
// Enumerate the registered providers and determine whether the Cavium CNG provider | |
// and the Cavium KSP provider exist. | |
// | |
void ListStorageProviders() | |
{ | |
NTSTATUS status; | |
ULONG cbBuffer = 0; | |
PCRYPT_PROVIDERS pBuffer = NULL; | |
bool foundCng = false; | |
bool foundKeystore = false; | |
DWORD pdwProviderCount = 0; | |
NCryptProviderName* ppProviderList = NULL; | |
NCryptEnumStorageProviders(&pdwProviderCount, &ppProviderList, NCRYPT_SILENT_FLAG); | |
if (ppProviderList != NULL) | |
{ | |
for (DWORD i = 0; i < pdwProviderCount; i++) | |
{ | |
NCryptProviderName current = ppProviderList[i]; | |
printf("Found %S\n", current.pszName); | |
} | |
} | |
// Free memory allocated for the CRYPT_PROVIDERS structure. | |
if (NULL != ppProviderList) | |
{ | |
NCryptFreeBuffer(ppProviderList); | |
} | |
} | |
// 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 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 KSP provider exists. | |
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 foundKeystore == true; | |
} | |
void CheckHardwareImpl(NCRYPT_HANDLE hProv) { | |
DWORD type = 0; | |
DWORD size = sizeof(type); | |
NCryptGetProperty(hProv, NCRYPT_IMPL_TYPE_PROPERTY, PBYTE(type), size, &size, 0); | |
if ((type & NCRYPT_IMPL_HARDWARE_FLAG) == 0) | |
{ | |
printf("Provider DOES NOT contain NCRYPT_IMPL_HARDWARE_FLAG\n"); | |
} | |
else | |
{ | |
printf("Provider contains NCRYPT_IMPL_HARDWARE_FLAG\n"); | |
} | |
} | |
// 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 GenerateEphemeralKeyPair(NCRYPT_PROV_HANDLE hProv, NCRYPT_KEY_HANDLE *hKey) | |
{ | |
NTSTATUS status; | |
// Generate the key pair. | |
status = NCryptCreatePersistedKey(hProv, hKey, L"RSA", NULL, 0, 0); | |
if (!NT_SUCCESS(status)) | |
{ | |
printf("NCryptCreatePersistedKey failed with code 0x%08x\n", status); | |
return status; | |
} | |
// Set export policy to no export | |
DWORD exportPolicy = 0; | |
NCryptSetProperty((NCRYPT_HANDLE)hKey, NCRYPT_EXPORT_POLICY_PROPERTY, PBYTE(exportPolicy), sizeof(exportPolicy), 0); | |
// Finalize the key pair. The public/private key pair cannot be used until this | |
// function is called. | |
status = NCryptFinalizeKey(*hKey, NCRYPT_SILENT_FLAG); | |
if (!NT_SUCCESS(status)) | |
{ | |
printf("NCryptFinalizeKey failed with code 0x%08x\n", status); | |
return status; | |
} | |
return status; | |
} | |
// Main function. | |
// | |
int main() | |
{ | |
NTSTATUS status; | |
NCRYPT_KEY_HANDLE hKey = NULL; | |
NCRYPT_PROV_HANDLE hProv = NULL; | |
printf("Available storage providers...\n"); | |
ListStorageProviders(); | |
// Enumerate the registered providers. | |
printf("Searching for Cavium providers...\n"); | |
if (VerifyProvider() == false) { | |
printf("Could not find the Keystore providers\n"); | |
return 1; | |
} | |
// Opening the Cavium Keystore Provider | |
status = NCryptOpenStorageProvider(&hProv, CAVIUM_KEYSTORE_PROVIDER, NCRYPT_SILENT_FLAG); | |
if (!NT_SUCCESS(status)) | |
{ | |
printf("NCryptOpenStorageProvider failed with code 0x%08x\n", status); | |
return status; | |
} | |
CheckHardwareImpl(hProv); | |
// Generate an asymmetric key pair using the RSA algorithm. | |
printf("Generating RSA Keypair\n"); | |
GenerateEphemeralKeyPair(hProv, &hKey); | |
if (hKey == NULL) | |
{ | |
printf("Invalid key handle returned\n"); | |
return 0; | |
} | |
printf("Done!\n"); | |
if (hProv != NULL) | |
{ | |
NCryptFreeBuffer(&hProv); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment