How to CopyMemory to copy struct using FileMapping? - c

I have following code, after CopyMemory my pBuf is empty, it contains no data from newCommand, or when I want to add something in that struct it doesnt work... What am I doing wrong?
struct StCommand
{
TCHAR sourcePath[MAX_PATH];
TCHAR sourceFile[MAX_PATH];
TCHAR fileName[MAX_PATH];
bool endThread;
};
handlesInstance.mapFileHandle = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
sizeof(StCommand), // maximum object size (low-order DWORD)
handlesInstance.valueBuffer); // name of mapping object
if (handlesInstance.mapFileHandle == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 0;
}
handlesInstance.pBuf = (StCommand*) MapViewOfFile(
handlesInstance.mapFileHandle, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
sizeof(StCommand));
if (handlesInstance.pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
return 0;
}
StCommand newCommand = { NULL, NULL, NULL, false };
CopyMemory(handlesInstance.pBuf, &newCommand, sizeof(StCommand));
CopyFiles(*handlesInstance.pBuf);
Here is CopyFiles function, where I send (*handlesInstance.pBuf) and I want to set values of pBuf here, to create path, to copy file later
void CopyFiles(StCommand stCommand)
{
while (!stCommand.endThread)
{
DWORD dwWaitEventResult;
dwWaitEventResult = WaitForSingleObject(handlesInstance.dataInEvent, INFINITE);
switch (dwWaitEventResult)
{
// Event object was signaled
case WAIT_OBJECT_0:
{
//Command processing
if (!stCommand.endThread)
{
GetSzSetting(pathValueName, REPOSITORY_PATH);
TCHAR newFile[MAX_PATH];
_tcscpy_s(newFile, handlesInstance.valueBuffer);
_tcscat_s(newFile, _T("/"));
TCHAR buffer[MAX_PATH];
swprintf_s(buffer, _T("%d"), GetDwordSetting(indexValueName, 0));
_tcscat_s(newFile, buffer);
_tcscat_s(newFile, _T("."));
_tcscat_s(newFile, stCommand.fileName);
TCHAR oldFile[MAX_PATH];
_tcscpy_s(oldFile, stCommand.sourcePath);
_tcscat_s(oldFile, _T("/"));
_tcscat_s(oldFile, stCommand.fileName);
if (CopyFile(oldFile, newFile, FALSE))
{
_tprintf(_T("File %s copied successfully into repository.\n"), stCommand.fileName);
SetDwordSetting(indexValueName, GetDwordSetting(indexValueName, 0) + 1);
}
else
{
_tprintf(_T("Could not copy file %s.\n"), stCommand.fileName);
_tprintf(_T("Failed with error code: %d\n"), GetLastError());
}
}
ResetEvent(handlesInstance.dataInEvent);
if (!SetEvent(handlesInstance.dataOutEvent))
{
printf("SetEvent OutEvent failed (%d)\n", GetLastError());
}
break;
}
// An error occurred
default:
printf("Wait error (%d)\n", GetLastError());
break;
}
}
}

Related

How to get the process name based on hwnd in C

Programming language: C
Objective: Get the process id and name based on the current hwnd.
Current code:
HWND hwnd;
DWORD process_ID;
PWSTR process_name = NULL;
hwnd = GetForegroundWindow();
process_ID = GetWindowThreadProcessId(hwnd,&process_ID)
process_name = ????
I am not sure if I am passing correctly the arguments to the function GetWindowThreadProcessId. I found on Internet that I could use GetModuleFileNameW to get the process name but I cannot understand the documentation. Please forgive me if it is too easy to solve. I am starting in the world of C. Thanks in advance
The return value of GetWindowThreadProcessId() is a thread ID, not a process ID, so DO NOT assign that return value to your process_ID variable, or else it will overwrite the value that was output by the lpdwProcessId parameter.
HWND hwnd = GetForegroundWindow();
DWORD process_ID = 0;
if (GetWindowThreadProcessId(hwnd, &process_ID))
{
// get the process name ...
}
else
{
// error handling ...
}
Once you have the process ID, you can pass it to OpenProcess() to get a HANDLE to the running process, and then use that HANDLE with either GetModuleFileNameEx(), GetProcessImageFileName() (XP+), or QueryFullProcessImageName() (Vista+) to get the full path and filename of that process's EXE file:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
if (GetModuleFileNameExW(hProcess, NULL, process_name, MAX_PATH))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
if (GetProcessImageFileNameW(hProcess, process_name, MAX_PATH))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
DWORD size = MAX_PATH;
if (QueryFullProcessImageNameW(hProcess, 0, process_name, &size))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}

