Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5131 lines
144 KiB

/////////////////////////////////////////////////////////////////////////////
// FILE : cryptapi.c //
// DESCRIPTION : Crypto API interface //
// AUTHOR : //
// HISTORY : //
// Dec 6 1994 larrys New //
// Jan 16 1995 larrys Added key verify //
// Jan 25 1995 larrys Added thread safe //
// Jan 27 1995 larrys Added Unicode support //
// Feb 21 1995 larrys Added Unicode support for CryptAcquireContext //
// Feb 21 1995 larrys Fixed Unicode problem in CryptAcquireContext //
// Mar 08 1995 larrys Removed CryptGetLastError //
// Mar 20 1995 larrys Removed Certificate APIs //
// Mar 22 1995 larrys #ifdef in WIN95 code //
// Apr 06 1995 larrys Increased signature key to 1024 bits //
// Apr 07 1995 larrys Removed CryptConfigure //
// Jun 14 1995 larrys Removed pointer from RSA key struct //
// Jun 29 1995 larrys Changed AcquireContext //
// Jul 17 1995 larrys Worked on AcquireContext //
// Aug 01 1995 larrys Removed CryptTranslate //
// And CryptDeinstallProvider //
// Changed CryptInstallProvider to //
// CryptSetProvider //
// Aug 03 1995 larrys Cleanup //
// Aug 10 1995 larrys CryptAcquireContext returns error //
// NTE_BAD_KEYSEY_PARAM now //
// Aug 14 1995 larrys Removed key exchange stuff //
// Aug 17 1995 larrys Changed registry entry to decimcal //
// Aug 23 1995 larrys Changed CryptFinishHash to CryptGetHashValue //
// Aug 28 1995 larrys Removed parameter from CryptVerifySignature //
// Aug 31 1995 larrys Remove GenRandom //
// Sep 14 1995 larrys Code review changes //
// Sep 26 1995 larrys Added Microsoft's signing key //
// Sep 27 1995 larrys Updated with more review changes //
// Oct 06 1995 larrys Added more APIs Get/SetHash/ProvParam //
// Oct 12 1995 larrys Remove CryptGetHashValue //
// Oct 20 1995 larrys Changed test key //
// Oct 24 1995 larrys Removed return of KeySet name //
// Oct 30 1995 larrys Removed WIN95 //
// Nov 9 1995 larrys Disable BUILD1057 //
// Nov 10 1995 larrys Fix a problem in EnterHashCritSec //
// May 30 1996 larrys Added hWnd support //
// Oct 10 1996 jeffspel Reordered SetLastErrors and save error on //
// AcquireContext failure //
// Mar 21 1997 jeffspel Added second tier signatures, new APIs //
// Apr 11 1997 jeffspel Replace critical sections with interlocked //
// inc/dec //
// Oct 02 1997 jeffspel Add caching of CSPs to CryptAcquireContext //
// Oct 10 1997 jeffspel Add verification scheme for signature in file //
// //
// Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
/////////////////////////////////////////////////////////////////////////////
#include "advapi.h"
#include "stdlib.h"
#include <wincrypt.h> // Include here, since not included by LEAN_AND_MEAN
#include <cspdk.h>
#include <ntstatus.h>
#include <rsa.h>
#include <md5.h>
#include <rc4.h>
#include <winperf.h>
#include <wtypes.h>
#include <mincrypt.h>
#define IDR_PUBKEY1 102
typedef struct _VTableStruc {
// ******************** WARNING **********************************************
// Do not place anything before these FARPROCs we init the table assuming
// that the first Function to call is the first thing in the table.
// ***************************************************************************
FARPROC FuncAcquireContext;
FARPROC FuncReleaseContext;
FARPROC FuncGenKey;
FARPROC FuncDeriveKey;
FARPROC FuncDestroyKey;
FARPROC FuncSetKeyParam;
FARPROC FuncGetKeyParam;
FARPROC FuncExportKey;
FARPROC FuncImportKey;
FARPROC FuncEncrypt;
FARPROC FuncDecrypt;
FARPROC FuncCreateHash;
FARPROC FuncHashData;
FARPROC FuncHashSessionKey;
FARPROC FuncDestroyHash;
FARPROC FuncSignHash;
FARPROC FuncVerifySignature;
FARPROC FuncGenRandom;
FARPROC FuncGetUserKey;
FARPROC FuncSetProvParam;
FARPROC FuncGetProvParam;
FARPROC FuncSetHashParam;
FARPROC FuncGetHashParam;
FARPROC FuncNULL;
FARPROC OptionalFuncDuplicateKey;
FARPROC OptionalFuncDuplicateHash;
FARPROC OptionalFuncNULL;
HANDLE DllHandle; // Handle to open DLL
HCRYPTPROV hProv; // Handle to provider
DWORD Version;
DWORD Inuse;
LONG RefCnt;
} VTableStruc, *PVTableStruc;
typedef struct _VKeyStruc {
// ******************** WARNING **********************************************
// Do not place anything before these FARPROCs we init the table assuming
// that the first Function to call is the first thing in the table.
// ***************************************************************************
FARPROC FuncGenKey;
FARPROC FuncDeriveKey;
FARPROC FuncDestroyKey;
FARPROC FuncSetKeyParam;
FARPROC FuncGetKeyParam;
FARPROC FuncExportKey;
FARPROC FuncImportKey;
FARPROC FuncEncrypt;
FARPROC FuncDecrypt;
FARPROC OptionalFuncDuplicateKey;
HCRYPTPROV hProv; // Handle to provider
HCRYPTKEY hKey; // Handle to key
DWORD Version;
DWORD Inuse;
} VKeyStruc, *PVKeyStruc;
typedef struct _VHashStruc {
// ******************** WARNING **********************************************
// Do not place anything before these FARPROCs we init the table assuming
// that the first Function to call is the first thing in the table.
// ***************************************************************************
FARPROC FuncCreateHash;
FARPROC FuncHashData;
FARPROC FuncHashSessionKey;
FARPROC FuncDestroyHash;
FARPROC FuncSignHash;
FARPROC FuncVerifySignature;
FARPROC FuncSetHashParam;
FARPROC FuncGetHashParam;
FARPROC OptionalFuncDuplicateHash;
HCRYPTPROV hProv; // Handle to provider
HCRYPTHASH hHash; // Handle to hash
DWORD Version;
DWORD Inuse;
} VHashStruc, *PVHashStruc;
//
// Crypto providers have to have the following entry points:
//
LPCSTR FunctionNames[] = {
"CPAcquireContext",
"CPReleaseContext",
"CPGenKey",
"CPDeriveKey",
"CPDestroyKey",
"CPSetKeyParam",
"CPGetKeyParam",
"CPExportKey",
"CPImportKey",
"CPEncrypt",
"CPDecrypt",
"CPCreateHash",
"CPHashData",
"CPHashSessionKey",
"CPDestroyHash",
"CPSignHash",
"CPVerifySignature",
"CPGenRandom",
"CPGetUserKey",
"CPSetProvParam",
"CPGetProvParam",
"CPSetHashParam",
"CPGetHashParam",
NULL
};
LPCSTR OptionalFunctionNames[] = {
"CPDuplicateKey",
"CPDuplicateHash",
NULL
};
#define CapiExceptionFilter \
(STATUS_ACCESS_VIOLATION == GetExceptionCode() ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH)
HWND hWnd = NULL;
BYTE *pbContextInfo = NULL;
DWORD cbContextInfo;
#define KEYSIZE512 0x48
#define KEYSIZE1024 0x88
// designatred resource for in file signatures
#define OLD_CRYPT_SIG_RESOURCE_NUMBER "#666"
typedef struct _SECONDTIER_SIG
{
DWORD dwMagic;
DWORD cbSig;
BSAFE_PUB_KEY Pub;
} SECOND_TIER_SIG, *PSECOND_TIER_SIG;
#ifdef TEST_BUILD_EXPONENT
#pragma message("WARNING: building advapai32.dll with TESTKEY enabled!")
static struct _TESTKEY {
BSAFE_PUB_KEY PUB;
unsigned char pubmodulus[KEYSIZE512];
} TESTKEY = {
{
0x66b8443b,
0x6f5fc900,
0xa12132fe,
0xff1b06cf,
0x2f4826eb,
},
{
0x3e, 0x69, 0x4f, 0x45, 0x31, 0x95, 0x60, 0x6c,
0x80, 0xa5, 0x41, 0x99, 0x3e, 0xfc, 0x92, 0x2c,
0x93, 0xf9, 0x86, 0x23, 0x3d, 0x48, 0x35, 0x81,
0x19, 0xb6, 0x7c, 0x04, 0x43, 0xe6, 0x3e, 0xd4,
0xd5, 0x43, 0xaf, 0x52, 0xdd, 0x51, 0x20, 0xac,
0xc3, 0xca, 0xee, 0x21, 0x9b, 0x4a, 0x2d, 0xf7,
0xd8, 0x5f, 0x32, 0xeb, 0x49, 0x72, 0xb9, 0x8d,
0x2e, 0x1a, 0x76, 0x7f, 0xde, 0xc6, 0x75, 0xab,
0xaf, 0x67, 0xe0, 0xf0, 0x8b, 0x30, 0x20, 0x92,
}
};
#endif
#ifdef MS_INTERNAL_KEY
static struct _mskey {
BSAFE_PUB_KEY PUB;
unsigned char pubmodulus[KEYSIZE1024];
} MSKEY = {
{
0x2bad85ae,
0x883adacc,
0xb32ebd68,
0xa7ec8b06,
0x58dbeb81,
},
{
0x42, 0x34, 0xb7, 0xab, 0x45, 0x0f, 0x60, 0xcd,
0x8f, 0x77, 0xb5, 0xd1, 0x79, 0x18, 0x34, 0xbe,
0x66, 0xcb, 0x5c, 0x66, 0x4a, 0x9f, 0x03, 0x18,
0x13, 0x36, 0x8e, 0x88, 0x21, 0x78, 0xb1, 0x94,
0xa1, 0xd5, 0x8f, 0x8c, 0xa5, 0xd3, 0x9f, 0x86,
0x43, 0x89, 0x05, 0xa0, 0xe3, 0xee, 0xe2, 0xd0,
0xe5, 0x1d, 0x5f, 0xaf, 0xff, 0x85, 0x71, 0x7a,
0x0a, 0xdb, 0x2e, 0xd8, 0xc3, 0x5f, 0x2f, 0xb1,
0xf0, 0x53, 0x98, 0x3b, 0x44, 0xee, 0x7f, 0xc9,
0x54, 0x26, 0xdb, 0xdd, 0xfe, 0x1f, 0xd0, 0xda,
0x96, 0x89, 0xc8, 0x9e, 0x2b, 0x5d, 0x96, 0xd1,
0xf7, 0x52, 0x14, 0x04, 0xfb, 0xf8, 0xee, 0x4d,
0x92, 0xd1, 0xb6, 0x37, 0x6a, 0xe0, 0xaf, 0xde,
0xc7, 0x41, 0x06, 0x7a, 0xe5, 0x6e, 0xb1, 0x8c,
0x8f, 0x17, 0xf0, 0x63, 0x8d, 0xaf, 0x63, 0xfd,
0x22, 0xc5, 0xad, 0x1a, 0xb1, 0xe4, 0x7a, 0x6b,
0x1e, 0x0e, 0xea, 0x60, 0x56, 0xbd, 0x49, 0xd0,
}
};
#endif
static struct _key {
BSAFE_PUB_KEY PUB;
unsigned char pubmodulus[KEYSIZE1024];
} KEY = {
{
0x3fcbf1a9,
0x08f597db,
0xe4aecab4,
0x75360f90,
0x9d6c0f00,
},
{
0x85, 0xdd, 0x9b, 0xf4, 0x4d, 0x0b, 0xc4, 0x96,
0x3e, 0x79, 0x86, 0x30, 0x6d, 0x27, 0x31, 0xee,
0x4a, 0x85, 0xf5, 0xff, 0xbb, 0xa9, 0xbd, 0x81,
0x86, 0xf2, 0x4f, 0x87, 0x6c, 0x57, 0x55, 0x19,
0xe4, 0xf4, 0x49, 0xa3, 0x19, 0x27, 0x08, 0x82,
0x9e, 0xf9, 0x8a, 0x8e, 0x41, 0xd6, 0x91, 0x71,
0x47, 0x48, 0xee, 0xd6, 0x24, 0x2d, 0xdd, 0x22,
0x72, 0x08, 0xc6, 0xa7, 0x34, 0x6f, 0x93, 0xd2,
0xe7, 0x72, 0x57, 0x78, 0x7a, 0x96, 0xc1, 0xe1,
0x47, 0x38, 0x78, 0x43, 0x53, 0xea, 0xf3, 0x88,
0x82, 0x66, 0x41, 0x43, 0xd4, 0x62, 0x44, 0x01,
0x7d, 0xb2, 0x16, 0xb3, 0x50, 0x89, 0xdb, 0x0a,
0x93, 0x17, 0x02, 0x02, 0x46, 0x49, 0x79, 0x76,
0x59, 0xb6, 0xb1, 0x2b, 0xfc, 0xb0, 0x9a, 0x21,
0xe6, 0xfa, 0x2d, 0x56, 0x07, 0x36, 0xbc, 0x13,
0x7f, 0x1c, 0xde, 0x55, 0xfb, 0x0d, 0x67, 0x0f,
0xc2, 0x17, 0x45, 0x8a, 0x14, 0x2b, 0xba, 0x55,
}
};
static struct _key2 {
BSAFE_PUB_KEY PUB;
unsigned char pubmodulus[KEYSIZE1024];
} KEY2 = {
{
0x685fc690,
0x97d49b6b,
0x1dccd9d2,
0xa5ec9b52,
0x64fd29d7,
},
{
0x03, 0x8c, 0xa3, 0x9e, 0xfb, 0x93, 0xb6, 0x72,
0x2a, 0xda, 0x6f, 0xa5, 0xec, 0x26, 0x39, 0x58,
0x41, 0xcd, 0x3f, 0x49, 0x10, 0x4c, 0xcc, 0x7e,
0x23, 0x94, 0xf9, 0x5d, 0x9b, 0x2b, 0xa3, 0x6b,
0xe8, 0xec, 0x52, 0xd9, 0x56, 0x64, 0x74, 0x7c,
0x44, 0x6f, 0x36, 0xb7, 0x14, 0x9d, 0x02, 0x3c,
0x0e, 0x32, 0xb6, 0x38, 0x20, 0x25, 0xbd, 0x8c,
0x9b, 0xd1, 0x46, 0xa7, 0xb3, 0x58, 0x4a, 0xb7,
0xdd, 0x0e, 0x38, 0xb6, 0x16, 0x44, 0xbf, 0xc1,
0xca, 0x4d, 0x6a, 0x9f, 0xcb, 0x6f, 0x3c, 0x5f,
0x03, 0xab, 0x7a, 0xb8, 0x16, 0x70, 0xcf, 0x98,
0xd0, 0xca, 0x8d, 0x25, 0x57, 0x3a, 0x22, 0x8b,
0x44, 0x96, 0x37, 0x51, 0x30, 0x00, 0x92, 0x1b,
0x03, 0xb9, 0xf9, 0x0d, 0xb3, 0x1a, 0xe2, 0xb4,
0xc5, 0x7b, 0xc9, 0x4b, 0xe2, 0x42, 0x25, 0xfe,
0x3d, 0x42, 0xfa, 0x45, 0xc6, 0x94, 0xc9, 0x8e,
0x87, 0x7e, 0xf6, 0x68, 0x90, 0x30, 0x65, 0x10,
}
};
#define CACHESIZE 32
static HANDLE gCSPCache[CACHESIZE];
#define TABLEPROV 0x11111111
#define TABLEKEY 0x22222222
#define TABLEHASH 0x33333333
CHAR szreg[] = "SOFTWARE\\Microsoft\\Cryptography\\Providers\\";
CHAR szusertype[] = "SOFTWARE\\Microsoft\\Cryptography\\Providers\\Type ";
CHAR szmachinetype[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type ";
CHAR szprovider[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\";
CHAR szenumproviders[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider";
CHAR szprovidertypes[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider Types";
BOOL EnterProviderCritSec(IN PVTableStruc pVTable);
void LeaveProviderCritSec(IN PVTableStruc pVTable);
BOOL EnterKeyCritSec(IN PVKeyStruc pVKey);
void LeaveKeyCritSec(IN PVKeyStruc pVKey);
BOOL EnterHashCritSec(IN PVHashStruc pVHash);
void LeaveHashCritSec(IN PVHashStruc pVHash);
BOOL CheckSignatureInFile(LPCWSTR pszImage);
BOOL CProvVerifyImage(LPCSTR lpszImage,
BYTE *pSigData);
BOOL NewVerifyImage(LPCSTR lpszImage,
BYTE *pSigData,
DWORD cbData,
BOOL fUnknownLen);
BOOL BuildVKey(IN PVKeyStruc *ppVKey,
IN PVTableStruc pVTable);
BOOL BuildVHash(
IN PVHashStruc *ppVKey,
IN PVTableStruc pVTable
);
void CPReturnhWnd(HWND *phWnd);
static void __ltoa(DWORD val, char *buf);
BOOL CSPInCacheCheck(
LPSTR pszValue,
HANDLE *ph
)
{
HANDLE h = 0;
DWORD i;
BOOL fRet = FALSE;
// check if CSP has been loaded
if (0 == (h = GetModuleHandle(pszValue)))
goto Ret;
// check if the CSP is in the cache designating it as signed
for (i=0;i<CACHESIZE;i++)
{
if (h == gCSPCache[i])
{
*ph = h;
fRet = TRUE;
break;
}
}
Ret:
return fRet;
}
void AddHandleToCSPCache(
HANDLE h
)
{
DWORD i;
// check if the CSP is in the cache designating it as signed
for (i=0;i<CACHESIZE;i++)
{
if (0 == gCSPCache[i])
{
gCSPCache[i] = h;
break;
}
}
}
/*
- CryptAcquireContextW
-
* Purpose:
* The CryptAcquireContext function is used to acquire a context
* handle to a cryptograghic service provider (CSP).
*
*
* Parameters:
* OUT phProv - Handle to a CSP
* IN pszIdentity - Pointer to the name of the context's
* keyset.
* IN pszProvider - Pointer to the name of the provider.
* IN dwProvType - Requested CSP type
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptAcquireContextW(OUT HCRYPTPROV *phProv,
IN LPCWSTR pszIdentity,
IN LPCWSTR pszProvider,
IN DWORD dwProvType,
IN DWORD dwFlags)
{
ANSI_STRING AnsiString1;
ANSI_STRING AnsiString2;
UNICODE_STRING UnicodeString1;
UNICODE_STRING UnicodeString2;
NTSTATUS Status = STATUS_SUCCESS;
BOOL rt;
__try
{
memset(&AnsiString1, 0, sizeof(AnsiString1));
memset(&AnsiString2, 0, sizeof(AnsiString2));
memset(&UnicodeString1, 0, sizeof(UnicodeString1));
memset(&UnicodeString2, 0, sizeof(UnicodeString2));
if (NULL != pszIdentity)
{
RtlInitUnicodeString(&UnicodeString1, pszIdentity);
Status = RtlUnicodeStringToAnsiString(&AnsiString1, &UnicodeString1,
TRUE);
}
if (!NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(CRYPT_FAILED);
}
if (NULL != pszProvider)
{
RtlInitUnicodeString(&UnicodeString2, pszProvider);
Status = RtlUnicodeStringToAnsiString(&AnsiString2, &UnicodeString2,
TRUE);
}
if (!NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(CRYPT_FAILED);
}
rt = CryptAcquireContextA(phProv, AnsiString1.Buffer,
AnsiString2.Buffer,
dwProvType, dwFlags);
RtlFreeAnsiString(&AnsiString1);
RtlFreeAnsiString(&AnsiString2);
return(rt);
}
__except (CapiExceptionFilter)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
Try_Error_Return:
return(CRYPT_FAILED);
}
/*
- CryptAcquireContextA
-
* Purpose:
* The CryptAcquireContext function is used to acquire a context
* handle to a cryptograghic service provider (CSP).
*
*
* Parameters:
* OUT phProv - Handle to a CSP
* IN OUT pszIdentity - Pointer to the name of the context's
* keyset.
* IN OUT pszProvName - Pointer to the name of the provider.
* IN dwReqProvider - Requested CSP type
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptAcquireContextA(OUT HCRYPTPROV *phProv,
IN LPCSTR pszIdentity,
IN LPCSTR pszProvName,
IN DWORD dwReqProvider,
IN DWORD dwFlags)
{
HANDLE handle = 0;
DWORD bufsize;
ULONG_PTR *pTable;
PVTableStruc pVTable = NULL;
LPSTR pszTmpProvName = NULL;
DWORD i;
HKEY hKey = 0;
DWORD cbValue;
DWORD cbTemp;
CHAR *pszValue = NULL;
CHAR *pszDest = NULL;
BYTE *SignatureBuf = NULL;
DWORD provtype;
BOOL rt = CRYPT_FAILED;
DWORD dwType;
LONG err;
DWORD dwErr;
CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
HCRYPTPROV hTmpProv = 0;
VTableProvStruc VTableProv;
UNICODE_STRING String ;
BOOL SigInFile ;
__try
{
if (dwReqProvider == 0 || dwReqProvider > 999)
{
SetLastError((DWORD) NTE_BAD_PROV_TYPE);
goto Ret;
}
if (pszProvName != NULL && pszProvName[0] != 0)
{
// Do nothing just check for invalid pointers
;
}
if (pszProvName != NULL && pszProvName[0] != 0)
{
cbValue = strlen(pszProvName);
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
(UINT) cbValue +
strlen(szprovider) + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if ((pszTmpProvName = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
(UINT) cbValue + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszTmpProvName, pszProvName);
strcpy(pszValue, szprovider);
strcat(pszValue, pszProvName);
}
else
{
//
// We no longer look under HKCU for a default csp. We only look
// under HKLM.
//
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
5 + strlen(szmachinetype))) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
__ltoa(dwReqProvider, typebuf);
strcpy(pszValue, szmachinetype);
strcat(pszValue, &typebuf[5]);
if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszValue, 0L,
KEY_READ, &hKey)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
goto Ret;
}
if ((err = RegQueryValueEx(hKey, "Name", NULL, &dwType,
NULL, &cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
goto Ret;
}
LocalFree(pszValue);
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
cbValue +
strlen(szprovider) + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if ((pszTmpProvName = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
(UINT) cbValue + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszValue, szprovider);
cbTemp = cbValue;
if ((err = RegQueryValueEx(hKey, "Name", NULL, &dwType,
(LPBYTE)pszTmpProvName,
&cbTemp)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
goto Ret;
}
strcat(pszValue, pszTmpProvName);
RegCloseKey(hKey);
hKey = 0;
}
if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszValue,
0L, KEY_READ, &hKey)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_KEYSET_NOT_DEF);
goto Ret;
}
LocalFree(pszValue);
pszValue = NULL;
cbValue = sizeof(DWORD);
if ((err = RegQueryValueEx(hKey, "Type", NULL, &dwType,
(LPBYTE)&provtype,
&cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
goto Ret;
}
// Check that requested provider type is same as registry entry
if (provtype != dwReqProvider)
{
SetLastError((DWORD) NTE_PROV_TYPE_NO_MATCH);
goto Ret;
}
// Determine size of path for provider
if ((err = RegQueryValueEx(hKey, "Image Path", NULL,
&dwType, NULL, &cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
goto Ret;
}
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
(UINT) cbValue)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
// Get value from registry
if ((err = RegQueryValueEx(hKey, "Image Path", NULL, &dwType,
(LPBYTE)pszValue, &cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
goto Ret;
}
pszDest = NULL;
cbTemp = 0;
if ((cbTemp = ExpandEnvironmentStrings(pszValue, (CHAR *) &pszDest, cbTemp)) == 0)
{
goto Ret;
}
if ((pszDest = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
(UINT) cbTemp)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if ((cbTemp = ExpandEnvironmentStrings(pszValue, pszDest,
cbTemp)) == 0)
{
goto Ret;
}
LocalFree(pszValue);
pszValue = pszDest;
pszDest = NULL;
cbValue = cbTemp;
if (!CSPInCacheCheck(pszValue, &handle))
{
if ( RtlCreateUnicodeStringFromAsciiz( &String, pszValue ) )
{
// check if the CSP is registered as having the signature in the file
SigInFile = CheckSignatureInFile( String.Buffer );
RtlFreeUnicodeString( &String );
if (! SigInFile )
{
// Determine size of signature
if ((err = RegQueryValueEx(hKey, "Signature", NULL,
&dwType, NULL, &cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_BAD_SIGNATURE);
goto Ret;
}
if ((SignatureBuf = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,
(UINT) cbValue)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
// Get Digital signature from registry
if ((err = RegQueryValueEx(hKey, "Signature", NULL, &dwType,
SignatureBuf,
&cbValue)) != ERROR_SUCCESS)
{
SetLastError((DWORD) NTE_BAD_SIGNATURE);
goto Ret;
}
if (RCRYPT_FAILED(NewVerifyImage(pszValue, SignatureBuf, cbValue, FALSE)))
{
SetLastError((DWORD) NTE_BAD_SIGNATURE);
goto Ret;
}
}
}
if ((handle = LoadLibrary(pszValue)) == NULL)
{
SetLastError((DWORD) NTE_PROVIDER_DLL_FAIL);
goto Ret;
}
AddHandleToCSPCache(handle);
}
// DLLs exist allocate VTable struct to hold address of entry points
bufsize = sizeof(VTableStruc);
if ((pVTable = (PVTableStruc) LocalAlloc(LMEM_ZEROINIT,
(UINT) bufsize)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
pTable = (ULONG_PTR *) pVTable;
// Build table of pointers to Crypto API for this DLL
i = 0;
while (FunctionNames[i] != NULL)
{
*pTable = (ULONG_PTR) GetProcAddress(handle, FunctionNames[i]);
if (*pTable == 0)
{
SetLastError((DWORD) NTE_PROVIDER_DLL_FAIL);
goto Ret;
}
pTable++;
i++;
}
// Build the table of optional pointers to Crypto API for this DLL
i = 0;
pTable++;
while (OptionalFunctionNames[i] != NULL)
{
*pTable = (ULONG_PTR) GetProcAddress(handle, OptionalFunctionNames[i]);
pTable++;
i++;
}
pVTable->DllHandle = handle;
memset(&VTableProv, 0, sizeof(VTableProv));
VTableProv.Version = 3;
VTableProv.FuncVerifyImage = (CRYPT_VERIFY_IMAGE_A)CProvVerifyImage;
VTableProv.FuncReturnhWnd = (CRYPT_RETURN_HWND)CPReturnhWnd;
VTableProv.dwProvType = dwReqProvider;
VTableProv.pszProvName = pszTmpProvName;
VTableProv.pbContextInfo = pbContextInfo;
VTableProv.cbContextInfo = cbContextInfo;
*phProv = (HCRYPTPROV) NULL;
rt = (BOOL)pVTable->FuncAcquireContext(&hTmpProv, pszIdentity, dwFlags,
&VTableProv);
if (RCRYPT_SUCCEEDED(rt) &&
((dwFlags & CRYPT_DELETEKEYSET) != CRYPT_DELETEKEYSET))
{
pVTable->hProv = hTmpProv;
*phProv = (HCRYPTPROV)pVTable;
pVTable->Version = TABLEPROV;
pVTable->Inuse = 1;
pVTable->RefCnt = 1;
}
}
__except (CapiExceptionFilter)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
dwErr = GetLastError();
if (pszTmpProvName)
LocalFree(pszTmpProvName);
if (pszValue)
LocalFree(pszValue);
if (hKey)
RegCloseKey(hKey);
if (pszDest)
LocalFree(pszDest);
if (SignatureBuf)
LocalFree(SignatureBuf);
if ((CRYPT_SUCCEED != rt) || (dwFlags & CRYPT_DELETEKEYSET))
{
if (pVTable)
LocalFree(pVTable);
SetLastError(dwErr);
}
return rt;
}
/*
- CryptContextAddRef
-
* Purpose:
* Increments the reference counter on the provider handle.
*
* Parameters:
* IN hProv - Handle to a CSP
* IN pdwReserved - Reserved parameter
* IN dwFlags - Flags values
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptContextAddRef(
IN HCRYPTPROV hProv,
IN DWORD *pdwReserved,
IN DWORD dwFlags
)
{
PVTableStruc pVTable;
BOOL fRet = CRYPT_FAILED;
__try
{
if ((NULL != pdwReserved) || (0 != dwFlags))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
pVTable = (PVTableStruc) hProv;
if (pVTable->Version != TABLEPROV)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (InterlockedIncrement(&pVTable->RefCnt) <= 0)
SetLastError(ERROR_INVALID_PARAMETER);
else
fRet = CRYPT_SUCCEED;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return fRet;
}
/*
- CryptReleaseContext
-
* Purpose:
* The CryptReleaseContext function is used to release a
* context created by CryptAcquireContext.
*
* Parameters:
* IN hProv - Handle to a CSP
* IN dwFlags - Flags values
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptReleaseContext(IN HCRYPTPROV hProv,
IN DWORD dwFlags)
{
PVTableStruc pVTable;
BOOL rt;
BOOL fRet = CRYPT_FAILED;
DWORD dwErr = 0;
__try
{
pVTable = (PVTableStruc) hProv;
if (pVTable->Version != TABLEPROV)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (pVTable->RefCnt <= 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 == InterlockedDecrement(&pVTable->RefCnt))
{
if (0 < InterlockedDecrement((LPLONG)&pVTable->Inuse))
{
InterlockedIncrement((LPLONG)&pVTable->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVTable->Inuse);
if (FALSE == (rt = (BOOL)pVTable->FuncReleaseContext(pVTable->hProv, dwFlags)))
{
dwErr = GetLastError();
}
pVTable->Version = 0;
LocalFree(pVTable);
if (!rt)
{
SetLastError(dwErr);
goto Ret;
}
}
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
return fRet;
}
/*
- CryptGenKey
-
* Purpose:
* Generate cryptographic keys
*
*
* Parameters:
* IN hProv - Handle to a CSP
* IN Algid - Algorithm identifier
* IN dwFlags - Flags values
* OUT phKey - Handle to a generated key
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGenKey(IN HCRYPTPROV hProv,
IN ALG_ID Algid,
IN DWORD dwFlags,
OUT HCRYPTKEY * phKey)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
BOOL fProvCritSec = FALSE;
DWORD dwErr;
BOOL fRet = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
{
goto Ret;
}
if (RCRYPT_FAILED(pVTable->FuncGenKey(pVTable->hProv, Algid, dwFlags,
phKey)))
{
goto Ret;
}
pVKey->hKey = *phKey;
*phKey = (HCRYPTKEY) pVKey;
pVKey->Version = TABLEKEY;
pVKey->hProv = hProv;
pVKey->Inuse = 1;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
dwErr = GetLastError();
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (CRYPT_SUCCEED != fRet)
{
if (pVKey)
LocalFree(pVKey);
SetLastError(dwErr);
}
return fRet;
}
/*
- CryptDuplicateKey
-
* Purpose:
* Duplicate a cryptographic key
*
*
* Parameters:
* IN hKey - Handle to the key to be duplicated
* IN pdwReserved - Reserved for later use
* IN dwFlags - Flags values
* OUT phKey - Handle to the new duplicate key
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDuplicateKey(
IN HCRYPTKEY hKey,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT HCRYPTKEY * phKey
)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey;
PVKeyStruc pVNewKey = NULL;
HCRYPTKEY hNewKey;
BOOL fProvCritSecSet = FALSE;
DWORD dwErr = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
if (IsBadWritePtr(phKey, sizeof(HCRYPTKEY)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
pVKey = (PVKeyStruc) hKey;
if (pVKey->Version != TABLEKEY)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (NULL == pVKey->OptionalFuncDuplicateKey)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Ret;
}
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fProvCritSecSet = TRUE;
if (RCRYPT_FAILED(BuildVKey(&pVNewKey, pVTable)))
{
goto Ret;
}
if (RCRYPT_FAILED(pVKey->OptionalFuncDuplicateKey(pVTable->hProv, pVKey->hKey,
pdwReserved, dwFlags, &hNewKey)))
{
goto Ret;
}
pVNewKey->hKey = hNewKey;
pVNewKey->Version = TABLEKEY;
pVNewKey->hProv = pVKey->hProv;
pVKey->Inuse = 1;
*phKey = (HCRYPTKEY) pVNewKey;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
dwErr = GetLastError();
if (fProvCritSecSet)
LeaveProviderCritSec(pVTable);
if (fRet == CRYPT_FAILED)
{
if (NULL != pVNewKey)
LocalFree(pVNewKey);
SetLastError(dwErr);
}
return fRet;
}
/*
- CryptDeriveKey
-
* Purpose:
* Derive cryptographic keys from base data
*
*
* Parameters:
* IN hProv - Handle to a CSP
* IN Algid - Algorithm identifier
* IN hHash - Handle to hash of base data
* IN dwFlags - Flags values
* IN OUT phKey - Handle to a generated key
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDeriveKey(IN HCRYPTPROV hProv,
IN ALG_ID Algid,
IN HCRYPTHASH hHash,
IN DWORD dwFlags,
IN OUT HCRYPTKEY * phKey)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
PVHashStruc pVHash = NULL;
BOOL fProvCritSec = FALSE;
BOOL fKeyCritSec = FALSE;
BOOL fHashCritSec = FALSE;
BOOL fUpdate = FALSE;
DWORD dwErr = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
if (dwFlags & CRYPT_UPDATE_KEY)
{
fUpdate = TRUE;
pVKey = (PVKeyStruc) phKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fKeyCritSec = TRUE;
}
else
{
if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
{
goto Ret;
}
}
if (RCRYPT_FAILED(pVTable->FuncDeriveKey(pVTable->hProv, Algid,
pVHash->hHash, dwFlags, phKey)))
{
goto Ret;
}
if ((dwFlags & CRYPT_UPDATE_KEY) != CRYPT_UPDATE_KEY)
{
pVKey->hKey = *phKey;
*phKey = (HCRYPTKEY)pVKey;
pVKey->hProv = hProv;
pVKey->Version = TABLEKEY;
pVKey->Inuse = 1;
}
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (CRYPT_SUCCEED != fRet)
dwErr = GetLastError();
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
if (CRYPT_SUCCEED != fRet)
{
if (pVKey && (!fUpdate))
LocalFree(pVKey);
SetLastError(dwErr);
}
return fRet;
}
/*
- CryptDestroyKey
-
* Purpose:
* Destroys the cryptographic key that is being referenced
* with the hKey parameter
*
*
* Parameters:
* IN hKey - Handle to a key
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDestroyKey(IN HCRYPTKEY hKey)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey;
BOOL fProvCritSec = FALSE;
BOOL rt;
DWORD dwErr = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
pVKey = (PVKeyStruc) hKey;
if (pVKey->Version != TABLEKEY)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 < InterlockedDecrement((LPLONG)&pVKey->Inuse))
{
InterlockedIncrement((LPLONG)&pVKey->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVKey->Inuse);
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
if (FALSE == (rt = (BOOL)pVKey->FuncDestroyKey(pVTable->hProv, pVKey->hKey)))
dwErr = GetLastError();
pVKey->Version = 0;
LocalFree(pVKey);
if (!rt)
{
SetLastError(dwErr);
goto Ret;
}
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (CRYPT_SUCCEED != fRet)
dwErr = GetLastError();
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (CRYPT_SUCCEED != fRet)
SetLastError(dwErr);
return fRet;
}
/*
- CryptSetKeyParam
-
* Purpose:
* Allows applications to customize various aspects of the
* operations of a key
*
* Parameters:
* IN hKey - Handle to a key
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptSetKeyParam(IN HCRYPTKEY hKey,
IN DWORD dwParam,
IN CONST BYTE *pbData,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey;
BOOL rt = CRYPT_FAILED;
BOOL fCritSec = FALSE;
__try
{
pVKey = (PVKeyStruc) hKey;
if (pVKey->Version != TABLEKEY)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 < InterlockedDecrement((LPLONG)&pVKey->Inuse))
{
InterlockedIncrement((LPLONG)&pVKey->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVKey->Inuse);
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fCritSec = TRUE;
rt = (BOOL)pVKey->FuncSetKeyParam(pVTable->hProv, pVKey->hKey,
dwParam, pbData, dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fCritSec)
LeaveProviderCritSec(pVTable);
return(rt);
}
/*
- CryptGetKeyParam
-
* Purpose:
* Allows applications to get various aspects of the
* operations of a key
*
* Parameters:
* IN hKey - Handle to a key
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN pdwDataLen - Length of parameter data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGetKeyParam(IN HCRYPTKEY hKey,
IN DWORD dwParam,
IN BYTE *pbData,
IN DWORD *pdwDataLen,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
BOOL rt = CRYPT_FAILED;
BOOL fKeyCritSec = FALSE;
BOOL fTableCritSec = FALSE;
__try
{
pVKey = (PVKeyStruc) hKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
rt = (BOOL)pVKey->FuncGetKeyParam(pVTable->hProv, pVKey->hKey,
dwParam, pbData, pdwDataLen,
dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
return(rt);
}
/*
- CryptGenRandom
-
* Purpose:
* Used to fill a buffer with random bytes
*
*
* Parameters:
* IN hProv - Handle to the user identifcation
* IN dwLen - Number of bytes of random data requested
* OUT pbBuffer - Pointer to the buffer where the random
* bytes are to be placed
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGenRandom(IN HCRYPTPROV hProv,
IN DWORD dwLen,
OUT BYTE *pbBuffer)
{
PVTableStruc pVTable = NULL;
BOOL fTableCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
rt = (BOOL)pVTable->FuncGenRandom(pVTable->hProv, dwLen, pbBuffer);
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
return(rt);
}
/*
- CryptGetUserKey
-
* Purpose:
* Gets a handle to a permanent user key
*
*
* Parameters:
* IN hProv - Handle to the user identifcation
* IN dwKeySpec - Specification of the key to retrieve
* OUT phUserKey - Pointer to key handle of retrieved key
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGetUserKey(IN HCRYPTPROV hProv,
IN DWORD dwKeySpec,
OUT HCRYPTKEY *phUserKey)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
BOOL fTableCritSec = FALSE;
BOOL fRet = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
{
goto Ret;
}
if (RCRYPT_FAILED(pVTable->FuncGetUserKey(pVTable->hProv, dwKeySpec,
phUserKey)))
{
goto Ret;
}
pVKey->hKey = *phUserKey;
pVKey->hProv = hProv;
*phUserKey = (HCRYPTKEY)pVKey;
pVKey->Version = TABLEKEY;
pVKey->Inuse = 1;
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if ((CRYPT_SUCCEED != fRet) && pVKey)
LocalFree(pVKey);
return fRet;
}
/*
- CryptExportKey
-
* Purpose:
* Export cryptographic keys out of a CSP in a secure manner
*
*
* Parameters:
* IN hKey - Handle to the key to export
* IN hPubKey - Handle to the exchange public key value of
* the destination user
* IN dwBlobType - Type of key blob to be exported
* IN dwFlags - Flags values
* OUT pbData - Key blob data
* OUT pdwDataLen - Length of key blob in bytes
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptExportKey(IN HCRYPTKEY hKey,
IN HCRYPTKEY hPubKey,
IN DWORD dwBlobType,
IN DWORD dwFlags,
OUT BYTE *pbData,
OUT DWORD *pdwDataLen)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
PVKeyStruc pVPublicKey = NULL;
BOOL fKeyCritSec = FALSE;
BOOL fPubKeyCritSec = FALSE;
BOOL fTableCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVKey = (PVKeyStruc) hKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
pVPublicKey = (PVKeyStruc) hPubKey;
if (pVPublicKey != NULL)
{
if (RCRYPT_FAILED(EnterKeyCritSec(pVPublicKey)))
{
goto Ret;
}
fPubKeyCritSec = TRUE;
}
rt = (BOOL)pVKey->FuncExportKey(pVTable->hProv, pVKey->hKey,
(pVPublicKey == NULL ? 0 : pVPublicKey->hKey),
dwBlobType, dwFlags, pbData,
pdwDataLen);
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if (pVPublicKey != NULL)
{
if (fPubKeyCritSec)
LeaveKeyCritSec(pVPublicKey);
}
return(rt);
}
/*
- CryptImportKey
-
* Purpose:
* Import cryptographic keys
*
*
* Parameters:
* IN hProv - Handle to the CSP user
* IN pbData - Key blob data
* IN dwDataLen - Length of the key blob data
* IN hPubKey - Handle to the exchange public key value of
* the destination user
* IN dwFlags - Flags values
* OUT phKey - Pointer to the handle to the key which was
* Imported
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptImportKey(IN HCRYPTPROV hProv,
IN CONST BYTE *pbData,
IN DWORD dwDataLen,
IN HCRYPTKEY hPubKey,
IN DWORD dwFlags,
OUT HCRYPTKEY *phKey)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
PVKeyStruc pVPublicKey = NULL;
BOOL fKeyCritSec = FALSE;
BOOL fPubKeyCritSec = FALSE;
BOOL fTableCritSec = FALSE;
BOOL fBuiltKey = FALSE;
BOOL fRet = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
pVPublicKey = (PVKeyStruc)hPubKey;
if (pVPublicKey != NULL)
{
if (RCRYPT_FAILED(EnterKeyCritSec(pVPublicKey)))
{
goto Ret;
}
fPubKeyCritSec = TRUE;
}
if (dwFlags & CRYPT_UPDATE_KEY)
{
pVKey = (PVKeyStruc) phKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
}
else
{
if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
{
goto Ret;
}
fBuiltKey = TRUE;
}
if (RCRYPT_FAILED(pVTable->FuncImportKey(pVTable->hProv, pbData,
dwDataLen,
(pVPublicKey == NULL ? 0 : pVPublicKey->hKey),
dwFlags, phKey)))
{
goto Ret;
}
if ((dwFlags & CRYPT_UPDATE_KEY) != CRYPT_UPDATE_KEY)
{
pVKey->hKey = *phKey;
*phKey = (HCRYPTKEY) pVKey;
pVKey->hProv = hProv;
pVKey->Version = TABLEKEY;
}
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if (pVPublicKey != NULL)
{
if (fPubKeyCritSec)
LeaveKeyCritSec(pVPublicKey);
}
if ((dwFlags & CRYPT_UPDATE_KEY) && fKeyCritSec)
{
LeaveKeyCritSec(pVKey);
}
else if ((CRYPT_SUCCEED != fRet) && fBuiltKey && pVKey)
{
LocalFree(pVKey);
}
return fRet;
}
/*
- CryptEncrypt
-
* Purpose:
* Encrypt data
*
*
* Parameters:
* IN hKey - Handle to the key
* IN hHash - Optional handle to a hash
* IN Final - Boolean indicating if this is the final
* block of plaintext
* IN dwFlags - Flags values
* IN OUT pbData - Data to be encrypted
* IN OUT pdwDataLen - Pointer to the length of the data to be
* encrypted
* IN dwBufLen - Size of Data buffer
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptEncrypt(IN HCRYPTKEY hKey,
IN HCRYPTHASH hHash,
IN BOOL Final,
IN DWORD dwFlags,
IN OUT BYTE *pbData,
IN OUT DWORD *pdwDataLen,
IN DWORD dwBufLen)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
PVHashStruc pVHash = NULL;
BOOL fKeyCritSec = FALSE;
BOOL fTableCritSec = FALSE;
BOOL fHashCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVKey = (PVKeyStruc) hKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
pVHash = (PVHashStruc) hHash;
if (pVHash != NULL)
{
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
}
rt = (BOOL)pVKey->FuncEncrypt(pVTable->hProv, pVKey->hKey,
(pVHash == NULL ? 0 : pVHash->hHash),
Final, dwFlags, pbData,
pdwDataLen, dwBufLen);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
if (pVHash != NULL)
{
if (fHashCritSec)
LeaveHashCritSec(pVHash);
}
return rt;
}
/*
- CryptDecrypt
-
* Purpose:
* Decrypt data
*
*
* Parameters:
* IN hKey - Handle to the key
* IN hHash - Optional handle to a hash
* IN Final - Boolean indicating if this is the final
* block of ciphertext
* IN dwFlags - Flags values
* IN OUT pbData - Data to be decrypted
* IN OUT pdwDataLen - Pointer to the length of the data to be
* decrypted
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDecrypt(IN HCRYPTKEY hKey,
IN HCRYPTHASH hHash,
IN BOOL Final,
IN DWORD dwFlags,
IN OUT BYTE *pbData,
IN OUT DWORD *pdwDataLen)
{
PVTableStruc pVTable = NULL;
PVKeyStruc pVKey = NULL;
PVHashStruc pVHash = NULL;
BOOL fKeyCritSec = FALSE;
BOOL fTableCritSec = FALSE;
BOOL fHashCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVKey = (PVKeyStruc) hKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
pVTable = (PVTableStruc) pVKey->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fTableCritSec = TRUE;
pVHash = (PVHashStruc) hHash;
if (pVHash != NULL)
{
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
}
rt = (BOOL)pVKey->FuncDecrypt(pVTable->hProv, pVKey->hKey,
(pVHash == NULL ? 0 : pVHash->hHash),
Final, dwFlags, pbData, pdwDataLen);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
if (pVHash != NULL)
{
if (fHashCritSec)
LeaveHashCritSec(pVHash);
}
return(rt);
}
/*
- CryptCreateHash
-
* Purpose:
* initate the hashing of a stream of data
*
*
* Parameters:
* IN hProv - Handle to the user identifcation
* IN Algid - Algorithm identifier of the hash algorithm
* to be used
* IN hKey - Optional key for MAC algorithms
* IN dwFlags - Flags values
* OUT pHash - Handle to hash object
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptCreateHash(IN HCRYPTPROV hProv,
IN ALG_ID Algid,
IN HCRYPTKEY hKey,
IN DWORD dwFlags,
OUT HCRYPTHASH *phHash)
{
PVTableStruc pVTable = NULL;
DWORD bufsize;
PVKeyStruc pVKey = NULL;
PVHashStruc pVHash = NULL;
BOOL fTableCritSec = FALSE;
BOOL fKeyCritSec = FALSE;
BOOL fRet = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fTableCritSec = TRUE;
pVKey = (PVKeyStruc) hKey;
if (pVKey != NULL)
{
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fKeyCritSec = TRUE;
}
bufsize = sizeof(VHashStruc);
if (!BuildVHash(&pVHash, pVTable))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (RCRYPT_FAILED(pVTable->FuncCreateHash(pVTable->hProv, Algid,
(pVKey == NULL ? 0 : pVKey->hKey),
dwFlags, phHash)))
{
goto Ret;
}
pVHash->hHash = *phHash;
*phHash = (HCRYPTHASH) pVHash;
pVHash->Version = TABLEHASH;
pVHash->Inuse = 1;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (fTableCritSec)
LeaveProviderCritSec(pVTable);
if (pVKey != NULL)
{
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
}
if ((CRYPT_SUCCEED != fRet) && pVHash)
LocalFree(pVHash);
return fRet;
}
/*
- CryptDuplicateHash
-
* Purpose:
* Duplicate a cryptographic hash
*
*
* Parameters:
* IN hHash - Handle to the hash to be duplicated
* IN pdwReserved - Reserved for later use
* IN dwFlags - Flags values
* OUT phHash - Handle to the new duplicate hash
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDuplicateHash(
IN HCRYPTHASH hHash,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT HCRYPTHASH * phHash
)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash;
PVHashStruc pVNewHash = NULL;
HCRYPTHASH hNewHash;
BOOL fProvCritSecSet = FALSE;
DWORD dwErr = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
if (IsBadWritePtr(phHash, sizeof(HCRYPTHASH)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
pVHash = (PVHashStruc) hHash;
if (pVHash->Version != TABLEHASH)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (NULL == pVHash->OptionalFuncDuplicateHash)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Ret;
}
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fProvCritSecSet = TRUE;
if (RCRYPT_FAILED(BuildVHash(&pVNewHash, pVTable)))
{
goto Ret;
}
if (RCRYPT_FAILED(pVHash->OptionalFuncDuplicateHash(pVTable->hProv, pVHash->hHash,
pdwReserved, dwFlags, &hNewHash)))
{
goto Ret;
}
pVNewHash->hHash = hNewHash;
pVNewHash->Version = TABLEHASH;
pVNewHash->hProv = pVHash->hProv;
pVHash->Inuse = 1;
*phHash = (HCRYPTHASH) pVNewHash;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (CRYPT_SUCCEED != fRet)
dwErr = GetLastError();
if ((fRet == CRYPT_FAILED) && (NULL != pVNewHash))
LocalFree(pVNewHash);
if (fProvCritSecSet)
LeaveProviderCritSec(pVTable);
if (CRYPT_SUCCEED != fRet)
SetLastError(dwErr);
return fRet;
}
/*
- CryptHashData
-
* Purpose:
* Compute the cryptograghic hash on a stream of data
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN pbData - Pointer to data to be hashed
* IN dwDataLen - Length of the data to be hashed
* IN dwFlags - Flags values
*
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptHashData(IN HCRYPTHASH hHash,
IN CONST BYTE *pbData,
IN DWORD dwDataLen,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash = NULL;
BOOL fProvCritSec = FALSE;
BOOL fHashCritSec = FALSE;
DWORD dwErr = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
if (!pVHash->FuncHashData(pVTable->hProv,
pVHash->hHash,
pbData, dwDataLen, dwFlags))
goto Ret;
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (CRYPT_SUCCEED != fRet)
dwErr = GetLastError();
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (CRYPT_SUCCEED != fRet)
SetLastError(dwErr);
return fRet;
}
/*
- CryptHashSessionKey
-
* Purpose:
* Compute the cryptograghic hash on a key object
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN hKey - Handle to a key object
* IN dwFlags - Flags values
*
* Returns:
* CRYPT_FAILED
* CRYPT_SUCCEED
*/
WINADVAPI
BOOL
WINAPI CryptHashSessionKey(IN HCRYPTHASH hHash,
IN HCRYPTKEY hKey,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash = NULL;
PVKeyStruc pVKey = NULL;
BOOL fHashCritSec = FALSE;
BOOL fProvCritSec = FALSE;
BOOL fKeyCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
pVKey = (PVKeyStruc) hKey;
if (pVKey != NULL)
{
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
}
rt = (BOOL)pVHash->FuncHashSessionKey(pVTable->hProv,
pVHash->hHash,
pVKey->hKey,
dwFlags);
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (pVKey != NULL)
{
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
}
return rt;
}
/*
- CryptDestoryHash
-
* Purpose:
* Destory the hash object
*
*
* Parameters:
* IN hHash - Handle to hash object
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptDestroyHash(IN HCRYPTHASH hHash)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash;
BOOL fProvCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (pVHash->Version != TABLEHASH)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 < InterlockedDecrement((LPLONG)&pVHash->Inuse))
{
InterlockedIncrement((LPLONG)&pVHash->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVHash->Inuse);
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
rt = (BOOL)pVHash->FuncDestroyHash(pVTable->hProv, pVHash->hHash);
pVHash->Version = 0;
LocalFree(pVHash);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
return rt;
}
WINADVAPI
BOOL
WINAPI LocalSignHashW(IN HCRYPTHASH hHash,
IN DWORD dwKeySpec,
IN LPCWSTR sDescription,
IN DWORD dwFlags,
OUT BYTE *pbSignature,
OUT DWORD *pdwSigLen)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash = NULL;
BOOL fHashCritSec = FALSE;
BOOL fProvCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
rt = (BOOL)pVHash->FuncSignHash(pVTable->hProv, pVHash->hHash,
dwKeySpec,
sDescription, dwFlags,
pbSignature, pdwSigLen);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
return rt;
}
/*
- CryptSignHashW
-
* Purpose:
* Create a digital signature from a hash
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN dwKeySpec - Key pair that is used to sign with
* algorithm to be used
* IN sDescription - Description of data to be signed
* IN dwFlags - Flags values
* OUT pbSignture - Pointer to signature data
* OUT pdwSigLen - Pointer to the len of the signature data
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptSignHashW(IN HCRYPTHASH hHash,
IN DWORD dwKeySpec,
IN LPCWSTR sDescription,
IN DWORD dwFlags,
OUT BYTE *pbSignature,
OUT DWORD *pdwSigLen)
{
return LocalSignHashW(hHash, dwKeySpec, sDescription,
dwFlags, pbSignature, pdwSigLen);
}
/*
- CryptSignHashA
-
* Purpose:
* Create a digital signature from a hash
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN dwKeySpec - Key pair that is used to sign with
* algorithm to be used
* IN sDescription - Description of data to be signed
* IN dwFlags - Flags values
* OUT pbSignture - Pointer to signature data
* OUT pdwSigLen - Pointer to the len of the signature data
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptSignHashA(IN HCRYPTHASH hHash,
IN DWORD dwKeySpec,
IN LPCSTR sDescription,
IN DWORD dwFlags,
OUT BYTE *pbSignature,
OUT DWORD *pdwSigLen)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL rt = CRYPT_FAILED;
__try
{
memset(&AnsiString, 0, sizeof(AnsiString));
memset(&UnicodeString, 0, sizeof(UnicodeString));
if (NULL != sDescription)
{
RtlInitAnsiString(&AnsiString, sDescription);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
if ( !NT_SUCCESS(Status) )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
}
rt = LocalSignHashW(hHash, dwKeySpec, UnicodeString.Buffer,
dwFlags, pbSignature, pdwSigLen);
RtlFreeUnicodeString(&UnicodeString);
} __except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return rt;
}
WINADVAPI
BOOL
WINAPI LocalVerifySignatureW(IN HCRYPTHASH hHash,
IN CONST BYTE *pbSignature,
IN DWORD dwSigLen,
IN HCRYPTKEY hPubKey,
IN LPCWSTR sDescription,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash = NULL;
PVKeyStruc pVKey = NULL;
BOOL fHashCritSec = FALSE;
BOOL fProvCritSec = FALSE;
BOOL fKeyCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
pVKey = (PVKeyStruc) hPubKey;
if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
{
goto Ret;
}
fKeyCritSec = TRUE;
rt = (BOOL)pVHash->FuncVerifySignature(pVTable->hProv,
pVHash->hHash, pbSignature,
dwSigLen,
(pVKey == NULL ? 0 : pVKey->hKey),
sDescription, dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
if (fKeyCritSec)
LeaveKeyCritSec(pVKey);
return rt;
}
/*
- CryptVerifySignatureW
-
* Purpose:
* Used to verify a signature against a hash object
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN pbSignture - Pointer to signature data
* IN dwSigLen - Length of the signature data
* IN hPubKey - Handle to the public key for verifying
* the signature
* IN sDescription - String describing the signed data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptVerifySignatureW(IN HCRYPTHASH hHash,
IN CONST BYTE *pbSignature,
IN DWORD dwSigLen,
IN HCRYPTKEY hPubKey,
IN LPCWSTR sDescription,
IN DWORD dwFlags)
{
return LocalVerifySignatureW(hHash, pbSignature, dwSigLen,
hPubKey, sDescription, dwFlags);
}
/*
- CryptVerifySignatureA
-
* Purpose:
* Used to verify a signature against a hash object
*
*
* Parameters:
* IN hHash - Handle to hash object
* IN pbSignture - Pointer to signature data
* IN dwSigLen - Length of the signature data
* IN hPubKey - Handle to the public key for verifying
* the signature
* IN sDescription - String describing the signed data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptVerifySignatureA(IN HCRYPTHASH hHash,
IN CONST BYTE *pbSignature,
IN DWORD dwSigLen,
IN HCRYPTKEY hPubKey,
IN LPCSTR sDescription,
IN DWORD dwFlags)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL rt = CRYPT_FAILED;
__try
{
memset(&AnsiString, 0, sizeof(AnsiString));
memset(&UnicodeString, 0, sizeof(UnicodeString));
if (NULL != sDescription)
{
RtlInitAnsiString(&AnsiString, sDescription);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
if ( !NT_SUCCESS(Status) )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
}
rt = LocalVerifySignatureW(hHash, pbSignature, dwSigLen,
hPubKey, UnicodeString.Buffer, dwFlags);
RtlFreeUnicodeString(&UnicodeString);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return rt;
}
/*
- CryptSetProvParam
-
* Purpose:
* Allows applications to customize various aspects of the
* operations of a provider
*
* Parameters:
* IN hProv - Handle to a provider
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptSetProvParam(IN HCRYPTPROV hProv,
IN DWORD dwParam,
IN CONST BYTE *pbData,
IN DWORD dwFlags)
{
PVTableStruc pVTable;
BYTE *pbTmp;
CRYPT_DATA_BLOB *pBlob;
BOOL rt = CRYPT_FAILED;
__try
{
if (dwParam == PP_CLIENT_HWND)
{
hWnd = *((HWND *) pbData);
rt = CRYPT_SUCCEED;
goto Ret;
}
else if (dwParam == PP_CONTEXT_INFO)
{
pBlob = (CRYPT_DATA_BLOB*)pbData;
// allocate space for the new context info
if (NULL == (pbTmp = (BYTE*)LocalAlloc(LMEM_ZEROINIT, pBlob->cbData)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
memcpy(pbTmp, pBlob->pbData, pBlob->cbData);
// free any previously allocated context info
if (NULL != pbContextInfo)
{
LocalFree(pbContextInfo);
}
cbContextInfo = pBlob->cbData;
pbContextInfo = pbTmp;
rt = CRYPT_SUCCEED;
goto Ret;
}
pVTable = (PVTableStruc) hProv;
if (pVTable->Version != TABLEPROV)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 < InterlockedDecrement((LPLONG)&pVTable->Inuse))
{
InterlockedIncrement((LPLONG)&pVTable->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVTable->Inuse);
rt = (BOOL)pVTable->FuncSetProvParam(pVTable->hProv, dwParam, pbData,
dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return(rt);
}
/*
- CryptGetProvParam
-
* Purpose:
* Allows applications to get various aspects of the
* operations of a provider
*
* Parameters:
* IN hProv - Handle to a proivder
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN pdwDataLen - Length of parameter data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGetProvParam(IN HCRYPTPROV hProv,
IN DWORD dwParam,
IN BYTE *pbData,
IN DWORD *pdwDataLen,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
BOOL fProvCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVTable = (PVTableStruc) hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
rt = (BOOL)pVTable->FuncGetProvParam(pVTable->hProv, dwParam, pbData,
pdwDataLen, dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
return rt;
}
/*
- CryptSetHashParam
-
* Purpose:
* Allows applications to customize various aspects of the
* operations of a hash
*
* Parameters:
* IN hHash - Handle to a hash
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptSetHashParam(IN HCRYPTHASH hHash,
IN DWORD dwParam,
IN CONST BYTE *pbData,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash;
BOOL fProvCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (pVHash->Version != TABLEHASH)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 < InterlockedDecrement((LPLONG)&pVHash->Inuse))
{
InterlockedIncrement((LPLONG)&pVHash->Inuse);
SetLastError(ERROR_BUSY);
goto Ret;
}
InterlockedIncrement((LPLONG)&pVHash->Inuse);
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
rt = (BOOL)pVHash->FuncSetHashParam(pVTable->hProv, pVHash->hHash,
dwParam, pbData, dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
return rt;
}
/*
- CryptGetHashParam
-
* Purpose:
* Allows applications to get various aspects of the
* operations of a hash
*
* Parameters:
* IN hHash - Handle to a hash
* IN dwParam - Parameter number
* IN pbData - Pointer to data
* IN pdwDataLen - Length of parameter data
* IN dwFlags - Flags values
*
* Returns:
*/
WINADVAPI
BOOL
WINAPI CryptGetHashParam(IN HCRYPTKEY hHash,
IN DWORD dwParam,
IN BYTE *pbData,
IN DWORD *pdwDataLen,
IN DWORD dwFlags)
{
PVTableStruc pVTable = NULL;
PVHashStruc pVHash = NULL;
BOOL fHashCritSec = FALSE;
BOOL fProvCritSec = FALSE;
BOOL rt = CRYPT_FAILED;
__try
{
pVHash = (PVHashStruc) hHash;
if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
{
goto Ret;
}
fHashCritSec = TRUE;
pVTable = (PVTableStruc) pVHash->hProv;
if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
{
goto Ret;
}
fProvCritSec = TRUE;
rt = (BOOL)pVHash->FuncGetHashParam(pVTable->hProv, pVHash->hHash,
dwParam, pbData, pdwDataLen,
dwFlags);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
if (fHashCritSec)
LeaveHashCritSec(pVHash);
if (fProvCritSec)
LeaveProviderCritSec(pVTable);
return rt;
}
/*
- CryptSetProviderW
-
* Purpose:
* Set a cryptography provider
*
*
* Parameters:
*
* IN pszProvName - Name of the provider to install
* IN dwProvType - Type of the provider to install
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptSetProviderW(IN LPCWSTR pszProvName,
IN DWORD dwProvType)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL rt = FALSE;
__try
{
RtlInitUnicodeString(&UnicodeString, pszProvName);
Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
if (!NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
rt = CryptSetProviderA((LPCSTR) AnsiString.Buffer,
dwProvType);
RtlFreeAnsiString(&AnsiString);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return(rt);
}
/*
- CryptSetProviderA
-
* Purpose:
* Set a cryptography provider
*
*
* Parameters:
*
* IN pszProvName - Name of the provider to install
* IN dwProvType - Type of the provider to install
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptSetProviderA(IN LPCSTR pszProvName,
IN DWORD dwProvType)
{
BOOL fRet = CRYPT_FAILED;
LPSTR pszCurrent = NULL;
DWORD cbCurrent = 0;
__try
{
if (dwProvType == 0 || dwProvType > 999 || pszProvName == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
//
// We don't support setting the user default provider any more. See
// if the current default provider of the specified type matches the
// caller's. If it does, we'll let the call "succeed".
//
if (! CryptGetDefaultProvider(
dwProvType,
NULL,
CRYPT_MACHINE_DEFAULT,
NULL,
&cbCurrent))
{
goto Ret;
}
pszCurrent = (LPSTR) HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY, cbCurrent);
if (NULL == pszCurrent)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (! CryptGetDefaultProvider(
dwProvType,
NULL,
CRYPT_MACHINE_DEFAULT,
pszCurrent,
&cbCurrent))
{
goto Ret;
}
if (0 != strcmp(pszProvName, pszCurrent))
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
goto Ret;
}
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (pszCurrent)
HeapFree(GetProcessHeap(), 0, pszCurrent);
return fRet;
}
/*
- CryptSetProviderExW
-
* Purpose:
* Set the cryptographic provider as the default
* either for machine or for user.
*
*
* Parameters:
*
* IN pszProvName - Name of the provider to install
* IN dwProvType - Type of the provider to install
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter (for machine or for user)
*
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptSetProviderExW(
IN LPCWSTR pszProvName,
IN DWORD dwProvType,
IN DWORD *pdwReserved,
IN DWORD dwFlags
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL fRet = CRYPT_FAILED;
__try
{
RtlInitUnicodeString(&UnicodeString, pszProvName);
Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
if (!NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
fRet = CryptSetProviderExA((LPCSTR) AnsiString.Buffer,
dwProvType,
pdwReserved,
dwFlags);
RtlFreeAnsiString(&AnsiString);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
Ret:
return fRet;
}
/*
- CryptSetProviderExA
-
* Purpose:
* Set the cryptographic provider as the default
* either for machine or for user.
*
*
* Parameters:
*
* IN pszProvName - Name of the provider to install
* IN dwProvType - Type of the provider to install
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter (for machine or for user)
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptSetProviderExA(
IN LPCSTR pszProvName,
IN DWORD dwProvType,
IN DWORD *pdwReserved,
IN DWORD dwFlags
)
{
HKEY hCurrUser = 0;
HKEY hRegKey = 0;
LONG err;
DWORD dwDisp;
DWORD cbValue;
CHAR *pszValue = NULL;
CHAR *pszFullName = NULL;
DWORD cbFullName;
CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
DWORD dwKeyType;
DWORD dw;
DWORD cbProvType;
BOOL fRet = CRYPT_FAILED;
__try
{
if ((dwProvType == 0) || (dwProvType > 999) ||
(pszProvName == NULL) || (pdwReserved != NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if ((dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)) ||
((dwFlags & CRYPT_MACHINE_DEFAULT) && (dwFlags & CRYPT_USER_DEFAULT)))
{
SetLastError((DWORD)NTE_BAD_FLAGS);
goto Ret;
}
cbValue = strlen(pszProvName);
// check if the CSP has been installed
cbFullName = cbValue + sizeof(szenumproviders) + sizeof(CHAR);
if (NULL == (pszFullName = (CHAR *) LocalAlloc(LMEM_ZEROINIT, cbFullName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszFullName, szenumproviders);
pszFullName[sizeof(szenumproviders) - 1] = '\\';
strcpy(pszFullName + sizeof(szenumproviders), pszProvName);
if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszFullName,
0L, KEY_READ, &hRegKey)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
cbProvType = sizeof(dw);
if (ERROR_SUCCESS != (err = RegQueryValueEx(hRegKey,
(const char *) "Type",
NULL, &dwKeyType, (BYTE*)&dw,
&cbProvType)))
{
SetLastError(err);
goto Ret;
}
if (dwProvType != dw)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegCloseKey(hRegKey)))
{
SetLastError(err);
goto Ret;
}
hRegKey = NULL;
if (dwFlags & CRYPT_MACHINE_DEFAULT)
{
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
strlen(szmachinetype) + 5 + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszValue, szmachinetype);
__ltoa(dwProvType, typebuf);
strcat(pszValue, &typebuf[5]);
if ((err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszValue,
0L, NULL, REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE, NULL, &hRegKey, &dwDisp)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
// check the delete flag
if (dwFlags & CRYPT_DELETE_DEFAULT)
{
if (ERROR_SUCCESS != (err = RegDeleteValue(hRegKey, "Name")))
{
SetLastError(err);
goto Ret;
}
fRet = CRYPT_SUCCEED;
goto Ret;
}
}
else if (dwFlags & CRYPT_USER_DEFAULT)
{
if (dwFlags & CRYPT_DELETE_DEFAULT)
{
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
strlen(szusertype) + 5 + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszValue, szusertype);
__ltoa(dwProvType, typebuf);
strcat(pszValue, &typebuf[5]);
if (!NT_SUCCESS(RtlOpenCurrentUser(KEY_READ | KEY_WRITE, &hCurrUser)))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegDeleteKey(hCurrUser,
(const char *)pszValue)))
{
NtClose(hCurrUser);
SetLastError(err);
goto Ret;
}
fRet = CRYPT_SUCCEED;
NtClose(hCurrUser);
goto Ret;
}
else
{
// The User flag is set, but Delete is not. Handle this case
// in CryptSetProvider.
fRet = CryptSetProviderA(pszProvName, dwProvType);
goto Ret;
}
}
if (ERROR_SUCCESS != (err = RegSetValueEx(hRegKey, "Name", 0L, REG_SZ,
(const LPBYTE) pszProvName, cbValue)))
{
SetLastError(err);
goto Ret;
}
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (pszFullName)
LocalFree(pszFullName);
if (pszValue)
LocalFree(pszValue);
if (hRegKey)
RegCloseKey(hRegKey);
return fRet;
}
/*
- CryptGetDefaultProviderW
-
* Purpose:
* Get the default cryptographic provider of the specified
* type for either the machine or for the user.
*
* Parameters:
* IN dwProvType - Type of the provider to install
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter (for machine or for user)
* OUT pszProvName - Name of the default provider
* IN OUT pcbProvName - Length in bytes of the provider name
*
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptGetDefaultProviderW(
IN DWORD dwProvType,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT LPWSTR pszProvName,
IN OUT DWORD *pcbProvName
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
LPSTR pszName = NULL;
DWORD cbName;
NTSTATUS Status;
BOOL fRet = CRYPT_FAILED;
memset(&UnicodeString, 0, sizeof(UnicodeString));
__try
{
memset(&AnsiString, 0, sizeof(AnsiString));
if (!CryptGetDefaultProviderA(dwProvType,
pdwReserved,
dwFlags,
NULL,
&cbName))
goto Ret;
if (NULL == (pszName = LocalAlloc(LMEM_ZEROINIT, cbName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (!CryptGetDefaultProviderA(dwProvType,
pdwReserved,
dwFlags,
pszName,
&cbName))
goto Ret;
RtlInitAnsiString(&AnsiString, pszName);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
if (!NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (NULL == pszProvName)
{
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
fRet = CRYPT_SUCCEED;
goto Ret;
}
if (*pcbProvName < UnicodeString.Length + sizeof(WCHAR))
{
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
memset(pszProvName, 0, *pcbProvName);
memcpy(pszProvName, UnicodeString.Buffer, UnicodeString.Length);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (UnicodeString.Buffer)
RtlFreeUnicodeString(&UnicodeString);
if (pszName)
LocalFree(pszName);
return fRet;
}
/*
- CryptGetDefaultProviderA
-
* Purpose:
* Get the default cryptographic provider of the specified
* type for either the machine or for the user.
*
*
* Parameters:
* IN dwProvType - Type of the provider to install
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter (for machine or for user)
* OUT pszProvName - Name of the default provider
* IN OUT pcbProvName - Length in bytes of the provider name
* including the NULL terminator
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINAPI CryptGetDefaultProviderA(
IN DWORD dwProvType,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT LPSTR pszProvName,
IN OUT DWORD *pcbProvName
)
{
HKEY hRegKey = 0;
LONG err;
CHAR *pszValue = NULL;
DWORD dwValType;
CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
DWORD cbProvName = 0;
BOOL fRet = CRYPT_FAILED;
__try
{
if (dwProvType == 0 || dwProvType > 999 || pdwReserved != NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if ((dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT)) ||
((dwFlags & CRYPT_MACHINE_DEFAULT) && (dwFlags & CRYPT_USER_DEFAULT)))
{
SetLastError((DWORD)NTE_BAD_FLAGS);
goto Ret;
}
//
// We no longer look for a User default, but instead treat the USER_
// and MACHINE_ flags as identical, and only look in HKLM.
//
if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
strlen(szmachinetype) + 5 + 1)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
strcpy(pszValue, szmachinetype);
__ltoa(dwProvType, typebuf);
strcat(pszValue, &typebuf[5]);
if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) pszValue,
0L, KEY_READ, &hRegKey)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if ((err = RegQueryValueEx(hRegKey, "Name", 0L, &dwValType,
NULL,
&cbProvName)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (NULL == pszProvName)
{
*pcbProvName = cbProvName;
fRet = CRYPT_SUCCEED;
goto Ret;
}
if (cbProvName > *pcbProvName)
{
*pcbProvName = cbProvName;
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
if ((err = RegQueryValueEx(hRegKey, "Name", 0L, &dwValType,
(BYTE*)pszProvName,
&cbProvName)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
*pcbProvName = cbProvName;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (hRegKey)
RegCloseKey(hRegKey);
if (pszValue)
LocalFree(pszValue);
return fRet;
}
/*
- CryptEnumProviderTypesW
-
* Purpose:
* Enumerate the provider types.
*
* Parameters:
* IN dwIndex - Index to the provider types to enumerate
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter
* OUT pdwProvType - Pointer to the provider type
* OUT pszTypeName - Name of the enumerated provider type
* IN OUT pcbTypeName - Length of the enumerated provider type
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptEnumProviderTypesW(
IN DWORD dwIndex,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT DWORD *pdwProvType,
OUT LPWSTR pszTypeName,
IN OUT DWORD *pcbTypeName
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
LPSTR pszTmpTypeName = NULL;
DWORD cbTmpTypeName = 0;
NTSTATUS Status;
BOOL fRet = CRYPT_FAILED;
memset(&UnicodeString, 0, sizeof(UnicodeString));
__try
{
memset(&AnsiString, 0, sizeof(AnsiString));
if (!CryptEnumProviderTypesA(dwIndex,
pdwReserved,
dwFlags,
pdwProvType,
NULL,
&cbTmpTypeName))
goto Ret;
if (NULL == (pszTmpTypeName = LocalAlloc(LMEM_ZEROINIT, cbTmpTypeName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (!CryptEnumProviderTypesA(dwIndex,
pdwReserved,
dwFlags,
pdwProvType,
pszTmpTypeName,
&cbTmpTypeName))
goto Ret;
if (0 != cbTmpTypeName)
{
RtlInitAnsiString(&AnsiString, pszTmpTypeName);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
if ( !NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
// check if caller is asking for length, in addition the name of the provider
// may not be available, in this case a name length of 0 is returned
if ((NULL == pszTypeName) || (0 == cbTmpTypeName))
{
*pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
fRet = CRYPT_SUCCEED;
goto Ret;
}
if (*pcbTypeName < UnicodeString.Length + sizeof(WCHAR))
{
*pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
*pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
memset(pszTypeName, 0, *pcbTypeName);
memcpy(pszTypeName, UnicodeString.Buffer, UnicodeString.Length);
}
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (UnicodeString.Buffer)
RtlFreeUnicodeString(&UnicodeString);
if (pszTmpTypeName)
LocalFree(pszTmpTypeName);
return fRet;
}
/*
- CryptEnumProviderTypesA
-
* Purpose:
* Enumerate the provider types.
*
* Parameters:
* IN dwIndex - Index to the provider types to enumerate
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter
* OUT pdwProvType - Pointer to the provider type
* OUT pszTypeName - Name of the enumerated provider type
* IN OUT pcbTypeName - Length of the enumerated provider type
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptEnumProviderTypesA(
IN DWORD dwIndex,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT DWORD *pdwProvType,
OUT LPSTR pszTypeName,
IN OUT DWORD *pcbTypeName
)
{
HKEY hRegKey = 0;
HKEY hTypeKey = 0;
LONG err;
CHAR *pszRegKeyName = NULL;
DWORD cbClass;
FILETIME ft;
CHAR rgcType[] = {'T', 'y', 'p', 'e', ' '};
LPSTR pszValue;
long Type;
DWORD cSubKeys;
DWORD cbMaxKeyName;
DWORD cbMaxClass;
DWORD cValues;
DWORD cbMaxValName;
DWORD cbMaxValData;
DWORD cbTmpTypeName = 0;
DWORD dwValType;
BOOL fRet = CRYPT_FAILED;
__try
{
if (NULL != pdwReserved)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 != dwFlags)
{
SetLastError((DWORD)NTE_BAD_FLAGS);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) szprovidertypes,
0L,
KEY_READ,
&hRegKey)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegQueryInfoKey(hRegKey,
NULL,
NULL,
NULL,
&cSubKeys,
&cbMaxKeyName,
&cbMaxClass,
&cValues,
&cbMaxValName,
&cbMaxValData,
NULL,
&ft)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
cbMaxKeyName += sizeof(CHAR);
if (NULL == (pszRegKeyName = LocalAlloc(LMEM_ZEROINIT, cbMaxKeyName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegEnumKeyEx(hRegKey,
dwIndex, pszRegKeyName, &cbMaxKeyName, NULL,
NULL, &cbClass, &ft)))
{
if (ERROR_NO_MORE_ITEMS == err)
{
SetLastError((DWORD)err);
}
else
{
SetLastError((DWORD)NTE_FAIL);
}
goto Ret;
}
if (memcmp(pszRegKeyName, rgcType, sizeof(rgcType)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
pszValue = pszRegKeyName + sizeof(rgcType);
if (0 == (Type = atol(pszValue)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
*pdwProvType = (DWORD)Type;
// check for the type name
if (ERROR_SUCCESS != (err = RegOpenKeyEx(hRegKey,
(const char *)pszRegKeyName,
0L,
KEY_READ,
&hTypeKey)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
if ((err = RegQueryValueEx(hTypeKey, "TypeName", 0L, &dwValType,
NULL, &cbTmpTypeName)) != ERROR_SUCCESS)
{
fRet = CRYPT_SUCCEED;
goto Ret;
}
if (NULL == pszTypeName)
{
*pcbTypeName = cbTmpTypeName;
fRet = CRYPT_SUCCEED;
goto Ret;
}
else if (*pcbTypeName < cbTmpTypeName)
{
*pcbTypeName = cbTmpTypeName;
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
if ((err = RegQueryValueEx(hTypeKey, "TypeName", 0L, &dwValType,
(BYTE*)pszTypeName, &cbTmpTypeName)) != ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
*pcbTypeName = cbTmpTypeName;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (hRegKey)
RegCloseKey(hRegKey);
if (hTypeKey)
RegCloseKey(hTypeKey);
if (pszRegKeyName)
LocalFree(pszRegKeyName);
return fRet;
}
/*
- CryptEnumProvidersW
-
* Purpose:
* Enumerate the providers.
*
* Parameters:
* IN dwIndex - Index to the providers to enumerate
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter
* OUT pdwProvType - The type of the provider
* OUT pszProvName - Name of the enumerated provider
* IN OUT pcbProvName - Length of the enumerated provider
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptEnumProvidersW(
IN DWORD dwIndex,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT DWORD *pdwProvType,
OUT LPWSTR pszProvName,
IN OUT DWORD *pcbProvName
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
LPSTR pszTmpProvName = NULL;
DWORD cbTmpProvName;
NTSTATUS Status;
BOOL fRet = CRYPT_FAILED;
memset(&UnicodeString, 0, sizeof(UnicodeString));
__try
{
memset(&AnsiString, 0, sizeof(AnsiString));
if (!CryptEnumProvidersA(dwIndex,
pdwReserved,
dwFlags,
pdwProvType,
NULL,
&cbTmpProvName))
goto Ret;
if (NULL == (pszTmpProvName = LocalAlloc(LMEM_ZEROINIT, cbTmpProvName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (!CryptEnumProvidersA(dwIndex,
pdwReserved,
dwFlags,
pdwProvType,
pszTmpProvName,
&cbTmpProvName))
goto Ret;
RtlInitAnsiString(&AnsiString, pszTmpProvName);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
if ( !NT_SUCCESS(Status))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (NULL == pszProvName)
{
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
fRet = CRYPT_SUCCEED;
goto Ret;
}
if (*pcbProvName < UnicodeString.Length + sizeof(WCHAR))
{
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
*pcbProvName = UnicodeString.Length + sizeof(WCHAR);
memset(pszProvName, 0, *pcbProvName);
memcpy(pszProvName, UnicodeString.Buffer, UnicodeString.Length);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (UnicodeString.Buffer)
RtlFreeUnicodeString(&UnicodeString);
if (pszTmpProvName)
LocalFree(pszTmpProvName);
return fRet;
}
/*
- CryptEnumProvidersA
-
* Purpose:
* Enumerate the providers.
*
* Parameters:
* IN dwIndex - Index to the providers to enumerate
* IN pdwReserved - Reserved for future use
* IN dwFlags - Flags parameter
* OUT pdwProvType - The type of the provider
* OUT pszProvName - Name of the enumerated provider
* IN OUT pcbProvName - Length of the enumerated provider
*
* Returns:
* BOOL
* Use get extended error information use GetLastError
*/
WINADVAPI
BOOL
WINAPI CryptEnumProvidersA(
IN DWORD dwIndex,
IN DWORD *pdwReserved,
IN DWORD dwFlags,
OUT DWORD *pdwProvType,
OUT LPSTR pszProvName,
IN OUT DWORD *pcbProvName
)
{
HKEY hRegKey = 0;
HKEY hProvRegKey = 0;
LONG err;
DWORD cbClass;
FILETIME ft;
DWORD dwKeyType;
DWORD cbProvType;
DWORD dw;
DWORD cSubKeys;
DWORD cbMaxKeyName;
DWORD cbMaxClass;
DWORD cValues;
DWORD cbMaxValName;
DWORD cbMaxValData;
LPSTR pszTmpProvName = NULL;
DWORD cbTmpProvName;
BOOL fRet = CRYPT_FAILED;
__try
{
if (NULL != pdwReserved)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
if (0 != dwFlags)
{
SetLastError((DWORD)NTE_BAD_FLAGS);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(const char *) szenumproviders,
0L, KEY_READ, &hRegKey)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegQueryInfoKey(hRegKey,
NULL,
NULL,
NULL,
&cSubKeys,
&cbMaxKeyName,
&cbMaxClass,
&cValues,
&cbMaxValName,
&cbMaxValData,
NULL,
&ft)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
cbMaxKeyName += sizeof(CHAR);
if (NULL == (pszTmpProvName = LocalAlloc(LMEM_ZEROINIT, cbMaxKeyName)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegEnumKeyEx(hRegKey, dwIndex, pszTmpProvName,
&cbMaxKeyName, NULL,
NULL, &cbClass, &ft)))
{
SetLastError((DWORD)err);
goto Ret;
}
if (ERROR_SUCCESS != (err = RegOpenKeyEx(hRegKey,
(const char *) pszTmpProvName,
0L, KEY_READ, &hProvRegKey)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
cbProvType = sizeof(dw);
if (ERROR_SUCCESS != (err = RegQueryValueEx(hProvRegKey,
(const char *) "Type",
NULL, &dwKeyType, (BYTE*)&dw,
&cbProvType)))
{
SetLastError((DWORD)NTE_FAIL);
goto Ret;
}
*pdwProvType = dw;
cbTmpProvName = strlen(pszTmpProvName) + sizeof(CHAR);
if (NULL != pszProvName)
{
if (*pcbProvName < cbTmpProvName)
{
*pcbProvName = cbTmpProvName;
SetLastError(ERROR_MORE_DATA);
goto Ret;
}
strcpy(pszProvName, pszTmpProvName);
}
*pcbProvName = cbTmpProvName;
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Ret;
}
fRet = CRYPT_SUCCEED;
Ret:
if (pszTmpProvName)
LocalFree(pszTmpProvName);
if (hRegKey)
RegCloseKey(hRegKey);
if (hProvRegKey)
RegCloseKey(hProvRegKey);
return fRet;
}
BOOL EnterProviderCritSec(IN PVTableStruc pVTable)
{
__try
{
if (pVTable->Version != TABLEPROV)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
InterlockedIncrement((LPLONG)&pVTable->Inuse);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
return(CRYPT_SUCCEED);
Try_Error_Return:
return(CRYPT_FAILED);
}
void LeaveProviderCritSec(IN PVTableStruc pVTable)
{
InterlockedDecrement((LPLONG)&pVTable->Inuse);
}
BOOL EnterKeyCritSec(IN PVKeyStruc pVKey)
{
__try
{
if (pVKey->Version != TABLEKEY)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
InterlockedIncrement((LPLONG)&pVKey->Inuse);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
return(CRYPT_SUCCEED);
Try_Error_Return:
return(CRYPT_FAILED);
}
void LeaveKeyCritSec(IN PVKeyStruc pVKey)
{
InterlockedDecrement((LPLONG)&pVKey->Inuse);
}
BOOL EnterHashCritSec(IN PVHashStruc pVHash)
{
__try
{
if (pVHash->Version != TABLEHASH)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
InterlockedIncrement((LPLONG)&pVHash->Inuse);
}
__except ( CapiExceptionFilter )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto Try_Error_Return;
}
return(CRYPT_SUCCEED);
Try_Error_Return:
return(CRYPT_FAILED);
}
void LeaveHashCritSec(IN PVHashStruc pVHash)
{
InterlockedDecrement((LPLONG)&pVHash->Inuse);
}
BOOL BuildVKey(IN PVKeyStruc *ppVKey,
IN PVTableStruc pVTable)
{
DWORD bufsize;
PVKeyStruc pVKey;
bufsize = sizeof(VKeyStruc);
if ((pVKey = (PVKeyStruc) LocalAlloc(LMEM_ZEROINIT,
(UINT) bufsize)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(CRYPT_FAILED);
}
pVKey->FuncGenKey = pVTable->FuncGenKey;
pVKey->FuncDeriveKey = pVTable->FuncDeriveKey;
pVKey->FuncDestroyKey = pVTable->FuncDestroyKey;
pVKey->FuncSetKeyParam = pVTable->FuncSetKeyParam;
pVKey->FuncGetKeyParam = pVTable->FuncGetKeyParam;
pVKey->FuncExportKey = pVTable->FuncExportKey;
pVKey->FuncImportKey = pVTable->FuncImportKey;
pVKey->FuncEncrypt = pVTable->FuncEncrypt;
pVKey->FuncDecrypt = pVTable->FuncDecrypt;
pVKey->OptionalFuncDuplicateKey = pVTable->OptionalFuncDuplicateKey;
pVKey->hProv = pVTable->hProv;
*ppVKey = pVKey;
return(CRYPT_SUCCEED);
}
BOOL BuildVHash(
IN PVHashStruc *ppVHash,
IN PVTableStruc pVTable
)
{
DWORD bufsize;
PVHashStruc pVHash;
bufsize = sizeof(VHashStruc);
if ((pVHash = (PVHashStruc) LocalAlloc(LMEM_ZEROINIT, (UINT) bufsize)) == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(CRYPT_FAILED);
}
pVHash->FuncCreateHash = pVTable->FuncCreateHash;
pVHash->FuncHashData = pVTable->FuncHashData;
pVHash->FuncHashSessionKey = pVTable->FuncHashSessionKey;
pVHash->FuncDestroyHash = pVTable->FuncDestroyHash;
pVHash->FuncSignHash = pVTable->FuncSignHash;
pVHash->FuncVerifySignature = pVTable->FuncVerifySignature;
pVHash->FuncGetHashParam = pVTable->FuncGetHashParam;
pVHash->FuncSetHashParam = pVTable->FuncSetHashParam;
pVHash->OptionalFuncDuplicateHash = pVTable->OptionalFuncDuplicateHash;
pVHash->hProv = (HCRYPTPROV)pVTable;
*ppVHash = pVHash;
return(CRYPT_SUCCEED);
}
#define RC4_KEYSIZE 5
void EncryptKey(BYTE *pdata, DWORD size, BYTE val)
{
RC4_KEYSTRUCT key;
BYTE RealKey[RC4_KEYSIZE] = {0xa2, 0x17, 0x9c, 0x98, 0xca};
DWORD index;
for (index = 0; index < RC4_KEYSIZE; index++)
{
RealKey[index] ^= val;
}
rc4_key(&key, RC4_KEYSIZE, RealKey);
rc4(&key, size, pdata);
}
void MD5HashData(
BYTE *pb,
DWORD cb,
BYTE *pbHash
)
{
MD5_CTX HashState;
MD5Init(&HashState);
__try
{
MD5Update(&HashState, pb, cb);
} __except ( CapiExceptionFilter )
{
SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
return;
}
// Finish the hash
MD5Final(&HashState);
memcpy(pbHash, HashState.digest, 16);
}
BOOL CheckSignature(
BYTE *pbKey,
DWORD cbKey,
BYTE *pbSig,
DWORD cbSig,
BYTE *pbHash,
BOOL fUnknownLen)
{
BYTE rgbResult[KEYSIZE1024];
BYTE rgbSig[KEYSIZE1024];
BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
BYTE rgbKeyHash[16];
BYTE *pbSecondKey;
DWORD cbSecondKey;
BYTE *pbKeySig;
PSECOND_TIER_SIG pSecondTierSig;
LPBSAFE_PUB_KEY pTmp;
BOOL fRet = FALSE;
memset(rgbResult, 0, KEYSIZE1024);
memset(rgbSig, 0, KEYSIZE1024);
// just check the straight signature if version is 1
pTmp = (LPBSAFE_PUB_KEY)pbKey;
// check if sig length is the same as the key length
if (fUnknownLen || (cbSig == pTmp->keylen))
{
memcpy(rgbSig, pbSig, pTmp->keylen);
BSafeEncPublic(pTmp, rgbSig, rgbResult);
if (RtlEqualMemory(pbHash, rgbResult, 16) &&
rgbResult[cbKey-1] == 0 &&
rgbResult[cbKey-2] == 1 &&
rgbResult[16] == 0 &&
rgbResult[17] == 0xFF)
{
fRet = TRUE;
goto Ret;
}
}
// check the the second tier signature if the magic equals 2
pSecondTierSig = (PSECOND_TIER_SIG)pbSig;
if (0x00000002 != pSecondTierSig->dwMagic)
goto Ret;
if (0x31415352 != pSecondTierSig->Pub.magic)
goto Ret;
if (pSecondTierSig->Pub.keylen > KEYSIZE1024)
goto Ret;
// assign the pointers
cbSecondKey = sizeof(BSAFE_PUB_KEY) + pSecondTierSig->Pub.keylen;
pbSecondKey = pbSig + (sizeof(SECOND_TIER_SIG) - sizeof(BSAFE_PUB_KEY));
pbKeySig = pbSecondKey + cbSecondKey;
// hash the second tier key
MD5HashData(pbSecondKey, cbSecondKey, rgbKeyHash);
// Decrypt the signature data on the second tier key
memset(rgbResult, 0, sizeof(rgbResult));
memset(rgbSig, 0, sizeof(rgbSig));
if (pSecondTierSig->cbSig > sizeof(rgbSig))
goto Ret;
memcpy(rgbSig, pbKeySig, pSecondTierSig->cbSig);
BSafeEncPublic(pTmp, rgbSig, rgbResult);
if ((FALSE == RtlEqualMemory(rgbKeyHash, rgbResult, 16)) ||
rgbResult[cbKey-1] != 0 ||
rgbResult[cbKey-2] != 1 ||
rgbResult[16] != 0 ||
rgbResult[17] != 0)
{
goto Ret;
}
// Decrypt the signature data on the CSP
memset(rgbResult, 0, sizeof(rgbResult));
memset(rgbSig, 0, sizeof(rgbSig));
memset(rgbKey, 0, sizeof(rgbKey));
memcpy(rgbSig, pbKeySig + pSecondTierSig->cbSig, pSecondTierSig->cbSig);
memcpy(rgbKey, pbSecondKey, cbSecondKey);
pTmp = (LPBSAFE_PUB_KEY)rgbKey;
BSafeEncPublic(pTmp, rgbSig, rgbResult);
if (RtlEqualMemory(pbHash, rgbResult, 16) &&
rgbResult[pTmp->keylen-1] == 0 &&
rgbResult[pTmp->keylen-2] == 1 &&
rgbResult[16] == 0)
{
fRet = TRUE;
}
Ret:
return fRet;
}
// Given hInst, allocs and returns pointers to signature pulled from
// resource
BOOL GetCryptSigResourcePtr(
HMODULE hInst,
BYTE **ppbRsrcSig,
DWORD *pcbRsrcSig
)
{
HRSRC hRsrc;
BOOL fRet = FALSE;
// Nab resource handle for our signature
if (NULL == (hRsrc = FindResource(hInst, OLD_CRYPT_SIG_RESOURCE_NUMBER,
RT_RCDATA)))
goto Ret;
// get a pointer to the actual signature data
if (NULL == (*ppbRsrcSig = (PBYTE)LoadResource(hInst, hRsrc)))
goto Ret;
// determine the size of the resource
if (0 == (*pcbRsrcSig = SizeofResource(hInst, hRsrc)))
goto Ret;
fRet = TRUE;
Ret:
return fRet;
}
#define CSP_TO_BE_HASHED_CHUNK 4096
// Given hFile, reads the specified number of bytes (cbToBeHashed) from the file
// and hashes these bytes. The function does this in chunks.
BOOL HashBytesOfFile(
IN HANDLE hFile,
IN DWORD cbToBeHashed,
IN OUT MD5_CTX *pMD5Hash
)
{
BYTE rgbChunk[CSP_TO_BE_HASHED_CHUNK];
DWORD cbRemaining = cbToBeHashed;
DWORD cbToRead;
DWORD dwBytesRead;
BOOL fRet = FALSE;
//
// loop over the file for the specified number of bytes
// updating the hash as we go.
//
while (cbRemaining > 0)
{
if (cbRemaining < CSP_TO_BE_HASHED_CHUNK)
cbToRead = cbRemaining;
else
cbToRead = CSP_TO_BE_HASHED_CHUNK;
if(!ReadFile(hFile, rgbChunk, cbToRead, &dwBytesRead, NULL))
goto Ret;
if (dwBytesRead != cbToRead)
goto Ret;
MD5Update(pMD5Hash, rgbChunk, dwBytesRead);
cbRemaining -= cbToRead;
}
fRet = TRUE;
Ret:
return fRet;
}
BOOL HashTheFile(
LPCWSTR pszImage,
DWORD cbImage,
BYTE **ppbSig,
DWORD *pcbSig,
BYTE *pbHash
)
{
HMODULE hInst;
MEMORY_BASIC_INFORMATION MemInfo;
BYTE *pbRsrcSig;
DWORD cbRsrcSig;
BYTE *pbStart = NULL;
BYTE *pbZeroSig = NULL;
MD5_CTX MD5Hash;
BYTE *pbPostCRC; // pointer to just after CRC
DWORD cbCRCToSig; // number of bytes from CRC to sig
DWORD cbPostSig; // size - (already hashed + signature size)
BYTE *pbPostSig;
DWORD *pdwSigInFileVer;
DWORD *pdwCRCOffset;
DWORD dwCRCOffset;
DWORD dwZeroCRC = 0;
HANDLE File = INVALID_HANDLE_VALUE ;
HANDLE hMapping = NULL;
BOOL fRet = FALSE;
memset(&MD5Hash, 0, sizeof(MD5Hash));
memset(&MemInfo, 0, sizeof(MemInfo));
// Load the file
File = CreateFileW(
pszImage,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( File == INVALID_HANDLE_VALUE )
{
goto Ret ;
}
hMapping = CreateFileMapping( File,
NULL,
PAGE_READONLY,
0,
0,
NULL);
if(hMapping == NULL)
{
goto Ret;
}
pbStart = MapViewOfFile(hMapping,
FILE_MAP_READ,
0,
0,
0);
if(pbStart == NULL)
{
goto Ret;
}
// Convert pointer to HMODULE, using the same scheme as
// LoadLibrary (windows\base\client\module.c).
hInst = (HMODULE)((ULONG_PTR)pbStart | 0x00000001);
// the resources signature
if (!GetCryptSigResourcePtr(hInst, &pbRsrcSig, &cbRsrcSig))
goto Ret;
if (cbRsrcSig < (sizeof(DWORD) * 2))
goto Ret;
// check the sig in file version and get the CRC offset
pdwSigInFileVer = (DWORD*)pbRsrcSig;
pdwCRCOffset = (DWORD*)(pbRsrcSig + sizeof(DWORD));
dwCRCOffset = *pdwCRCOffset;
if ((0x00000100 != *pdwSigInFileVer) || (dwCRCOffset > cbImage))
goto Ret;
// create a zero byte signature
if (NULL == (pbZeroSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, cbRsrcSig)))
goto Ret;
memcpy(pbZeroSig, pbRsrcSig, sizeof(DWORD) * 2);
pbPostCRC = pbStart + *pdwCRCOffset + sizeof(DWORD);
cbCRCToSig = (DWORD)(pbRsrcSig - pbPostCRC);
pbPostSig = pbRsrcSig + cbRsrcSig;
cbPostSig = (cbImage - (DWORD)(pbPostSig - pbStart));
// allocate the real signature and copy the resource sig into the real sig
*pcbSig = cbRsrcSig - (sizeof(DWORD) * 2);
if (NULL == (*ppbSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, *pcbSig)))
goto Ret;
memcpy(*ppbSig, pbRsrcSig + (sizeof(DWORD) * 2), *pcbSig);
// hash over the relevant data
MD5Init(&MD5Hash);
// hash up to the CRC
if (!HashBytesOfFile(File, dwCRCOffset, &MD5Hash))
goto Ret;
// pretend CRC is zeroed
MD5Update(&MD5Hash, (BYTE*)&dwZeroCRC, sizeof(DWORD));
if (!SetFilePointer(File, sizeof(DWORD), NULL, FILE_CURRENT))
{
goto Ret;
}
// hash from CRC to sig resource
if (!HashBytesOfFile(File, cbCRCToSig, &MD5Hash))
goto Ret;
// pretend image has zeroed sig
MD5Update(&MD5Hash, pbZeroSig, cbRsrcSig);
if (!SetFilePointer(File, cbRsrcSig, NULL, FILE_CURRENT))
{
goto Ret;
}
// hash after the sig resource
if (!HashBytesOfFile(File, cbPostSig, &MD5Hash))
goto Ret;
// Finish the hash
MD5Final(&MD5Hash);
memcpy(pbHash, MD5Hash.digest, MD5DIGESTLEN);
fRet = TRUE;
Ret:
if (pbZeroSig)
LocalFree(pbZeroSig);
if(pbStart)
UnmapViewOfFile(pbStart);
if(hMapping)
CloseHandle(hMapping);
if ( File != INVALID_HANDLE_VALUE )
{
CloseHandle( File );
}
return fRet;
}
/*
- CheckAllSignatures
-
* Purpose:
* Check signature against all keys
*
*
* Returns:
* BOOL
*/
BOOL CheckAllSignatures(
BYTE *pbSig,
DWORD cbSig,
BYTE *pbHash,
BOOL fUnknownLen
)
{
BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
BYTE rgbKey2[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
#ifdef MS_INTERNAL_KEY
BYTE rgbMSKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
#endif
#ifdef TEST_BUILD_EXPONENT
BYTE rgbTestKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE512];
#endif
BOOL fRet = FALSE;
// decrypt the keys once for each process
memcpy(rgbKey, (BYTE*)&KEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
EncryptKey(rgbKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 0);
#ifdef MS_INTERNAL_KEY
memcpy(rgbMSKey, (BYTE*)&MSKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
EncryptKey(rgbMSKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 1);
#endif
memcpy(rgbKey2, (BYTE*)&KEY2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
EncryptKey(rgbKey2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 2);
#ifdef TEST_BUILD_EXPONENT
memcpy(rgbTestKey, (BYTE*)&TESTKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE512);
EncryptKey(rgbTestKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE512, 3);
#endif // TEST_BUILD_EXPONENT
if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbKey, 128, pbSig,
cbSig, pbHash, fUnknownLen)))
{
fRet = TRUE;
goto Ret;
}
#ifdef MS_INTERNAL_KEY
if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbMSKey, 128, pbSig,
cbSig, pbHash, fUnknownLen)))
{
fRet = TRUE;
goto Ret;
}
#endif
if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbKey2, 128, pbSig,
cbSig, pbHash, fUnknownLen)))
{
fRet = TRUE;
goto Ret;
}
#ifdef TEST_BUILD_EXPONENT
if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbTestKey, 64, pbSig,
cbSig, pbHash, fUnknownLen)))
{
fRet = TRUE;
goto Ret;
}
#endif // TEST_BUILD_EXPONENT
Ret:
return fRet;
}
/*
- CheckSignatureInFile
-
* Purpose:
* Check signature which is in the resource in the file
*
*
* Parameters:
* IN pszImage - address of file
*
* Returns:
* BOOL
*/
BOOL CheckSignatureInFile(
LPCWSTR pszImage)
{
DWORD cbImage;
BYTE *pbSig = NULL;
DWORD cbSig;
BYTE rgbHash[MD5DIGESTLEN];
BOOL fRet = FALSE;
WIN32_FILE_ATTRIBUTE_DATA FileData ;
WCHAR FullName[ MAX_PATH ];
PWSTR FilePart ;
SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo;
BYTE rgbMincryptHash[MINCRYPT_MAX_HASH_LEN];
DWORD cbMincryptHash = MINCRYPT_MAX_HASH_LEN;
CRYPT_HASH_BLOB HashBlob;
DWORD dwErr = ERROR_SUCCESS;
NtQuerySystemInformation(
SystemKernelDebuggerInformation,
&KdInfo,
sizeof(KdInfo),
NULL);
// Allow any CSP to load if a Kd is attached
// and "responsive"
if ( TRUE == KdInfo.KernelDebuggerEnabled &&
FALSE == KdInfo.KernelDebuggerNotPresent)
return TRUE;
if ( !SearchPathW(NULL,
pszImage,
NULL,
MAX_PATH,
FullName,
&FilePart ) )
{
goto Ret ;
}
//
// Try new signature check. Use "mincrypt"
// functionality.
//
// Look for valid embedded "signcode" signature
// in the CSP.
//
if (ERROR_SUCCESS == MinCryptVerifySignedFile(
MINCRYPT_FILE_NAME,
(PVOID) FullName,
0, NULL, NULL, NULL))
{
// Valid signature was found.
return TRUE;
}
//
// The new signcode-style signature checks failed,
// so revert to legacy resource-based signature check.
//
if ( !GetFileAttributesExW( FullName,
GetFileExInfoStandard,
&FileData ) )
{
goto Ret ;
}
if ( FileData.nFileSizeHigh )
{
goto Ret ;
}
cbImage = FileData.nFileSizeLow ;
if (!HashTheFile(FullName, cbImage, &pbSig, &cbSig, rgbHash))
goto Ret;
// check signature against all public keys
if (!CheckAllSignatures(pbSig, cbSig, rgbHash, FALSE))
goto Ret;
fRet = TRUE;
Ret:
if (pbSig)
LocalFree(pbSig);
return fRet;
}
/*
- NewVerifyImage
-
* Purpose:
* Check signature of file
*
*
* Parameters:
* IN lpszImage - address of file
* IN pSigData - address of signature data
* IN cbSig - length of signature data
* IN fUnknownLen - BOOL to tell if length is not passed in
*
* Returns:
* BOOL
*/
BOOL NewVerifyImage(LPCSTR lpszImage,
BYTE *pSigData,
DWORD cbSig,
BOOL fUnknownLen)
{
HFILE hFileProv = HFILE_ERROR;
DWORD NumBytes;
DWORD lpdwFileSizeHigh;
MD5_CTX HashState;
OFSTRUCT ImageInfoBuf;
BOOL fRet = CRYPT_FAILED;
memset(&HashState, 0, sizeof(HashState));
if (HFILE_ERROR == (hFileProv = OpenFile(lpszImage, &ImageInfoBuf,
OF_READ)))
{
SetLastError((DWORD) NTE_PROV_DLL_NOT_FOUND);
goto Ret;
}
if (0xffffffff == (NumBytes = GetFileSize((HANDLE)IntToPtr(hFileProv),
&lpdwFileSizeHigh)))
{
SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
goto Ret;
}
MD5Init(&HashState);
if (!HashBytesOfFile((HANDLE)IntToPtr(hFileProv), NumBytes, &HashState))
{
SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
goto Ret;
}
MD5Final(&HashState);
// check the signature against all keys
if (!CheckAllSignatures(pSigData, cbSig, HashState.digest, fUnknownLen))
{
SetLastError((DWORD) NTE_BAD_SIGNATURE);
goto Ret;
}
fRet = TRUE;
Ret:
if (HFILE_ERROR != hFileProv)
_lclose(hFileProv);
return fRet;
}
/*
- CProvVerifyImage
-
* Purpose:
* Check signature of file
*
*
* Parameters:
* IN lpszImage - address of file
* IN lpSigData - address of signature data
*
* Returns:
* BOOL
*/
BOOL CProvVerifyImage(LPCSTR lpszImage,
BYTE *pSigData)
{
UNICODE_STRING String ;
BOOL Result ;
if (NULL == pSigData)
{
if ( RtlCreateUnicodeStringFromAsciiz( &String, lpszImage ) )
{
Result = CheckSignatureInFile( String.Buffer );
RtlFreeUnicodeString( &String );
}
else
{
Result = FALSE ;
}
}
else
{
Result = NewVerifyImage(lpszImage, pSigData, 0, TRUE);
}
return Result;
}
/*
- CPReturnhWnd
-
* Purpose:
* Return a window handle back to a CSP
*
*
* Parameters:
* OUT phWnd - pointer to a hWnd to return
*
* Returns:
* void
*/
void CPReturnhWnd(HWND *phWnd)
{
__try
{
*phWnd = hWnd;
} __except ( CapiExceptionFilter )
{ ; }
return;
}
static void __ltoa(DWORD val, char *buf)
{
char *p; /* pointer to traverse string */
char *firstdig; /* pointer to first digit */
char temp; /* temp char */
unsigned digval; /* value of digit */
int i;
p = buf;
firstdig = p; /* save pointer to first digit */
for (i = 0; i < 8; i++) {
digval = (unsigned) (val % 10);
val /= 10; /* get next digit */
/* convert to ascii and store */
*p++ = (char) (digval + '0'); /* a digit */
}
/* We now have the digit of the number in the buffer, but in reverse
order. Thus we reverse them now. */
*p-- = '\0'; /* terminate string; p points to last digit */
do {
temp = *p;
*p = *firstdig;
*firstdig = temp; /* swap *p and *firstdig */
--p;
++firstdig; /* advance to next two digits */
} while (firstdig < p); /* repeat until halfway */
}