1018 lines
31 KiB
C++
1018 lines
31 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
|
//
|
||
|
// File: sp3crmsg.cpp
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// File: sp3crmsg.cpp
|
||
|
//
|
||
|
// Contents: Installable OID functions providing backwards compatiblity
|
||
|
// with the way the NT4.0 SP3 and IE 3.02 versions of crypt32.dll
|
||
|
// encrypted the symmetric key in a PKCS #7 EnvelopedData message.
|
||
|
//
|
||
|
// The SP3 version of crypt32.dll failed to byte reverse the
|
||
|
// encrypted symmetric key. It also added zero salt instead
|
||
|
// of no salt.
|
||
|
//
|
||
|
// Functions: DllMain
|
||
|
// DllRegisterServer
|
||
|
// DllUnregisterServer
|
||
|
// SP3ImportEncryptKey
|
||
|
// SP3GenEncryptKey
|
||
|
// SP3ExportEncryptKey
|
||
|
#ifdef CMS_PKCS7
|
||
|
// DllInstall
|
||
|
// CryptMsgDllGenContentEncryptKey
|
||
|
// CryptMsgDllExportKeyTrans
|
||
|
// CryptMsgDllImportKeyTrans
|
||
|
// NotImplCryptMsgDllImportKeyTrans
|
||
|
#endif // CMS_PKCS7
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#define CMS_PKCS7 1
|
||
|
#include <windows.h>
|
||
|
#include <wincrypt.h>
|
||
|
|
||
|
#include "sp3crmsg.h"
|
||
|
|
||
|
// memory management
|
||
|
#define SP3Alloc(cb) ((void*)LocalAlloc(LPTR, cb))
|
||
|
#define SP3Free(pv) (LocalFree((HLOCAL)pv))
|
||
|
|
||
|
// The Thread Local Storage (TLS) referenced by iSP3TLS has pointer of
|
||
|
// ((void *) 0x1) if SP3 compatible encryption is enabled. Otherwise, its 0.
|
||
|
static DWORD iSP3TLS = 0xFFFFFFFF;
|
||
|
#define SP3_TLS_POINTER ((void *) 0x1)
|
||
|
|
||
|
typedef struct _SIMPLEBLOBHEADER {
|
||
|
ALG_ID aiEncAlg;
|
||
|
} SIMPLEBLOBHEADER, *PSIMPLEBLOBHEADER;
|
||
|
|
||
|
typedef struct _OID_REG_ENTRY {
|
||
|
LPCSTR pszOID;
|
||
|
LPCSTR pszOverrideFuncName;
|
||
|
} OID_REG_ENTRY, *POID_REG_ENTRY;
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// ImportEncryptKey OID Installable Functions
|
||
|
//--------------------------------------------------------------------------
|
||
|
static HCRYPTOIDFUNCSET hImportEncryptKeyFuncSet;
|
||
|
static PFN_CMSG_IMPORT_ENCRYPT_KEY pfnDefaultImportEncryptKey = NULL;
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3ImportEncryptKey(
|
||
|
IN HCRYPTPROV hCryptProv,
|
||
|
IN DWORD dwKeySpec,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
|
||
|
IN PBYTE pbEncodedKey,
|
||
|
IN DWORD cbEncodedKey,
|
||
|
OUT HCRYPTKEY *phEncryptKey);
|
||
|
|
||
|
static const CRYPT_OID_FUNC_ENTRY ImportEncryptKeyFuncTable[] = {
|
||
|
szOID_OIWSEC_desCBC, SP3ImportEncryptKey,
|
||
|
szOID_RSA_RC2CBC, SP3ImportEncryptKey,
|
||
|
szOID_RSA_RC4, SP3ImportEncryptKey
|
||
|
};
|
||
|
#define IMPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ImportEncryptKeyFuncTable) / \
|
||
|
sizeof(ImportEncryptKeyFuncTable[0]))
|
||
|
|
||
|
static const OID_REG_ENTRY ImportEncryptKeyRegTable[] = {
|
||
|
szOID_OIWSEC_desCBC, "SP3ImportEncryptKey",
|
||
|
szOID_RSA_RC2CBC, "SP3ImportEncryptKey",
|
||
|
szOID_RSA_RC4, "SP3ImportEncryptKey"
|
||
|
};
|
||
|
#define IMPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ImportEncryptKeyRegTable) / \
|
||
|
sizeof(ImportEncryptKeyRegTable[0]))
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// GenEncryptKey OID Installable Functions
|
||
|
//--------------------------------------------------------------------------
|
||
|
static HCRYPTOIDFUNCSET hGenEncryptKeyFuncSet;
|
||
|
static PFN_CMSG_GEN_ENCRYPT_KEY pfnDefaultGenEncryptKey = NULL;
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3GenEncryptKey(
|
||
|
IN OUT HCRYPTPROV *phCryptProv,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
|
||
|
IN PVOID pvEncryptAuxInfo,
|
||
|
IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
|
||
|
IN PFN_CMSG_ALLOC pfnAlloc,
|
||
|
OUT HCRYPTKEY *phEncryptKey,
|
||
|
OUT PBYTE *ppbEncryptParameters,
|
||
|
OUT PDWORD pcbEncryptParameters);
|
||
|
|
||
|
static const CRYPT_OID_FUNC_ENTRY GenEncryptKeyFuncTable[] = {
|
||
|
szOID_OIWSEC_desCBC, SP3GenEncryptKey,
|
||
|
szOID_RSA_RC2CBC, SP3GenEncryptKey,
|
||
|
szOID_RSA_RC4, SP3GenEncryptKey
|
||
|
};
|
||
|
#define GEN_ENCRYPT_KEY_FUNC_COUNT (sizeof(GenEncryptKeyFuncTable) / \
|
||
|
sizeof(GenEncryptKeyFuncTable[0]))
|
||
|
|
||
|
static const OID_REG_ENTRY GenEncryptKeyRegTable[] = {
|
||
|
szOID_OIWSEC_desCBC, "SP3GenEncryptKey",
|
||
|
szOID_RSA_RC2CBC, "SP3GenEncryptKey",
|
||
|
szOID_RSA_RC4, "SP3GenEncryptKey"
|
||
|
};
|
||
|
#define GEN_ENCRYPT_KEY_REG_COUNT (sizeof(GenEncryptKeyRegTable) / \
|
||
|
sizeof(GenEncryptKeyRegTable[0]))
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// ExportEncryptKey OID Installable Functions
|
||
|
//--------------------------------------------------------------------------
|
||
|
static HCRYPTOIDFUNCSET hExportEncryptKeyFuncSet;
|
||
|
static PFN_CMSG_EXPORT_ENCRYPT_KEY pfnDefaultExportEncryptKey = NULL;
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3ExportEncryptKey(
|
||
|
IN HCRYPTPROV hCryptProv,
|
||
|
IN HCRYPTKEY hEncryptKey,
|
||
|
IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
|
||
|
OUT PBYTE pbData,
|
||
|
IN OUT PDWORD pcbData);
|
||
|
|
||
|
static const CRYPT_OID_FUNC_ENTRY ExportEncryptKeyFuncTable[] = {
|
||
|
szOID_RSA_RSA, SP3ExportEncryptKey
|
||
|
};
|
||
|
#define EXPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ExportEncryptKeyFuncTable) / \
|
||
|
sizeof(ExportEncryptKeyFuncTable[0]))
|
||
|
|
||
|
static const OID_REG_ENTRY ExportEncryptKeyRegTable[] = {
|
||
|
szOID_RSA_RSA, "SP3ExportEncryptKey"
|
||
|
};
|
||
|
#define EXPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ExportEncryptKeyRegTable) / \
|
||
|
sizeof(ExportEncryptKeyRegTable[0]))
|
||
|
|
||
|
static char szCrypt32[]="crypt32.dll";
|
||
|
|
||
|
// First post IE4.0 versions of crypt32.dll start with "5.101.1681.1"
|
||
|
static DWORD dwLowVersion = (1681 << 16) | 1;
|
||
|
static DWORD dwHighVersion = (5 << 16) | 101;
|
||
|
|
||
|
static BOOL IsPostIE4Crypt32()
|
||
|
{
|
||
|
BOOL fPostIE4 = FALSE; // default to IE4
|
||
|
DWORD dwHandle = 0;
|
||
|
DWORD cbInfo;
|
||
|
void *pvInfo = NULL;
|
||
|
VS_FIXEDFILEINFO *pFixedFileInfo = NULL; // not allocated
|
||
|
UINT ccFixedFileInfo = 0;
|
||
|
|
||
|
if (0 == (cbInfo = GetFileVersionInfoSizeA(szCrypt32, &dwHandle)))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
if (NULL == (pvInfo = SP3Alloc(cbInfo)))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
if (!GetFileVersionInfoA(
|
||
|
szCrypt32,
|
||
|
0, // dwHandle, ignored
|
||
|
cbInfo,
|
||
|
pvInfo
|
||
|
))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
if (!VerQueryValueA(
|
||
|
pvInfo,
|
||
|
"\\", // VS_FIXEDFILEINFO
|
||
|
(void **) &pFixedFileInfo,
|
||
|
&ccFixedFileInfo
|
||
|
))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
if (pFixedFileInfo->dwFileVersionMS > dwHighVersion ||
|
||
|
(pFixedFileInfo->dwFileVersionMS == dwHighVersion &&
|
||
|
pFixedFileInfo->dwFileVersionLS >= dwLowVersion))
|
||
|
fPostIE4 = TRUE;
|
||
|
|
||
|
CommonReturn:
|
||
|
if (pvInfo)
|
||
|
SP3Free(pvInfo);
|
||
|
return fPostIE4;
|
||
|
ErrorReturn:
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
static HRESULT HError()
|
||
|
{
|
||
|
DWORD dw = GetLastError();
|
||
|
|
||
|
HRESULT hr;
|
||
|
if ( dw <= 0xFFFF )
|
||
|
hr = HRESULT_FROM_WIN32 ( dw );
|
||
|
else
|
||
|
hr = dw;
|
||
|
|
||
|
if ( ! FAILED ( hr ) )
|
||
|
{
|
||
|
// somebody failed a call without properly setting an error condition
|
||
|
|
||
|
hr = E_UNEXPECTED;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDAPI DllRegisterServer(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
DWORD dwFlags = CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG;
|
||
|
for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
|
||
|
ImportEncryptKeyRegTable[i].pszOID,
|
||
|
L"sp3crmsg.dll",
|
||
|
ImportEncryptKeyRegTable[i].pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptSetOIDFunctionValue(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
|
||
|
ImportEncryptKeyRegTable[i].pszOID,
|
||
|
CRYPT_OID_REG_FLAGS_VALUE_NAME,
|
||
|
REG_DWORD,
|
||
|
(BYTE *) &dwFlags,
|
||
|
sizeof(dwFlags)
|
||
|
))
|
||
|
return HError();
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
|
||
|
GenEncryptKeyRegTable[i].pszOID,
|
||
|
L"sp3crmsg.dll",
|
||
|
GenEncryptKeyRegTable[i].pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptSetOIDFunctionValue(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
|
||
|
GenEncryptKeyRegTable[i].pszOID,
|
||
|
CRYPT_OID_REG_FLAGS_VALUE_NAME,
|
||
|
REG_DWORD,
|
||
|
(BYTE *) &dwFlags,
|
||
|
sizeof(dwFlags)
|
||
|
))
|
||
|
return HError();
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
|
||
|
ExportEncryptKeyRegTable[i].pszOID,
|
||
|
L"sp3crmsg.dll",
|
||
|
ExportEncryptKeyRegTable[i].pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptSetOIDFunctionValue(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
|
||
|
ExportEncryptKeyRegTable[i].pszOID,
|
||
|
CRYPT_OID_REG_FLAGS_VALUE_NAME,
|
||
|
REG_DWORD,
|
||
|
(BYTE *) &dwFlags,
|
||
|
sizeof(dwFlags)
|
||
|
))
|
||
|
return HError();
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDAPI DllUnregisterServer(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
|
||
|
ImportEncryptKeyRegTable[i].pszOID
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
|
||
|
GenEncryptKeyRegTable[i].pszOID
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) {
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
|
||
|
ExportEncryptKeyRegTable[i].pszOID
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef CMS_PKCS7
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
|
||
|
szOID_RSA_RC2CBC
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RSA
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RSA "!" szOID_RSA_RC2CBC
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
|
||
|
if (!CryptUnregisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RC2CBC
|
||
|
)) {
|
||
|
if (ERROR_FILE_NOT_FOUND != GetLastError())
|
||
|
hr = HError();
|
||
|
}
|
||
|
|
||
|
#endif // CMS_PKCS7
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#ifdef CMS_PKCS7
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllInstall
|
||
|
//
|
||
|
// Synopsis: dll installation entry point
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
STDAPI DllInstall (BOOL fRegister, LPCSTR pszCommand)
|
||
|
{
|
||
|
if (!fRegister)
|
||
|
return DllUnregisterServer();
|
||
|
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
|
||
|
szOID_RSA_RC2CBC,
|
||
|
L"sp3crmsg.dll",
|
||
|
NULL // pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RSA,
|
||
|
L"sp3crmsg.dll",
|
||
|
NULL // pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RSA "!" szOID_RSA_RC2CBC,
|
||
|
L"sp3crmsg.dll",
|
||
|
"NotImplCryptMsgDllImportKeyTrans"
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
if (!CryptRegisterOIDFunction(
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_KEY_TRANS_FUNC,
|
||
|
szOID_RSA_RC2CBC,
|
||
|
L"sp3crmsg.dll",
|
||
|
NULL // pszOverrideFuncName
|
||
|
))
|
||
|
return HError();
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
#endif // CMS_PKCS7
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// Function: DllMain
|
||
|
//
|
||
|
// Synopsis: Process/Thread attach/detach
|
||
|
//
|
||
|
// At process attach install the SP3 compatible version of
|
||
|
// CryptMsgDllImportEncryptKey, CryptMsgDllGenEncryptKey and
|
||
|
// CryptMsgDllExportEncryptKey.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
DllMain(
|
||
|
HMODULE hInst,
|
||
|
ULONG ulReason,
|
||
|
LPVOID lpReserved)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
HCRYPTOIDFUNCADDR hFuncAddr;
|
||
|
|
||
|
switch (ulReason) {
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
#if 0
|
||
|
// Post IE 4.0 releases of crypt32.dll already have the SP3
|
||
|
// backwards compatible fix.
|
||
|
if (IsPostIE4Crypt32())
|
||
|
return TRUE;
|
||
|
#endif
|
||
|
|
||
|
if (NULL == (hImportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
|
||
|
0)))
|
||
|
goto ErrorReturn;
|
||
|
if (NULL == (hGenEncryptKeyFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
|
||
|
0)))
|
||
|
goto ErrorReturn;
|
||
|
if (NULL == (hExportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
|
||
|
0)))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
// Get the default import encrypt key function which we will call if
|
||
|
// unable to do a successful import without byte reversing the
|
||
|
// encrypted symmetric key.
|
||
|
if (CryptGetOIDFunctionAddress(
|
||
|
hImportEncryptKeyFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
szOID_RSA_RC2CBC,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultImportEncryptKey,
|
||
|
&hFuncAddr))
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
|
||
|
#if 0
|
||
|
if (!CryptInstallOIDFunctionAddress(
|
||
|
hInst,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
|
||
|
IMPORT_ENCRYPT_KEY_FUNC_COUNT,
|
||
|
ImportEncryptKeyFuncTable,
|
||
|
CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
|
||
|
))
|
||
|
goto ErrorReturn;
|
||
|
#endif
|
||
|
|
||
|
// Get the default gen and export encrypt key functions which we will
|
||
|
// call if pvEncryptionAuxInfo points to a
|
||
|
// CMSG_SP3_COMPATIBLE_AUX_INFO data structure.
|
||
|
if (CryptGetOIDFunctionAddress(
|
||
|
hGenEncryptKeyFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
szOID_RSA_RC2CBC,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultGenEncryptKey,
|
||
|
&hFuncAddr))
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
if (CryptGetOIDFunctionAddress(
|
||
|
hExportEncryptKeyFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
szOID_RSA_RSA,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultExportEncryptKey,
|
||
|
&hFuncAddr))
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
|
||
|
#if 0
|
||
|
if (!CryptInstallOIDFunctionAddress(
|
||
|
hInst,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
|
||
|
GEN_ENCRYPT_KEY_FUNC_COUNT,
|
||
|
GenEncryptKeyFuncTable,
|
||
|
CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
|
||
|
))
|
||
|
goto ErrorReturn;
|
||
|
if (!CryptInstallOIDFunctionAddress(
|
||
|
hInst,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
|
||
|
EXPORT_ENCRYPT_KEY_FUNC_COUNT,
|
||
|
ExportEncryptKeyFuncTable,
|
||
|
CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
|
||
|
))
|
||
|
goto ErrorReturn;
|
||
|
#endif
|
||
|
|
||
|
// Allocate TLS which contains a pointer of ((void *) 0x1) for SP3
|
||
|
// compatible encryption. This pointer will be passed from
|
||
|
// SP3GenEncryptKey() to SP3ExportEncryptKey().
|
||
|
//
|
||
|
// If not SP3 encryption, the pointer is NULL.
|
||
|
if ((iSP3TLS = TlsAlloc()) == 0xFFFFFFFF)
|
||
|
goto ErrorReturn;
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
if (iSP3TLS != 0xFFFFFFFF) {
|
||
|
TlsFree(iSP3TLS);
|
||
|
iSP3TLS = 0xFFFFFFFF;
|
||
|
}
|
||
|
break;
|
||
|
case DLL_THREAD_DETACH:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
return fResult;
|
||
|
|
||
|
ErrorReturn:
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// SP3 import of the encryption key.
|
||
|
//
|
||
|
// The SP3 version of crypt32.dll didn't include any parameters for the
|
||
|
// encryption algorithm. Later versions of crypt32.dll do. Therefore, we only
|
||
|
// need to attempt to import the key without byte reversal if there aren't
|
||
|
// any parameters present.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3ImportEncryptKey(
|
||
|
IN HCRYPTPROV hCryptProv,
|
||
|
IN DWORD dwKeySpec,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
|
||
|
IN PBYTE pbEncodedKey,
|
||
|
IN DWORD cbEncodedKey,
|
||
|
OUT HCRYPTKEY *phEncryptKey
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
HCRYPTKEY hEncryptKey = 0;
|
||
|
HCRYPTKEY hUserKey = 0;
|
||
|
DWORD dwAlgIdEncrypt;
|
||
|
DWORD dwAlgIdPubKey;
|
||
|
PBYTE pbCspKey = NULL;
|
||
|
DWORD cbCspKey;
|
||
|
PUBLICKEYSTRUC *ppks;
|
||
|
PSIMPLEBLOBHEADER psbh;
|
||
|
PCCRYPT_OID_INFO pOIDInfo;
|
||
|
|
||
|
// Check if more than just the NULL parameters
|
||
|
if (2 < paiEncrypt->Parameters.cbData) {
|
||
|
fResult = FALSE;
|
||
|
goto DefaultImport;
|
||
|
}
|
||
|
|
||
|
// Map the ASN algorithm identifier to the CSP ALG_ID.
|
||
|
if (NULL == (pOIDInfo = CryptFindOIDInfo(
|
||
|
CRYPT_OID_INFO_OID_KEY,
|
||
|
paiEncrypt->pszObjId,
|
||
|
CRYPT_ENCRYPT_ALG_OID_GROUP_ID)))
|
||
|
goto GetEncryptAlgidError;
|
||
|
dwAlgIdEncrypt = pOIDInfo->Algid;
|
||
|
|
||
|
// Create the CSP encrypted symmetric key structure WITHOUT BYTE REVERSAL.
|
||
|
dwAlgIdPubKey = CALG_RSA_KEYX;
|
||
|
cbCspKey = cbEncodedKey + sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
|
||
|
if (NULL == (pbCspKey = (PBYTE)SP3Alloc( cbCspKey)))
|
||
|
goto OutOfMemory;
|
||
|
ppks = (PUBLICKEYSTRUC *)pbCspKey;
|
||
|
ppks->bType = SIMPLEBLOB;
|
||
|
ppks->bVersion = CUR_BLOB_VERSION;
|
||
|
ppks->reserved = 0;
|
||
|
ppks->aiKeyAlg = dwAlgIdEncrypt;
|
||
|
psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
|
||
|
psbh->aiEncAlg = dwAlgIdPubKey;
|
||
|
// NO BYTE REVERSAL as done in SP3.
|
||
|
memcpy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
|
||
|
|
||
|
if (0 != dwKeySpec) {
|
||
|
// Get private key to use.
|
||
|
if (!CryptGetUserKey(
|
||
|
hCryptProv,
|
||
|
dwKeySpec,
|
||
|
&hUserKey)) {
|
||
|
hUserKey = 0;
|
||
|
goto GetUserKeyFailed;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Try importing as an NT4.0 SP3 encypted key that wasn't byte
|
||
|
// reversed and with zero salt.
|
||
|
fResult = CryptImportKey(
|
||
|
hCryptProv,
|
||
|
pbCspKey,
|
||
|
cbCspKey,
|
||
|
hUserKey,
|
||
|
0, // dwFlags
|
||
|
&hEncryptKey);
|
||
|
if (!fResult && hUserKey) {
|
||
|
// Try without using the specified user key.
|
||
|
fResult = CryptImportKey(
|
||
|
hCryptProv,
|
||
|
pbCspKey,
|
||
|
cbCspKey,
|
||
|
0, // hUserKey
|
||
|
0, // dwFlags
|
||
|
&hEncryptKey);
|
||
|
}
|
||
|
|
||
|
if (!fResult)
|
||
|
goto ImportKeyFailed;
|
||
|
|
||
|
fResult = TRUE;
|
||
|
CommonReturn:
|
||
|
if (pbCspKey)
|
||
|
SP3Free(pbCspKey);
|
||
|
if (hUserKey) {
|
||
|
DWORD dwError = GetLastError();
|
||
|
CryptDestroyKey(hUserKey);
|
||
|
SetLastError(dwError);
|
||
|
}
|
||
|
|
||
|
DefaultImport:
|
||
|
if (!fResult && pfnDefaultImportEncryptKey)
|
||
|
// Try importing using the default
|
||
|
return pfnDefaultImportEncryptKey(
|
||
|
hCryptProv,
|
||
|
dwKeySpec,
|
||
|
paiEncrypt,
|
||
|
paiPubKey,
|
||
|
pbEncodedKey,
|
||
|
cbEncodedKey,
|
||
|
phEncryptKey);
|
||
|
else {
|
||
|
*phEncryptKey = hEncryptKey;
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
GetEncryptAlgidError:
|
||
|
OutOfMemory:
|
||
|
GetUserKeyFailed:
|
||
|
ImportKeyFailed:
|
||
|
hEncryptKey = 0;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// SP3 generation of the encryption key.
|
||
|
//
|
||
|
// The SP3 version of crypt32.dll didn't include the IV octet string for the
|
||
|
// encryption algorithm. Also, the encryption key had zero salt instead
|
||
|
// of no salt.
|
||
|
//
|
||
|
// For SP3 compatible generation, the caller must pass in a non-NULL
|
||
|
// hCryptProv and set pvEncryptAuxInfo to point to a
|
||
|
// CMSG_SP3_COMPATIBLE_AUX_INFO data structure with the
|
||
|
// CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG set.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3GenEncryptKey(
|
||
|
IN OUT HCRYPTPROV *phCryptProv,
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
|
||
|
IN PVOID pvEncryptAuxInfo,
|
||
|
IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
|
||
|
IN PFN_CMSG_ALLOC pfnAlloc,
|
||
|
OUT HCRYPTKEY *phEncryptKey,
|
||
|
OUT PBYTE *ppbEncryptParameters,
|
||
|
OUT PDWORD pcbEncryptParameters
|
||
|
)
|
||
|
{
|
||
|
HCRYPTPROV hCryptProv;
|
||
|
PCMSG_SP3_COMPATIBLE_AUX_INFO pSP3AuxInfo =
|
||
|
(PCMSG_SP3_COMPATIBLE_AUX_INFO) pvEncryptAuxInfo;
|
||
|
PCCRYPT_OID_INFO pOIDInfo;
|
||
|
DWORD dwAlgIdEncrypt;
|
||
|
|
||
|
hCryptProv = *phCryptProv;
|
||
|
if (0 == hCryptProv || NULL == pSP3AuxInfo ||
|
||
|
sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO) > pSP3AuxInfo->cbSize ||
|
||
|
0 == (pSP3AuxInfo->dwFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)) {
|
||
|
|
||
|
// Let SP3ExportEncryptKey() know this will be a default export
|
||
|
TlsSetValue(iSP3TLS, NULL);
|
||
|
|
||
|
if (pfnDefaultGenEncryptKey)
|
||
|
// Generate using the default
|
||
|
return pfnDefaultGenEncryptKey(
|
||
|
phCryptProv,
|
||
|
paiEncrypt,
|
||
|
pvEncryptAuxInfo,
|
||
|
pPublicKeyInfo,
|
||
|
pfnAlloc,
|
||
|
phEncryptKey,
|
||
|
ppbEncryptParameters,
|
||
|
pcbEncryptParameters
|
||
|
);
|
||
|
else {
|
||
|
// We don't have a default
|
||
|
*phEncryptKey = 0;
|
||
|
SetLastError((DWORD) E_UNEXPECTED);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Let SP3ExportEncryptKey() know this will be a SP3 compatible export.
|
||
|
TlsSetValue(iSP3TLS, SP3_TLS_POINTER);
|
||
|
|
||
|
// Map the ASN algorithm identifier to the CSP ALG_ID.
|
||
|
if (NULL == (pOIDInfo = CryptFindOIDInfo(
|
||
|
CRYPT_OID_INFO_OID_KEY,
|
||
|
paiEncrypt->pszObjId,
|
||
|
CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) {
|
||
|
*phEncryptKey = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
dwAlgIdEncrypt = pOIDInfo->Algid;
|
||
|
|
||
|
// Since CRYPT_NO_SALT flag isn't set, uses zero salt
|
||
|
if (!CryptGenKey(
|
||
|
hCryptProv,
|
||
|
dwAlgIdEncrypt,
|
||
|
CRYPT_EXPORTABLE,
|
||
|
phEncryptKey)) {
|
||
|
*phEncryptKey = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
// SP3 export of the encryption key.
|
||
|
//
|
||
|
// The SP3 version of crypt32.dll encoded the encrypted symmetric key as
|
||
|
// little endian instead of as big endian.
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SP3ExportEncryptKey(
|
||
|
IN HCRYPTPROV hCryptProv,
|
||
|
IN HCRYPTKEY hEncryptKey,
|
||
|
IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
|
||
|
OUT PBYTE pbData,
|
||
|
IN OUT PDWORD pcbData
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
DWORD dwError = ERROR_SUCCESS;
|
||
|
HCRYPTKEY hPubKey = NULL;
|
||
|
PBYTE pb = NULL;
|
||
|
DWORD cb;
|
||
|
|
||
|
if (SP3_TLS_POINTER != TlsGetValue(iSP3TLS)) {
|
||
|
if (pfnDefaultExportEncryptKey)
|
||
|
// Export using the default function
|
||
|
return pfnDefaultExportEncryptKey(
|
||
|
hCryptProv,
|
||
|
hEncryptKey,
|
||
|
pPublicKeyInfo,
|
||
|
pbData,
|
||
|
pcbData
|
||
|
);
|
||
|
else {
|
||
|
// We don't have a default
|
||
|
*pcbData = 0;
|
||
|
SetLastError((DWORD) E_UNEXPECTED);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SP3 compatible export and encode
|
||
|
|
||
|
|
||
|
if (!CryptImportPublicKeyInfo(
|
||
|
hCryptProv,
|
||
|
X509_ASN_ENCODING,
|
||
|
pPublicKeyInfo,
|
||
|
&hPubKey))
|
||
|
goto ImportKeyError;
|
||
|
if (!CryptExportKey(
|
||
|
hEncryptKey,
|
||
|
hPubKey,
|
||
|
SIMPLEBLOB,
|
||
|
0, // dwFlags
|
||
|
NULL,
|
||
|
&cb))
|
||
|
goto ExportKeySizeError;
|
||
|
if (NULL == (pb = (PBYTE) SP3Alloc(cb)))
|
||
|
goto ExportKeyAllocError;
|
||
|
if (!CryptExportKey(
|
||
|
hEncryptKey,
|
||
|
hPubKey,
|
||
|
SIMPLEBLOB,
|
||
|
0, // dwFlags
|
||
|
pb,
|
||
|
&cb))
|
||
|
goto ExportKeyError;
|
||
|
cb -= sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
|
||
|
|
||
|
fResult = TRUE;
|
||
|
if (pbData) {
|
||
|
if (*pcbData < cb) {
|
||
|
SetLastError((DWORD) ERROR_MORE_DATA);
|
||
|
fResult = FALSE;
|
||
|
} else if (0 < cb) {
|
||
|
// Don't byte reverse
|
||
|
memcpy(pbData,
|
||
|
pb + (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)), cb);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CommonReturn:
|
||
|
*pcbData = cb;
|
||
|
if (pb)
|
||
|
SP3Free(pb);
|
||
|
if (hPubKey)
|
||
|
CryptDestroyKey(hPubKey);
|
||
|
SetLastError(dwError);
|
||
|
return fResult;
|
||
|
|
||
|
ImportKeyError:
|
||
|
ExportKeySizeError:
|
||
|
ExportKeyAllocError:
|
||
|
ExportKeyError:
|
||
|
dwError = GetLastError();
|
||
|
cb = 0;
|
||
|
fResult = FALSE;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
#ifdef CMS_PKCS7
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
CryptMsgDllGenContentEncryptKey(
|
||
|
IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL void *pvReserved
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
HCRYPTOIDFUNCSET hGenContentFuncSet;
|
||
|
HCRYPTOIDFUNCADDR hFuncAddr;
|
||
|
PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY pfnDefaultGenContent;
|
||
|
|
||
|
if (NULL == (hGenContentFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0)))
|
||
|
return FALSE;
|
||
|
|
||
|
// Get the default gen content encrypt key function which we will call
|
||
|
if (!CryptGetOIDFunctionAddress(
|
||
|
hGenContentFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultGenContent,
|
||
|
&hFuncAddr))
|
||
|
return FALSE;
|
||
|
|
||
|
fResult = pfnDefaultGenContent(
|
||
|
pContentEncryptInfo,
|
||
|
dwFlags,
|
||
|
pvReserved
|
||
|
);
|
||
|
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
CryptMsgDllExportKeyTrans(
|
||
|
IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
|
||
|
IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
|
||
|
IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL void *pvReserved
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
HCRYPTOIDFUNCSET hExportKeyTransFuncSet;
|
||
|
HCRYPTOIDFUNCADDR hFuncAddr;
|
||
|
PFN_CMSG_EXPORT_KEY_TRANS pfnDefaultExportKeyTrans;
|
||
|
|
||
|
if (NULL == (hExportKeyTransFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0)))
|
||
|
return FALSE;
|
||
|
|
||
|
// Get the default export key trans function which we will call
|
||
|
if (!CryptGetOIDFunctionAddress(
|
||
|
hExportKeyTransFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultExportKeyTrans,
|
||
|
&hFuncAddr))
|
||
|
return FALSE;
|
||
|
|
||
|
fResult = pfnDefaultExportKeyTrans(
|
||
|
pContentEncryptInfo,
|
||
|
pKeyTransEncodeInfo,
|
||
|
pKeyTransEncryptInfo,
|
||
|
dwFlags,
|
||
|
pvReserved
|
||
|
);
|
||
|
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
CryptMsgDllImportKeyTrans(
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
|
||
|
IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL void *pvReserved,
|
||
|
OUT HCRYPTKEY *phContentEncryptKey
|
||
|
)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
HCRYPTOIDFUNCSET hImportKeyTransFuncSet;
|
||
|
HCRYPTOIDFUNCADDR hFuncAddr;
|
||
|
PFN_CMSG_IMPORT_KEY_TRANS pfnDefaultImportKeyTrans;
|
||
|
|
||
|
if (NULL == (hImportKeyTransFuncSet = CryptInitOIDFunctionSet(
|
||
|
CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0)))
|
||
|
return FALSE;
|
||
|
|
||
|
// Get the default import key trans function which we will call
|
||
|
if (!CryptGetOIDFunctionAddress(
|
||
|
hImportKeyTransFuncSet,
|
||
|
X509_ASN_ENCODING,
|
||
|
CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
|
||
|
CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
|
||
|
(void **) &pfnDefaultImportKeyTrans,
|
||
|
&hFuncAddr))
|
||
|
return FALSE;
|
||
|
|
||
|
fResult = pfnDefaultImportKeyTrans(
|
||
|
pContentEncryptionAlgorithm,
|
||
|
pKeyTransDecryptPara,
|
||
|
dwFlags,
|
||
|
pvReserved,
|
||
|
phContentEncryptKey
|
||
|
);
|
||
|
|
||
|
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
NotImplCryptMsgDllImportKeyTrans(
|
||
|
IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
|
||
|
IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OPTIONAL void *pvReserved,
|
||
|
OUT HCRYPTKEY *phContentEncryptKey
|
||
|
)
|
||
|
{
|
||
|
SetLastError((DWORD) E_NOTIMPL);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#endif // CMS_PKCS7
|