monitor session change event in c

I try to build a service that monitor user sessions activity. currently focusing on logon and lock of user.
i am using http://msdn.microsoft.com/en-us/library/bb540475(v=VS.85).aspx example
my code :
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#pragma comment(lib, "advapi32.lib")
#define SVCNAME TEXT("SvcName")
#define SVC_ERROR 4
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
VOID SvcInstall(void);
DWORD WINAPI SvcCtrlHandler(DWORD , DWORD , LPVOID , LPVOID );
VOID WINAPI SvcMain(DWORD, LPTSTR *);
VOID ReportSvcStatus(DWORD, DWORD, DWORD);
VOID SvcInit(DWORD, LPTSTR *);
VOID SvcReportEvent(LPTSTR);
void __cdecl _tmain(int argc, TCHAR *argv[])
{
if (lstrcmpi(argv[1], TEXT("install")) == 0)
{
SvcInstall();
return;
}
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
VOID SvcInstall()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];
if (!GetModuleFileName(NULL, szPath, MAX_PATH))
{
printf("Cannot install service (%d)\n", GetLastError());
return;
}
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Create the service
schService = CreateService(
schSCManager, // SCM database
SVCNAME, // name of service
SVCNAME, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
{
printf("CreateService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else printf("Service installed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME,SvcCtrlHandler,NULL);
OutputDebugString(L"\n***SVCMAIN");
if (!gSvcStatusHandle)
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
SvcInit(dwArgc, lpszArgv);
}
VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv)
{
FILE *f = fopen("c:\\test\\file.txt", "a");
OutputDebugString(L"\n***SVCINIT");
fprintf(f, "init\n");
fclose(f);
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if (ghSvcStopEvent == NULL)
{
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
while (WaitForSingleObject(ghSvcStopEvent, 3000) != WAIT_OBJECT_0){
OutputDebugString(L"\n***BEEP");
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "beep\n");
fclose(f);
Beep(1000, 100);
}
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
}
VOID ReportSvcStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
DWORD my_error = 0;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_SESSIONCHANGE | SERVICE_ACCEPT_STOP;
if ((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED)){
gSvcStatus.dwCheckPoint = 0;
}
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
my_error = GetLastError();
FILE *f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "last error %d \n",my_error);
fprintf(f, "\n***controls accepted %d ***\n", gSvcStatus.dwControlsAccepted);
fclose(f);
}
DWORD WINAPI SvcCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
DWORD dwErrorCode = NO_ERROR;
FILE *f = fopen("c:\\test\\file.txt", "a");
// Handle the requested control code.
fprintf(f, "dwCtrl is = %d \n", dwControl);
fclose(f);
switch (dwControl)
{
case SERVICE_CONTROL_TIMECHANGE:
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "time\n");
fclose(f);
OutputDebugString(L"\n****GOT time!!!\n\n");
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
break;
case SERVICE_CONTROL_SESSIONCHANGE:
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "session\n");
fclose(f);
OutputDebugString(L"\n****GOT Session!\n\n");
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
break;
case SERVICE_CONTROL_STOP:
OutputDebugString(L"\n****GOT STOP!\n\n");
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "stop\n");
fclose(f);
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
VOID SvcReportEvent(LPTSTR szFunction)
{
HANDLE hEventSource;
LPCTSTR lpszStrings[2];
TCHAR Buffer[80];
hEventSource = RegisterEventSource(NULL, SVCNAME);
if (NULL != hEventSource)
{
StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());
lpszStrings[0] = SVCNAME;
lpszStrings[1] = Buffer;
ReportEvent(hEventSource, // event log handle
EVENTLOG_ERROR_TYPE, // event type
0, // event category
SVC_ERROR, // event identifier
NULL, // no security identifier
2, // size of lpszStrings array
0, // no binary data
lpszStrings, // array of strings
NULL); // no binary data
DeregisterEventSource(hEventSource);
}
}
any ideas why i am not getting any "case SERVICE_CONTROL_SESSIONCHANGE" and only stop?
in my log file i see the beep log and controls accepted - 129 (stop + session change)
this is my log file content :
last error 0
***controls accepted 129 ***
init
last error 0
***controls accepted 129 ***
beep
beep
beep
beep
beep
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME,SvcCtrlHandler,NULL);
should be :
gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME,SvcCtrlHandler,NULL);

