Last time we described a set of semi- and undocumented data compression functions in Windows.
Today's subject is cryptographic functions.
There are such functions in Windows that allow you to use few cryptographic primitives easier, without a whole CAPI overhead and hassle.
Here is the C example of how to generate secure random numbers and calculate SHA-1 hash.
First, the header file capix.h:
/* =======================================================================
CAPIx
Few cryptographic primitives for direct usage without CAPI overhead.
Based on un(semi)documented Windows XP+ interface
========================================================================= */
#pragma warning (push, 1)
#define WINDOWS_MEAN_AND_LEAN
#include <windows.h>
#pragma warning(pop)
typedef struct {
ULONG SomeJunk[6];
ULONG State[5];
ULONG Count[2];
UCHAR Buffer[64];
} SHA_CONTEXT, *PSHA_CONTEXT;
typedef BOOL (__stdcall *RtlGenRandom_Fn)(OUT PVOID, IN ULONG);
typedef PVOID (__stdcall *SHA_Init_Fn)(IN OUT PSHA_CONTEXT);
typedef PVOID (__stdcall *SHA_Update_Fn)(IN OUT PSHA_CONTEXT, IN PCHAR, IN UINT);
typedef PVOID (__stdcall *SHA_Final_Fn)(IN OUT PSHA_CONTEXT, OUT PVOID);
static HANDLE hAA32DLL = NULL;
static RtlGenRandom_Fn pf_rand = NULL;
static SHA_Init_Fn pf_sha_init = NULL;
static SHA_Update_Fn pf_sha_update = NULL;
static SHA_Final_Fn pf_sha_final = NULL;
BOOL InitCAPIX (void)
{
hAA32DLL = LoadLibrary ("advapi32.dll");
if ( hAA32DLL != NULL )
{
pf_rand = (RtlGenRandom_Fn) GetProcAddress(hAA32DLL, "SystemFunction036");
pf_sha_init = (SHA_Init_Fn) GetProcAddress(hAA32DLL, "A_SHAInit");
pf_sha_update = (SHA_Update_Fn) GetProcAddress(hAA32DLL, "A_SHAUpdate");
pf_sha_final = (SHA_Final_Fn) GetProcAddress(hAA32DLL, "A_SHAFinal");
}
return ( hAA32DLL != NULL );
} /* initcapix */
void _inline ReleaseCAPIX (void)
{
pf_rand = NULL;
pf_sha_init = NULL;
pf_sha_update = NULL;
pf_sha_final = NULL;
while (!FreeLibrary (hAA32DLL) );
hAA32DLL = NULL;
} /* donecapix */
#define random_s(x,y) ((pf_rand != NULL)?(*pf_rand)(x,y):FALSE)
#define sha1_init(x) ((pf_sha_init != NULL)?(*pf_sha_init)(x):NULL)
#define sha1_update(x,y,z) ((pf_sha_update != NULL)?(*pf_sha_update)(x,(PCHAR)y,z):NULL)
#define sha1_final(x,y) ((pf_sha_final != NULL)?(*pf_sha_final)(x,y):NULL)
Now, the simple demo program:
#pragma warning (push, 1)
#include "capix.h"
#include <stdlib.h>
#include <stdio.h>
#pragma warning(pop)
int main (void)
{
BYTE hash[20] = {0}, buf[12] = {0};
SHA_CONTEXT ctx;
PVOID dw;
register BYTE i;
InitCAPIX();
if ( !random_s(buf, sizeof(buf)) ) printf("Failed at generate random\n");
printf("data: ");
for (i = 0; i< sizeof(buf); i++) printf("%02x", buf[i]);
printf("\n");
dw = sha1_init(&ctx);
if ( dw ) dw = sha1_update(&ctx, buf, sizeof(buf));
if ( dw ) dw = sha1_final(&ctx, hash);
if ( dw )
{
printf("hash: ");
for (i = 0; i< sizeof(hash); i++) printf("%02x", hash[i]);
printf("\n");
}
else printf("SHA1 functions failed\n");
ReleaseCAPIX();
return 0;
}
Here we go. And remember, if you need a warning about not using such undocumented functions in your commercial software then you really should not do any.