Set the correct path to a file - c

Im trying to compile the code below, it is a code free available and Im trying to understand it. And I was trying to test it but Im getting an issue. I got a message error "Error opening file filename.txt. Error 2".
I think that should be because the file is not located in the appropriated folder. I have the file in the desktop, do you know how to set the path to the file in c as th the desktop?
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
DWORD main()
{
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
LPCSTR filename = "filename.txt";
// Logic to check usage goes here.
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwStatus = GetLastError();
printf("Error opening file %s\nError: %d\n", filename,
dwStatus);
return dwStatus;
}
// Get handle to the crypto provider
if (!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE,
&cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
{
dwStatus = GetLastError();
printf("CryptHashData failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
}
if (!bResult)
{
dwStatus = GetLastError();
printf("ReadFile failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
cbHash = MD5LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
DWORD i;
printf("MD5 hash of file %s is: ", filename);
for (i = 0; i < cbHash; i++)
{
printf("%c%c", rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
}
printf("\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;
}

Or copy the file to where .exe resides.

Related

Defragmenting File Programatically On Windows

I am attempting to follow this tutorial: Defragmenting Files.
I call DeviceIoControl() with FSCTL_GET_VOLUME_BITMAP on a handle to the C: volume, and I get a proper response.
I then open a handle to another file (I tried files from 10KB to a few MB) successfully, then I call DeviceIoControl() with FSCTL_GET_RETRIEVAL_POINTERS, and it succeeds with no last error or failed result, but the RETRIEVAL_POINTERS_BUFFER is not filled.
I also tried calling it on the C: volume handle, but it keeps returning ERROR_HANDLE_EOF even after trying to set the OVERLAPPED offset to 0, and setting the file pointer with SetFilePointer() to 0 relative to the beginning of the file.
BOOL dic(HANDLE dev, DWORD code, LPVOID in, DWORD ins, LPVOID out, LPDWORD outs)
{
HANDLE h = GetProcessHeap();
DWORD s = 1000;
DWORD r = 0;
out = HeapAlloc(h,HEAP_ZERO_MEMORY,s);
while (!DeviceIoControl(dev, code, in, ins, out, s, &r, 0))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError() || ERROR_MORE_DATA == GetLastError())
{
s *= 10;
LPVOID t = HeapReAlloc(h, HEAP_ZERO_MEMORY, out, s);
if(!t){
HeapFree(h, 0, out);
return 0;
}
out = t;
}
else
{
HeapFree(h, 0, out);
printf("dic unk: %d\n", GetLastError());
return 0;
}
}
*outs = s;
return 1;
}
BOOL getvolptr(HANDLE volh, PRETRIEVAL_POINTERS_BUFFER rpb, LPDWORD rpbs)
{
STARTING_VCN_INPUT_BUFFER vcn = { 0 };
return dic(volh, FSCTL_GET_RETRIEVAL_POINTERS, &vcn, sizeof(vcn), rpb, rpbs);
}
RETRIEVAL_POINTERS_BUFFER rpb = { 0 };
DWORD rpbs = 0;
ULONGLONG cluster_cnt=0;
HANDLE fi = openfile("C:\\Windows\\System32\\Kernel32.dll");
if (INVALID_HANDLE_VALUE == fi)
{
printf("failed to open file! (%d)\n", GetLastError());
getchar();
}
r = getvolptr(fi, &rpb, &rpbs);
if (!r)
{
printf("failed to get vol ptrs! (%d)\n", GetLastError());
getchar();
}
for (int i = 0; i < rpb.ExtentCount; ++i)
{
cluster_cnt = (ULONGLONG)(rpb.Extents[i].NextVcn.QuadPart) - (ULONGLONG)(rpb.StartingVcn.QuadPart);
printf("%d) size: %llu clusters (0x%016X)\n", i, cluster_cnt, rpb.Extents[i].Lcn.QuadPart);
}
You are not checking the first HeapAlloc() for failure. And HeapFree() can wipe the last error code from DeviceIoControl() before you print it.
But more importantly, you are not passing the out data back to the caller correctly, so you are leaking the allocated memory, and the caller ends up with garbage for output.
Since the caller is passing in their own RETRIEVAL_POINTERS_BUFFER to receive the data, you need to copy the contents of the allocate memory into that buffer, eg:
BOOL dic(HANDLE dev, DWORD code, LPVOID in, DWORD ins, LPVOID out, LPDWORD outs)
{
if (!in || !out || !outs)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*outs = 0;
HANDLE h = GetProcessHeap();
DWORD s = 1000;
LPVOID buf = HeapAlloc(h, HEAP_ZERO_MEMORY, s);
if (!buf)
return FALSE;
DWORD r = 0;
while (!DeviceIoControl(dev, code, in, ins, buf, s, &r, 0))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError() || ERROR_MORE_DATA == GetLastError())
{
s *= 10;
LPVOID t = HeapReAlloc(h, HEAP_ZERO_MEMORY, buf, s);
if (!t)
{
HeapFree(h, 0, buf);
return FALSE;
}
buf = t;
}
else
{
printf("dic unk: %u\n", GetLastError());
HeapFree(h, 0, buf);
return FALSE;
}
}
if (s > *outs)
{
HeapFree(h, 0, buf);
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
CopyMemory(out, buf, s);
*outs = s;
HeapFree(h, 0, buf);
return TRUE;
}
BOOL getvolptr(HANDLE volh, PRETRIEVAL_POINTERS_BUFFER rpb, LPDWORD rpbs)
{
STARTING_VCN_INPUT_BUFFER vcn = { 0 };
return dic(volh, FSCTL_GET_RETRIEVAL_POINTERS, &vcn, sizeof(vcn), rpb, rpbs);
}
HANDLE fi = openfile("C:\\Windows\\System32\\Kernel32.dll");
if (INVALID_HANDLE_VALUE == fi)
{
printf("failed to open file! (%u)\n", GetLastError());
getchar();
}
else
{
RETRIEVAL_POINTERS_BUFFER rpb = { 0 };
DWORD rpbs = sizeof(rpb);
if (!getvolptr(fi, &rpb, &rpbs))
{
printf("failed to get vol ptrs! (%u)\n", GetLastError());
getchar();
}
else
{
ULONGLONG cluster_cnt = 0;
for (int i = 0; i < rpb.ExtentCount; ++i)
{
cluster_cnt = (ULONGLONG)(rpb.Extents[i].NextVcn.QuadPart) - (ULONGLONG)(rpb.StartingVcn.QuadPart);
printf("%d) size: %llu clusters (0x%016X)\n", i, cluster_cnt, rpb.Extents[i].Lcn.QuadPart);
}
}
closefile(fi);
}
Alternatively, you can return the pointer to the allocated memory to the caller, and the caller will have to free the memory when done using it, eg:
BOOL dic(HANDLE dev, DWORD code, LPVOID in, DWORD ins, LPVOID* out, LPDWORD outs)
{
if (!in || !out || !outs)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*out = NULL;
*outs = 0;
HANDLE h = GetProcessHeap();
DWORD s = 1000;
LPVOID buf = HeapAlloc(h, HEAP_ZERO_MEMORY, s);
if (!buf)
return FALSE;
DWORD r = 0;
while (!DeviceIoControl(dev, code, in, ins, buf, s, &r, 0))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError() || ERROR_MORE_DATA == GetLastError())
{
s *= 10;
LPVOID t = HeapReAlloc(h, HEAP_ZERO_MEMORY, buf, s);
if (!t)
{
HeapFree(h, 0, buf);
return FALSE;
}
buf = t;
}
else
{
printf("dic unk: %u\n", GetLastError());
HeapFree(h, 0, buf);
return FALSE;
}
}
*out = buf;
*outs = s;
return TRUE;
}
BOOL getvolptr(HANDLE volh, PRETRIEVAL_POINTERS_BUFFER* rpb, LPDWORD rpbs)
{
STARTING_VCN_INPUT_BUFFER vcn = { 0 };
return dic(volh, FSCTL_GET_RETRIEVAL_POINTERS, &vcn, sizeof(vcn), (void**)rpb, rpbs);
}
HANDLE fi = openfile("C:\\Windows\\System32\\Kernel32.dll");
if (INVALID_HANDLE_VALUE == fi)
{
printf("failed to open file! (%u)\n", GetLastError());
getchar();
}
else
{
PRETRIEVAL_POINTERS_BUFFER rpb = NULL;
DWORD rpbs = 0;
if (!getvolptr(fi, &rpb, &rpbs))
{
printf("failed to get vol ptrs! (%u)\n", GetLastError());
getchar();
}
else
{
ULONGLONG cluster_cnt = 0;
for (int i = 0; i < rpb->ExtentCount; ++i)
{
cluster_cnt = (ULONGLONG)(rpb->Extents[i].NextVcn.QuadPart) - (ULONGLONG)(rpb->StartingVcn.QuadPart);
printf("%d) size: %llu clusters (0x%016X)\n", i, cluster_cnt, rpb->Extents[i].Lcn.QuadPart);
}
HeapFree(GetProcessHeap(), 0, rpb);
}
closefile(fi);
}