How does HidD_GetAttributes retrieve the attributes from a Device Object?

I'm working on creating a virtual HID device in Windows 10. To prepare myself for writing the drivers, I've been analyzing the sample provided here: https://github.com/Microsoft/Windows-driver-samples/tree/master/hid/vhidmini2.
In the file app/testvhid.c, HidD_GetAttributes is used to retrieve the attributes of the HID device. It appears that the attributes are initialized in driver/vhidmini.c (hidAttributes in the EvtDeviceAdd function). However, hidAttributes is stored inside of a DEVICE_CONTEXT structure, which (from my understanding) is defined by the driver.
If hidAttributes is a user defined attribute, then how does HidD_GetAttributes know to retrieve it from the device?
I've tried to replicate this for myself by creating a KMDF driver which is based mostly on the sample given. The relevant driver code is as follows (The majority of this was taken from the sample, with the exception of the call to WdfDeviceCreateDeviceInterface):
NTSTATUS
kmdfTest2CreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
WDF_OBJECT_ATTRIBUTES deviceAttributes;
PDEVICE_CONTEXT deviceContext;
WDFDEVICE device;
NTSTATUS status;
PHID_DEVICE_ATTRIBUTES hidAttributes;
WdfFdoInitSetFilter(DeviceInit);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
if (NT_SUCCESS(status)) {
deviceContext = DeviceGetContext(device);
deviceContext->Device = device;
deviceContext->DeviceData = 0;
hidAttributes = &deviceContext->HidDeviceAttributes;
RtlZeroMemory(hidAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
hidAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
hidAttributes->VendorID = HIDMINI_VID;
hidAttributes->ProductID = HIDMINI_PID;
hidAttributes->VersionNumber = HIDMINI_VERSION;
if (NT_SUCCESS(status)) {
status = kmdfTest2QueueInitialize(device);
}
deviceContext->HidDescriptor = G_DefaultHidDescriptor;
deviceContext->ReportDescriptor = G_DefaultReportDescriptor;
status = WdfDeviceCreateDeviceInterface(
device,
&GUID_DEVINTERFACE_HID,
NULL // ReferenceString
);
}
return status;
}
The relevant section of code in the user mode test application is as follows (this code is virtually entirely from the given sample):
BOOLEAN
CheckIfOurDevice(
HANDLE file)
{
PHIDP_PREPARSED_DATA Ppd; // The opaque parser info describing this device
HIDP_CAPS Caps; // The Capabilities of this hid device.
HIDD_ATTRIBUTES attr; // Device attributes
if (!HidD_GetAttributes(file, &attr))
{
printf("Error: HidD_GetAttributes failed \n");
return FALSE;
}
printf("Device Attributes - PID: 0x%x, VID: 0x%x \n", attr.ProductID, attr.VendorID);
if ((attr.VendorID != HIDMINI_VID) || (attr.ProductID != HIDMINI_PID))
{
printf("Device attributes doesn't match the sample \n");
return FALSE;
}
if (!HidD_GetPreparsedData(file, &Ppd))
{
printf("Error: HidD_GetPreparsedData failed \n");
return FALSE;
}
if (!HidP_GetCaps(Ppd, &Caps))
{
printf("Error: HidP_GetCaps failed \n");
HidD_FreePreparsedData(Ppd);
return FALSE;
}
if ((Caps.UsagePage == g_MyUsagePage) && (Caps.Usage == g_MyUsage)) {
printf("Success: Found my device.. \n");
return TRUE;
}
else {
printf("failed: UsagePage: %d, Usage: %d \n", Caps.UsagePage, Caps.Usage);
}
return FALSE;
}
BOOLEAN
GetHidInterface(_Out_ HANDLE* Handle) {
CONFIGRET cr = CR_SUCCESS;
*Handle = INVALID_HANDLE_VALUE;
ULONG deviceInterfaceListLength = 0;
GUID InterfaceGuid;
PSTR deviceInterfaceList = NULL;
HANDLE devHandle = INVALID_HANDLE_VALUE;
if (NULL == Handle) {
printf("Error: Invalid device handle parameter\n");
return FALSE;
}
HidD_GetHidGuid(&InterfaceGuid);
cr = CM_Get_Device_Interface_List_Size(
&deviceInterfaceListLength,
&InterfaceGuid,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS) {
printf("Error 0x%x retrieving device interface list size.\n", cr);
return FALSE;
}
if (deviceInterfaceListLength <= 1) {
printf("Error: No active device interfaces found.\n"
" Is the sample driver loaded?");
return FALSE;
}
deviceInterfaceList = (PSTR)malloc(deviceInterfaceListLength * sizeof(WCHAR));
if (deviceInterfaceList == NULL) {
printf("Error allocating memory for device interface list.\n");
return FALSE;
}
ZeroMemory(deviceInterfaceList, deviceInterfaceListLength * sizeof(WCHAR));
cr = CM_Get_Device_Interface_List(
&InterfaceGuid,
NULL,
deviceInterfaceList,
deviceInterfaceListLength,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS) {
printf("Error 0x%x retrieving device interface list.\n", cr);
return FALSE;
}
printf("\n....looking for our HID device (with UP=0x%04X "
"and Usage=0x%02X)\n", g_MyUsagePage, g_MyUsage);
PSTR currentInterface;
for (currentInterface = deviceInterfaceList;
*currentInterface;
currentInterface += strlen(currentInterface) + 1) {
devHandle = CreateFile(currentInterface,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
0, // No special attributes
NULL); // No template file
if (INVALID_HANDLE_VALUE == devHandle) {
printf("Warning: CreateFile failed: %d\n", GetLastError());
continue;
}
if (CheckIfOurDevice(devHandle)) {
*Handle = devHandle;
return TRUE;
}
else {
CloseHandle(devHandle);
}
}
return FALSE;
}
The HidD_GetAttributes function passes, but the CheckIfOurDevice function fails when checking the device attributes ("Device attributes doesn't match the sample"). I've checked some of the attribute values that are being set by HidD_GetAttributes, but they don't match up with the ones set by the driver. Is the sample making some other call that I'm missing?

