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.
658 lines
19 KiB
658 lines
19 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: cryptfnc.cpp
|
|
//
|
|
// Module: CMSECURE.LIB
|
|
//
|
|
// Synopsis: This file implements the cryptfnc class that provides
|
|
// easy to use interfaces on the CryptoAPI.
|
|
//
|
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
//
|
|
// Author: AshishS Created 12/03/96
|
|
// henryt modified for CM 5/21/97
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
#include "cryptfnc.h"
|
|
|
|
#ifdef UNICODE
|
|
#define LoadLibraryExU LoadLibraryExW
|
|
#else
|
|
#define LoadLibraryExU LoadLibraryExA
|
|
#endif
|
|
#include "linkdll.h" // LinkToDll and BindLinkage
|
|
|
|
CCryptFunctions::~CCryptFunctions()
|
|
{
|
|
// Release provider handle.
|
|
if (m_hProv != 0)
|
|
{
|
|
m_fnCryptReleaseContext(m_hProv, 0);
|
|
}
|
|
|
|
if (m_AdvApiLink.hInstAdvApi32)
|
|
{
|
|
FreeLibrary(m_AdvApiLink.hInstAdvApi32);
|
|
ZeroMemory(&m_AdvApiLink, sizeof(m_AdvApiLink));
|
|
}
|
|
}
|
|
|
|
|
|
CCryptFunctions::CCryptFunctions()
|
|
{
|
|
m_hProv = 0;
|
|
ZeroMemory(&m_AdvApiLink, sizeof(m_AdvApiLink));
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptAcquireContext(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider,
|
|
DWORD dwProvType, DWORD dwFlags)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptAcquireContext);
|
|
if (m_AdvApiLink.pfnCryptAcquireContext)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptAcquireContext(phProv, pszContainer, pszProvider,
|
|
dwProvType, dwFlags);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
|
|
DWORD dwFlags, HCRYPTHASH *phHash)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptCreateHash);
|
|
|
|
if (m_AdvApiLink.pfnCryptCreateHash)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptCreateHash(hProv, Algid, hKey, dwFlags, phHash);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags,
|
|
BYTE *pbData, DWORD *pdwDataLen)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptDecrypt);
|
|
|
|
if (m_AdvApiLink.pfnCryptDecrypt)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
|
|
DWORD dwFlags, HCRYPTKEY *phKey)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptDeriveKey);
|
|
|
|
if (m_AdvApiLink.pfnCryptDeriveKey)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptDestroyHash(HCRYPTHASH hHash)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptDestroyHash);
|
|
|
|
if (m_AdvApiLink.pfnCryptDestroyHash)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptDestroyHash(hHash);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptDestroyKey(HCRYPTKEY hKey)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptDestroyKey);
|
|
|
|
if (m_AdvApiLink.pfnCryptDestroyKey)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptDestroyKey(hKey);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptEncrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags,
|
|
BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptEncrypt);
|
|
|
|
if (m_AdvApiLink.pfnCryptEncrypt)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptEncrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptHashData(HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptHashData);
|
|
|
|
if (m_AdvApiLink.pfnCryptHashData)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptHashData(hHash, pbData, dwDataLen, dwFlags);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_fnCryptReleaseContext(HCRYPTPROV hProv, ULONG_PTR dwFlags)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptReleaseContext);
|
|
|
|
if (m_AdvApiLink.pfnCryptReleaseContext)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptReleaseContext(hProv, dwFlags);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL CCryptFunctions::m_pfnCryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
MYDBGASSERT(m_AdvApiLink.pfnCryptGenRandom);
|
|
|
|
if (m_AdvApiLink.pfnCryptGenRandom)
|
|
{
|
|
bReturn = m_AdvApiLink.pfnCryptGenRandom(hProv, dwLen, pbBuffer);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
//
|
|
// Calls m_pfnCryptGenRandom to create a random key
|
|
//
|
|
BOOL CCryptFunctions::GenerateRandomKey(PBYTE pbData, DWORD cbData)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
if (pbData)
|
|
{
|
|
fReturn = m_pfnCryptGenRandom(m_hProv, cbData, pbData);
|
|
}
|
|
return fReturn;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Func: CCryptFunctions::GenerateSessionKeyFromPassword
|
|
//
|
|
// Desc: this function Generates a SessionKey using the pszPassword parameter
|
|
//
|
|
// Args: [phKey] - location to store the session key
|
|
// [pszPassword] - password to generate the session key from
|
|
// [dwEncKeyLen] - how many bits of encryption
|
|
//
|
|
// Return: BOOL (FALSE if a fatal error occurred, else TRUE)
|
|
//
|
|
// Notes:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CCryptFunctions::GenerateSessionKeyFromPassword(
|
|
HCRYPTKEY * phKey,
|
|
LPTSTR pszPassword,
|
|
DWORD dwEncKeyLen)
|
|
{
|
|
DWORD dwLength;
|
|
HCRYPTHASH hHash = 0;
|
|
|
|
// Create hash object.
|
|
//
|
|
if (!m_fnCryptCreateHash(m_hProv, // handle to CSP
|
|
CALG_SHA, // use SHA hash algorithm
|
|
0, // not keyed hash
|
|
0, // flags - always 0
|
|
&hHash)) // address where hash object should be created
|
|
{
|
|
MYDBG(("Error 0x%x during CryptCreateHash", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
// Hash password string.
|
|
//
|
|
dwLength = lstrlen(pszPassword) * sizeof(TCHAR);
|
|
if (!m_fnCryptHashData(hHash, // handle to hash object
|
|
(BYTE *)pszPassword, // address of data to be hashed
|
|
dwLength, // length of data
|
|
0)) // flags
|
|
{
|
|
MYDBG(("Error 0x%x during CryptHashData", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
// Create block cipher session key based on hash of the password.
|
|
//
|
|
if (!m_fnCryptDeriveKey(m_hProv, //CSP provider
|
|
CALG_RC2, // use RC2 block cipher algorithm
|
|
hHash, //handle to hash object
|
|
(dwEncKeyLen << 16), // just the key length, no flags - we do not need the key to be exportable
|
|
phKey)) //address the newly created key should be copied
|
|
{
|
|
MYDBG(("Error 0x%x during CryptDeriveKey", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
// Destroy hash object.
|
|
m_fnCryptDestroyHash(hHash);
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
// Destroy hash object.
|
|
if (hHash != 0)
|
|
{
|
|
m_fnCryptDestroyHash(hHash);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This function must be called before any member functions of the
|
|
// class are used.
|
|
// Returns FALSE if a Fatal error occured, TRUE otherwise
|
|
BOOL CCryptFunctions::InitCrypt()
|
|
{
|
|
LPCSTR ArrayOfCryptFuncs [] =
|
|
{
|
|
#ifdef UNICODE
|
|
"CryptAcquireContextW", // this has never been tested
|
|
#else
|
|
"CryptAcquireContextA",
|
|
#endif
|
|
"CryptCreateHash",
|
|
"CryptDecrypt",
|
|
"CryptDeriveKey",
|
|
"CryptDestroyHash",
|
|
"CryptDestroyKey",
|
|
"CryptEncrypt",
|
|
"CryptHashData",
|
|
"CryptReleaseContext",
|
|
"CryptGenRandom", // to create a random session key
|
|
NULL
|
|
};
|
|
|
|
BOOL bRet = LinkToDll(&(m_AdvApiLink.hInstAdvApi32), TEXT("Advapi32.dll"), ArrayOfCryptFuncs,
|
|
m_AdvApiLink.apvPfn);
|
|
|
|
if (!bRet)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// Get handle to user default provider.
|
|
if (! m_fnCryptAcquireContext(&m_hProv, // address to get the handle to CSP
|
|
CM_CRYPTO_CONTAINER, // contianer name
|
|
MS_DEF_PROV, // provider
|
|
PROV_RSA_FULL, // type of provider
|
|
0)) // no flags
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
MYDBGTST(dwError, ("Error 0x%x during CryptAcquireContext", dwError));
|
|
|
|
MYDBG(("Calling CryptAcquireContext again to create keyset"));
|
|
|
|
if (! m_fnCryptAcquireContext(&m_hProv,// handle to CSP
|
|
CM_CRYPTO_CONTAINER,// contianer name
|
|
MS_DEF_PROV, // provider
|
|
PROV_RSA_FULL, // type of provider
|
|
CRYPT_NEWKEYSET) ) // create the keyset
|
|
{
|
|
MYDBG(("Fatal Error 0x%x during second call to CryptAcquireContext", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
// Release provider handle.
|
|
if (m_hProv != 0)
|
|
{
|
|
m_fnCryptReleaseContext(m_hProv, 0);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// Given a key string, and data to encrypt this function generates a
|
|
// session key from the key string. This session key is then used to
|
|
// encrypt the data.
|
|
|
|
// Returns FALSE if a Fatal error occured, TRUE otherwise
|
|
BOOL CCryptFunctions::EncryptDataWithKey(
|
|
LPTSTR pszKey, // password
|
|
PBYTE pbData, // Data to be encrypted
|
|
DWORD dwDataLength, // Length of data in bytes
|
|
PBYTE *ppbEncryptedData, // Encrypted secret key will be stored here
|
|
DWORD *pdwEncryptedBufferLen, // Length of this buffer
|
|
PFN_CMSECUREALLOC pfnAlloc,
|
|
PFN_CMSECUREFREE pfnFree,
|
|
DWORD dwEncKeySize // how many bits of encryption do we want? (0 implies "don't care")
|
|
)
|
|
{
|
|
HCRYPTKEY hKey = 0;
|
|
DWORD dwErr;
|
|
DWORD dwBufferLen;
|
|
BOOL fOk = FALSE;
|
|
PBYTE pbBuf = NULL;
|
|
|
|
//
|
|
// Init should have been successfully called before
|
|
// if no data to be encrypted, don't do anything
|
|
//
|
|
if (m_hProv == 0 || !dwDataLength)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!GenerateSessionKeyFromPassword(&hKey, pszKey, dwEncKeySize))
|
|
goto cleanup;
|
|
|
|
// copy the data into another buffer to encrypt it
|
|
*pdwEncryptedBufferLen = dwDataLength;
|
|
dwBufferLen = dwDataLength + DEFAULT_CRYPTO_EXTRA_BUFFER_SIZE;
|
|
|
|
while (1)
|
|
{
|
|
//
|
|
// alloc memory for output buffer
|
|
//
|
|
if (pfnAlloc)
|
|
{
|
|
*ppbEncryptedData = (PBYTE)pfnAlloc(dwBufferLen);
|
|
}
|
|
else
|
|
{
|
|
*ppbEncryptedData = (PBYTE)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwBufferLen);
|
|
}
|
|
if (!*ppbEncryptedData)
|
|
{
|
|
MYDBG(("EncryptDataWithKey: out of memory error"));
|
|
goto cleanup;
|
|
}
|
|
|
|
// copy the data into another buffer to encrypt it
|
|
memcpy (*ppbEncryptedData, pbData, dwDataLength);
|
|
|
|
|
|
// now encrypt the secret key using the key generated
|
|
if ( ! m_fnCryptEncrypt(hKey,
|
|
0, // no hash required
|
|
TRUE, // Final packet
|
|
0, // Flags - always 0
|
|
*ppbEncryptedData, // data buffer
|
|
pdwEncryptedBufferLen, // length of data
|
|
dwBufferLen ) ) // size of buffer
|
|
{
|
|
MYDBG(("Error 0x%x during CryptEncrypt", GetLastError()));
|
|
|
|
if (pfnFree)
|
|
{
|
|
pfnFree(*ppbEncryptedData);
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *ppbEncryptedData);
|
|
}
|
|
*ppbEncryptedData = NULL;
|
|
|
|
dwErr = GetLastError();
|
|
//
|
|
// if the output is too small, realloc it.
|
|
//
|
|
if (dwErr == ERROR_MORE_DATA || dwErr == NTE_BAD_LEN)
|
|
{
|
|
dwBufferLen += DEFAULT_CRYPTO_EXTRA_BUFFER_SIZE;
|
|
continue;
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// we now have the data encrypted. we need to uuencode it.
|
|
//
|
|
if (pfnAlloc)
|
|
{
|
|
pbBuf = (PBYTE)pfnAlloc(*pdwEncryptedBufferLen);
|
|
}
|
|
else
|
|
{
|
|
pbBuf = (PBYTE)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
*pdwEncryptedBufferLen);
|
|
}
|
|
if (!pbBuf)
|
|
{
|
|
MYDBG(("EncryptDataWithKey: out of memory error"));
|
|
if (pfnFree)
|
|
{
|
|
pfnFree(*ppbEncryptedData);
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *ppbEncryptedData);
|
|
}
|
|
*ppbEncryptedData = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pbBuf, *ppbEncryptedData, *pdwEncryptedBufferLen);
|
|
uuencode(pbBuf, *pdwEncryptedBufferLen, (CHAR*)*ppbEncryptedData, dwBufferLen);
|
|
//
|
|
// set the encrypted buffer len
|
|
//
|
|
*pdwEncryptedBufferLen = lstrlen((LPTSTR)*ppbEncryptedData);
|
|
|
|
if (pfnFree)
|
|
{
|
|
pfnFree(pbBuf);
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pbBuf);
|
|
}
|
|
pbBuf = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
fOk = TRUE;
|
|
|
|
cleanup:
|
|
// destroy session key
|
|
if (hKey != 0)
|
|
m_fnCryptDestroyKey(hKey);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
// Given a key string, and encrypted data using EncryptDataWithPassword,
|
|
// this function generates a session key from the key string. This
|
|
// session key is then used to decrypt the data.
|
|
|
|
// returns
|
|
// CRYPT_FNC_NO_ERROR no error
|
|
// CRYPT_FNC_BAD_PASSWORD password bad try again
|
|
// CRYPT_FNC_INSUFFICIENT_BUFFER larger buffer is required
|
|
// *pdwEncrytedBufferLen is set to required length
|
|
// CRYPT_FNC_INIT_NOT_CALLED InitCrypt not successfully called
|
|
// CRYPT_FNC_INTERNAL_ERROR
|
|
DWORD CCryptFunctions::DecryptDataWithKey(
|
|
LPTSTR pszKey, // password
|
|
PBYTE pbEncryptedData, // Encrypted data
|
|
DWORD dwEncrytedDataLen, // Length of encrypted data
|
|
PBYTE *ppbData, // Decrypted Data will be stored here
|
|
DWORD *pdwDataBufferLength,// Length of the above buffer in bytes
|
|
PFN_CMSECUREALLOC pfnAlloc,
|
|
PFN_CMSECUREFREE pfnFree,
|
|
DWORD dwEncKeySize // how many bits of encryption do we want? (0 implies "don't care")
|
|
)
|
|
{
|
|
DWORD dwBufferLen;
|
|
DWORD dwUUDecodeBufLen;
|
|
HCRYPTKEY hKey = 0;
|
|
DWORD dwError;
|
|
DWORD dwMaxBufSize = 1024 * 10; // Just some max buffer size (10K) in order to exit the while loop
|
|
|
|
//
|
|
// Init should have been successfully called before
|
|
// if no data to be decrypted, then don't do anything
|
|
//
|
|
if (m_hProv == 0 || !dwEncrytedDataLen)
|
|
{
|
|
dwError = CRYPT_FNC_INIT_NOT_CALLED;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!GenerateSessionKeyFromPassword(&hKey, pszKey, dwEncKeySize))
|
|
{
|
|
dwError = CRYPT_FNC_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
// copy the data into another buffer to encrypt it
|
|
dwBufferLen = dwEncrytedDataLen + DEFAULT_CRYPTO_EXTRA_BUFFER_SIZE;
|
|
// *pdwDataBufferLength = dwEncrytedDataLen;
|
|
|
|
//
|
|
// Loop until we get to dwMaxBufSize. This is a safeguard to get out
|
|
// of the infinite loop problem. DBCS passwords used to loop continuously.
|
|
//
|
|
|
|
while(dwBufferLen < dwMaxBufSize)
|
|
{
|
|
//
|
|
// alloc memory for output buffer
|
|
//
|
|
if (pfnAlloc)
|
|
{
|
|
*ppbData = (PBYTE)pfnAlloc(dwBufferLen);
|
|
}
|
|
else
|
|
{
|
|
*ppbData = (PBYTE)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwBufferLen);
|
|
}
|
|
if (!*ppbData)
|
|
{
|
|
dwError = CRYPT_FNC_OUT_OF_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// set uudecode output buf size
|
|
//
|
|
dwUUDecodeBufLen = dwBufferLen;
|
|
|
|
uudecode((char*)pbEncryptedData, (CHAR*)*ppbData, &dwUUDecodeBufLen);
|
|
|
|
*pdwDataBufferLength = dwUUDecodeBufLen;
|
|
|
|
// now decrypt the secret key using the key generated
|
|
if ( ! m_fnCryptDecrypt(hKey,
|
|
0, // no hash required
|
|
TRUE, // Final packet
|
|
0, // Flags - always 0
|
|
*ppbData, // data buffer
|
|
pdwDataBufferLength )) // length of data
|
|
{
|
|
DWORD dwCryptError = GetLastError();
|
|
MYDBGTST(dwCryptError, ("Error 0x%x during CryptDecrypt", dwCryptError));
|
|
|
|
if (pfnFree)
|
|
{
|
|
pfnFree(*ppbData);
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *ppbData);
|
|
}
|
|
*ppbData = NULL;
|
|
|
|
//
|
|
// if the output is too small, realloc it.
|
|
//
|
|
if (dwCryptError == NTE_BAD_LEN)
|
|
{
|
|
dwBufferLen *= 2; // to speed up memory alloc double the size
|
|
continue;
|
|
}
|
|
|
|
// CryptDecrypt fails with error NTE_BAD_DATA if the password
|
|
// is incorrect. Hence we should check for this error and prompt the
|
|
// user again for the password. If the data is garbled in transit, then the secret key
|
|
// will still be decrypted into a wrong value and the user will not
|
|
// know about it.
|
|
if (dwCryptError == NTE_BAD_DATA)
|
|
{
|
|
dwError = CRYPT_FNC_BAD_KEY;
|
|
}
|
|
else
|
|
{
|
|
dwError = CRYPT_FNC_INTERNAL_ERROR;
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
break;
|
|
}
|
|
if (dwBufferLen < dwMaxBufSize)
|
|
{
|
|
dwError = CRYPT_FNC_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
CMTRACE1(TEXT("DecryptDataWithKey: not enough buffer = %d bytes"), dwBufferLen);
|
|
MYDBGASSERT(FALSE);
|
|
dwError = NTE_BAD_LEN;
|
|
}
|
|
|
|
|
|
cleanup:
|
|
// destroy session key
|
|
if (hKey != 0)
|
|
{
|
|
m_fnCryptDestroyKey(hKey);
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|
|
|