CRP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:66k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright 1996-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. // CRP.C
  11. #include "cfiler.h"
  12. HCRYPTPROV hMe;
  13. ALG_ID AlgidEncrypt;
  14. ALG_ID AlgidSign;
  15. TCHAR sPass[BUF_SIZE];
  16. TCHAR szPassName[BUF_SIZE];
  17. extern HANDLE   ghModule; 
  18. extern HMENU ghMenu;                                                                     
  19. /************************************************************************
  20. * EnterPass()
  21. *
  22. * Dialog procedure for the "PASSWORD" dialog box.
  23. *
  24. * Stores the password entered by the user into 
  25. * the global buffer sPass
  26. ************************************************************************/
  27. WINAPI EnterPass(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam)  {
  28. TCHAR szMessage[BUF_SIZE];
  29. switch(wMsgID) {
  30. case WM_INITDIALOG:
  31. lstrcpy(szMessage, TEXT("Enter password: "));
  32. lstrcat(szMessage, szPassName);
  33. SetDlgItemText(hDlg, IDC_PASSTEXT, szMessage);
  34. SetDlgItemText(hDlg, IDC_EDIT1, TEXT(""));
  35. SetDlgItemText(hDlg, IDC_EDIT2, TEXT(""));
  36. return FALSE;
  37. case WM_COMMAND:
  38. switch(LOWORD(wParam)) {
  39. TCHAR szVerify[BUF_SIZE];
  40. case IDOK:
  41. if (!GetDlgItemText(hDlg, IDC_EDIT1, sPass, BUF_SIZE)) {
  42.                  if (MessageBox(hDlg, TEXT("No password entered."), NULL, MB_OK) == IDOK) {
  43. EndDialog(hDlg, FALSE);
  44. return FALSE;
  45. }
  46. }
  47.                 
  48. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  49. if (!GetDlgItemText(hDlg, IDC_EDIT2, szVerify, BUF_SIZE)) {
  50. MessageBox(hDlg, TEXT("No password entered."), NULL, MB_OK);
  51. EndDialog(hDlg, FALSE);
  52. return FALSE;
  53. }
  54. if (lstrcmp(sPass, szVerify)) {
  55. MessageBox(hDlg, TEXT("Could not verify password."), NULL, MB_OK);
  56. EndDialog(hDlg, FALSE);
  57. return FALSE;
  58. }
  59. EndDialog(hDlg, TRUE);
  60. return TRUE;
  61. case IDCANCEL:
  62. EndDialog(hDlg, -1);
  63. return -1;
  64. default:
  65. return FALSE;
  66. }
  67. break;
  68. }
  69. return FALSE;
  70. }
  71. /************************************************************************
  72. * CryptDlgProc()
  73. *
  74. * Dialog procedure for all dialog boxes of the
  75. * application besides "PASSWORD", "ENCRYPTION_ALGORITHM,"
  76. * and "HASH_ALGORITHM."
  77. ************************************************************************/
  78. LRESULT WINAPI CryptDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  79. switch(wMsgID) {
  80. case WM_INITDIALOG:
  81. return FALSE;
  82. case WM_COMMAND:
  83. switch(LOWORD(wParam)) {
  84. case IDOK:
  85. EndDialog(hDlg, TRUE);
  86. return TRUE;
  87. case IDCANCEL:
  88. EndDialog(hDlg, FALSE);
  89. return TRUE;
  90. default:
  91. return FALSE;
  92. }
  93. break;
  94. }
  95. return FALSE;
  96. }
  97. /************************************************************************
  98. * EncryptDlgProc()
  99. *
  100. * Dialog procedure for "ENCRYPTION_ALGORITHM" dialog box.
  101. ************************************************************************/
  102. LRESULT WINAPI EncryptDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  103. switch(wMsgID) {
  104. case WM_INITDIALOG:
  105. if (AlgidEncrypt == CALG_RC4)
  106. CheckRadioButton(hDlg, IDC_RC2, IDC_RC4, IDC_RC4);
  107. else
  108. CheckRadioButton(hDlg, IDC_RC2, IDC_RC4, IDC_RC2);
  109. return FALSE;
  110. case WM_COMMAND:
  111. switch(LOWORD(wParam)) {
  112. case IDC_RC2:
  113. AlgidEncrypt = CALG_RC2;
  114. return TRUE;
  115. case IDC_RC4:
  116. AlgidEncrypt = CALG_RC4;
  117. return TRUE;
  118. case IDOK:
  119. if (!AlgidEncrypt)
  120. AlgidEncrypt = CALG_RC2;
  121. EndDialog(hDlg, TRUE);
  122. return TRUE;
  123. case IDCANCEL:
  124. EndDialog(hDlg, FALSE);
  125. return TRUE;
  126. default:
  127. return FALSE;
  128. }
  129. break;
  130. }
  131. return FALSE;
  132. }
  133. /************************************************************************
  134. * HashDlgProc()
  135. *
  136. * Dialog procedure for "HASH_ALGORITHM" dialog box
  137. ************************************************************************/
  138. LRESULT WINAPI HashDlgProc(HWND hDlg, UINT wMsgID, UINT wParam, LPARAM lParam) {
  139. switch(wMsgID) {
  140. case WM_INITDIALOG:
  141. if (AlgidSign == CALG_SHA)
  142. CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_SHA);
  143. else if (AlgidSign == CALG_MD5)
  144. CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_MD5);
  145. else
  146. CheckRadioButton(hDlg, IDC_MD4, IDC_SHA, IDC_MD4);
  147. return FALSE;
  148. case WM_COMMAND:
  149. switch(LOWORD(wParam)) {
  150. case IDC_MD4:
  151. AlgidSign = CALG_MD4;
  152. return TRUE;
  153. case IDC_MD5:
  154. AlgidSign = CALG_MD5;
  155. return TRUE;
  156. case IDC_SHA:
  157. AlgidSign = CALG_SHA;
  158. return TRUE;
  159. case IDOK:
  160. EndDialog(hDlg, TRUE);
  161. return TRUE;
  162. case IDCANCEL:
  163. EndDialog(hDlg, FALSE);
  164. return TRUE;
  165. default:
  166. return FALSE;
  167. }
  168. break;
  169. }
  170. return FALSE;
  171. }
  172. /************************************************************************
  173. * GetPass()
  174. *
  175. * input:
  176. * hWnd - HWND of caller
  177. *
  178. * purpose:
  179. * Creates a dialog box prompting the user to enter a password.
  180. *
  181. * returns:
  182. * TRUE if successful
  183. * FALSE if unsuccessful
  184. ************************************************************************/
  185. BOOL GetPass(HWND hWnd) {
  186. INT bRet = 0;
  187. do {
  188. if (bRet == -1)
  189. break;
  190. // Prompt the user to enter a password.
  191. bRet = DialogBox(ghModule, TEXT("PASSWORD"), hWnd, EnterPass);
  192. } while (!bRet || !lstrcmp(sPass, TEXT("")) || !lstrcmp(sPass, TEXT("")));
  193. AlgidEncrypt = 0;
  194. return TRUE;
  195. }
  196. /************************************************************************
  197. * GetfnKey()
  198. *
  199. * purpose:
  200. * Retrieves fnKey from the registry.
  201. * fnKey is used to encrypt and decrypt filenames.
  202. * If fnKey does not exist in the registry, GetfnKey creates it.
  203. *
  204. * returns
  205. * a valid key if successful
  206. * 0 if unsuccessful.
  207. ************************************************************************/
  208. HCRYPTKEY GetfnKey(HWND hWnd) {
  209. BYTE  pbFileKeyBlob[BUF_SIZE];
  210. DWORD  dwFileBlobLen = BUF_SIZE;
  211. LONG lRv;
  212. HKEY hKey;
  213. DWORD dwType;
  214. DWORD dwSize;
  215. DWORD dwDisposition;
  216. HCRYPTKEY phEncryptPubKey;
  217. HCRYPTKEY hfnKey;
  218. if (!GetEncryptPublicKey(hWnd, &phEncryptPubKey)) {
  219. ErrorMsg(TEXT("GetfnKey: GetEncryptPublicKey failed."));
  220. return (HCRYPTKEY)0;
  221. }
  222. #ifdef WIN95
  223. lRv = RegOpenKeyEx(HKEY_CURRENT_USER, 
  224.      TEXT("SOFTWARE\Microsoft\Cryptfiler.ini"), 
  225.    0, 
  226.    KEY_ALL_ACCESS,
  227.    &hKey);
  228. #else
  229. lRv = RegOpenKeyEx(HKEY_CURRENT_USER, 
  230.      TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\Cryptfiler.ini"), 
  231.    0, 
  232.    KEY_ALL_ACCESS,
  233.    &hKey);
  234. #endif
  235. if (lRv != ERROR_SUCCESS) {
  236. // not in registry; we must create.
  237. #ifdef WIN95
  238. lRv = RegCreateKeyEx(HKEY_CURRENT_USER, 
  239.    TEXT("SOFTWARE\Microsoft\Cryptfiler.ini"), 
  240.  0, 
  241.  NULL, 
  242.  REG_OPTION_NON_VOLATILE,
  243.  KEY_ALL_ACCESS,
  244.  NULL,
  245.  &hKey,
  246.  &dwDisposition);
  247. #else
  248. lRv = RegCreateKeyEx(HKEY_CURRENT_USER, 
  249.    TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\Cryptfiler.ini"), 
  250.  0, 
  251.  NULL, 
  252.  REG_OPTION_NON_VOLATILE,
  253.  KEY_ALL_ACCESS,
  254.  NULL,
  255.  &hKey,
  256.  &dwDisposition);
  257. #endif
  258. if (lRv != ERROR_SUCCESS) {
  259. ErrorMsg(TEXT("GetfnKey: RegCreateKeyEx failed."));
  260. return (HCRYPTKEY)0;
  261. }
  262. if (RCRYPT_FAILED(CryptGenKey(hMe, CALG_RC4, CRYPT_EXPORTABLE, &hfnKey))) {
  263. ErrorMsg(TEXT("GetfnKey: CryptGenKey failed."));
  264. return (HCRYPTKEY)0;
  265. //Export the key so that it can be stored in the registry.
  266. if (RCRYPT_FAILED(CryptExportKey(hfnKey, 
  267.   phEncryptPubKey, 
  268.   SIMPLEBLOB, 
  269.   0, 
  270.   pbFileKeyBlob, 
  271.   &dwFileBlobLen))) {
  272. ErrorMsg(TEXT("GetfnKey: CryptExportKey failed."));
  273. return (HCRYPTKEY)0;
  274. }
  275. // Store the key blob in the registry.
  276. if (RegSetValueEx(hKey,
  277.   TEXT("fnKey"),
  278.   0,
  279.   REG_BINARY,
  280.   pbFileKeyBlob,
  281.   dwFileBlobLen * sizeof(*pbFileKeyBlob)) != ERROR_SUCCESS) {
  282. ErrorMsg(TEXT("GetfnKey: RegSetValueEx failed."));
  283. return (HCRYPTKEY)0;
  284. }
  285. }
  286. else {
  287. // in registry. We must extract.
  288. dwType = 0;
  289. dwFileBlobLen = 0;
  290. dwSize = BUF_SIZE;
  291. if (RegQueryValueEx(hKey, 
  292. TEXT("fnKey"),
  293. NULL, 
  294. &dwType, 
  295. pbFileKeyBlob, 
  296. &dwSize) != ERROR_SUCCESS)
  297. {
  298. MessageBox(hWnd, TEXT("GetfnKey: RegQueryValueEx failed querrying pbFileKeyBlob."), NULL, MB_OK);
  299. return (HCRYPTKEY)0;
  300. };
  301. // Read the key blob from the disk into a Buf.
  302. if (!dwSize || (dwSize > BUF_SIZE)) {
  303. ErrorMsg(TEXT("GetfnKey: dwSize is not in acceptable range."));
  304. return FALSE;
  305. }
  306. // Import the key whose blob is contained in the Buf pbDecryptBlob
  307. dwFileBlobLen = dwSize;
  308. if (RCRYPT_FAILED(CryptImportKey(hMe, 
  309.   pbFileKeyBlob, 
  310.   dwFileBlobLen, 
  311.   0, 
  312.   0,
  313.   &hfnKey))) {
  314. MessageBox(hWnd, TEXT("GetfnKey: CryptImportKey failed"), NULL, MB_OK);
  315. return (HCRYPTKEY)0;
  316. }
  317. }
  318. return hfnKey;
  319. }
  320. /************************************************************************
  321. * Logon()
  322. *
  323. * input:
  324. * hWnd - HWND of caller
  325. *
  326. * purpose:
  327. * Creates a dialog box which says "Performing context acquisition."
  328. * Calls CryptAcquireContext.
  329. * Destroys the dialog box
  330. *
  331. * returns:
  332. * TRUE if successful
  333. * FALSE if unsuccessful
  334. ************************************************************************/
  335. BOOL Logon(HWND hWnd) {
  336. HWND hwndDlg;
  337. TCHAR pszName[64];
  338. pszName[0] = TEXT('');
  339. hwndDlg = CreateDialog(ghModule, TEXT("ACQUIRE_CONTEXT"), hWnd, CryptDlgProc);
  340. if (!hwndDlg) {
  341. ErrorMsg(TEXT("Logon: CreateDialog failed."));
  342. return FALSE;
  343. }
  344. if (RCRYPT_FAILED(CryptAcquireContext(&hMe, pszName, MS_DEF_PROV, PROV_RSA_FULL, 0))) {
  345. if (RCRYPT_FAILED(CryptAcquireContext(&hMe, 
  346.   pszName, 
  347.   TEXT(MS_DEF_PROV), 
  348.   PROV_RSA_FULL, 
  349.   CRYPT_NEWKEYSET))) {
  350. EndDialog(hwndDlg, FALSE);
  351. MessageBox(hWnd, TEXT("Logon: CryptAcquireContext failed."), NULL, MB_OK);
  352. return FALSE;
  353. }
  354. }
  355. EndDialog(hwndDlg, FALSE);
  356. return TRUE;
  357. return FALSE;
  358. }
  359. /************************************************************************
  360. * Logoff()
  361. *
  362. * input:
  363. * hWnd - HWND of caller
  364. *
  365. * purpose:
  366. * Calls CryptReleaseContext.
  367. *
  368. * returns:
  369. * TRUE if successful
  370. * FALSE if unsuccessful
  371. ************************************************************************/
  372. BOOL Logoff(HWND hWnd) 
  373. {
  374. if (hMe) {
  375. if (RCRYPT_FAILED(CryptReleaseContext(hMe, 0))) {
  376.          ErrorMsg(TEXT("Logoff: CryptReleaseContext failed."));
  377.          return FALSE;
  378.      }
  379. }
  380. else {
  381. ErrorMsg(TEXT("Logoff: hMe is NULL."));
  382. return FALSE;
  383. }
  384. return TRUE;
  385. }
  386. /************************************************************************
  387. * GetEncryptPublicKey()
  388. *
  389. * input:
  390. * hWnd - HWND specified by caller
  391. * phEncryptPubKey - address to store key
  392. *
  393. * purpose: calls CryptGetUserKey to obtain the AT_KEYEXCHANGE public
  394. * key.
  395. *
  396. * returns:
  397. * TRUE if successful
  398. * FALSE if unsuccessful
  399. ************************************************************************/
  400. BOOL GetEncryptPublicKey(HWND hWnd, HCRYPTKEY *phEncryptPubKey) {
  401. if (!phEncryptPubKey) {
  402. ErrorMsg(TEXT("GetEncryptPubKey: phEncryptPubKey is NULL."));
  403. return FALSE;
  404. }
  405. if (RCRYPT_FAILED(CryptGetUserKey(hMe, AT_KEYEXCHANGE, phEncryptPubKey))) {
  406. if (RCRYPT_FAILED(CryptGenKey(hMe, AT_KEYEXCHANGE, 0, phEncryptPubKey))) {
  407. ErrorMsg(TEXT("GetEncryptPublicKey: CryptGenKey failed."));
  408. return TRUE;
  409. }
  410. }
  411. return TRUE;
  412. }
  413. /************************************************************************
  414. * GetSignaturePublicKey()
  415. *
  416. * input:
  417. * hWnd - HWND specified by caller
  418. * phSignaturePubKey - address to store key
  419. *
  420. * purpose: calls CryptGetUserKey to obtain the AT_SIGNATURE public
  421. * key.
  422. *
  423. * returns:
  424. * TRUE if successful
  425. * FALSE if unsuccessful
  426. ************************************************************************/
  427. BOOL GetSignaturePublicKey(HWND hWnd, HCRYPTKEY *phSignaturePubKey) {
  428. if (!phSignaturePubKey) {
  429. ErrorMsg(TEXT("GetSignaturePublicKey: phSignaturePubKey is NULL."));
  430. return FALSE;
  431. }
  432. if (RCRYPT_FAILED(CryptGetUserKey(hMe, AT_SIGNATURE, phSignaturePubKey))) {
  433. if (RCRYPT_FAILED(CryptGenKey(hMe, AT_SIGNATURE, 0, phSignaturePubKey))) {
  434. ErrorMsg(TEXT("GetSignaturePublicKey: CryptGenKey failed."));
  435. return FALSE;
  436. }
  437. }
  438. return TRUE;
  439. }
  440. /************************************************************************
  441. * MakeHashDirectory()
  442. *
  443. * purpose: 
  444. * Creates the directory sig on the same drive as the 
  445. * system directory as a hidden directory if
  446. * it doesn't exist and checks the menu item ID_HIDE.
  447. * If it does exist and it is hidden it checks the menu item ID_HIDE.
  448. * If it does exist and it is not hidden it sets the menu item ID_HIDE
  449. * to be unchecked.
  450. *
  451. * returns: 
  452. * TRUE if successful
  453. * FALSE if unsuccessful
  454. ************************************************************************/
  455. BOOL MakeHashDirectory(VOID) {
  456. DWORD dwFileAttributes;
  457. TCHAR szSigDir[PATH_SIZE];
  458. GetSigDir(szSigDir);
  459. // Does this directory exist?
  460. if (GetFileAttributes(szSigDir) == 0xFFFFFFFF) {
  461. // Create the directory
  462. if (!CreateDirectory(szSigDir, NULL)) {
  463. ErrorMsg(TEXT("MakeHashDirectory: CreateDirectory failed."));
  464. return FALSE;
  465. }
  466. // Make the directory hidden
  467. if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN)) {
  468. ErrorMsg(TEXT("Another process is using the \sig directory."));
  469. return FALSE;
  470. }
  471. }
  472. dwFileAttributes = GetFileAttributes(szSigDir);
  473. // Toggle the "Hide Signatures" menu item appropriately.
  474. if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
  475.        CheckMenuItem(ghMenu, ID_HIDE, MF_CHECKED);
  476.     else
  477.      CheckMenuItem(ghMenu, ID_HIDE, MF_UNCHECKED);
  478.       
  479.     return TRUE;
  480. }
  481. /************************************************************************
  482. * DeleteHashDirectory()
  483. *
  484. * purpose: 
  485. * Deletes the directory sig on the same drive as the system directory
  486. * if the sig directory is empty. This function is called when the
  487. * application terminates.
  488. *
  489. * returns: 
  490. * TRUE if successful
  491. * FALSE if unsuccessful
  492. ************************************************************************/
  493. BOOL DeleteHashDirectory(VOID) {
  494. TCHAR szSigDir[PATH_SIZE];
  495. TCHAR szFiles[PATH_SIZE];
  496. WIN32_FIND_DATA FindFileData;
  497. HANDLE hFindFile;
  498. GetSigDir(szSigDir);
  499. lstrcpy(szFiles, szSigDir);
  500. lstrcat(szFiles, TEXT("\*"));
  501. // Does this directory exist?
  502. if (GetFileAttributes(szSigDir) == 0xFFFFFFFF) {
  503. return TRUE;
  504. }
  505. hFindFile = FindFirstFile(szFiles, &FindFileData);
  506. FindNextFile(hFindFile, &FindFileData);
  507. if (!FindNextFile(hFindFile, &FindFileData)) {
  508. FindClose(hFindFile);
  509. SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  510. if (!RemoveDirectory(szSigDir)) {
  511. ErrorMsg(TEXT("DeleteHashDirectory: RemoveDirectory failed."));
  512. return FALSE;
  513. }
  514. }
  515. else      
  516.      FindClose(hFindFile);
  517.     
  518.     return TRUE;
  519. }
  520. /************************************************************************
  521. * HideSignatures()
  522. *
  523. * purpose:
  524. * Hides the directory sig and its contents
  525. *
  526. * returns
  527. * TRUE if successful
  528. * FALSE if unsuccessful
  529. ************************************************************************/
  530. BOOL HideSignatures(VOID) {
  531. WIN32_FIND_DATA FindFileData;
  532. HANDLE hFindFile;
  533. TCHAR szFiles[PATH_SIZE];
  534. TCHAR szFileName[PATH_SIZE];
  535. TCHAR szSigDir[PATH_SIZE];
  536. GetSigDir(szSigDir);
  537. lstrcpy(szFiles, szSigDir);
  538. lstrcat(szFiles, TEXT("\*"));
  539. // hide the directory.
  540. if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN)) {
  541. ErrorMsg(TEXT("Another process is using the \sig directory."));
  542. return FALSE;
  543. }
  544. hFindFile = FindFirstFile(szFiles, &FindFileData);
  545. if (hFindFile == INVALID_HANDLE_VALUE) {
  546. SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  547. return FALSE;
  548. }
  549. // Hide all the signature files.
  550. do {
  551. lstrcpy(szFileName, szSigDir);
  552. lstrcat(szFileName, TEXT("\"));
  553. lstrcat(szFileName, FindFileData.cFileName);
  554. if (!CFilerIsDirectory(szFileName)) {
  555. if (!SetFileAttributes(szFileName, FILE_ATTRIBUTE_HIDDEN)) {
  556. SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL);
  557. FindClose(hFindFile);
  558. ErrorMsg(TEXT("Another process is using a signature file."));
  559. return FALSE;
  560. }
  561. }
  562. } while (FindNextFile(hFindFile, &FindFileData) 
  563. || GetLastError() != ERROR_NO_MORE_FILES);
  564. FindClose(hFindFile);
  565. return TRUE;
  566. }
  567. /************************************************************************
  568. * ShowSignatures()
  569. *
  570. * purpose:
  571. * "unhides" the directory sig and its contents
  572. *
  573. * returns
  574. * TRUE if successful
  575. * FALSE if unsuccessful
  576. ************************************************************************/
  577. BOOL ShowSignatures(VOID) {
  578. WIN32_FIND_DATA FindFileData;
  579. HANDLE hFindFile;
  580. TCHAR szFiles[PATH_SIZE];
  581. TCHAR szFileName[PATH_SIZE];
  582. TCHAR szSigDir[PATH_SIZE];
  583. GetSigDir(szSigDir);
  584. lstrcpy(szFiles, szSigDir);
  585. lstrcat(szFiles, TEXT("\*"));
  586. // unhide the directory
  587. if (!SetFileAttributes(szSigDir, FILE_ATTRIBUTE_NORMAL)) {
  588. ErrorMsg(TEXT("Another process is using the \sig directory."));
  589. return FALSE;
  590. }
  591. hFindFile = FindFirstFile(szFiles, &FindFileData);
  592. if (hFindFile == INVALID_HANDLE_VALUE) {
  593. SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN);
  594. return FALSE;
  595. }
  596. // unhide all the signature files.
  597. do {
  598. lstrcpy(szFileName, szSigDir);
  599. lstrcat(szFileName, TEXT("\"));
  600. lstrcat(szFileName, FindFileData.cFileName);
  601. if (!CFilerIsDirectory(szFileName)) {
  602. if (!SetFileAttributes(szFileName, FILE_ATTRIBUTE_NORMAL)) {
  603. SetFileAttributes(szSigDir, FILE_ATTRIBUTE_HIDDEN);
  604. FindClose(hFindFile);
  605. ErrorMsg(TEXT("Another process is using a signature file."));
  606. return FALSE;
  607. }
  608. }
  609. } while (FindNextFile(hFindFile, &FindFileData) 
  610. || GetLastError() != ERROR_NO_MORE_FILES);
  611. FindClose(hFindFile);
  612. return TRUE;
  613. }
  614. /************************************************************************
  615. * c2r64()
  616. *
  617. * input:
  618. * i - integer value to be converted to a radix64 character
  619. * c - address where character is to be stored
  620. *
  621. * purpose:
  622. * converts an integer between 0 and 63 to a character.
  623. * 0-25 -> A-Z
  624. * 26 - 51 -> a-z
  625. * 52 - 61 -> 0-9
  626. * 62 -> +
  627. * 63 -> _
  628. *
  629. * returns:
  630. * TRUE if successful
  631. * FALSE if unsuccessful
  632. ************************************************************************/
  633. BOOL c2r64(INT i, LPTSTR c) {
  634. if (!c) {
  635. ErrorMsg(TEXT("c2r64: c is NULL."));
  636. return FALSE;
  637. }
  638. if (0 <= i && i <= 25)
  639. *c = TEXT('A') + i;
  640. else if (26 <= i && i <= 51)
  641. *c = TEXT('a') + i - 26;
  642. else if (52 <= i && i <= 61)
  643. *c = TEXT('0') + i - 52;
  644. else if (i == 62)
  645. *c = TEXT('+');
  646. else if (i == 63)
  647. *c = TEXT('_');
  648. else {
  649. ErrorMsg(TEXT("c2r64: c is not between 0 and 63."));
  650. return FALSE;
  651. }
  652. return TRUE;
  653. }
  654. /************************************************************************
  655. * SHAtoRadix64 takes as input a SHA_SIZE-byte hash of the full 
  656. * pathname of a file. It produces a 27-byte "Radix64" 
  657. * representation of the hash, where each byte in the
  658. * "Radix64" representation is between 0 and 2^6.
  659. * It pretends that the SHZ_SIZE + 1st input byte is NULL.
  660. ************************************************************************/
  661. BOOL SHAtoRadix64(LPBYTE pbPathHash, LPTSTR szFileName) {
  662. INT i, j;
  663. TCHAR c1 = 0, c2 = 0, c3 = 0, c4 = 0;
  664. if (!pbPathHash) {
  665. ErrorMsg(TEXT("SHAtoRadix64: pbPathHash is NULL."));
  666. return FALSE;
  667. }
  668. if (!szFileName) {
  669. ErrorMsg(TEXT("SHAtoRadix64: szFileName is NULL."));
  670. return FALSE;
  671. }
  672. for (i = 0, j = 0; i < 18 && j < 24; i += 3, j += 4) {
  673. c1 = c1 | (((pbPathHash[i + 0] >> 7) & 1) << 5);
  674. c1 = c1 | (((pbPathHash[i + 0] >> 6) & 1) << 4);
  675. c1 = c1 | (((pbPathHash[i + 0] >> 5) & 1) << 3);
  676. c1 = c1 | (((pbPathHash[i + 0] >> 4) & 1) << 2);
  677. c1 = c1 | (((pbPathHash[i + 0] >> 3) & 1) << 1);
  678. c1 = c1 | (((pbPathHash[i + 0] >> 2) & 1) << 0);
  679. c2 = c2 | (((pbPathHash[i + 0] >> 1) & 1) << 5);
  680. c2 = c2 | (((pbPathHash[i + 0] >> 0) & 1) << 4);
  681. c2 = c2 | (((pbPathHash[i + 1] >> 7) & 1) << 3);
  682. c2 = c2 | (((pbPathHash[i + 1] >> 6) & 1) << 2);
  683. c2 = c2 | (((pbPathHash[i + 1] >> 5) & 1) << 1);
  684. c2 = c2 | (((pbPathHash[i + 1] >> 4) & 1) << 0);
  685. c3 = c3 | (((pbPathHash[i + 1] >> 3) & 1) << 5);
  686. c3 = c3 | (((pbPathHash[i + 1] >> 2) & 1) << 4);
  687. c3 = c3 | (((pbPathHash[i + 1] >> 1) & 1) << 3);
  688. c3 = c3 | (((pbPathHash[i + 1] >> 0) & 1) << 2);
  689. c3 = c3 | (((pbPathHash[i + 2] >> 7) & 1) << 1);
  690. c3 = c3 | (((pbPathHash[i + 2] >> 6) & 1) << 0);
  691. c4 = c4 | (((pbPathHash[i + 2] >> 5) & 1) << 5);
  692. c4 = c4 | (((pbPathHash[i + 2] >> 4) & 1) << 4);
  693. c4 = c4 | (((pbPathHash[i + 2] >> 3) & 1) << 3);
  694. c4 = c4 | (((pbPathHash[i + 2] >> 2) & 1) << 2);
  695. c4 = c4 | (((pbPathHash[i + 2] >> 1) & 1) << 1);
  696. c4 = c4 | (((pbPathHash[i + 2] >> 0) & 1) << 0);
  697. c2r64(c1, &(szFileName[j + 0]));
  698. c2r64(c2, &(szFileName[j + 1]));
  699. c2r64(c3, &(szFileName[j + 2]));
  700. c2r64(c4, &(szFileName[j + 3]));
  701. c1 = 0; c2 = 0; c3 = 0; c4 = 0;
  702. }
  703. c1 = c1 | (((pbPathHash[18] >> 7) & 1) << 5);
  704. c1 = c1 | (((pbPathHash[18] >> 6) & 1) << 4);
  705. c1 = c1 | (((pbPathHash[18] >> 5) & 1) << 3);
  706. c1 = c1 | (((pbPathHash[18] >> 4) & 1) << 2);
  707. c1 = c1 | (((pbPathHash[18] >> 3) & 1) << 1);
  708. c1 = c1 | (((pbPathHash[18] >> 2) & 1) << 0);
  709. c2 = c2 | (((pbPathHash[18] >> 1) & 1) << 5);
  710. c2 = c2 | (((pbPathHash[18] >> 0) & 1) << 4);
  711. c2 = c2 | (((pbPathHash[19] >> 7) & 1) << 3);
  712. c2 = c2 | (((pbPathHash[19] >> 6) & 1) << 2);
  713. c2 = c2 | (((pbPathHash[19] >> 5) & 1) << 1);
  714. c2 = c2 | (((pbPathHash[19] >> 4) & 1) << 0);
  715. c3 = c3 | (((pbPathHash[19] >> 3) & 1) << 5);
  716. c3 = c3 | (((pbPathHash[19] >> 2) & 1) << 4);
  717. c3 = c3 | (((pbPathHash[19] >> 1) & 1) << 3);
  718. c3 = c3 | (((pbPathHash[19] >> 0) & 1) << 2);
  719. c3 = c3 | (((0              >> 7) & 1) << 1);
  720. c3 = c3 | (((0              >> 6) & 1) << 0);
  721. c2r64(c1, &(szFileName[24]));
  722. c2r64(c2, &(szFileName[25]));
  723. c2r64(c3, &(szFileName[26]));
  724. szFileName[27] = TEXT('');
  725. return TRUE;
  726. }
  727. /************************************************************************
  728. * Exit1 and Exit2 close handles, etc. for CFILEREncryptFile,
  729. * CFILERDecryptFile, SignFile, and VerifyFile.
  730. ************************************************************************/
  731. void Exit1(HWND hWnd, LPTSTR message, HANDLE hFile1, HANDLE hFile2) {
  732. CloseHandle(hFile1);
  733. CloseHandle(hFile2);
  734. MessageBox(hWnd, message, NULL, MB_OK);
  735. return;
  736. }
  737. void Exit2(HWND hWnd, LPTSTR message, HWND hwndDlg, HANDLE hFile1, HANDLE hFile2) {
  738. CloseHandle(hFile1);
  739. CloseHandle(hFile2);
  740. EndDialog(hwndDlg, FALSE);
  741. MessageBox(hWnd, message, NULL, MB_OK);
  742. return;
  743. }
  744. /************************************************************************
  745. * CFILEREncryptFile()
  746. *
  747. * input:
  748. * hWnd - HWND specified by caller
  749. * szFileName - buffer containing full pathname of file to encrypt
  750. *
  751. * Opens a file to encrypt and saves the file in
  752. * encrypted form in the same path as the plaintext file.
  753. * It is saved as a hidden file with a random filename. Its filename is
  754. * encrypted with fnKey and is stored in the header of the file.
  755. * Deletes the plaintext file.
  756. *
  757. * returns:
  758. * TRUE if successful
  759. * FALSE if unsuccessful
  760. ************************************************************************/
  761. BOOL CFILEREncryptFile(HWND hWnd, LPTSTR szFileName) {
  762. TCHAR szEncryptedFileName[PATH_SIZE];
  763. TCHAR szFileName2[PATH_SIZE];
  764. TCHAR szRandomName[PATH_SIZE];
  765. TCHAR szDirBuf[PATH_SIZE];
  766. BYTE pEncryptBuf[2 * BUF_SIZE];
  767. DWORD dwNumBytesRead = BUF_SIZE;
  768. DWORD dwNumBytesWritten;
  769. DWORD dwEncryptLen = BUF_SIZE;
  770. HWND hwndDlg;
  771. HCRYPTKEY hFileKey;
  772. HCRYPTKEY phEncryptPubKey;
  773. HCRYPTKEY hfnKey;
  774. BYTE  pbFileKeyBlob[BUF_SIZE];
  775. DWORD  dwFileBlobLen = BUF_SIZE;
  776. HANDLE hFileRead = INVALID_HANDLE_VALUE;
  777. HANDLE hFileWrite = INVALID_HANDLE_VALUE;
  778. HCRYPTHASH hHash;
  779. DWORD dwBufLen = HEADER_SIZE * sizeof(TCHAR);
  780. DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  781. if (!szFileName) {
  782. MessageBox(hWnd, TEXT("CFILEREncryptFile: szFileName is NULL."), NULL, MB_OK);
  783. return FALSE;
  784. }
  785. hfnKey = GetfnKey(hWnd);
  786. if (!hfnKey) {
  787. MessageBox(hWnd, TEXT("CFILEREncryptFile: GetfnKey failed."), NULL, MB_OK);
  788. return FALSE;
  789. }
  790. SeparatePathName2(szFileName, szDirBuf, szEncryptedFileName);
  791. GetEncryptPublicKey(hWnd, &phEncryptPubKey);
  792. GenRandomName(szRandomName);
  793. // Generate a key to encrypt this file only if the user
  794. // selected the password option
  795. if (!AlgidEncrypt) {
  796. if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_MD4, 0, 0, &hHash))) {
  797. MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptCreateHash failed."), NULL, MB_OK);
  798. return FALSE;
  799. }
  800. if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)sPass, lstrlen(sPass), 0))) {
  801. MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptHashData failed."), NULL, MB_OK);
  802. return FALSE;
  803. }
  804. if (RCRYPT_FAILED(CryptDeriveKey(hMe, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hFileKey))) {
  805. MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptDeriveKey failed."), NULL, MB_OK);
  806. return FALSE;
  807. }
  808. CryptDestroyHash(hHash);
  809. }
  810. // Generate a key to encrypt this file only (not derived from password).
  811. else if (RCRYPT_FAILED(CryptGenKey(hMe, AlgidEncrypt, CRYPT_EXPORTABLE, &hFileKey))) {
  812. MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptGenKey failed."), NULL, MB_OK);
  813. return FALSE;
  814. dwFileBlobLen = MAXBLOBLEN;
  815. //Export the key so that it can be stored on the disk.
  816. if (RCRYPT_FAILED(CryptExportKey(hFileKey, 
  817.   phEncryptPubKey, 
  818.   SIMPLEBLOB, 
  819.   0, 
  820.   pbFileKeyBlob, 
  821.   &dwFileBlobLen))) {
  822. MessageBox(hWnd, TEXT("CFILEREncryptFile: CryptExportKey failed."), NULL, MB_OK);
  823. return FALSE;
  824. }
  825.     if (!AlgidEncrypt)
  826.     dwFileBlobLen = 0;
  827.    
  828.     // Open a file to encrypt
  829. hFileRead = CreateFile(szFileName, 
  830.    GENERIC_READ, 
  831.    0, 
  832.    0, 
  833.    OPEN_EXISTING, 
  834.    FILE_ATTRIBUTE_READONLY, 
  835.    0);
  836. if (hFileRead == INVALID_HANDLE_VALUE) {
  837. MessageBox(hWnd, TEXT("CFILEREncryptFile: CreateFile failed."), NULL, MB_OK);
  838. return FALSE;
  839. }
  840.       
  841. lstrcpy(szFileName2, szDirBuf);
  842. lstrcat(szFileName2, TEXT("\"));
  843. lstrcat(szFileName2, szRandomName); 
  844. // Create a hidden .CRP file with a random filename.
  845. hFileWrite = CreateFile(szFileName2, 
  846. GENERIC_READ | GENERIC_WRITE, 
  847. 0, 
  848. 0, 
  849. CREATE_NEW, 
  850. FILE_ATTRIBUTE_HIDDEN, 
  851. 0);
  852. if (hFileWrite == INVALID_HANDLE_VALUE) {
  853. MessageBox(hWnd, TEXT("Cannot write to media."), NULL, MB_OK);
  854. CloseHandle(hFileRead);
  855. return FALSE;
  856. }
  857. // Tell the user that the program is busy encrypting data
  858. hwndDlg = CreateDialog(ghModule, TEXT("ENCRYPTING"), hWnd, CryptDlgProc);
  859. if (!hwndDlg) {
  860. Exit2(hWnd, TEXT("CFILEREncryptFile: CreateDialog failed."), hwndDlg, hFileRead, hFileWrite);
  861. DeleteFile(szFileName2);
  862. return FALSE;
  863. }
  864. if (RCRYPT_FAILED(CryptEncrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szEncryptedFileName, &dwDataLen, dwBufLen))) {
  865. Exit2(hWnd, TEXT("CFILEREncryptFile: CryptEncrypt failed."), hwndDlg, hFileRead, hFileWrite);
  866. DeleteFile(szFileName2);
  867. return FALSE;
  868. }
  869. // Write the original file's encrypted name to disk.
  870. if (RCRYPT_FAILED(WriteFile(hFileWrite, 
  871.       szEncryptedFileName, 
  872.       HEADER_SIZE * sizeof(*szEncryptedFileName), 
  873.       &dwNumBytesWritten, 
  874.       0))) {
  875. Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  876. DeleteFile(szFileName2);
  877. return FALSE;
  878. }
  879. // Write the key blob length to disk.
  880. if (!WriteFile(hFileWrite, &dwFileBlobLen, sizeof(dwFileBlobLen), &dwNumBytesWritten, 0)) {
  881. Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  882. DeleteFile(szFileName2);
  883. return FALSE;
  884. }
  885. // Write the key blob to disk.
  886. if (dwFileBlobLen && !WriteFile(hFileWrite, 
  887. pbFileKeyBlob, 
  888. dwFileBlobLen, 
  889. &dwNumBytesWritten, 
  890. 0)) {
  891. Exit2(hWnd, TEXT("CFILEREncryptFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  892. DeleteFile(szFileName2);
  893. return FALSE;
  894. }
  895. // Encrypt the file by reading small amounts
  896. // of data from the disk, encrypting those Bufs, and saving the
  897. // encrypted Bufs to disk. The loop terminates as soon as there is
  898. // not enough data left on the disk to read a full Buf.
  899. for ( ; ; ) {
  900. if (!ReadFile(hFileRead, pEncryptBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  901. Exit2(hWnd, 
  902. TEXT("CFILEREncryptFile: ReadFile failed."),
  903. hwndDlg, 
  904. hFileRead, 
  905. hFileWrite);
  906. DeleteFile(szFileName2);
  907. return FALSE;
  908. }
  909. if (dwNumBytesRead != BUF_SIZE)
  910. break;
  911. if (RCRYPT_FAILED(CryptEncrypt(hFileKey, 0, FALSE, 0, pEncryptBuf, &dwEncryptLen, BUF_SIZE))) {
  912. Exit2(hWnd, 
  913. TEXT("CFILEREncryptFile: CryptEncrypt failed."),
  914. hwndDlg, 
  915. hFileRead, 
  916. hFileWrite);
  917. DeleteFile(szFileName2);
  918. return FALSE;
  919. }
  920. if (!WriteFile(hFileWrite, pEncryptBuf, dwEncryptLen, &dwNumBytesWritten, 0)) {
  921. Exit2(hWnd, 
  922. TEXT("CFILEREncryptFile: WriteFile failed."),
  923. hwndDlg, 
  924. hFileRead, 
  925. hFileWrite);
  926. DeleteFile(szFileName2);
  927. return FALSE;
  928. }
  929. dwEncryptLen = BUF_SIZE;
  930. }
  931. // Encrypt the last block of data.
  932. if (0 < dwNumBytesRead && dwNumBytesRead < BUF_SIZE) {
  933. dwEncryptLen = dwNumBytesRead;
  934. if (RCRYPT_FAILED(CryptEncrypt(hFileKey, 0, TRUE, 0, pEncryptBuf, &dwEncryptLen, BUF_SIZE))) {
  935. Exit2(hWnd, TEXT("CryptEncrypt failed."), hwndDlg, hFileRead, hFileWrite);
  936. DeleteFile(szFileName2);
  937. return FALSE;
  938. }
  939. if (!WriteFile(hFileWrite, pEncryptBuf, dwEncryptLen, &dwNumBytesWritten, 0)) {
  940. Exit2(hWnd, TEXT("WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  941. DeleteFile(szFileName2);
  942. return FALSE;
  943. }
  944. }
  945. if (RCRYPT_FAILED(CryptDestroyKey(hFileKey))) {
  946. Exit2(hWnd, TEXT("CryptDestroyKey failed."), hwndDlg, hFileRead,hFileWrite);
  947. DeleteFile(szFileName2);
  948. return FALSE;
  949. }
  950. CloseHandle(hFileRead);
  951. if (!DeleteFile(szFileName)) {
  952. EndDialog(hwndDlg, FALSE);
  953. MessageBox(hWnd, TEXT("File cannot be deleted: It is either in use by another process, or it is a system file."), NULL, MB_OK);
  954. CloseHandle(hFileWrite);
  955. DeleteFile(szFileName2);
  956. return FALSE;
  957. }
  958. EndDialog(hwndDlg, FALSE);
  959. CloseHandle(hFileWrite);
  960. SetFileAttributes(szFileName2, FILE_ATTRIBUTE_HIDDEN);
  961. return TRUE;
  962. }
  963. /************************************************************************
  964. * CFILERDecryptFile()
  965. *
  966. * input:
  967. * hWnd - HWND specified by caller
  968. * szFileName - buffer containing full pathname of file to decrypt.
  969. *
  970. * purpose:
  971. * decrypts the file specified by szFileName and stores the file in
  972. * the same directory. Deletes the encrypted file.
  973. *
  974. * returns:
  975. * TRUE if successful
  976. * FALSE if unsuccessful
  977. ************************************************************************/
  978. BOOL CFILERDecryptFile(HWND hWnd, LPTSTR szFileName)
  979. {
  980. TCHAR szFileName2[PATH_SIZE];
  981. TCHAR szDecryptedFileName[PATH_SIZE];
  982. TCHAR szFile[PATH_SIZE];
  983. BYTE pDecryptBuf[2 * BUF_SIZE];
  984. DWORD dwNumBytesRead;
  985. DWORD dwNumBytesWritten;
  986. DWORD dwDecryptDataLen = BUF_SIZE;
  987. HCRYPTKEY hFileKey;
  988. HCRYPTKEY phEncryptPubKey;
  989. BYTE  pbDecryptBlob[BUF_SIZE];
  990. DWORD  dwDecryptBlobLen;
  991. HWND hwndDlg;
  992. HANDLE hFileRead;
  993. HANDLE hFileWrite = INVALID_HANDLE_VALUE;
  994. HCRYPTHASH hHash;
  995. DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  996. // BYTE pHashData[BUF_SIZE];
  997. DWORD HashDataLen;
  998. if (!szFileName) {
  999. MessageBox(hWnd, TEXT("CFILERDecryptFile: szFileName is NULL."), NULL, MB_OK);
  1000. return FALSE;
  1001. }
  1002. GetEncryptPublicKey(hWnd, &phEncryptPubKey);
  1003. GetDecryptedFileName(hWnd, 
  1004.  szFileName, 
  1005.  szDecryptedFileName, 
  1006.  &hFileRead);
  1007. // Read the key blob length from the disk.
  1008. if (!ReadFile(hFileRead, &dwDecryptBlobLen, sizeof(dwDecryptBlobLen), &dwNumBytesRead, 0)) {
  1009. MessageBox(hWnd, TEXT("CFILERDecryptFile: ReadFile failed."), NULL, MB_OK);
  1010. CloseHandle(hFileRead);
  1011. return FALSE;
  1012. }
  1013. // Read the key blob from the disk into a Buf.
  1014. if (dwDecryptBlobLen && !ReadFile(hFileRead, 
  1015.   pbDecryptBlob, 
  1016.   dwDecryptBlobLen, 
  1017.   &dwNumBytesRead, 
  1018.   0)) {
  1019. MessageBox(hWnd, TEXT("CFILERDecryptFile: ReadFile failed."), NULL, MB_OK);
  1020. CloseHandle(hFileRead);
  1021. return FALSE;
  1022. // Import the key whose blob is contained in the Buf pbDecryptBlob
  1023. if (dwDecryptBlobLen && !CryptImportKey(hMe, 
  1024. pbDecryptBlob, 
  1025. dwDecryptBlobLen, 
  1026. 0, 
  1027. 0, 
  1028. &hFileKey)) {
  1029. MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptImportKey failed."), NULL, MB_OK);
  1030. CloseHandle(hFileRead);
  1031. return FALSE;
  1032. }
  1033. SeparatePathName(szFileName, szFileName2, szFile);
  1034. lstrcat(szFileName2, TEXT("\"));
  1035. lstrcat(szFileName2, szDecryptedFileName);
  1036. // Generate a key to decrypt this file if the user
  1037. // selected the password option
  1038. if (!dwDecryptBlobLen) {
  1039. lstrcpy(szPassName, szFileName2);
  1040. if (!GetPass(hWnd)) {
  1041. MessageBox(hWnd, TEXT("CFILERDecryptFile: GetPass failed."), NULL, MB_OK);
  1042. CloseHandle(hFileRead);
  1043. return FALSE;
  1044. }
  1045. lstrcpy(szPassName, TEXT(""));
  1046. if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_MD4, 0, 0, &hHash))) {
  1047. MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptCreateHash failed."), NULL, MB_OK);
  1048. CloseHandle(hFileRead);
  1049. return FALSE;
  1050. }
  1051. if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)sPass, lstrlen(sPass), 0))) {
  1052. MessageBox(hWnd, TEXT("DecrypttFile: CryptHashData failed."), NULL, MB_OK);
  1053. return FALSE;
  1054. }
  1055. HashDataLen = BUF_SIZE;
  1056. if (RCRYPT_FAILED(CryptDeriveKey(hMe, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hFileKey))) {
  1057. MessageBox(hWnd, TEXT("CFILERDecryptFile: CryptDeriveKey failed."), NULL, MB_OK);
  1058. CloseHandle(hFileRead);
  1059. return FALSE;
  1060. }
  1061. CryptDestroyHash(hHash);
  1062. dwDecryptBlobLen = 0;
  1063. }
  1064. // Recreate the plaintext file
  1065. hFileWrite = CreateFile(szFileName2, 
  1066. GENERIC_READ | GENERIC_WRITE, 
  1067. 0, 
  1068. 0, 
  1069. CREATE_ALWAYS, 
  1070. FILE_ATTRIBUTE_NORMAL, 
  1071. 0);
  1072. if (hFileWrite == INVALID_HANDLE_VALUE) {
  1073. if (GetLastError() == ERROR_FILENAME_EXCED_RANGE) {
  1074. TCHAR szEmergencyName[PATH_SIZE];
  1075. TCHAR szEmergencyRandomName[PATH_SIZE];
  1076. TCHAR szDir1[PATH_SIZE];
  1077. TCHAR szFile1[PATH_SIZE];
  1078. SeparatePathName(szFileName, szDir1, szFile1);
  1079. GenRandomName2(szEmergencyRandomName);
  1080. lstrcpy(szEmergencyName, szDir1);
  1081. lstrcat(szEmergencyName, TEXT("\recovered"));
  1082. lstrcat(szEmergencyName, szEmergencyRandomName);
  1083. hFileWrite = CreateFile(szEmergencyName, GENERIC_READ | GENERIC_WRITE,
  1084. 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  1085. if (hFileWrite == INVALID_HANDLE_VALUE) {
  1086. ErrorMsg(TEXT("Could not recover file."));
  1087. return FALSE;
  1088. }
  1089. }
  1090. else {
  1091. MessageBox(hWnd, TEXT("CFILERDecryptFile: CreateFile failed."), NULL, MB_OK);
  1092. CloseHandle(hFileRead);
  1093. return FALSE;
  1094. }
  1095. }
  1096. // Create a dialog box to inform the user that the program is busy decrypting data.
  1097. hwndDlg = CreateDialog(ghModule, TEXT("DECRYPTING"), hWnd, CryptDlgProc);
  1098. if (!hwndDlg) {
  1099. Exit2(hWnd, TEXT("CFILERDecryptFile: CreateDialog failed."), hwndDlg, hFileRead, hFileWrite);
  1100. DeleteFile(szFileName2);
  1101. return FALSE;
  1102. }
  1103. // The following for loop decrypts the data in units of BUF_SIZE
  1104. // at a time and stores the decrypted data into the file hFileWrite.
  1105. // The loop terminates when fewer than BUF_SIZE have been read.
  1106. for ( ; ; ) {
  1107. if (!ReadFile(hFileRead, pDecryptBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1108. Exit2(hWnd, 
  1109. TEXT("CFILERDecryptFile: ReadFile failed."),
  1110. hwndDlg, 
  1111. hFileRead, 
  1112. hFileWrite);
  1113. DeleteFile(szFileName2);
  1114. return FALSE;
  1115. }
  1116. if (dwNumBytesRead != BUF_SIZE)
  1117. break;
  1118. if (RCRYPT_FAILED(CryptDecrypt(hFileKey, 0, FALSE, 0, pDecryptBuf, &dwDecryptDataLen))) {
  1119. Exit2(hWnd, 
  1120. TEXT("CFILERDecryptFile: CryptDecrypt failed."),
  1121. hwndDlg, 
  1122. hFileRead, 
  1123. hFileWrite);
  1124. DeleteFile(szFileName2);
  1125. return FALSE;
  1126. }
  1127. if (!WriteFile(hFileWrite, pDecryptBuf, dwDecryptDataLen, &dwNumBytesWritten, 0)) {
  1128. Exit2(hWnd, 
  1129. TEXT("CFILERDecryptFile: WriteFile failed."),
  1130. hwndDlg, 
  1131. hFileRead, 
  1132. hFileWrite);
  1133. DeleteFile(szFileName2);
  1134. return FALSE;
  1135. }
  1136. dwDecryptDataLen = BUF_SIZE;
  1137. }
  1138. // Decrypt the final block of data.
  1139. if (0 < dwNumBytesRead && dwNumBytesRead < BUF_SIZE) {
  1140. dwDecryptDataLen = dwNumBytesRead;
  1141. if (RCRYPT_FAILED(CryptDecrypt(hFileKey, 0, TRUE, 0, pDecryptBuf, &dwDecryptDataLen))) {
  1142. MessageBox(hWnd, TEXT("GetfnKey: CryptImportKey failed"), NULL, MB_OK);
  1143. Exit2(hWnd, 
  1144. TEXT("CFILERDecryptFile: CryptDecrypt failed."),
  1145. hwndDlg, 
  1146. hFileRead, 
  1147. hFileWrite);
  1148. DeleteFile(szFileName2);
  1149. return FALSE;
  1150. }
  1151. if (!WriteFile(hFileWrite, pDecryptBuf, dwDecryptDataLen, &dwNumBytesWritten, 0)) {
  1152. Exit2(hWnd, 
  1153. TEXT("CFILERDecryptFile: WriteFile failed."),
  1154. hwndDlg, 
  1155. hFileRead, 
  1156. hFileWrite);
  1157. DeleteFile(szFileName2);
  1158. return FALSE;
  1159. }
  1160. }
  1161. if (!CryptDestroyKey(hFileKey)) {
  1162. Exit2(hWnd, 
  1163. TEXT("CFILERDecryptFile: CryptDestroyKey failed."),
  1164. hwndDlg, 
  1165. hFileRead, 
  1166. hFileWrite);
  1167. DeleteFile(szFileName2);
  1168. return FALSE;
  1169. }
  1170. EndDialog(hwndDlg, FALSE);
  1171. CloseHandle(hFileRead);
  1172. CloseHandle(hFileWrite);
  1173. if (!DeleteFile(szFileName)) {
  1174. MessageBox(hWnd, TEXT("CFILERDecryptFile: DeleteFile failed."), NULL, MB_OK);
  1175. DeleteFile(szFileName2);
  1176. }
  1177. return TRUE;
  1178. }
  1179. /************************************************************************
  1180. * SignFile:
  1181. * Opens a file, creates a hash value of the file,
  1182. * signs that hash value, and stores the result to disk.
  1183. ************************************************************************/
  1184. BOOL SignFile(HWND hWnd, LPTSTR szFileName) {
  1185. TCHAR  szFilter1[] = TEXT("Signature Files (*.SGN)*.SGN");
  1186. TCHAR  szFilter2[] = TEXT("All Files (*.*)*.*");
  1187. TCHAR szFile[PATH_SIZE] = TEXT("");
  1188. TCHAR szFile2[PATH_SIZE] = TEXT("");
  1189. TCHAR szFileTitle[PATH_SIZE];
  1190. TCHAR szFileName2[PATH_SIZE];
  1191. DWORD dwNumBytesRead = BUF_SIZE;
  1192. DWORD dwNumBytesWritten;
  1193. HWND hwndDlg;
  1194. HANDLE hFileRead = INVALID_HANDLE_VALUE;
  1195. HANDLE hFileWrite = INVALID_HANDLE_VALUE;
  1196. HCRYPTKEY phSignaturePubKey;
  1197. HCRYPTHASH hHash;
  1198. BYTE pSignBuf[BUF_SIZE];
  1199. BYTE pbHash[BUF_SIZE];
  1200. DWORD dwHashLen;
  1201. GetSignaturePublicKey(hWnd, &phSignaturePubKey);
  1202. if (!szFileName) {
  1203. MessageBox(hWnd, TEXT("SignFile: szFileName is NULL."), NULL, MB_OK);
  1204. return FALSE;
  1205. }
  1206. lstrcpy(szFile, TEXT(""));
  1207. lstrcpy(szFileTitle, TEXT(""));
  1208. // Open plaintext file
  1209. hFileRead = CreateFile(szFileName, 
  1210.    GENERIC_READ, 
  1211.    0, 
  1212.    0, 
  1213.    OPEN_EXISTING, 
  1214.    FILE_ATTRIBUTE_READONLY, 
  1215.    0);
  1216. if (hFileRead == INVALID_HANDLE_VALUE) {
  1217. MessageBox(hWnd, TEXT("SignFile: CreateFile failed."), NULL, MB_OK);
  1218. return FALSE;
  1219. }
  1220. // hash the full pathname of the file. This will be the name of
  1221. // the signature file.
  1222. if (!GetSigFileName(szFileName, szFileName2)) {
  1223. MessageBox(hWnd, TEXT("SignFile: GetSigFileName failed."), NULL, MB_OK);
  1224. return FALSE;
  1225. }
  1226. // Create signature file.
  1227. if (GetFileAttributes(szFileName2) == 0xFFFFFFFF) {
  1228. hFileWrite = CreateFile(szFileName2, 
  1229. GENERIC_READ | GENERIC_WRITE, 
  1230. 0, 
  1231. 0, 
  1232. CREATE_NEW, 
  1233. FILE_ATTRIBUTE_HIDDEN, 
  1234. 0);
  1235. if (hFileWrite == INVALID_HANDLE_VALUE) {
  1236. Exit1(hWnd, TEXT("SignFile: CreateFile failed."), hFileRead, hFileWrite);
  1237. return FALSE;
  1238. }
  1239. else {
  1240. if (MessageBox(hWnd, 
  1241.    TEXT("Delete signature?"), 
  1242.    TEXT("Signature file already exists."), 
  1243.    MB_OKCANCEL) == IDOK) {
  1244. DeleteFile(szFileName2);
  1245. hFileWrite = CreateFile(szFileName2,
  1246. GENERIC_READ | GENERIC_WRITE,
  1247. 0,
  1248. 0,
  1249. CREATE_NEW,
  1250. FILE_ATTRIBUTE_HIDDEN,
  1251. 0);
  1252. if (hFileWrite == INVALID_HANDLE_VALUE) {
  1253. Exit1(hWnd, TEXT("SignFile: CreateFile failed."), hFileRead, hFileWrite);
  1254. return FALSE;
  1255. }
  1256. }
  1257. else {
  1258. CloseHandle(hFileRead);
  1259. return FALSE;
  1260. }
  1261. }
  1262. // Create a dialog box to inform the user that the program is hashing data.
  1263. hwndDlg = CreateDialog(ghModule, TEXT("SIGNING"), hWnd, CryptDlgProc);
  1264. if (RCRYPT_FAILED(CryptCreateHash(hMe, AlgidSign, 0, 0, &hHash))) {
  1265. Exit2(hWnd, TEXT("SignFile: CryptCreateHash failed."), hwndDlg, hFileRead, hFileWrite);
  1266. DeleteFile(szFileName2);
  1267. return FALSE;
  1268. }
  1269. // The following for loop hashes the file in BUF_SIZE Bufs at a time.
  1270. for (dwNumBytesRead = BUF_SIZE ; dwNumBytesRead == BUF_SIZE; ) {
  1271. if (!ReadFile(hFileRead, pSignBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1272. Exit2(hWnd, 
  1273. TEXT("SignFile: ReadFile failed."), 
  1274. hwndDlg, 
  1275. hFileRead, 
  1276. hFileWrite);
  1277. DeleteFile(szFileName2);
  1278. return FALSE;
  1279. }
  1280. else if (RCRYPT_FAILED(CryptHashData(hHash, pSignBuf, dwNumBytesRead, 0))) {
  1281. Exit2(hWnd, 
  1282. TEXT("SignFile: CryptHashData failed."), 
  1283. hwndDlg, 
  1284. hFileRead, 
  1285. hFileWrite);
  1286. DeleteFile(szFileName2);
  1287. return FALSE;
  1288. }
  1289. }
  1290. dwHashLen = BUF_SIZE;
  1291. if (RCRYPT_FAILED(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbHash, &dwHashLen)))
  1292. {
  1293. MessageBox(hWnd, TEXT("SignFile: CryptSignHash failed"), NULL, MB_OK);
  1294. Exit2(hWnd, 
  1295. TEXT("SignFile: CryptSignHash failed."), 
  1296. hwndDlg, 
  1297. hFileRead, 
  1298. hFileWrite);
  1299. DeleteFile(szFileName2);
  1300. return FALSE;
  1301. // Write ALG_ID to disk
  1302. if (!WriteFile(hFileWrite, &AlgidSign, sizeof(ALG_ID), &dwNumBytesWritten, 0)) {
  1303. Exit2(hWnd, TEXT("SignFile: WriteFile failed."), hwndDlg, hFileRead, hFileWrite);
  1304. return FALSE;
  1305. }
  1306. // Write hash to disk.
  1307. if (!WriteFile(hFileWrite, pbHash, dwHashLen, &dwNumBytesWritten, 0)) {
  1308. Exit2(hWnd, 
  1309. TEXT("SignFile: WriteFile failed."), 
  1310. hwndDlg, 
  1311. hFileRead, 
  1312. hFileWrite);
  1313. DeleteFile(szFileName2);
  1314. return FALSE;
  1315. }
  1316. CryptDestroyHash(hHash);
  1317. EndDialog(hwndDlg, FALSE);
  1318. CloseHandle(hFileRead);
  1319. CloseHandle(hFileWrite);
  1320. return TRUE;
  1321. }
  1322. /************************************************************************
  1323. * VerifyFile
  1324. * Opens a signature file and the original file.
  1325. * Hashes the original file and tries to verify
  1326. * the hash.
  1327. ************************************************************************/
  1328. BOOL VerifyFile(HWND hWnd, LPTSTR szFileName) {
  1329. TCHAR  szFilter1[] = TEXT("Signature Files (*.SGN)*.SGN");
  1330. TCHAR  szFilter2[] = TEXT("All Files (*.*)*.*");
  1331. TCHAR szFile[PATH_SIZE] = TEXT("");
  1332. TCHAR szFile2[PATH_SIZE] = TEXT("");
  1333. TCHAR szFileTitle[PATH_SIZE];
  1334. TCHAR szFileName2[PATH_SIZE];
  1335. DWORD dwNumBytesRead;
  1336. DWORD dwNumBytesRead2;
  1337. HWND hwndDlg;
  1338. HANDLE hFileOrig = INVALID_HANDLE_VALUE;
  1339. HANDLE hFileSig = INVALID_HANDLE_VALUE;
  1340. BYTE pbSig[BUF_SIZE];
  1341. BYTE pVerifyBuf[BUF_SIZE];
  1342. DWORD dwSigLen;
  1343. HCRYPTHASH hHash;
  1344. HCRYPTKEY phSignaturePubKey;
  1345. ALG_ID  DiskAlgid;
  1346. if (!szFileName) {
  1347. MessageBox(hWnd, TEXT("VerifyFile: szFileName is NULL."), NULL, MB_OK);
  1348. return FALSE;
  1349. }
  1350. GetSignaturePublicKey(hWnd, &phSignaturePubKey);
  1351. // hash the full pathname of the file to determine the signature file
  1352. // to open.
  1353. if (!GetSigFileName(szFileName, szFileName2)) {
  1354. MessageBox(hWnd, TEXT("VerifyFile: GetSigFileName failed."), NULL, MB_OK);
  1355. return FALSE;
  1356. }
  1357. lstrcpy(szFile, TEXT(""));
  1358. lstrcpy(szFileTitle, TEXT(""));
  1359. // Open the plaintext file to hash it.
  1360. hFileOrig = CreateFile(szFileName, 
  1361.    GENERIC_READ, 
  1362.    0, 
  1363.    0, 
  1364.    OPEN_EXISTING, 
  1365.    FILE_ATTRIBUTE_READONLY, 
  1366.    0);
  1367. if (hFileOrig == INVALID_HANDLE_VALUE) {
  1368. MessageBox(hWnd, TEXT("VerifyFile: CreateFile failed."), NULL, MB_OK);
  1369. CloseHandle(hFileOrig);
  1370. return FALSE;
  1371. }
  1372. // Automatically open the signature file if it 
  1373. // exists in the same directory as the file to be verified.
  1374. // Otherwise, prompt the user to browse the directory tree 
  1375. // for the signature file.
  1376. if (GetFileAttributes(szFileName2) != 0xFFFFFFFF) {
  1377. hFileSig = CreateFile(szFileName2, 
  1378.   GENERIC_READ, 
  1379.   0, 
  1380.   0, 
  1381.   OPEN_EXISTING, 
  1382.   FILE_ATTRIBUTE_READONLY, 
  1383.   0);
  1384. if (hFileSig == INVALID_HANDLE_VALUE) {
  1385. Exit1(hWnd, TEXT("VerifyFile: CreateFile failed."), hFileOrig, hFileSig);
  1386. return FALSE;
  1387. }
  1388. else {
  1389. Exit1(hWnd, TEXT("Signature file does not exist."), hFileOrig, hFileSig);
  1390. return FALSE;
  1391. // Create a dialog box to tell the user that the program is busy hashing data.
  1392. hwndDlg = CreateDialog(ghModule, TEXT("VERIFYING"), hWnd, CryptDlgProc);
  1393. // Read the ALG_ID
  1394. if (!ReadFile(hFileSig, &DiskAlgid, sizeof(ALG_ID), &dwNumBytesRead2, 0)) {
  1395. Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1396. return FALSE;
  1397. }
  1398. // Read the hash
  1399. if (!ReadFile(hFileSig, pbSig, BUF_SIZE, &dwSigLen, 0)) {
  1400. Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1401. return FALSE;
  1402. }
  1403. if (RCRYPT_FAILED(CryptCreateHash(hMe, DiskAlgid, 0, 0, &hHash))) {
  1404. Exit2(hWnd, TEXT("VerifyFile: CryptCreateHash failed."), hwndDlg, hFileOrig, hFileSig);
  1405. return FALSE;
  1406. }
  1407. // hash the file in BUF_SIZE chunks
  1408. for (dwNumBytesRead = BUF_SIZE; dwNumBytesRead == BUF_SIZE; ) {
  1409. if (!ReadFile(hFileOrig, pVerifyBuf, BUF_SIZE, &dwNumBytesRead, 0)) {
  1410. Exit2(hWnd, TEXT("VerifyFile: ReadFile failed."), hwndDlg, hFileOrig, hFileSig);
  1411. return FALSE;
  1412. }
  1413. if (RCRYPT_FAILED(CryptHashData(hHash, pVerifyBuf, dwNumBytesRead, 0))) {
  1414. Exit2(hWnd, 
  1415. TEXT("VerifyFile: CryptHashData failed."), 
  1416. hwndDlg, 
  1417. hFileOrig, 
  1418. hFileSig);
  1419. return FALSE;
  1420. }
  1421. }
  1422. if (RCRYPT_FAILED(CryptVerifySignature(hHash, pbSig, dwSigLen, phSignaturePubKey, 0, 0))) {
  1423. EndDialog(hwndDlg, FALSE);
  1424. MessageBox(hWnd, 
  1425.    TEXT("Could not verify signature."), 
  1426.    TEXT("Result"), 
  1427.    MB_OK | MB_ICONINFORMATION);
  1428. CloseHandle(hFileOrig);
  1429. CloseHandle(hFileSig);
  1430. return TRUE;
  1431. }
  1432. if (RCRYPT_FAILED(CryptDestroyHash(hHash))) {
  1433. Exit2(hWnd, 
  1434. TEXT("Could not destroy hash."), 
  1435. hwndDlg, 
  1436. hFileOrig, 
  1437. hFileSig);
  1438. return FALSE;
  1439. }
  1440. EndDialog(hwndDlg, FALSE);
  1441. MessageBox(hWnd, 
  1442.    TEXT("Signature verified."), 
  1443.    TEXT("Result"), 
  1444.    MB_OK | MB_ICONINFORMATION);
  1445. CloseHandle(hFileOrig);
  1446. CloseHandle(hFileSig);
  1447. return TRUE;
  1448. }
  1449. /************************************************************************
  1450. * EncryptDir()
  1451. *
  1452. * in parameters
  1453. * hWnd - HWND specified by caller
  1454. * szDirName - full path of directory to encrypt
  1455. * lpCInfo - instance data for drive child
  1456. *
  1457. * purpose: 
  1458. * Encrypts szDirName and recursively encrypts all of its
  1459. * subdirectories. Confirmation is needed for each subdirectory.
  1460. * A random directory name is generated, and szDirName is
  1461. * renamed and given hidden attributes.
  1462. * dirinfo contains the fnKey-encrypted directory name.
  1463. *
  1464. * returns
  1465. * TRUE if successful
  1466. * FALSE if unsuccessful
  1467. ************************************************************************/
  1468. BOOL EncryptDir(HWND hWnd, LPTSTR szDirName, LPCINFO lpCInfo) {
  1469. TCHAR szDirInfo[PATH_SIZE];
  1470. TCHAR szFileName[PATH_SIZE];
  1471. TCHAR szEncryptedDirName[PATH_SIZE];
  1472. TCHAR szRandom[PATH_SIZE];
  1473. TCHAR szRandomName[PATH_SIZE];
  1474. TCHAR szDir[PATH_SIZE];
  1475. TCHAR szFile[PATH_SIZE];
  1476. TCHAR szMessage[PATH_SIZE];
  1477. TCHAR szOldDir[PATH_SIZE];
  1478. TCHAR Buf[PATH_SIZE];
  1479. TCHAR szDirName2[PATH_SIZE];
  1480. LPTSTR lpszDirName2;
  1481. HANDLE  hFileDirInfo;
  1482. HANDLE hFindFile;
  1483. WIN32_FIND_DATA FindFileData;
  1484. BOOL fNextFile;
  1485. DWORD dwLastError;
  1486. DWORD dwDataLen = BUF_SIZE;
  1487. DWORD dwNumBytesWritten;
  1488. LONG lIndex;
  1489. LONG lCount;
  1490. HCRYPTKEY hfnKey;
  1491. if (!szDirName) {
  1492. MessageBox(hWnd, TEXT("EncryptDir: szDirName is NULL."), NULL, MB_OK);
  1493. return FALSE;
  1494. }
  1495. if (!lpCInfo) {
  1496. MessageBox(hWnd, TEXT("EncryptDir: lpCInfo is NULL."), NULL, MB_OK);
  1497. return FALSE;
  1498. }
  1499. hfnKey = GetfnKey(hWnd);
  1500. if (!hfnKey) {
  1501. MessageBox(hWnd, TEXT("EncryptDir: GetfnKey failed."), NULL, MB_OK);
  1502. return FALSE;
  1503. }
  1504. SeparatePathName2(szDirName, szDir, szEncryptedDirName);
  1505. lstrcpy(szMessage, TEXT(""));
  1506. wsprintf(szMessage, TEXT("Encrypt the directory %s?n"), szDirName);
  1507. // ask for confirmation about encrypting the directory
  1508. if (MessageBox(hWnd, szMessage, 
  1509. TEXT("Confirmation needed."), MB_OKCANCEL) == IDCANCEL)
  1510. return FALSE;
  1511. lstrcpy(szFileName, szDir);
  1512. lstrcat(szFileName, TEXT("\"));
  1513. lstrcat(szFileName, szEncryptedDirName);
  1514. if (!szDirName) {
  1515. MessageBox(hWnd, TEXT("EncryptDir: szDirName is NULL."), NULL, MB_OK);
  1516. return FALSE;
  1517. }
  1518. GenRandomName(szRandom);
  1519. lstrcpy(szRandomName, szDir);
  1520. lstrcat(szRandomName, TEXT("\"));
  1521. lstrcat(szRandomName, szRandom);
  1522. lstrcpy(szDirInfo, szFileName);
  1523. lstrcat(szDirInfo, TEXT("\dirinfo"));
  1524. // Create a file called "dirinfo" in directory about to encrypted.
  1525. // This will contain the original directory name encrypted with fnKey.
  1526. hFileDirInfo = CreateFile(szDirInfo, 
  1527.   GENERIC_READ | GENERIC_WRITE, 
  1528.   0, 
  1529.   0, 
  1530.   CREATE_ALWAYS, 
  1531.   FILE_ATTRIBUTE_HIDDEN, 
  1532.   0);
  1533. if (hFileDirInfo == INVALID_HANDLE_VALUE) {
  1534. MessageBox(hWnd, TEXT("EncryptDir: CreateFile failed."), NULL, MB_OK);
  1535. return FALSE;
  1536. }
  1537. // Encrypt the directory name with fnKey.
  1538. if (RCRYPT_FAILED(CryptEncrypt(hfnKey, 
  1539.   0, 
  1540.   TRUE, 
  1541.   0, 
  1542.   (LPBYTE)szEncryptedDirName, 
  1543.   &dwDataLen, 
  1544.   HEADER_SIZE * sizeof(*szEncryptedDirName)))) {
  1545. MessageBox(hWnd, TEXT("EncryptDir: CryptEncrypt failed."), NULL, MB_OK);
  1546. CloseHandle(hFileDirInfo);
  1547. return FALSE;
  1548. }
  1549. // Write the original directory's encrypted name to disk.
  1550. if (!WriteFile(hFileDirInfo, 
  1551.    szEncryptedDirName, 
  1552.    HEADER_SIZE * sizeof(*szEncryptedDirName), 
  1553.    &dwNumBytesWritten, 
  1554.    0)) {
  1555. MessageBox(hWnd, TEXT("EncryptDir: WriteFile failed."), NULL, MB_OK);
  1556. CloseHandle(hFileDirInfo);
  1557. return FALSE;
  1558. }
  1559. CloseHandle(hFileDirInfo);
  1560. SeparatePathName2(szDirName, szDir, szFile);
  1561. lstrcpy(szDirName, szDir);
  1562. lstrcat(szDirName, TEXT("\"));
  1563. lstrcat(szDirName, szFile);
  1564. lstrcpy(szOldDir, szDirName);
  1565. lstrcat(szDirName, TEXT("\*"));
  1566. if ((hFindFile = FindFirstFile(szDirName, &FindFileData)) 
  1567. == INVALID_HANDLE_VALUE) {
  1568. MessageBox(hWnd, TEXT("EncryptDir: FindFirstFile failed."), NULL, MB_OK);
  1569. return FALSE;
  1570. }
  1571. // Loop through, calling FindNextFiles until no more files are left.
  1572. do {
  1573. lstrcpy(szFileName, szDir);
  1574. lstrcat(szFileName, TEXT("\"));
  1575. lstrcat(szFileName, szFile);
  1576. lstrcat(szFileName, TEXT("\"));
  1577. lstrcat(szFileName, FindFileData.cFileName);
  1578. // is szFileName encrypted and not .., ., or dirinfo?
  1579. if (!IsEncrypted(szFileName)
  1580.    && lstrcmp(FindFileData.cFileName, TEXT("."))
  1581.    && lstrcmp(FindFileData.cFileName, TEXT(".."))
  1582.    && lstrcmp(FindFileData.cFileName, TEXT("dirinfo"))) {
  1583. // Is szFileName a directory?
  1584. if (CFilerIsDirectory(szFileName)) {
  1585. // Encrypt the directory szFileName.
  1586. if (!EncryptDir(hWnd, szFileName, lpCInfo)) {
  1587. MessageBox(hWnd, TEXT("EncryptDir: EncryptDir failed."), NULL, MB_OK);
  1588. return FALSE;
  1589. }
  1590. }
  1591. // encrypt the file szFileName.
  1592. else if (!CFILEREncryptFile(hWnd, szFileName)) {
  1593. MessageBox(hWnd, TEXT("EncryptDir: CFILEREncryptFile failed."), NULL, MB_OK);
  1594. return FALSE;
  1595. }
  1596. }
  1597. fNextFile = FindNextFile(hFindFile, &FindFileData);
  1598. dwLastError = GetLastError();
  1599. } while (fNextFile || dwLastError != ERROR_NO_MORE_FILES);
  1600. FindClose(hFindFile);
  1601. lpszDirName2 = szDirName2;
  1602. // Collapse the selected directory.
  1603. lIndex = GetLBText(lpCInfo->hDirLB, Buf);
  1604. lCount = GetDirDepth(Buf, &lpszDirName2);
  1605. CollapseDir(lpCInfo, lIndex, lCount);
  1606. // rename the directory with a random name.
  1607. #ifdef UNICODE
  1608. if (_wrename((const wchar_t *)szOldDir, (const wchar_t *)szRandomName)) {
  1609. #else
  1610. if (rename(szOldDir, szRandomName)) {
  1611. #endif
  1612. MessageBox(hWnd, TEXT("Another process is using this directory."), NULL, MB_OK);
  1613. return FALSE;
  1614. }
  1615. // hide the directory.
  1616. SetFileAttributes(szRandomName, FILE_ATTRIBUTE_HIDDEN);
  1617. return TRUE;
  1618. }
  1619. /************************************************************************
  1620. * GenRandomName()
  1621. *
  1622. * out parameters
  1623. * szRandomName - buffer to receive random filename
  1624. *
  1625. * purpose:
  1626. * Uses the random number generator to generate a random filename with
  1627. * a .CRP extension.
  1628. *
  1629. * returns
  1630. * TRUE if successful
  1631. * FALSE if unsuccessful
  1632. ************************************************************************/
  1633. BOOL GenRandomName(LPTSTR szRandomName) {
  1634. INT i;
  1635. if (!szRandomName) {
  1636. ErrorMsg(TEXT("GenRandomName: szRandomName is NULL."));
  1637. return FALSE;
  1638. }
  1639. for (i = 0; i < RANDOM_NAME_LENGTH; i++)
  1640. szRandomName[i] = rand() % 26 + TEXT('a');
  1641. szRandomName[i] = TEXT('');
  1642. lstrcat(szRandomName, TEXT(".CRP"));
  1643. return TRUE;
  1644. }
  1645. /************************************************************************
  1646. * GenRandomName2()
  1647. *
  1648. * out parameters
  1649. * szRandomName - buffer to receive random filename
  1650. *
  1651. * purpose:
  1652. * Uses the random number generator to generate a random filename without
  1653. * a .CRP extension.
  1654. *
  1655. * returns
  1656. * TRUE if successful
  1657. * FALSE if unsuccessful
  1658. ************************************************************************/
  1659. BOOL GenRandomName2(LPTSTR szRandomName) {
  1660. INT i;
  1661. if (!szRandomName) {
  1662. ErrorMsg(TEXT("GenRandomName: szRandomName is NULL."));
  1663. return FALSE;
  1664. }
  1665. for (i = 0; i < RANDOM_NAME_LENGTH; i++)
  1666. szRandomName[i] = rand() % 26 + TEXT('a');
  1667. szRandomName[i] = TEXT('');
  1668. return TRUE;
  1669. }
  1670. /************************************************************************
  1671. * GetSigFileName()
  1672. *
  1673. * input
  1674. * in parameters:
  1675. * szFileName - full path of filename
  1676. * out parameters:
  1677. * szOutName - buffer containing name of signature file.
  1678. *
  1679. * purpose:
  1680. * obtains the name of the signature file that corresponds to szFileName.
  1681. * by hashing it and converting it to ascii.
  1682. *
  1683. * returns
  1684. * TRUE if successful
  1685. * FALSE if unsuccessful
  1686. ************************************************************************/
  1687. BOOL GetSigFileName(LPTSTR szFileName, LPTSTR szOutName) {
  1688. HCRYPTHASH hHash;
  1689. BYTE pbHash[BUF_SIZE];
  1690. DWORD dwHashLen;
  1691. TCHAR szFileBuf[PATH_SIZE];
  1692. TCHAR szSigDir[PATH_SIZE];
  1693. if (!szFileName) {
  1694. ErrorMsg(TEXT("GetSigFileName: szFileName is NULL."));
  1695. return FALSE;
  1696. }
  1697. if (!szOutName) {
  1698. ErrorMsg(TEXT("GetSigFileName: szOutName is NULL."));
  1699. return FALSE;
  1700. }
  1701.   GetSigDir(szSigDir);
  1702. // Hash szFileName.
  1703. if (RCRYPT_FAILED(CryptCreateHash(hMe, CALG_SHA, 0, 0, &hHash))) {
  1704. ErrorMsg(TEXT("GetSigFileName: CryptCreateHash failed."));
  1705. return FALSE;
  1706. }
  1707. if (RCRYPT_FAILED(CryptHashData(hHash, (LPBYTE)szFileName, lstrlen(szFileName) * sizeof(*szFileName), 0))) {
  1708. ErrorMsg(TEXT("GetSigFileName: CryptHashData failed."));
  1709. return FALSE;
  1710. }
  1711. dwHashLen = SHA_SIZE;
  1712. if (RCRYPT_FAILED(CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0))) {
  1713. ErrorMsg(TEXT("GetSigFileName: CryptFinishHash failed."));
  1714. return FALSE;
  1715. }
  1716. // Convert the hash to ascii
  1717. if (!SHAtoRadix64(pbHash, szFileBuf)) {
  1718. ErrorMsg(TEXT("DrvWndProc: FILLFILE: SHAtoRadix64 failed."));
  1719. return 0;
  1720. }
  1721. lstrcpy(szOutName, szSigDir);
  1722. lstrcat(szOutName, TEXT("\"));
  1723. lstrcat(szOutName, szFileBuf);
  1724. CryptDestroyHash(hHash);
  1725. }
  1726. /************************************************************************
  1727. * HasSignature()
  1728. *
  1729. * in parameters
  1730. * szFileName - full path of filename in question
  1731. * sigtable - pointer to a string table with displayed fields containing
  1732. * the filenames of all the files in the sig directory, which is located
  1733. * on the same drive as the system directory.
  1734. *
  1735. * out parameters
  1736. * bHasSignature - flag specifying whether szFileName has a signature
  1737. *
  1738. * purpose:
  1739. * determines whether sigszFileName has a signature by calling
  1740. * GetSigFileName.
  1741. *
  1742. * returns
  1743. * TRUE if such a file exists
  1744. * FALSE otherwise or if unsuccessful
  1745. ************************************************************************/
  1746. BOOL HasSignature(LPTSTR szFileName, TABLE sigtable, BOOL *bHasSignature) {
  1747. TCHAR szFileName2[PATH_SIZE];
  1748. if (!szFileName) {
  1749. ErrorMsg(TEXT("HasSignature: szFileName is NULL."));
  1750. return FALSE;
  1751. }
  1752. if (!bHasSignature) {
  1753. ErrorMsg(TEXT("HasSignature: bHasSignature is NULL."));
  1754. return FALSE;
  1755. }
  1756. if (!GetSigFileName(szFileName, szFileName2)) {
  1757. ErrorMsg(TEXT("HasSignature: GetSigFileName failed."));
  1758. return FALSE;
  1759. }
  1760. // Does this file exist?
  1761. if (TableFind(sigtable, szFileName2))
  1762. *bHasSignature = TRUE;
  1763. else
  1764. *bHasSignature = FALSE;
  1765. }
  1766. /************************************************************************
  1767. * GetDecryptedFileName()
  1768. *
  1769. * in parameters
  1770. * hWnd - HWND specified by caller
  1771. * szFileName - full path of file
  1772. * out parameters
  1773. * szDecryptedFileName - buffer to hold full decrypted path
  1774. * hFileRead - pointer to file handle
  1775. *
  1776. * purpose:
  1777. * reads HEADER_SIZE bytes from szFileName, decrypts it with fnKey, and
  1778. * stores the result on szDecryptedFileName, the decrypted file name.
  1779. *
  1780. * returns:
  1781. * TRUE if successful
  1782. * FALSE if unsuccessful
  1783. ************************************************************************/
  1784. BOOL GetDecryptedFileName(HWND hWnd, 
  1785.   LPTSTR szFileName, 
  1786.   LPTSTR szDecryptedFileName, 
  1787.   HANDLE *hFileRead) {
  1788. DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  1789. DWORD dwNumBytesRead;
  1790. TCHAR szDir[PATH_SIZE];
  1791. HCRYPTKEY hfnKey;
  1792. if (!szFileName) {
  1793. MessageBox(hWnd, TEXT("GetDecryptedFileName: szFileName is NULL."), NULL, MB_OK);
  1794. return FALSE;
  1795. }
  1796. if (!szDecryptedFileName) {
  1797. MessageBox(hWnd, TEXT("GetDecryptedFileName: szDecryptedFileName is NULL."), NULL, MB_OK);
  1798. return FALSE;
  1799. }
  1800. hfnKey = GetfnKey(hWnd);
  1801. if (!hfnKey) {
  1802. MessageBox(hWnd, TEXT("GetDecryptedFileName: GetfnKey failed."), NULL, MB_OK);
  1803. return FALSE;
  1804. }
  1805. // Open encrypted file.
  1806. *hFileRead = CreateFile(szFileName, 
  1807.    GENERIC_READ, 
  1808.    0, 
  1809.    0, 
  1810.    OPEN_EXISTING, 
  1811.    GetFileAttributes(szFileName),
  1812.    0);
  1813. if (*hFileRead == INVALID_HANDLE_VALUE) {
  1814. MessageBox(hWnd, TEXT("GetDecryptedFileName: CreateFile failed."), NULL, MB_OK);
  1815. return FALSE;
  1816. }
  1817. // Read the encrypted filename from the disk.
  1818. if (!ReadFile(*hFileRead, 
  1819.     szDecryptedFileName, 
  1820.     HEADER_SIZE * sizeof(*szDecryptedFileName), 
  1821.     &dwNumBytesRead, 
  1822.     0))
  1823. return FALSE;
  1824. if (dwNumBytesRead != HEADER_SIZE * sizeof(*szDecryptedFileName)) {
  1825. SeparatePathName2(szFileName, szDir, szDecryptedFileName);
  1826. return FALSE;
  1827. }
  1828. // Decrypt the filename.
  1829. CryptDecrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szDecryptedFileName, &dwDataLen);
  1830. return TRUE;
  1831. }
  1832. /************************************************************************
  1833. * GetDecryptedDirName()
  1834. *
  1835. * in parameters
  1836. * hWnd - HWND specified by caller
  1837. * szDirectoryName - full path of directory
  1838. * bDeldirinfo - flag: TRUE means caller wants dirinfo to be deleted
  1839. *
  1840. * out parameters
  1841. * szDecryptedDirName - buffer to hold full decrypted pathname of
  1842. * szDirName
  1843. * hFileRead - pointer to file handle
  1844. *
  1845. * purpose:
  1846. * reads HEADER_SIZE bytes from file dirinfo in directory szDirectoryName,
  1847. * decrypts it with fnKey, and stores the result in szDecryptedDirName,
  1848. * a buffer to hold the decrypted directory name.
  1849. *
  1850. * returns
  1851. * TRUE if successful
  1852. * FALSE if unsuccessful
  1853. ************************************************************************/
  1854. BOOL GetDecryptedDirName(HWND hWnd, 
  1855.    LPTSTR szDirectoryName, 
  1856.    LPTSTR szDecryptedDirName, 
  1857.    BOOL bDeldirinfo,
  1858.    HANDLE *hFileRead) {
  1859. DWORD dwDataLen = HEADER_SIZE * sizeof(TCHAR);
  1860. DWORD dwNumBytesRead;
  1861. TCHAR szDir[PATH_SIZE];
  1862. TCHAR szBuf[PATH_SIZE];
  1863. HCRYPTKEY hfnKey;
  1864. hfnKey = GetfnKey(hWnd);
  1865. if (!hfnKey) {
  1866. MessageBox(hWnd, TEXT("GetDecryptedFileName: GetfnKey failed."), NULL, MB_OK);
  1867. return FALSE;
  1868. }
  1869. if (!szDirectoryName) {
  1870. MessageBox(hWnd, TEXT("GetDecryptedDirName: szDirectoryName is NULL."), NULL, MB_OK);
  1871. return FALSE;
  1872. }
  1873. if (!szDecryptedDirName) {
  1874. MessageBox(hWnd, TEXT("GetDecryptedDirNAme: szDecryptedDirName is NULL."), NULL, MB_OK);
  1875. return FALSE;
  1876. }
  1877. lstrcpy(szDir, szDirectoryName);
  1878. if (szDir[lstrlen(szDir) - 1] != TEXT('\'))
  1879. lstrcat(szDir, TEXT("\"));
  1880. lstrcat(szDir, TEXT("dirinfo"));
  1881. // open dirinfo in szDirectoryName.
  1882. *hFileRead = CreateFile(szDir,
  1883.     GENERIC_READ,
  1884.     0,
  1885.     0,
  1886.     OPEN_EXISTING,
  1887.     GetFileAttributes(szDir),
  1888.     0);
  1889. if (*hFileRead == INVALID_HANDLE_VALUE)
  1890. return FALSE;
  1891. // Read the encrypted filename from the disk.
  1892. if (!ReadFile(*hFileRead,
  1893.     szDecryptedDirName,
  1894.     HEADER_SIZE * sizeof(*szDecryptedDirName),
  1895.     &dwNumBytesRead,
  1896.     0))
  1897. return FALSE;
  1898. CloseHandle(*hFileRead);
  1899. // Decrypt the directoryname.
  1900. CryptDecrypt(hfnKey, 0, TRUE, 0, (LPBYTE)szDecryptedDirName, &dwDataLen);
  1901. // enclose the directory name with brackets.
  1902. lstrcpy(szBuf, TEXT("["));
  1903. lstrcat(szBuf, szDecryptedDirName);
  1904. lstrcat(szBuf, TEXT("]"));
  1905. lstrcpy(szDecryptedDirName, szBuf);
  1906. if (bDeldirinfo)
  1907. DeleteFile(szDir);
  1908. return TRUE;
  1909. }
  1910. /************************************************************************
  1911. * DecryptDir()
  1912. *
  1913. * in parameters
  1914. * hWnd - HWND specified by caller
  1915. * szDirName - Full path of directory to be decrypted
  1916. * lpCInfo - instance data for drive child
  1917. *
  1918. * purpose:
  1919. * recursively decrypts szDirName and all of its subdirectories.
  1920. *
  1921. * returns
  1922. * TRUE if successful
  1923. * FALSE if unsuccessful
  1924. ************************************************************************/
  1925. BOOL DecryptDir(HWND hWnd, LPTSTR szDirName, LPCINFO lpCInfo) {
  1926. INT i, j;
  1927. TCHAR szDir[PATH_SIZE];
  1928. TCHAR szDir2[PATH_SIZE];
  1929. TCHAR szFile[PATH_SIZE];
  1930. TCHAR szBuf2[PATH_SIZE];
  1931. TCHAR Buf[PATH_SIZE];
  1932. TCHAR szDecryptedDirName[PATH_SIZE];
  1933. TCHAR szFileName[PATH_SIZE];
  1934. TCHAR szDirName2[PATH_SIZE];
  1935. LPTSTR lpszDirName2;
  1936. HANDLE hFileRead;
  1937. HANDLE hFindFile;
  1938. WIN32_FIND_DATA FindFileData;
  1939. BOOL fNextFile;
  1940. DWORD dwLastError;
  1941. LONG lIndex, lCount;
  1942. if (!szDirName) {
  1943. MessageBox(hWnd, TEXT("DecryptDir: szDirName is NULL."), NULL, MB_OK);
  1944. return FALSE;
  1945. }
  1946. if (!lpCInfo) {
  1947. MessageBox(hWnd, TEXT("DecryptDir: lpCInfo is NULL."), NULL, MB_OK);
  1948. return FALSE;
  1949. }
  1950. GetDecryptedDirName(hWnd, szDirName, szDecryptedDirName, 1, &hFileRead);
  1951. // strip the brackets off szDecryptedDirName.
  1952. if (szDecryptedDirName[0] == TEXT('[')) {
  1953. for (i = 1, j = 0; szDecryptedDirName[i] 
  1954. && szDecryptedDirName[i] != TEXT(']'); i++, j++)
  1955. szBuf2[j] = szDecryptedDirName[i];
  1956. szBuf2[j] = TEXT('');
  1957. lstrcpy(szDecryptedDirName, szBuf2);
  1958. }
  1959. CloseHandle(hFileRead);
  1960. lpszDirName2 = szDirName2;
  1961. // Collapse the selected directory in the directory listbox.
  1962. lIndex = GetLBText(lpCInfo->hDirLB, Buf);
  1963. lCount = GetDirDepth(Buf, &lpszDirName2);
  1964. CollapseDir(lpCInfo, lIndex, lCount);
  1965. SeparatePathName2(szDirName, szDir, szFile);
  1966. // unhide the directory.
  1967. lstrcat(szDir, TEXT("\"));
  1968. lstrcat(szDir, szDecryptedDirName);
  1969. SetFileAttributes(szDirName, GetFileAttributes(szDirName) ^ FILE_ATTRIBUTE_HIDDEN);
  1970. // rename the directory to its original name.
  1971. #ifdef UNICODE
  1972. if (_wrename((const wchar_t *)szDirName, (const wchar_t *)szDir)) {
  1973. #else
  1974. if (rename(szDirName, szDir)) {
  1975. #endif
  1976. MessageBox(hWnd, TEXT("Another process is using this directory."), NULL, MB_OK);
  1977. return FALSE;
  1978. }
  1979. lstrcpy(szDir2, szDir);
  1980. lstrcat(szDir2, TEXT("\*"));
  1981. if ((hFindFile = FindFirstFile(szDir2, &FindFileData)) == INVALID_HANDLE_VALUE) {
  1982. MessageBox(hWnd, TEXT("DecryptDir: FindFirstFile failed."), NULL, MB_OK);
  1983. return FALSE;
  1984. }
  1985. // decrypt all the files in the directory, recursing on directories
  1986. do {
  1987. lstrcpy(szFileName, szDir);
  1988. lstrcat(szFileName, TEXT("\"));
  1989. lstrcat(szFileName, FindFileData.cFileName);
  1990. // is szFileName encrypted?
  1991. if (IsEncrypted(szFileName)
  1992.    && lstrcmp(FindFileData.cFileName, TEXT("."))
  1993.    && lstrcmp(FindFileData.cFileName, TEXT(".."))) {
  1994. // is szFileName a directory?
  1995. if (CFilerIsDirectory(szFileName)) {
  1996. // Decrypt the directory szFileName.
  1997. if (!DecryptDir(hWnd, szFileName, lpCInfo)) {
  1998. MessageBox(hWnd, TEXT("DecryptDir: DecryptDir failed."), NULL, MB_OK);
  1999. return FALSE;
  2000. }
  2001. }
  2002. // decrypt the file szFileName.
  2003. else if (!CFILERDecryptFile(hWnd, szFileName)) {
  2004. MessageBox(hWnd, TEXT("DecryptDir: CFILERDecryptFile failed."), NULL, MB_OK);
  2005. return FALSE;
  2006. }
  2007. }
  2008. fNextFile = FindNextFile(hFindFile, &FindFileData);
  2009. dwLastError = GetLastError();
  2010. } while (fNextFile || dwLastError != ERROR_NO_MORE_FILES);
  2011. FindClose(hFindFile);
  2012. return TRUE;
  2013. }
  2014. /************************************************************************
  2015. * GetSigDir()
  2016. *
  2017. * in parameters
  2018. * szSigDir - buffer to hold result
  2019. *
  2020. * purpose: 
  2021. * stores in buffer szSigDir the name of the directory containing
  2022. * the signatures
  2023. *
  2024. * returns
  2025. * TRUE if successful
  2026. * FALSE if unsuccessful
  2027. ************************************************************************/
  2028. BOOL GetSigDir(LPTSTR szSigDir)
  2029. {
  2030. TCHAR szSystemDirectory[PATH_SIZE];
  2031. if (!szSigDir) {
  2032. ErrorMsg(TEXT("GetSigDir: szSigDir is NULL."));
  2033. return FALSE;
  2034. }
  2035. // [system directory drive]:sig -> szSigDir
  2036. GetSystemDirectory(szSystemDirectory, PATH_SIZE * sizeof(*szSystemDirectory));
  2037. szSigDir[0] = szSystemDirectory[0];
  2038. szSigDir[1] = TEXT('');
  2039. lstrcat(szSigDir, TEXT(":\sig"));
  2040. return TRUE;
  2041. }