Openssl EVP encryption/decryption not working

The purpose of the application is to pull the $MFT, ecnrypt it and save it on the disk. The second part of the code is decrypting it and saving it in clear form.
For some reason the decryption process is not working, I get only gibberish and apparently the same 4096 bytes repeat over and over.
I know the code is dirty, I tried to minimize it as much as possible, but if anyone spots any clear problem, please do let me know.
Thanks
char publicKey[]="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
rsa_pkey = createRSA(publicKey,1);
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
printf("EVP_PKEY_assign_RSA: failed.\n");
return 1;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
{
printf("EVP_SealInit: failed.\n");
}
eklen_n = htonl(eklen);
DWORD BytesWritten2;
if(WriteFile(outputMFTfile, &eklen_n, sizeof(eklen_n), &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [EK LEN]\n",BytesWritten2);
}
if(WriteFile(outputMFTfile, ek, eklen, &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [EK]\n",BytesWritten2);
}
if(WriteFile(outputMFTfile, iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [IV]\n",BytesWritten2);
}
while (ReadFile(hRawDisk, FINAL_MFT_BUFFER, 4096, &bytesRead, NULL))
{
bytesCounter = bytesCounter+(unsigned long long)bytesRead;
if (bytesCounter<final_length)
{
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, FINAL_MFT_BUFFER, bytesRead))
{
printf("FAILED SEAL UPDATE \n");
}
WriteFile(outputMFTfile, buffer_out, len_out, &BytesWritten, NULL);
}
else
{
break;
}
}
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
{
printf("FINAL SEAL FAILED\n");
}
else
{
DWORD BytesWritten;
WriteFile(outputMFTfile, buffer_out, len_out, &BytesWritten, NULL);
}
EVP_CIPHER_CTX_cleanup(&ctx);
The following code is used for decryption(I removed the part where I provide the private key and initialize EVP):
HANDLE decryptedMFTfile=CreateFile("MFT_decrypted.dat",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD BytesWritten2;
while(bytesRead>0)
{
ReadFile(encryptedMFT,buffer,sizeof(buffer),&bytesRead,NULL);
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
printf("EVP OPEN FAILED \n");
}
WriteFile(decryptedMFTfile, &buffer_out, sizeof(buffer_out), &BytesWritten2, NULL);
}
CreateRsa code on request:
RSA * createRSA(unsigned char * key,int public)
{
RSA *rsa= NULL;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1);
if (keybio==NULL)
{
printf( "Failed to create key BIO");
return 0;
}
if(public)
{
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
}
else
{
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
}
if(rsa == NULL)
{
printf( "Failed to create RSA");
}
return rsa;
}

