Source code of Windows XP (NT5)
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.

1002 lines
28 KiB

  1. #include <windows.h>
  2. #include <malloc.h>
  3. #include <string.h>
  4. #include <wchar.h>
  5. #include <WINSOCK2.H>
  6. #include <Ws2tcpip.h>
  7. #include <Wincrypt.h>
  8. #include <setupbat.h>
  9. // 40 bit key length
  10. //#define KEYLENGTH 0x00280000
  11. // 128 bit key length
  12. //#define KEYLENGTH 0x00800000
  13. // 56 bit key length needed to use DES.
  14. //#define KEYLENGTH 0x00380000
  15. // 168 bit key length needed to use 3DES.
  16. #define KEYLENGTH 0x00A80000
  17. #define CRYPT_PROV MS_ENHANCED_PROV_A
  18. #define ENCRYPT_ALGORITHM CALG_3DES
  19. //CALG_RC4
  20. #define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' || (c) == '\v' || (c) == '\f')
  21. #define IsDigit(c) ((c) >= '0' && (c) <= '9')
  22. // 32 bytes of random password data, generated once using CryptGenRandom
  23. BYTE iPassword[] = {0xc7, 0x1e, 0x6a, 0xab, 0xe3, 0x8f, 0x76, 0x5b, 0x0d, 0x7b, 0xe0, 0xcb, 0xbf, 0x1c, 0xee, 0x54,
  24. 0x9d, 0x62, 0xbd, 0xb6, 0x6a, 0x38, 0x69, 0x4b, 0xe1, 0x44, 0x9b, 0x76, 0x4a, 0xe4, 0x79, 0xce};
  25. //=================================================================================================
  26. //
  27. // copied from msdev\crt\src\atox.c
  28. //
  29. // long MyAtoL(char *nptr) - Convert string to long
  30. //
  31. // Purpose:
  32. // Converts ASCII string pointed to by nptr to binary.
  33. // Overflow is not detected. So that this lib does not need CRT
  34. //
  35. // Entry:
  36. // nptr = ptr to string to convert
  37. //
  38. // Exit:
  39. // return long int value of the string
  40. //
  41. // Exceptions:
  42. // None - overflow is not detected.
  43. //
  44. //=================================================================================================
  45. long MyAtoL(const char *nptr)
  46. {
  47. int c; /* current char */
  48. long total; /* current total */
  49. int sign; /* if '-', then negative, otherwise positive */
  50. // NOTE: no need to worry about DBCS chars here because IsSpace(c), IsDigit(c),
  51. // '+' and '-' are "pure" ASCII chars, i.e., they are neither DBCS Leading nor
  52. // DBCS Trailing bytes -- pritvi
  53. /* skip whitespace */
  54. while ( IsSpace((int)(unsigned char)*nptr) )
  55. ++nptr;
  56. c = (int)(unsigned char)*nptr++;
  57. sign = c; /* save sign indication */
  58. if (c == '-' || c == '+')
  59. c = (int)(unsigned char)*nptr++; /* skip sign */
  60. total = 0;
  61. while (IsDigit(c)) {
  62. total = 10 * total + (c - '0'); /* accumulate digit */
  63. c = (int)(unsigned char)*nptr++; /* get next char */
  64. }
  65. if (sign == '-')
  66. return -total;
  67. else
  68. return total; /* return result, negated if necessary */
  69. }
  70. // Check that the time/date field has only digits, as a validation that no one manipulated the data
  71. BOOL OnlyDigits(LPSTR szValue)
  72. {
  73. BOOL bRet = TRUE;
  74. LPSTR pTemp = szValue;
  75. while (*pTemp)
  76. {
  77. if (!IsDigit(*pTemp))
  78. {
  79. bRet = FALSE;
  80. }
  81. pTemp++;
  82. }
  83. return bRet;
  84. }
  85. // To decode and encode the binary buffer we get from the encyption function
  86. unsigned char * base64decode (unsigned char * bufcoded, DWORD * plDecodedSize)
  87. {
  88. int pr2six[256];
  89. int i;
  90. int j=0;
  91. unsigned char * cCurr = bufcoded;
  92. int bDone = FALSE;
  93. long lBufSize = 0;
  94. long lCount = 0;
  95. unsigned char * bufin;
  96. unsigned char * bufout;
  97. unsigned char * temp = NULL;
  98. unsigned char * pBufDecoded = NULL;
  99. int lop_off;
  100. HRESULT hr = S_OK;
  101. //
  102. // Build up the reverse index from base64 characters to values
  103. // The multiple loops are easier
  104. //
  105. for (i=65; i<91; i++) {
  106. pr2six[i]=j++;
  107. }
  108. for (i=97; i<123; i++) {
  109. pr2six[i]=j++;
  110. }
  111. for (i=48; i<58; i++) {
  112. pr2six[i]=j++;
  113. }
  114. pr2six[43]=j++;
  115. pr2six[47]=j++;
  116. pr2six[61]=0;
  117. //
  118. // The old code relied on the size of the original data provided before
  119. // the encoding. We don't have that, so we'll just allocate as much as
  120. // the encoded data, relying on the fact that the encoded data is always
  121. // larger. (+4 for good measure)
  122. //
  123. lBufSize=lstrlenA((char *)cCurr)-1+4;
  124. *plDecodedSize = lBufSize;
  125. pBufDecoded = GlobalAlloc(GPTR, lBufSize);
  126. if(!pBufDecoded)
  127. {
  128. //_tprintf(_T("Out of memory."));
  129. return NULL;
  130. }
  131. ZeroMemory(pBufDecoded, lBufSize);
  132. lCount = lstrlenA((char *)cCurr);
  133. // Do the decoding to new buffer
  134. bufin = cCurr;
  135. bufout = pBufDecoded;
  136. while(lCount > 0) {
  137. *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  138. *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  139. *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  140. bufin += 4;
  141. lCount -= 4;
  142. }
  143. //
  144. // The line below does not make much sense since \0 is really a valid
  145. // binary value, so we can't add it to our data stream
  146. //
  147. //*(bufout++) = '\0';
  148. //
  149. // Let's calculate the real size of our data
  150. //
  151. *plDecodedSize=(ULONG)(bufout-pBufDecoded);
  152. //
  153. // if there were pads in the encoded stream, lop off the nulls the
  154. // NULLS they created
  155. //
  156. lop_off=0;
  157. if (bufin[-1]=='=') lop_off++;
  158. if (bufin[-2]=='=') lop_off++;
  159. *plDecodedSize=*plDecodedSize-lop_off;
  160. temp = GlobalAlloc(GPTR, (*plDecodedSize) + 2);
  161. if (temp==NULL)
  162. {
  163. //_tprintf(_T("Out of memory."));
  164. return NULL;
  165. }
  166. ZeroMemory(temp, *plDecodedSize);
  167. memcpy(temp, pBufDecoded, *plDecodedSize);
  168. temp[(*plDecodedSize)+0] = 0;
  169. temp[(*plDecodedSize)+1] = 0;
  170. if (pBufDecoded) {
  171. GlobalFree(pBufDecoded);
  172. }
  173. return temp;
  174. }
  175. //
  176. // the map for the encoder, according to RFC 1521
  177. //
  178. char _six2pr64[64] = {
  179. 'A','B','C','D','E','F','G','H','I','J','K','L','M',
  180. 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  181. 'a','b','c','d','e','f','g','h','i','j','k','l','m',
  182. 'n','o','p','q','r','s','t','u','v','w','x','y','z',
  183. '0','1','2','3','4','5','6','7','8','9','+','/'
  184. };
  185. unsigned char * base64encode(unsigned char * bufin, int nbytes)
  186. {
  187. unsigned char *outptr;
  188. unsigned char *to_return;
  189. long i;
  190. long OutBufSize;
  191. char *six2pr = _six2pr64;
  192. //
  193. // Size of input buffer * 133%
  194. //
  195. OutBufSize = nbytes + ((nbytes + 3) / 3) + 5;
  196. //
  197. // Allocate buffer with 133% of nbytes
  198. //
  199. outptr = GlobalAlloc(GPTR,OutBufSize + 1);
  200. if(outptr==NULL) {
  201. //_tprintf(_T("Out of memory."));
  202. return NULL;
  203. }
  204. ZeroMemory(outptr, OutBufSize + 1);
  205. to_return = outptr;
  206. nbytes = nbytes - 3;
  207. //
  208. // Encode everything
  209. //
  210. for (i=0; i<nbytes; i += 3) {
  211. *(outptr++) = six2pr[*bufin >> 2]; // c1
  212. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
  213. *(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];// c3
  214. *(outptr++) = six2pr[bufin[2] & 077]; // c4
  215. bufin += 3;
  216. }
  217. //
  218. // If nbytes was not a multiple of 3, then we have encoded too
  219. // many characters. Adjust appropriately.
  220. //
  221. if(i == nbytes) {
  222. // There are 3 bytes in the last group
  223. *(outptr++) = six2pr[*bufin >> 2]; // c1
  224. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
  225. *(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];// c3
  226. *(outptr++) = six2pr[bufin[2] & 077]; // c4
  227. } else if(i == nbytes+1) {
  228. // There are only 2 bytes in the last group
  229. *(outptr++) = six2pr[*bufin >> 2]; // c1
  230. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; // c2
  231. *(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((0 >> 6) & 03)]; // c3
  232. *(outptr++) = '=';
  233. } else if(i == nbytes+2) {
  234. // There are only 1 byte in the last group
  235. *(outptr++) = six2pr[*bufin >> 2]; // c1
  236. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((0 >> 4) & 017)]; // c2
  237. *(outptr++) = '=';
  238. *(outptr++) = '=';
  239. }
  240. *outptr = '\0';
  241. return to_return;
  242. }
  243. // Unicode Ansi conversion function
  244. LPSTR _PEConvertW2A (
  245. IN LPCWSTR Unicode,
  246. IN UINT CodePage
  247. )
  248. {
  249. LPSTR ansi = NULL;
  250. DWORD rc;
  251. if (Unicode)
  252. {
  253. rc = WideCharToMultiByte (
  254. CodePage,
  255. 0,
  256. Unicode,
  257. -1,
  258. NULL,
  259. 0,
  260. NULL,
  261. NULL
  262. );
  263. if (rc || *Unicode == L'\0') {
  264. ansi = (LPSTR)GlobalAlloc(GPTR, (rc + 1) * sizeof (CHAR));
  265. if (ansi) {
  266. rc = WideCharToMultiByte (
  267. CodePage,
  268. 0,
  269. Unicode,
  270. -1,
  271. ansi,
  272. rc + 1,
  273. NULL,
  274. NULL
  275. );
  276. if (!(rc || *Unicode == L'\0')) {
  277. rc = GetLastError ();
  278. GlobalFree((PVOID)ansi);
  279. ansi = NULL;
  280. SetLastError (rc);
  281. }
  282. }
  283. }
  284. }
  285. return ansi;
  286. }
  287. // Ansi Unicode conversion function
  288. LPWSTR _PEConvertA2W (
  289. IN LPCSTR Ansi,
  290. IN UINT CodePage
  291. )
  292. {
  293. PWSTR unicode = NULL;
  294. DWORD rc;
  295. if (Ansi)
  296. {
  297. rc = MultiByteToWideChar (
  298. CodePage,
  299. MB_ERR_INVALID_CHARS,
  300. Ansi,
  301. -1,
  302. NULL,
  303. 0
  304. );
  305. if (rc || *Ansi == '\0') {
  306. unicode = (LPWSTR) GlobalAlloc (GPTR, (rc + 1) * sizeof (WCHAR));
  307. if (unicode) {
  308. rc = MultiByteToWideChar (
  309. CodePage,
  310. MB_ERR_INVALID_CHARS,
  311. Ansi,
  312. -1,
  313. unicode,
  314. rc + 1
  315. );
  316. if (!(rc || *Ansi == '\0')) {
  317. rc = GetLastError ();
  318. GlobalFree ((PVOID)unicode);
  319. unicode = NULL;
  320. SetLastError (rc);
  321. }
  322. }
  323. }
  324. }
  325. return unicode;
  326. }
  327. // Ansi version to Encypt the input data.
  328. // The encrypted and base 64 encoded buffer is allocated and returned to the caller.
  329. // The caller needs to GloblaFree the buffer.
  330. HRESULT EncryptDataA(LPSTR szInData, DWORD chSizeIn, LPSTR *szOutData)
  331. {
  332. HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  333. HCRYPTPROV hCryptProv;
  334. HCRYPTKEY hKey;
  335. HCRYPTHASH hHash;
  336. LPSTR pw;
  337. PBYTE pbData = NULL;
  338. *szOutData = NULL;
  339. pw = GlobalAlloc(GPTR, sizeof(iPassword)+1);
  340. if (pw == NULL)
  341. {
  342. return hr;
  343. }
  344. memcpy(pw, iPassword, sizeof(iPassword));
  345. // Get handle to the default provider.
  346. if(CryptAcquireContextA(
  347. &hCryptProv,
  348. NULL,
  349. CRYPT_PROV,
  350. PROV_RSA_FULL,
  351. CRYPT_VERIFYCONTEXT))
  352. {
  353. hr = E_FAIL;
  354. if(CryptCreateHash(
  355. hCryptProv,
  356. CALG_MD5,
  357. 0,
  358. 0,
  359. &hHash))
  360. {
  361. if(CryptHashData(hHash,
  362. (BYTE *)pw,
  363. lstrlenA(pw),
  364. 0))
  365. {
  366. if(CryptDeriveKey(
  367. hCryptProv,
  368. ENCRYPT_ALGORITHM,
  369. hHash,
  370. KEYLENGTH,
  371. &hKey))
  372. {
  373. DWORD dwCryptDataLen = chSizeIn;
  374. DWORD dwDataLen = dwCryptDataLen;
  375. CryptEncrypt(
  376. hKey,
  377. 0,
  378. TRUE,
  379. 0,
  380. NULL,
  381. &dwCryptDataLen,
  382. dwDataLen);
  383. pbData = GlobalAlloc(GPTR, dwCryptDataLen+1);
  384. if (pbData != NULL)
  385. {
  386. memcpy(pbData, szInData, chSizeIn);
  387. // size of the buffer
  388. dwDataLen = dwCryptDataLen;
  389. // number of bytes to be encrypted
  390. dwCryptDataLen = chSizeIn;
  391. if(CryptEncrypt(
  392. hKey,
  393. 0,
  394. TRUE,
  395. 0,
  396. pbData,
  397. &dwCryptDataLen,
  398. dwDataLen))
  399. {
  400. *szOutData = base64encode(pbData, (int)dwCryptDataLen);
  401. if (*szOutData)
  402. {
  403. hr = S_OK;
  404. }
  405. }
  406. else
  407. {
  408. hr = GetLastError();
  409. }
  410. }
  411. else
  412. {
  413. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  414. }
  415. CryptDestroyKey(hKey);
  416. }
  417. else
  418. {
  419. hr = GetLastError();
  420. }
  421. }
  422. else
  423. {
  424. hr = GetLastError();
  425. }
  426. CryptDestroyHash(hHash);
  427. }
  428. else
  429. {
  430. hr = GetLastError();
  431. }
  432. CryptReleaseContext(hCryptProv, 0);
  433. }
  434. else
  435. {
  436. hr = GetLastError();
  437. }
  438. if (pbData)
  439. {
  440. GlobalFree(pbData);
  441. }
  442. GlobalFree(pw);
  443. return hr;
  444. }
  445. // Unicode version to Encypt the input data.
  446. // Converts the in data to Ansi and calls the Ansi version and converts the out data to unicode
  447. // and returns the buffer to the caller.
  448. HRESULT EncryptDataW(LPWSTR szInData, DWORD chSizeIn, LPWSTR *szOutData)
  449. {
  450. HRESULT hr = E_FAIL;
  451. LPBYTE pBuffer = NULL;
  452. LPSTR szData = NULL;
  453. *szOutData = NULL;
  454. pBuffer = (LPBYTE)_PEConvertW2A (szInData, CP_ACP);
  455. if (pBuffer == NULL)
  456. {
  457. return hr;
  458. }
  459. if ((hr = EncryptDataA(pBuffer, lstrlenA(pBuffer)+1, &szData)) == S_OK)
  460. {
  461. *szOutData = _PEConvertA2W (szData, CP_ACP);
  462. if ((*szOutData) == NULL)
  463. {
  464. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  465. }
  466. GlobalFree(szData);
  467. }
  468. GlobalFree(pBuffer);
  469. return hr;
  470. }
  471. HRESULT DecryptDataA(LPSTR szInData, LPSTR *szOutData)
  472. {
  473. HRESULT hr = E_FAIL;
  474. HCRYPTPROV hCryptProv;
  475. HCRYPTKEY hKey;
  476. HCRYPTHASH hHash;
  477. DWORD dwErr;
  478. DWORD dwCipherTextLen = lstrlenA(szInData);
  479. char *pw;
  480. DWORD dwCount;
  481. char *pBuffer;
  482. *szOutData = NULL;
  483. pw = GlobalAlloc(GPTR, sizeof(iPassword)+1);
  484. if (pw == NULL)
  485. {
  486. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  487. return hr;
  488. }
  489. memcpy(pw, iPassword, sizeof(iPassword));
  490. pBuffer = (char *) (base64decode((unsigned char *)szInData, &dwCount));
  491. if (pBuffer == NULL)
  492. {
  493. GlobalFree(pw);
  494. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  495. return hr;
  496. }
  497. // Get a handle to the default provider.
  498. if(CryptAcquireContextA(
  499. &hCryptProv,
  500. NULL,
  501. CRYPT_PROV,
  502. PROV_RSA_FULL,
  503. CRYPT_VERIFYCONTEXT))
  504. {
  505. hr = E_FAIL;
  506. // Create a hash object.
  507. if(CryptCreateHash(
  508. hCryptProv,
  509. CALG_MD5,
  510. 0,
  511. 0,
  512. &hHash))
  513. {
  514. if(CryptHashData(hHash,
  515. (BYTE *)pw,
  516. lstrlenA(pw),
  517. 0))
  518. {
  519. if(CryptDeriveKey(
  520. hCryptProv,
  521. ENCRYPT_ALGORITHM,
  522. hHash,
  523. KEYLENGTH,
  524. &hKey))
  525. {
  526. // pBuffer is bigger when the data is encrypted.
  527. // The decrypted data (on output) is smaller, because we are using
  528. // a block cyoher at encryption.
  529. if(CryptDecrypt(
  530. hKey,
  531. 0,
  532. TRUE,
  533. 0,
  534. pBuffer,
  535. &dwCount))
  536. {
  537. *szOutData = GlobalAlloc(GPTR, dwCount+1);
  538. if (*szOutData)
  539. {
  540. // lstrcpyn includes the NULL in the count and makes sure there is one.
  541. lstrcpynA(*szOutData, pBuffer, dwCount+1);
  542. hr = S_OK;
  543. }
  544. else
  545. {
  546. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  547. }
  548. }
  549. else
  550. {
  551. hr = GetLastError();
  552. }
  553. CryptDestroyKey(hKey);
  554. }
  555. else
  556. {
  557. hr = GetLastError();
  558. }
  559. }
  560. else
  561. {
  562. hr = GetLastError();
  563. }
  564. CryptDestroyHash(hHash);
  565. hHash = 0;
  566. }
  567. else
  568. {
  569. hr = GetLastError();
  570. }
  571. CryptReleaseContext(hCryptProv, 0);
  572. }
  573. else
  574. {
  575. hr = GetLastError();
  576. }
  577. GlobalFree(pBuffer);
  578. GlobalFree(pw);
  579. return hr;
  580. }
  581. HRESULT DecryptDataW(LPWSTR szInData, LPWSTR *szOutData)
  582. {
  583. HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  584. LPBYTE pBuffer = NULL;
  585. LPSTR szData = NULL;
  586. *szOutData = NULL;
  587. pBuffer = (LPBYTE)_PEConvertW2A (szInData, CP_ACP);
  588. if (pBuffer == NULL)
  589. {
  590. return hr;
  591. }
  592. if ((hr = DecryptDataA(pBuffer, &szData)) == S_OK)
  593. {
  594. *szOutData = _PEConvertA2W (szData, CP_ACP);
  595. if ((*szOutData) == NULL)
  596. {
  597. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  598. }
  599. GlobalFree(szData);
  600. }
  601. GlobalFree(pBuffer);
  602. return hr;
  603. }
  604. #define _SECOND ((__int64) 10000000)
  605. #define _MINUTE (60 * _SECOND)
  606. #define _HOUR (60 * _MINUTE)
  607. #define _DAY (24 * _HOUR)
  608. // encode the position of the PID character. 0 is for the dashes
  609. int iPID[] = {3 ,251,43 ,89 ,75,0,
  610. 123,35 ,23 ,97 ,77,0,
  611. 5 ,135,189,213,13,0,
  612. 245,111,91 ,71 ,65,0,
  613. 25 ,49 ,81 ,129,239};
  614. int iTime1[] = {253, 247, 233, 221, 211, 191, 181, 171, 161, 151, 141, 131, 121, 112, 101, 93, 80, 70, 61, 51};
  615. int iTime2[] = {250, 242, 237, 225, 215, 195, 185, 175, 165, 155, 145, 137, 125, 115, 105, 95, 85, 73, 67, 55};
  616. HRESULT PrepareEncryptedPIDA(LPSTR szPID, UINT uiDays, LPSTR *szOut)
  617. {
  618. HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  619. HCRYPTPROV hCryptProv;
  620. FILETIME ft1, ft2;
  621. LONGLONG ll;
  622. LONGLONG ll2;
  623. char szLine[256];
  624. GetSystemTimeAsFileTime(&ft1);
  625. ll = ((LONGLONG)ft1.dwHighDateTime << 32) + ft1.dwLowDateTime;
  626. ll2 = ll - (_HOUR*12); // Substract 12 hours
  627. ll += (uiDays*_DAY) + (_HOUR*24); // Add 24 hours
  628. ft1.dwLowDateTime = (DWORD)ll2;
  629. ft1.dwHighDateTime = (DWORD)(ll2 >> 32);
  630. ft2.dwLowDateTime = (DWORD)ll;
  631. ft2.dwHighDateTime = (DWORD)(ll >> 32);
  632. // Build a 256 character string that we encode. In the 256 character strign we hide
  633. // the PID and the time/date info for the interval the encypted data is valid.
  634. // We need 20 characters each for the start and end of the time interval
  635. // and we need 25 characters for the PID. 20+20+25 = 65 characters. All other characters
  636. // are random.
  637. // 1. fill the string with random characters
  638. // 2. replace some with the PID charactes
  639. // 3. replace some with the time/date info
  640. if(CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  641. {
  642. int i;
  643. hr = S_OK;
  644. if(!CryptGenRandom(hCryptProv, sizeof(szLine), (PBYTE)szLine))
  645. {
  646. hr = GetLastError();
  647. }
  648. CryptReleaseContext(hCryptProv, 0);
  649. // in the case the random generator create 0x0 we want to replace it with
  650. // some value, otherwise we cannot use it as a character string,
  651. // the string would be terminated.
  652. for (i = 0; i < sizeof(szLine); i++)
  653. {
  654. if (szLine[i] == '\0')
  655. {
  656. szLine[i] = 0x01;
  657. }
  658. }
  659. szLine[i-1] = '\0'; // Make sure we have a terminated string.
  660. }
  661. if (hr == S_OK)
  662. {
  663. char szTime[21]; // 10 digits for dwHighDateTime and 10 for dwLowDateTime + termination
  664. // The buffer is filled with random characters
  665. // Now insert the PID characters
  666. int i = 0;
  667. while (szPID[i])
  668. {
  669. if (szPID[i] != '-')
  670. {
  671. szLine[iPID[i]] = szPID[i];
  672. }
  673. i++;
  674. }
  675. // Now fill in the time-date info
  676. wsprintf(szTime, "%010lu%010lu", ft1.dwHighDateTime, ft1.dwLowDateTime);
  677. i = 0;
  678. while (szTime[i])
  679. {
  680. szLine[iTime1[i]] = szTime[i];
  681. i++;
  682. }
  683. wsprintf(szTime, "%010lu%010lu", ft2.dwHighDateTime, ft2.dwLowDateTime);
  684. i = 0;
  685. while (szTime[i])
  686. {
  687. szLine[iTime2[i]] = szTime[i];
  688. i++;
  689. }
  690. // szLine has the mengled data in it. Pass it to the encryption.
  691. hr = EncryptDataA(szLine, sizeof(szLine), szOut);
  692. }
  693. return hr;
  694. }
  695. HRESULT PrepareEncryptedPIDW(LPWSTR szPID, UINT uiDays, LPWSTR *szOutData)
  696. {
  697. HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  698. LPSTR pPID = NULL;
  699. LPSTR szOut = NULL;
  700. *szOutData = NULL;
  701. pPID = _PEConvertW2A (szPID, CP_ACP);
  702. if (pPID != NULL)
  703. {
  704. hr = PrepareEncryptedPIDA(pPID, uiDays, &szOut);
  705. if (hr == S_OK)
  706. {
  707. *szOutData = _PEConvertA2W (szOut, CP_ACP);
  708. if (*szOutData)
  709. {
  710. hr = S_OK;
  711. }
  712. else
  713. {
  714. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  715. }
  716. GlobalFree(szOut);
  717. }
  718. GlobalFree(pPID);
  719. }
  720. return hr;
  721. }
  722. HRESULT ValidateEncryptedPIDA(LPSTR PID, LPSTR *szOutData)
  723. {
  724. HRESULT hr = E_FAIL;
  725. LPSTR szDecrypt = NULL;
  726. FILETIME ft, ftCurrent;
  727. LONGLONG ll1, ll2, llCurrent;
  728. int iCount = 0;
  729. char szPID[(5*5)+5]; // 5 characters 5 times + '-' inbetween + termimation
  730. char szTime[11]; // each part of hte time is 10 digits + termination
  731. GetSystemTimeAsFileTime(&ftCurrent);
  732. hr = DecryptDataA(PID, &szDecrypt);
  733. if (hr == S_OK)
  734. {
  735. int i = 0;
  736. hr = 0x01;
  737. // Extract the time values first.
  738. while (i < 10)
  739. {
  740. szTime[i] = szDecrypt[iTime1[i]];
  741. i++;
  742. }
  743. szTime[10] = '\0';
  744. if (OnlyDigits(szTime)) // 1. time
  745. {
  746. ft.dwHighDateTime = MyAtoL(szTime);
  747. while (i < 20)
  748. {
  749. szTime[i-10] = szDecrypt[iTime1[i]];
  750. i++;
  751. }
  752. szTime[10] = '\0';
  753. if (OnlyDigits(szTime))
  754. {
  755. ft.dwLowDateTime = MyAtoL(szTime);
  756. ll1 = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
  757. ll1 = ll1 /_HOUR; // FileTime in hours;
  758. hr = S_OK;
  759. }
  760. }
  761. if (hr == S_OK)
  762. {
  763. hr = 0x02;
  764. i = 0;
  765. while (i < 10)
  766. {
  767. szTime[i] = szDecrypt[iTime2[i]];
  768. i++;
  769. }
  770. szTime[10] = '\0';
  771. if (OnlyDigits(szTime)) // 1. time
  772. {
  773. ft.dwHighDateTime = MyAtoL(szTime);
  774. while (i < 20)
  775. {
  776. szTime[i-10] = szDecrypt[iTime2[i]];
  777. i++;
  778. }
  779. szTime[10] = '\0';
  780. if (OnlyDigits(szTime))
  781. {
  782. ft.dwLowDateTime = MyAtoL(szTime);
  783. ll2 = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
  784. ll2 = ll2 /_HOUR; // FileTime in hours;
  785. hr = S_OK;
  786. }
  787. }
  788. }
  789. if (hr == S_OK)
  790. {
  791. // Now that we have the time values, compare them and make sure that the current
  792. // time falls inside the time interval.
  793. hr = 0x03;
  794. llCurrent = ((LONGLONG)ftCurrent.dwHighDateTime << 32) + ftCurrent.dwLowDateTime;
  795. llCurrent = llCurrent /_HOUR; // FileTime in hours;
  796. if ((ll1 <= llCurrent) && ( llCurrent <= ll2))
  797. {
  798. i = 0;
  799. // Time is OK.
  800. // Extract the PID
  801. while (i < sizeof(iPID)/sizeof(iPID[0]))
  802. {
  803. if (iPID[i] != 0)
  804. {
  805. szPID[i] = szDecrypt[iPID[i]];
  806. }
  807. else
  808. {
  809. szPID[i] = '-';
  810. }
  811. i++;
  812. }
  813. szPID[i] = '\0';
  814. *szOutData = (LPSTR)GlobalAlloc(GPTR, lstrlen(szPID)+1);
  815. if (*szOutData)
  816. {
  817. lstrcpy(*szOutData, szPID);
  818. hr = S_OK;
  819. }
  820. }
  821. }
  822. }
  823. if (szDecrypt)
  824. {
  825. GlobalFree(szDecrypt);
  826. }
  827. return hr;
  828. }
  829. HRESULT ValidateEncryptedPIDW(LPWSTR szPID, LPWSTR *szOutData)
  830. {
  831. HRESULT hr = E_FAIL;
  832. LPSTR szData = NULL;
  833. LPSTR pPid = NULL;
  834. pPid = (LPBYTE)_PEConvertW2A (szPID, CP_ACP);
  835. if (pPid != NULL)
  836. {
  837. if ((hr = ValidateEncryptedPIDA(pPid, &szData)) == S_OK)
  838. {
  839. *szOutData = _PEConvertA2W (szData, CP_ACP);
  840. if (*szOutData)
  841. {
  842. hr = S_OK;
  843. }
  844. else
  845. {
  846. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  847. }
  848. GlobalFree(szData);
  849. }
  850. GlobalFree(pPid);
  851. }
  852. else
  853. {
  854. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  855. }
  856. return hr;
  857. }
  858. #if 0
  859. void
  860. _stdcall
  861. ModuleEntry(
  862. VOID
  863. )
  864. {
  865. CHAR szInData[256];
  866. CHAR szPID[] = "Ctpdw-6q4d3-wrgdy-796g2-9vrmq";
  867. LPSTR szOutData = NULL;
  868. CHAR *szDecrypt = NULL;
  869. #if 0
  870. SYSTEMTIME CurrentTime;
  871. SYSTEMTIME UniversalTime;
  872. GetLocalTime(&UniversalTime);
  873. wsprintf( szInData, "%s$%02d-%02d-%04d %02d:%02d:%02d",
  874. szPID,
  875. UniversalTime.wMonth,
  876. UniversalTime.wDay,
  877. UniversalTime.wYear,
  878. UniversalTime.wHour,
  879. UniversalTime.wMinute,
  880. UniversalTime.wSecond);
  881. WritePrivateProfileStringA("UserData","ProductID", szInData, "f:\\test.ini");
  882. EncryptDataA((LPSTR)szInData, sizeof(szInData), &szOutData);
  883. if (szOutData)
  884. {
  885. WritePrivateProfileStringA("UserData","ProductIDEncryped", szOutData, "f:\\test.ini");
  886. DecryptDataA(szOutData, &szDecrypt);
  887. if (lstrcmpA(szInData, szDecrypt) == 0)
  888. {
  889. WritePrivateProfileStringA("UserData","Compare", "Same", "f:\\test.ini");
  890. }
  891. else
  892. {
  893. WritePrivateProfileStringA("UserData","Compare", "Different", "f:\\test.ini");
  894. }
  895. GlobalFree ((PVOID)szOutData);
  896. if (szDecrypt)
  897. {
  898. WritePrivateProfileStringA("UserData","ProductIDDecypted", szDecrypt, "f:\\test.ini");
  899. GlobalFree ((PVOID)szDecrypt);
  900. }
  901. }
  902. #else
  903. WritePrivateProfileStringA("UserData","ProductID", szPID, "f:\\test.ini");
  904. if (PrepareEncryptedPIDA(szPID, 5, &szOutData) == S_OK)
  905. {
  906. WritePrivateProfileStringA("UserData","ProductIDEncryped", szOutData, "f:\\test.ini");
  907. if (ValidateEncryptedPIDA(szOutData, &szDecrypt) == S_OK)
  908. {
  909. WritePrivateProfileStringA("UserData","ProductIDDecypted", szDecrypt, "f:\\test.ini");
  910. }
  911. }
  912. #endif
  913. }
  914. #endif