1003 lines
28 KiB
C
1003 lines
28 KiB
C
|
#include <windows.h>
|
||
|
#include <malloc.h>
|
||
|
#include <string.h>
|
||
|
#include <wchar.h>
|
||
|
#include <WINSOCK2.H>
|
||
|
#include <Ws2tcpip.h>
|
||
|
#include <Wincrypt.h>
|
||
|
#include <setupbat.h>
|
||
|
|
||
|
// 40 bit key length
|
||
|
//#define KEYLENGTH 0x00280000
|
||
|
// 128 bit key length
|
||
|
//#define KEYLENGTH 0x00800000
|
||
|
// 56 bit key length needed to use DES.
|
||
|
//#define KEYLENGTH 0x00380000
|
||
|
// 168 bit key length needed to use 3DES.
|
||
|
#define KEYLENGTH 0x00A80000
|
||
|
#define CRYPT_PROV MS_ENHANCED_PROV_A
|
||
|
#define ENCRYPT_ALGORITHM CALG_3DES
|
||
|
//CALG_RC4
|
||
|
#define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' || (c) == '\v' || (c) == '\f')
|
||
|
#define IsDigit(c) ((c) >= '0' && (c) <= '9')
|
||
|
// 32 bytes of random password data, generated once using CryptGenRandom
|
||
|
BYTE iPassword[] = {0xc7, 0x1e, 0x6a, 0xab, 0xe3, 0x8f, 0x76, 0x5b, 0x0d, 0x7b, 0xe0, 0xcb, 0xbf, 0x1c, 0xee, 0x54,
|
||
|
0x9d, 0x62, 0xbd, 0xb6, 0x6a, 0x38, 0x69, 0x4b, 0xe1, 0x44, 0x9b, 0x76, 0x4a, 0xe4, 0x79, 0xce};
|
||
|
|
||
|
//=================================================================================================
|
||
|
//
|
||
|
// copied from msdev\crt\src\atox.c
|
||
|
//
|
||
|
// long MyAtoL(char *nptr) - Convert string to long
|
||
|
//
|
||
|
// Purpose:
|
||
|
// Converts ASCII string pointed to by nptr to binary.
|
||
|
// Overflow is not detected. So that this lib does not need CRT
|
||
|
//
|
||
|
// Entry:
|
||
|
// nptr = ptr to string to convert
|
||
|
//
|
||
|
// Exit:
|
||
|
// return long int value of the string
|
||
|
//
|
||
|
// Exceptions:
|
||
|
// None - overflow is not detected.
|
||
|
//
|
||
|
//=================================================================================================
|
||
|
long MyAtoL(const char *nptr)
|
||
|
{
|
||
|
int c; /* current char */
|
||
|
long total; /* current total */
|
||
|
int sign; /* if '-', then negative, otherwise positive */
|
||
|
|
||
|
// NOTE: no need to worry about DBCS chars here because IsSpace(c), IsDigit(c),
|
||
|
// '+' and '-' are "pure" ASCII chars, i.e., they are neither DBCS Leading nor
|
||
|
// DBCS Trailing bytes -- pritvi
|
||
|
|
||
|
/* skip whitespace */
|
||
|
while ( IsSpace((int)(unsigned char)*nptr) )
|
||
|
++nptr;
|
||
|
|
||
|
c = (int)(unsigned char)*nptr++;
|
||
|
sign = c; /* save sign indication */
|
||
|
if (c == '-' || c == '+')
|
||
|
c = (int)(unsigned char)*nptr++; /* skip sign */
|
||
|
|
||
|
total = 0;
|
||
|
|
||
|
while (IsDigit(c)) {
|
||
|
total = 10 * total + (c - '0'); /* accumulate digit */
|
||
|
c = (int)(unsigned char)*nptr++; /* get next char */
|
||
|
}
|
||
|
|
||
|
if (sign == '-')
|
||
|
return -total;
|
||
|
else
|
||
|
return total; /* return result, negated if necessary */
|
||
|
}
|
||
|
|
||
|
// Check that the time/date field has only digits, as a validation that no one manipulated the data
|
||
|
BOOL OnlyDigits(LPSTR szValue)
|
||
|
{
|
||
|
BOOL bRet = TRUE;
|
||
|
LPSTR pTemp = szValue;
|
||
|
while (*pTemp)
|
||
|
{
|
||
|
if (!IsDigit(*pTemp))
|
||
|
{
|
||
|
bRet = FALSE;
|
||
|
}
|
||
|
pTemp++;
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
// To decode and encode the binary buffer we get from the encyption function
|
||
|
unsigned char * base64decode (unsigned char * bufcoded, DWORD * plDecodedSize)
|
||
|
{
|
||
|
int pr2six[256];
|
||
|
int i;
|
||
|
int j=0;
|
||
|
unsigned char * cCurr = bufcoded;
|
||
|
int bDone = FALSE;
|
||
|
long lBufSize = 0;
|
||
|
long lCount = 0;
|
||
|
unsigned char * bufin;
|
||
|
unsigned char * bufout;
|
||
|
unsigned char * temp = NULL;
|
||
|
unsigned char * pBufDecoded = NULL;
|
||
|
int lop_off;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
//
|
||
|
// Build up the reverse index from base64 characters to values
|
||
|
// The multiple loops are easier
|
||
|
//
|
||
|
for (i=65; i<91; i++) {
|
||
|
pr2six[i]=j++;
|
||
|
}
|
||
|
|
||
|
for (i=97; i<123; i++) {
|
||
|
pr2six[i]=j++;
|
||
|
}
|
||
|
|
||
|
for (i=48; i<58; i++) {
|
||
|
pr2six[i]=j++;
|
||
|
}
|
||
|
|
||
|
pr2six[43]=j++;
|
||
|
pr2six[47]=j++;
|
||
|
pr2six[61]=0;
|
||
|
|
||
|
//
|
||
|
// The old code relied on the size of the original data provided before
|
||
|
// the encoding. We don't have that, so we'll just allocate as much as
|
||
|
// the encoded data, relying on the fact that the encoded data is always
|
||
|
// larger. (+4 for good measure)
|
||
|
//
|
||
|
lBufSize=lstrlenA((char *)cCurr)-1+4;
|
||
|
*plDecodedSize = lBufSize;
|
||
|
|
||
|
pBufDecoded = GlobalAlloc(GPTR, lBufSize);
|
||
|
if(!pBufDecoded)
|
||
|
{
|
||
|
//_tprintf(_T("Out of memory."));
|
||
|
return NULL;
|
||
|
}
|
||
|
ZeroMemory(pBufDecoded, lBufSize);
|
||
|
|
||
|
lCount = lstrlenA((char *)cCurr);
|
||
|
|
||
|
// Do the decoding to new buffer
|
||
|
bufin = cCurr;
|
||
|
bufout = pBufDecoded;
|
||
|
|
||
|
while(lCount > 0) {
|
||
|
*(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||
|
*(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||
|
*(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||
|
bufin += 4;
|
||
|
lCount -= 4;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The line below does not make much sense since \0 is really a valid
|
||
|
// binary value, so we can't add it to our data stream
|
||
|
//
|
||
|
//*(bufout++) = '\0';
|
||
|
|
||
|
//
|
||
|
// Let's calculate the real size of our data
|
||
|
//
|
||
|
*plDecodedSize=(ULONG)(bufout-pBufDecoded);
|
||
|
|
||
|
//
|
||
|
// if there were pads in the encoded stream, lop off the nulls the
|
||
|
// NULLS they created
|
||
|
//
|
||
|
lop_off=0;
|
||
|
if (bufin[-1]=='=') lop_off++;
|
||
|
if (bufin[-2]=='=') lop_off++;
|
||
|
|
||
|
*plDecodedSize=*plDecodedSize-lop_off;
|
||
|
|
||
|
temp = GlobalAlloc(GPTR, (*plDecodedSize) + 2);
|
||
|
if (temp==NULL)
|
||
|
{
|
||
|
//_tprintf(_T("Out of memory."));
|
||
|
return NULL;
|
||
|
}
|
||
|
ZeroMemory(temp, *plDecodedSize);
|
||
|
memcpy(temp, pBufDecoded, *plDecodedSize);
|
||
|
|
||
|
temp[(*plDecodedSize)+0] = 0;
|
||
|
temp[(*plDecodedSize)+1] = 0;
|
||
|
|
||
|
if (pBufDecoded) {
|
||
|
GlobalFree(pBufDecoded);
|
||
|
}
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// the map for the encoder, according to RFC 1521
|
||
|
//
|
||
|
char _six2pr64[64] = {
|
||
|
'A','B','C','D','E','F','G','H','I','J','K','L','M',
|
||
|
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
||
|
'a','b','c','d','e','f','g','h','i','j','k','l','m',
|
||
|
'n','o','p','q','r','s','t','u','v','w','x','y','z',
|
||
|
'0','1','2','3','4','5','6','7','8','9','+','/'
|
||
|
};
|
||
|
|
||
|
|
||
|
unsigned char * base64encode(unsigned char * bufin, int nbytes)
|
||
|
{
|
||
|
unsigned char *outptr;
|
||
|
unsigned char *to_return;
|
||
|
long i;
|
||
|
long OutBufSize;
|
||
|
char *six2pr = _six2pr64;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Size of input buffer * 133%
|
||
|
//
|
||
|
OutBufSize = nbytes + ((nbytes + 3) / 3) + 5;
|
||
|
|
||
|
//
|
||
|
// Allocate buffer with 133% of nbytes
|
||
|
//
|
||
|
outptr = GlobalAlloc(GPTR,OutBufSize + 1);
|
||
|
if(outptr==NULL) {
|
||
|
//_tprintf(_T("Out of memory."));
|
||
|
return NULL;
|
||
|
}
|
||
|
ZeroMemory(outptr, OutBufSize + 1);
|
||
|
to_return = outptr;
|
||
|
|
||
|
nbytes = nbytes - 3;
|
||
|
//
|
||
|
// Encode everything
|
||
|
//
|
||
|
for (i=0; i<nbytes; i += 3) {
|
||
|
*(outptr++) = six2pr[*bufin >> 2]; // c1
|
||
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
|
||
|
*(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];// c3
|
||
|
*(outptr++) = six2pr[bufin[2] & 077]; // c4
|
||
|
bufin += 3;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If nbytes was not a multiple of 3, then we have encoded too
|
||
|
// many characters. Adjust appropriately.
|
||
|
//
|
||
|
if(i == nbytes) {
|
||
|
// There are 3 bytes in the last group
|
||
|
*(outptr++) = six2pr[*bufin >> 2]; // c1
|
||
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
|
||
|
*(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];// c3
|
||
|
*(outptr++) = six2pr[bufin[2] & 077]; // c4
|
||
|
} else if(i == nbytes+1) {
|
||
|
// There are only 2 bytes in the last group
|
||
|
*(outptr++) = six2pr[*bufin >> 2]; // c1
|
||
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
|
||
|
*(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((0 >> 6) & 03)]; // c3
|
||
|
*(outptr++) = '=';
|
||
|
} else if(i == nbytes+2) {
|
||
|
// There are only 1 byte in the last group
|
||
|
*(outptr++) = six2pr[*bufin >> 2]; // c1
|
||
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((0 >> 4) & 017)]; // c2
|
||
|
*(outptr++) = '=';
|
||
|
*(outptr++) = '=';
|
||
|
}
|
||
|
|
||
|
*outptr = '\0';
|
||
|
|
||
|
return to_return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Unicode Ansi conversion function
|
||
|
LPSTR _PEConvertW2A (
|
||
|
IN LPCWSTR Unicode,
|
||
|
IN UINT CodePage
|
||
|
)
|
||
|
{
|
||
|
LPSTR ansi = NULL;
|
||
|
DWORD rc;
|
||
|
|
||
|
if (Unicode)
|
||
|
{
|
||
|
rc = WideCharToMultiByte (
|
||
|
CodePage,
|
||
|
0,
|
||
|
Unicode,
|
||
|
-1,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (rc || *Unicode == L'\0') {
|
||
|
|
||
|
ansi = (LPSTR)GlobalAlloc(GPTR, (rc + 1) * sizeof (CHAR));
|
||
|
if (ansi) {
|
||
|
rc = WideCharToMultiByte (
|
||
|
CodePage,
|
||
|
0,
|
||
|
Unicode,
|
||
|
-1,
|
||
|
ansi,
|
||
|
rc + 1,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!(rc || *Unicode == L'\0')) {
|
||
|
rc = GetLastError ();
|
||
|
GlobalFree((PVOID)ansi);
|
||
|
ansi = NULL;
|
||
|
SetLastError (rc);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return ansi;
|
||
|
}
|
||
|
|
||
|
// Ansi Unicode conversion function
|
||
|
LPWSTR _PEConvertA2W (
|
||
|
IN LPCSTR Ansi,
|
||
|
IN UINT CodePage
|
||
|
)
|
||
|
{
|
||
|
PWSTR unicode = NULL;
|
||
|
DWORD rc;
|
||
|
|
||
|
if (Ansi)
|
||
|
{
|
||
|
rc = MultiByteToWideChar (
|
||
|
CodePage,
|
||
|
MB_ERR_INVALID_CHARS,
|
||
|
Ansi,
|
||
|
-1,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
|
||
|
if (rc || *Ansi == '\0') {
|
||
|
|
||
|
unicode = (LPWSTR) GlobalAlloc (GPTR, (rc + 1) * sizeof (WCHAR));
|
||
|
if (unicode) {
|
||
|
rc = MultiByteToWideChar (
|
||
|
CodePage,
|
||
|
MB_ERR_INVALID_CHARS,
|
||
|
Ansi,
|
||
|
-1,
|
||
|
unicode,
|
||
|
rc + 1
|
||
|
);
|
||
|
|
||
|
if (!(rc || *Ansi == '\0')) {
|
||
|
rc = GetLastError ();
|
||
|
GlobalFree ((PVOID)unicode);
|
||
|
unicode = NULL;
|
||
|
SetLastError (rc);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return unicode;
|
||
|
}
|
||
|
|
||
|
// Ansi version to Encypt the input data.
|
||
|
// The encrypted and base 64 encoded buffer is allocated and returned to the caller.
|
||
|
// The caller needs to GloblaFree the buffer.
|
||
|
HRESULT EncryptDataA(LPSTR szInData, DWORD chSizeIn, LPSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
HCRYPTPROV hCryptProv;
|
||
|
HCRYPTKEY hKey;
|
||
|
HCRYPTHASH hHash;
|
||
|
LPSTR pw;
|
||
|
PBYTE pbData = NULL;
|
||
|
|
||
|
*szOutData = NULL;
|
||
|
pw = GlobalAlloc(GPTR, sizeof(iPassword)+1);
|
||
|
if (pw == NULL)
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
memcpy(pw, iPassword, sizeof(iPassword));
|
||
|
// Get handle to the default provider.
|
||
|
if(CryptAcquireContextA(
|
||
|
&hCryptProv,
|
||
|
NULL,
|
||
|
CRYPT_PROV,
|
||
|
PROV_RSA_FULL,
|
||
|
CRYPT_VERIFYCONTEXT))
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
if(CryptCreateHash(
|
||
|
hCryptProv,
|
||
|
CALG_MD5,
|
||
|
0,
|
||
|
0,
|
||
|
&hHash))
|
||
|
{
|
||
|
if(CryptHashData(hHash,
|
||
|
(BYTE *)pw,
|
||
|
lstrlenA(pw),
|
||
|
0))
|
||
|
{
|
||
|
if(CryptDeriveKey(
|
||
|
hCryptProv,
|
||
|
ENCRYPT_ALGORITHM,
|
||
|
hHash,
|
||
|
KEYLENGTH,
|
||
|
&hKey))
|
||
|
{
|
||
|
DWORD dwCryptDataLen = chSizeIn;
|
||
|
DWORD dwDataLen = dwCryptDataLen;
|
||
|
CryptEncrypt(
|
||
|
hKey,
|
||
|
0,
|
||
|
TRUE,
|
||
|
0,
|
||
|
NULL,
|
||
|
&dwCryptDataLen,
|
||
|
dwDataLen);
|
||
|
|
||
|
pbData = GlobalAlloc(GPTR, dwCryptDataLen+1);
|
||
|
if (pbData != NULL)
|
||
|
{
|
||
|
memcpy(pbData, szInData, chSizeIn);
|
||
|
// size of the buffer
|
||
|
dwDataLen = dwCryptDataLen;
|
||
|
// number of bytes to be encrypted
|
||
|
dwCryptDataLen = chSizeIn;
|
||
|
|
||
|
if(CryptEncrypt(
|
||
|
hKey,
|
||
|
0,
|
||
|
TRUE,
|
||
|
0,
|
||
|
pbData,
|
||
|
&dwCryptDataLen,
|
||
|
dwDataLen))
|
||
|
{
|
||
|
*szOutData = base64encode(pbData, (int)dwCryptDataLen);
|
||
|
if (*szOutData)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
CryptDestroyKey(hKey);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptDestroyHash(hHash);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptReleaseContext(hCryptProv, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
|
||
|
if (pbData)
|
||
|
{
|
||
|
GlobalFree(pbData);
|
||
|
}
|
||
|
GlobalFree(pw);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Unicode version to Encypt the input data.
|
||
|
// Converts the in data to Ansi and calls the Ansi version and converts the out data to unicode
|
||
|
// and returns the buffer to the caller.
|
||
|
HRESULT EncryptDataW(LPWSTR szInData, DWORD chSizeIn, LPWSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
LPBYTE pBuffer = NULL;
|
||
|
LPSTR szData = NULL;
|
||
|
|
||
|
*szOutData = NULL;
|
||
|
pBuffer = (LPBYTE)_PEConvertW2A (szInData, CP_ACP);
|
||
|
if (pBuffer == NULL)
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if ((hr = EncryptDataA(pBuffer, lstrlenA(pBuffer)+1, &szData)) == S_OK)
|
||
|
{
|
||
|
*szOutData = _PEConvertA2W (szData, CP_ACP);
|
||
|
if ((*szOutData) == NULL)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
GlobalFree(szData);
|
||
|
}
|
||
|
GlobalFree(pBuffer);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT DecryptDataA(LPSTR szInData, LPSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
HCRYPTPROV hCryptProv;
|
||
|
HCRYPTKEY hKey;
|
||
|
HCRYPTHASH hHash;
|
||
|
DWORD dwErr;
|
||
|
DWORD dwCipherTextLen = lstrlenA(szInData);
|
||
|
char *pw;
|
||
|
DWORD dwCount;
|
||
|
char *pBuffer;
|
||
|
|
||
|
*szOutData = NULL;
|
||
|
|
||
|
pw = GlobalAlloc(GPTR, sizeof(iPassword)+1);
|
||
|
if (pw == NULL)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
return hr;
|
||
|
}
|
||
|
memcpy(pw, iPassword, sizeof(iPassword));
|
||
|
|
||
|
pBuffer = (char *) (base64decode((unsigned char *)szInData, &dwCount));
|
||
|
if (pBuffer == NULL)
|
||
|
{
|
||
|
GlobalFree(pw);
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Get a handle to the default provider.
|
||
|
if(CryptAcquireContextA(
|
||
|
&hCryptProv,
|
||
|
NULL,
|
||
|
CRYPT_PROV,
|
||
|
PROV_RSA_FULL,
|
||
|
CRYPT_VERIFYCONTEXT))
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
// Create a hash object.
|
||
|
if(CryptCreateHash(
|
||
|
hCryptProv,
|
||
|
CALG_MD5,
|
||
|
0,
|
||
|
0,
|
||
|
&hHash))
|
||
|
{
|
||
|
if(CryptHashData(hHash,
|
||
|
(BYTE *)pw,
|
||
|
lstrlenA(pw),
|
||
|
0))
|
||
|
{
|
||
|
if(CryptDeriveKey(
|
||
|
hCryptProv,
|
||
|
ENCRYPT_ALGORITHM,
|
||
|
hHash,
|
||
|
KEYLENGTH,
|
||
|
&hKey))
|
||
|
{
|
||
|
// pBuffer is bigger when the data is encrypted.
|
||
|
// The decrypted data (on output) is smaller, because we are using
|
||
|
// a block cyoher at encryption.
|
||
|
if(CryptDecrypt(
|
||
|
hKey,
|
||
|
0,
|
||
|
TRUE,
|
||
|
0,
|
||
|
pBuffer,
|
||
|
&dwCount))
|
||
|
{
|
||
|
*szOutData = GlobalAlloc(GPTR, dwCount+1);
|
||
|
if (*szOutData)
|
||
|
{
|
||
|
// lstrcpyn includes the NULL in the count and makes sure there is one.
|
||
|
lstrcpynA(*szOutData, pBuffer, dwCount+1);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptDestroyKey(hKey);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptDestroyHash(hHash);
|
||
|
hHash = 0;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptReleaseContext(hCryptProv, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
GlobalFree(pBuffer);
|
||
|
GlobalFree(pw);
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT DecryptDataW(LPWSTR szInData, LPWSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
LPBYTE pBuffer = NULL;
|
||
|
LPSTR szData = NULL;
|
||
|
|
||
|
*szOutData = NULL;
|
||
|
pBuffer = (LPBYTE)_PEConvertW2A (szInData, CP_ACP);
|
||
|
if (pBuffer == NULL)
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
if ((hr = DecryptDataA(pBuffer, &szData)) == S_OK)
|
||
|
{
|
||
|
*szOutData = _PEConvertA2W (szData, CP_ACP);
|
||
|
if ((*szOutData) == NULL)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
GlobalFree(szData);
|
||
|
}
|
||
|
GlobalFree(pBuffer);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define _SECOND ((__int64) 10000000)
|
||
|
#define _MINUTE (60 * _SECOND)
|
||
|
#define _HOUR (60 * _MINUTE)
|
||
|
#define _DAY (24 * _HOUR)
|
||
|
|
||
|
// encode the position of the PID character. 0 is for the dashes
|
||
|
int iPID[] = {3 ,251,43 ,89 ,75,0,
|
||
|
123,35 ,23 ,97 ,77,0,
|
||
|
5 ,135,189,213,13,0,
|
||
|
245,111,91 ,71 ,65,0,
|
||
|
25 ,49 ,81 ,129,239};
|
||
|
int iTime1[] = {253, 247, 233, 221, 211, 191, 181, 171, 161, 151, 141, 131, 121, 112, 101, 93, 80, 70, 61, 51};
|
||
|
int iTime2[] = {250, 242, 237, 225, 215, 195, 185, 175, 165, 155, 145, 137, 125, 115, 105, 95, 85, 73, 67, 55};
|
||
|
|
||
|
HRESULT PrepareEncryptedPIDA(LPSTR szPID, UINT uiDays, LPSTR *szOut)
|
||
|
{
|
||
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
HCRYPTPROV hCryptProv;
|
||
|
FILETIME ft1, ft2;
|
||
|
LONGLONG ll;
|
||
|
LONGLONG ll2;
|
||
|
char szLine[256];
|
||
|
|
||
|
GetSystemTimeAsFileTime(&ft1);
|
||
|
ll = ((LONGLONG)ft1.dwHighDateTime << 32) + ft1.dwLowDateTime;
|
||
|
ll2 = ll - (_HOUR*12); // Substract 12 hours
|
||
|
ll += (uiDays*_DAY) + (_HOUR*24); // Add 24 hours
|
||
|
|
||
|
ft1.dwLowDateTime = (DWORD)ll2;
|
||
|
ft1.dwHighDateTime = (DWORD)(ll2 >> 32);
|
||
|
|
||
|
ft2.dwLowDateTime = (DWORD)ll;
|
||
|
ft2.dwHighDateTime = (DWORD)(ll >> 32);
|
||
|
|
||
|
// Build a 256 character string that we encode. In the 256 character strign we hide
|
||
|
// the PID and the time/date info for the interval the encypted data is valid.
|
||
|
// We need 20 characters each for the start and end of the time interval
|
||
|
// and we need 25 characters for the PID. 20+20+25 = 65 characters. All other characters
|
||
|
// are random.
|
||
|
// 1. fill the string with random characters
|
||
|
// 2. replace some with the PID charactes
|
||
|
// 3. replace some with the time/date info
|
||
|
if(CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||
|
{
|
||
|
int i;
|
||
|
hr = S_OK;
|
||
|
if(!CryptGenRandom(hCryptProv, sizeof(szLine), (PBYTE)szLine))
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
}
|
||
|
CryptReleaseContext(hCryptProv, 0);
|
||
|
// in the case the random generator create 0x0 we want to replace it with
|
||
|
// some value, otherwise we cannot use it as a character string,
|
||
|
// the string would be terminated.
|
||
|
for (i = 0; i < sizeof(szLine); i++)
|
||
|
{
|
||
|
if (szLine[i] == '\0')
|
||
|
{
|
||
|
szLine[i] = 0x01;
|
||
|
}
|
||
|
}
|
||
|
szLine[i-1] = '\0'; // Make sure we have a terminated string.
|
||
|
}
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
char szTime[21]; // 10 digits for dwHighDateTime and 10 for dwLowDateTime + termination
|
||
|
// The buffer is filled with random characters
|
||
|
// Now insert the PID characters
|
||
|
int i = 0;
|
||
|
while (szPID[i])
|
||
|
{
|
||
|
if (szPID[i] != '-')
|
||
|
{
|
||
|
szLine[iPID[i]] = szPID[i];
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
// Now fill in the time-date info
|
||
|
wsprintf(szTime, "%010lu%010lu", ft1.dwHighDateTime, ft1.dwLowDateTime);
|
||
|
i = 0;
|
||
|
while (szTime[i])
|
||
|
{
|
||
|
szLine[iTime1[i]] = szTime[i];
|
||
|
i++;
|
||
|
}
|
||
|
wsprintf(szTime, "%010lu%010lu", ft2.dwHighDateTime, ft2.dwLowDateTime);
|
||
|
i = 0;
|
||
|
while (szTime[i])
|
||
|
{
|
||
|
szLine[iTime2[i]] = szTime[i];
|
||
|
i++;
|
||
|
}
|
||
|
// szLine has the mengled data in it. Pass it to the encryption.
|
||
|
hr = EncryptDataA(szLine, sizeof(szLine), szOut);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT PrepareEncryptedPIDW(LPWSTR szPID, UINT uiDays, LPWSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
LPSTR pPID = NULL;
|
||
|
LPSTR szOut = NULL;
|
||
|
|
||
|
*szOutData = NULL;
|
||
|
pPID = _PEConvertW2A (szPID, CP_ACP);
|
||
|
if (pPID != NULL)
|
||
|
{
|
||
|
hr = PrepareEncryptedPIDA(pPID, uiDays, &szOut);
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
*szOutData = _PEConvertA2W (szOut, CP_ACP);
|
||
|
if (*szOutData)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
GlobalFree(szOut);
|
||
|
}
|
||
|
GlobalFree(pPID);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT ValidateEncryptedPIDA(LPSTR PID, LPSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
LPSTR szDecrypt = NULL;
|
||
|
FILETIME ft, ftCurrent;
|
||
|
LONGLONG ll1, ll2, llCurrent;
|
||
|
int iCount = 0;
|
||
|
char szPID[(5*5)+5]; // 5 characters 5 times + '-' inbetween + termimation
|
||
|
char szTime[11]; // each part of hte time is 10 digits + termination
|
||
|
|
||
|
GetSystemTimeAsFileTime(&ftCurrent);
|
||
|
hr = DecryptDataA(PID, &szDecrypt);
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
int i = 0;
|
||
|
hr = 0x01;
|
||
|
// Extract the time values first.
|
||
|
while (i < 10)
|
||
|
{
|
||
|
szTime[i] = szDecrypt[iTime1[i]];
|
||
|
i++;
|
||
|
}
|
||
|
szTime[10] = '\0';
|
||
|
if (OnlyDigits(szTime)) // 1. time
|
||
|
{
|
||
|
ft.dwHighDateTime = MyAtoL(szTime);
|
||
|
while (i < 20)
|
||
|
{
|
||
|
szTime[i-10] = szDecrypt[iTime1[i]];
|
||
|
i++;
|
||
|
}
|
||
|
szTime[10] = '\0';
|
||
|
if (OnlyDigits(szTime))
|
||
|
{
|
||
|
ft.dwLowDateTime = MyAtoL(szTime);
|
||
|
ll1 = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
|
||
|
ll1 = ll1 /_HOUR; // FileTime in hours;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
hr = 0x02;
|
||
|
i = 0;
|
||
|
while (i < 10)
|
||
|
{
|
||
|
szTime[i] = szDecrypt[iTime2[i]];
|
||
|
i++;
|
||
|
}
|
||
|
szTime[10] = '\0';
|
||
|
if (OnlyDigits(szTime)) // 1. time
|
||
|
{
|
||
|
ft.dwHighDateTime = MyAtoL(szTime);
|
||
|
while (i < 20)
|
||
|
{
|
||
|
szTime[i-10] = szDecrypt[iTime2[i]];
|
||
|
i++;
|
||
|
}
|
||
|
szTime[10] = '\0';
|
||
|
if (OnlyDigits(szTime))
|
||
|
{
|
||
|
ft.dwLowDateTime = MyAtoL(szTime);
|
||
|
ll2 = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
|
||
|
ll2 = ll2 /_HOUR; // FileTime in hours;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
// Now that we have the time values, compare them and make sure that the current
|
||
|
// time falls inside the time interval.
|
||
|
hr = 0x03;
|
||
|
llCurrent = ((LONGLONG)ftCurrent.dwHighDateTime << 32) + ftCurrent.dwLowDateTime;
|
||
|
llCurrent = llCurrent /_HOUR; // FileTime in hours;
|
||
|
|
||
|
if ((ll1 <= llCurrent) && ( llCurrent <= ll2))
|
||
|
{
|
||
|
i = 0;
|
||
|
// Time is OK.
|
||
|
// Extract the PID
|
||
|
while (i < sizeof(iPID)/sizeof(iPID[0]))
|
||
|
{
|
||
|
if (iPID[i] != 0)
|
||
|
{
|
||
|
szPID[i] = szDecrypt[iPID[i]];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
szPID[i] = '-';
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
szPID[i] = '\0';
|
||
|
*szOutData = (LPSTR)GlobalAlloc(GPTR, lstrlen(szPID)+1);
|
||
|
if (*szOutData)
|
||
|
{
|
||
|
lstrcpy(*szOutData, szPID);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (szDecrypt)
|
||
|
{
|
||
|
GlobalFree(szDecrypt);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT ValidateEncryptedPIDW(LPWSTR szPID, LPWSTR *szOutData)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
LPSTR szData = NULL;
|
||
|
LPSTR pPid = NULL;
|
||
|
|
||
|
pPid = (LPBYTE)_PEConvertW2A (szPID, CP_ACP);
|
||
|
if (pPid != NULL)
|
||
|
{
|
||
|
if ((hr = ValidateEncryptedPIDA(pPid, &szData)) == S_OK)
|
||
|
{
|
||
|
*szOutData = _PEConvertA2W (szData, CP_ACP);
|
||
|
if (*szOutData)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
GlobalFree(szData);
|
||
|
}
|
||
|
GlobalFree(pPid);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
void
|
||
|
_stdcall
|
||
|
ModuleEntry(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
|
||
|
CHAR szInData[256];
|
||
|
CHAR szPID[] = "Ctpdw-6q4d3-wrgdy-796g2-9vrmq";
|
||
|
LPSTR szOutData = NULL;
|
||
|
CHAR *szDecrypt = NULL;
|
||
|
#if 0
|
||
|
SYSTEMTIME CurrentTime;
|
||
|
SYSTEMTIME UniversalTime;
|
||
|
|
||
|
GetLocalTime(&UniversalTime);
|
||
|
|
||
|
wsprintf( szInData, "%s$%02d-%02d-%04d %02d:%02d:%02d",
|
||
|
szPID,
|
||
|
UniversalTime.wMonth,
|
||
|
UniversalTime.wDay,
|
||
|
UniversalTime.wYear,
|
||
|
UniversalTime.wHour,
|
||
|
UniversalTime.wMinute,
|
||
|
UniversalTime.wSecond);
|
||
|
|
||
|
WritePrivateProfileStringA("UserData","ProductID", szInData, "f:\\test.ini");
|
||
|
EncryptDataA((LPSTR)szInData, sizeof(szInData), &szOutData);
|
||
|
if (szOutData)
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","ProductIDEncryped", szOutData, "f:\\test.ini");
|
||
|
DecryptDataA(szOutData, &szDecrypt);
|
||
|
if (lstrcmpA(szInData, szDecrypt) == 0)
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","Compare", "Same", "f:\\test.ini");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","Compare", "Different", "f:\\test.ini");
|
||
|
}
|
||
|
GlobalFree ((PVOID)szOutData);
|
||
|
if (szDecrypt)
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","ProductIDDecypted", szDecrypt, "f:\\test.ini");
|
||
|
GlobalFree ((PVOID)szDecrypt);
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
WritePrivateProfileStringA("UserData","ProductID", szPID, "f:\\test.ini");
|
||
|
if (PrepareEncryptedPIDA(szPID, 5, &szOutData) == S_OK)
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","ProductIDEncryped", szOutData, "f:\\test.ini");
|
||
|
if (ValidateEncryptedPIDA(szOutData, &szDecrypt) == S_OK)
|
||
|
{
|
||
|
WritePrivateProfileStringA("UserData","ProductIDDecypted", szDecrypt, "f:\\test.ini");
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#endif
|