CryptDecrypt fails with NT_BAD_DATA (0x80090005)

The following code by Alejandro Magencio generate key pairs, encrypts and decrypts files with the Microsoft CryptoAPI works well, but only for files smaller than the key:
http://blogs.msdn.com/b/alejacma/archive/2008/01/28/how-to-generate-key-pairs-encrypt-and-decrypt-data-with-cryptoapi.aspx
I am trying to extend this code in order to encrypt and decrypt larger files.
Here is the complete listing as far as I got. It encrypts but on the second time in the decrypt loop I get a bad data error.
Any help will be greatly appreciated and I promise to post the full working code.
Thanks in advance!
/*
EncryptDecrypt.c
This program was compiled on Windows 7 64-bit with Visual Studio 2013 Desktop Express. To run:
EncryptDecrypt.exe k C:\temp\myprivate.key C:\temp\mypublic.key
EncryptDecrypt.exe e C:\temp\myprivate.key C:\temp\todo.txt C:\temp\done.txt
EncryptDecrypt.exe d C:\temp\mypublic.key C:\temp\done.txt C:\temp\redone.txt
*/
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "wincrypt.h"
#include "tchar.h"
#define ENCRYPTEDLENGTH (128)
#define MAXSIZE (128 - 11) // size of chunk we can use for this program
// FUNCTIONS
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile);
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile);
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile);
// Main
int _tmain(int argc, _TCHAR* argv[])
{
int iResult = 0;
if ((argc == 4) && (_tcscmp(argv[1], _T("k")) == 0))
{
// Generate a new key pair
iResult = Keys(argv[2], argv[3]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("e")) == 0))
{
// Encrypt
iResult = Encrypt(argv[2], argv[3], argv[4]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("d")) == 0))
{
// Decrypt
iResult = Decrypt(argv[2], argv[3], argv[4]);
}
else
{
// Show usage
_tprintf(_T("Usage:\n"));
_tprintf(_T(" - New key pair: EncryptDecrypt k public_key_file private_key_file\n"));
_tprintf(_T(" - Encrypt: EncryptDecrypt e public_key_file plain_file encrypted_file\n"));
_tprintf(_T(" - Decrypt: EncryptDecrypt d private_key_file encrypted_file plain_file\n"));
iResult = 1;
}
_tprintf(_T("\n<< Press any key to continue >>\n"));
_getch();
return iResult;
}
// End of Main
// Keys
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPublicKey = NULL;
BYTE* pbPrivateKey = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hPrivateKeyFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("(ref 12) CryptAcquireContext error 0x%x\n"), GetLastError());
// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("(ref 13) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}
// Generate new key pair
_tprintf(_T("CryptGenKey...\n"));
if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hKey))
{
// Error
_tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
return 1;
}
// Get public key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("(ref 29) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Get public key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Get private key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("(ref 30) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Get private key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the public key
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 21) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPublicKeyFile,
(LPCVOID)pbPublicKey,
dwPublicKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 51) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the private key
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 22) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the private key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPrivateKeyFile,
(LPCVOID)pbPrivateKey,
dwPrivateKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 52) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Keys
// Encrypt
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwDataLen = 0;
DWORD dwEncryptedLen = 0;
DWORD myloopcount = 0;
DWORD mymodulus = 0;
DWORD i = 0;
DWORD myencryptedlength = 0;
DWORD mymaxsize = MAXSIZE;
BYTE* pbPublicKey = NULL;
BYTE* pbData = NULL;
BYTE* pbEncData = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
// Error
_tprintf(_T("(ref 9) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
// Open public key file
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 14) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPublicKeyLen = GetFileSize(hPublicKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 43) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("(ref 22) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read public key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPublicKeyFile, pbPublicKey, dwPublicKeyLen, &dwPublicKeyLen, NULL))
{
// Error
_tprintf(_T("(ref 31) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Import public key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPublicKey, dwPublicKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("(ref 38) CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}
// Open plain text file
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 15) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hPlainFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 40) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
_tprintf(_T("my data length is %d\n"), dwDataLen);
_tprintf(_T("my max size is %d\n"), MAXSIZE);
// Get length for encrypted data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwEncryptedLen, 0))
{
// Error
_tprintf(_T("(ref 1) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
if (dwDataLen < MAXSIZE)
{
// as before... Just one run through.
// BEGIN OLD BLOCK
// Create a buffer for the plain text
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("(ref 23) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read plain text
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("(ref 32) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Next line: dwEncryptedLen is the length of key! Ergo, when decrypting
// use 128 instead of MAXSIZE:
_tprintf(_T("My encrypted length is %d\n"), dwEncryptedLen);
// Create a buffer for encrypted data
_tprintf(_T("realloc...\n"));
if (!(pbData = (BYTE *)realloc(pbData, dwEncryptedLen)))
{
// Error
_tprintf(_T("(ref 24) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 2) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the encrypted data
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS, // will truncate if already existing
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 16) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 47) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
// END OLD BLOCK
return 0;
}
else
{
// File is bigger than key.
// Figure out how many times we will need to loop.
myloopcount = (DWORD)(dwDataLen / MAXSIZE);
_tprintf(_T("Loop counter is %d\n"), myloopcount);
mymodulus = dwDataLen % MAXSIZE;
_tprintf(_T("Remainder is %d\n"), mymodulus);
if (mymodulus == 0) // no remainder
{
myloopcount -= 1; // decrement by one
}
// Create a file to save the encrypted data with append flag.
// The parameter for appending data to a file is FILE_APPEND_DATA in the CreateFile function.
// Ref: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363778(v=vs.85).aspx
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile, // if you hardcode a filename here, use syntax: _T("C:\\temp\\append.txt"),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_APPEND_DATA,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 17) CreateFile error saving the encrypted data 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the plain text
_tprintf(_T("malloc...\n"));
pbData = NULL;
if (!(pbData = (BYTE *)malloc(MAXSIZE)))
{
// Error
_tprintf(_T("(ref 25) malloc error 0x%x\n"), GetLastError());
return 1;
}
_tprintf(_T("malloc...\n"));
pbEncData = NULL;
if (!(pbEncData = (BYTE *)malloc(ENCRYPTEDLENGTH)))
{
// Error
_tprintf(_T("(ref 53) malloc error 0x%x\n"), GetLastError());
return 1;
}
for (i = 0; i < myloopcount; i++)
{
// ref https://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx
if (i > 0)
{
SetFilePointer(
hPlainFile, // HANDLE hFile,
MAXSIZE, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
}
mymaxsize = MAXSIZE;
// Read plain text
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymaxsize, &mymaxsize, NULL))
{
// Error
_tprintf(_T("(ref 33) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, FALSE, 0, pbEncData, &mymaxsize, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 4) CryptEncrypt error in loop number %i 0x%x\n"),i, GetLastError());
return 1;
}
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbEncData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 48) WriteFile error, i is %d 0x%x\n"), i, GetLastError());
return 1;
}
} // end for loop
SetFilePointer(
hPlainFile, // HANDLE hFile,
MAXSIZE, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
mymaxsize = MAXSIZE;
if (mymodulus == 0)
{
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymaxsize, &mymaxsize, NULL))
{
// Error
_tprintf(_T("(ref 34) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data; last chunk must have TRUE flag when encrypting.
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbEncData, &dwDataLen, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 6) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
}
else
{
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymodulus, &mymodulus, NULL))
{
// Error
_tprintf(_T("(ref 35) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbEncData, &mymodulus, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 8) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
}
// Finish writing.
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbEncData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 49) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Encrypt
// Decrypt
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPrivateKeyLen = 0;
DWORD dwDataLen = 0;
DWORD myloopcount = 0;
DWORD mymodulus = 0;
DWORD i = 0;
DWORD mysize = 0;
BYTE* pbPrivateKey = NULL;
BYTE* pbData = NULL;
BYTE* pbEncData = NULL;
HANDLE hPrivateKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("(ref 10) CryptAcquireContext error 0x%x\n"), GetLastError());
// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("(ref 11) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}
// Open private key file
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 18) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPrivateKeyLen = GetFileSize(hPrivateKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 41) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("(ref 27) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read private key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPrivateKeyFile, pbPrivateKey, dwPrivateKeyLen, &dwPrivateKeyLen, NULL))
{
// Error
_tprintf(_T("(ref 36) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Import private key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPrivateKey, dwPrivateKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("(ref 39) CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}
// Open encrypted file
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 19) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hEncryptedFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 42) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
if (dwDataLen == ENCRYPTEDLENGTH)
{
// Create a buffer for the encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("(ref 28) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the plain text
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 20) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
else
{
// encrypted file is bigger than 128 bytes
// Figure out how many times we will need to loop.
myloopcount = (DWORD)(dwDataLen / ENCRYPTEDLENGTH);
_tprintf(_T("Loop counter is %d\n"), myloopcount);
mymodulus = dwDataLen % ENCRYPTEDLENGTH;
_tprintf(_T("Remainder is %d\n"), mymodulus);
if (mymodulus == 0) // no remainder
{
myloopcount -= 1; // decrement by one
}
// Create a file to save the plain text
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_APPEND_DATA,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 55) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(ENCRYPTEDLENGTH)))
{
// Error
_tprintf(_T("(ref 56) malloc error 0x%x\n"), GetLastError());
return 1;
}
for (i = 0; i < myloopcount; i++)
{
// ref https://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx
if (i > 0)
{
SetFilePointer(
hEncryptedFile, // HANDLE hFile,
ENCRYPTEDLENGTH, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
}
mysize = ENCRYPTEDLENGTH;
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, mysize, &mysize, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, FALSE, 0, pbData, &mysize))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error in loop number %d 0x%x\n"),i, GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
} // end for loop
SetFilePointer(
hEncryptedFile, // HANDLE hFile,
ENCRYPTEDLENGTH, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT // DWORD dwMoveMethod, with FILE_CURRENT it's more efficient, not forced
// to do (i * MAXSIZE) for second parameter size
);
mysize = ENCRYPTEDLENGTH;
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, mysize, &mysize, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &mysize))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error 0x%x\n"), GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
return 0;
}
__finally
{
// Clean up
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Decrypt
Yes; in general you cannot use RSA to encrypt data larger than the key size in a single pass, the limit is infact slightly shorter than the key size, depending on padding.
To encrypt larger amounts of data you would typically use a hybrid approach whereby you generate a symmetric key (say AES) and use that to encrypt your data.
You can then use your RSA public key to encrypt the AES key, combine it with the ciphertext and you have a blob that requires the private key to decrypt.

Resources