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
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 */
|
|
}
|