/* =======================================================================
   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)