strtok_s return incorrect data inside windbg

(Hello Everyone) I have some problem with strtok_s. I wrote this code(x64).
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
BOOL TestMD5(CONST WCHAR* MD5_DATABASE_FILE)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD FileSize = 0;
DWORD dwReaded = 0;
PBYTE pData = NULL;
BOOL bRead = FALSE;
PCHAR token_string = NULL;
PCHAR context = NULL;
CONST PCHAR delimeter = "\r\n";
hFile = CreateFileW(
MD5_DATABASE_FILE,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Can't open md5 database file: ");
return FALSE;
}
FileSize = GetFileSize(hFile, NULL);
if (FileSize == 0 || FileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
return FALSE;
}
pData = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)FileSize);
if (pData == NULL)
{
CloseHandle(hFile);
return FALSE;
}
bRead = ReadFile(hFile, pData, FileSize, &dwReaded, NULL);
if (bRead != TRUE || dwReaded != FileSize)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
token_string = (PCHAR)strtok_s(pData, delimeter, &context);
if (token_string == NULL)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
do {
printf("%s\n", token_string);
} while (token_string = (PCHAR)strtok_s(NULL, delimeter, &context));
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return TRUE;
}
int main(void)
{
WCHAR* MD5_DATABASE_FILE = L"c:\\md5.txt";
TestMD5(MD5_DATABASE_FILE);
}
When I run exe this gives me a incorrect data. Content of md5.txt (DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG + (\r\n)
output:
D:\repos\TestWindbg\x64\Debug>TestWindbg.exe
DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG
áááááááááááááááá
I open exe in windbg and I saw while(token_string) is not NULL after first time. But is must?
WinDbg image : "https://i.ibb.co/60nHk5S/Untitled.png"
What is problem? Thanks for reading
Jeffrey Shao - MSFT :Thank you for reply but this is not solution(but I changed my code PBYTE TO PCHAR). The problem is that strtok_s is a string function for this reason you must add NULL byte after buff. Like HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(SIZE_T)FileSize + 1) #1 for NULL character . HeapAlloc alloc buff size:FileSize and +1 For Null...
Thanks for blabb and Daniel Sęk:
I just change some types of pData and token_string.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
BOOL TestMD5(CONST WCHAR* MD5_DATABASE_FILE)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD FileSize = 0;
DWORD dwReaded = 0;
char* pData = NULL;
BOOL bRead = FALSE;
char* token_string = NULL;
PCHAR context = NULL;
CONST PCHAR delimeter = "\r\n";
hFile = CreateFileW(
MD5_DATABASE_FILE,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Can't open md5 database file: ");
return FALSE;
}
FileSize = GetFileSize(hFile, NULL);
if (FileSize == 0 || FileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
return FALSE;
}
pData = (char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(SIZE_T)FileSize + 1);
if (pData == NULL)
{
CloseHandle(hFile);
return FALSE;
}
bRead = ReadFile(hFile, pData, FileSize, &dwReaded, NULL);
if (bRead != TRUE || dwReaded != FileSize)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
token_string = strtok_s(pData, delimeter, &context);
if (token_string == NULL)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
do {
printf("%s\n", token_string);
} while (token_string = strtok_s(NULL, delimeter, &context));
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return TRUE;
}
int main(void)
{
WCHAR* MD5_DATABASE_FILE = L"c:\\md5.txt";
TestMD5(MD5_DATABASE_FILE);
}
Output:
DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG + (\r\n)

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);

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.

Windows crypto API

I'm having trouble with a function I made to create a sha1 hash of some strings. The function generates a valid hash for strings longer than 4 chars, but for chars less than that the hash is wrong. I've been looking all over for a solution but I can't see whats wrong.
int create_hash(char *plaintext, char *digest) {
char digest_buff[3];
DWORD buf_size = SHA1_HASH_LEN;
HCRYPTPROV prov;
HCRYPTHASH hash;
BYTE rgbHash[SHA1_HASH_LEN];
CHAR rgbDigits[] = "0123456789abcdef";
int i;
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if(DEBUG) {
printf("CryptAcquireContext failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptCreateHash(prov, CALG_SHA, NULL, NULL, &hash)) {
if(DEBUG) {
printf("CryptCreateHash failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptHashData(hash, (BYTE *)plaintext, sizeof(hash), NULL)) {
if(DEBUG) {
printf("CryptHashData failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptGetHashParam(hash, HP_HASHVAL, rgbHash, &buf_size, NULL)) {
if(DEBUG) {
printf("CryptGetHashParam failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
for(i=0; i < buf_size; i++) {
sprintf(digest_buff, "%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]);
strcat(digest, digest_buff);
}
if(!CryptDestroyHash(hash)) {
if(DEBUG) {
printf("CryptDestroyHash failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptReleaseContext(prov, NULL)) {
if(DEBUG) {
printf("CryptReleaseContext failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(DEBUG) {
printf("digest: %s\n", digest);
}
return 0;
}
CryptHashData accepts the length of the data as third parameter, and you pass size of the hash buffer there. You need to pass smth like strlen(plaintext) there.

Resources