Leaked source code of windows server 2003
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.

817 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: fencrypt.cpp
  8. //
  9. // Contents: File encryption tool. Encrypts a file looking in the MY
  10. // system certificate store for the specifed subject common name
  11. // with exchange private keys.
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <windows.h>
  15. #include <assert.h>
  16. #include "wincrypt.h"
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <memory.h>
  21. //+-------------------------------------------------------------------------
  22. // Helper function to make MBCS from Unicode string
  23. //--------------------------------------------------------------------------
  24. BOOL WINAPI MkMBStr(PBYTE pbBuff, DWORD cbBuff, LPCWSTR wsz, char ** pszMB) {
  25. DWORD cbConverted;
  26. assert(pszMB != NULL);
  27. *pszMB = NULL;
  28. if(wsz == NULL)
  29. return(TRUE);
  30. // how long is the mb string
  31. cbConverted = WideCharToMultiByte( 0,
  32. 0,
  33. wsz,
  34. -1,
  35. NULL,
  36. 0,
  37. NULL,
  38. NULL);
  39. // get a buffer long enough
  40. if(pbBuff != NULL && cbConverted < cbBuff)
  41. *pszMB = (char *) pbBuff;
  42. else
  43. *pszMB = (char *) malloc(cbConverted);
  44. if(*pszMB == NULL) {
  45. SetLastError(ERROR_OUTOFMEMORY);
  46. return(FALSE);
  47. }
  48. // now convert to MB
  49. WideCharToMultiByte(0,
  50. 0,
  51. wsz,
  52. -1,
  53. *pszMB,
  54. cbConverted,
  55. NULL,
  56. NULL);
  57. return(TRUE);
  58. }
  59. //+-------------------------------------------------------------------------
  60. // Frees string allocated by the above function
  61. //--------------------------------------------------------------------------
  62. void WINAPI FreeMBStr(PBYTE pbBuff, char * szMB) {
  63. if((szMB != NULL) && (pbBuff != (PBYTE)szMB))
  64. free(szMB);
  65. }
  66. //+-------------------------------------------------------------------------
  67. // Win95 only supports CryptAcquireContextA. This function converts the
  68. // unicode parameters to multibyte.
  69. //--------------------------------------------------------------------------
  70. BOOL WINAPI CryptAcquireContextU(
  71. HCRYPTPROV *phProv,
  72. LPCWSTR lpContainer,
  73. LPCWSTR lpProvider,
  74. DWORD dwProvType,
  75. DWORD dwFlags) {
  76. BYTE rgb1[_MAX_PATH];
  77. BYTE rgb2[_MAX_PATH];
  78. char * szContainer = NULL;
  79. char * szProvider = NULL;
  80. LONG err;
  81. err = FALSE;
  82. if(
  83. MkMBStr(rgb1, _MAX_PATH, lpContainer, &szContainer) &&
  84. MkMBStr(rgb2, _MAX_PATH, lpProvider, &szProvider) )
  85. err = CryptAcquireContextA (
  86. phProv,
  87. szContainer,
  88. szProvider,
  89. dwProvType,
  90. dwFlags
  91. );
  92. FreeMBStr(rgb1, szContainer);
  93. FreeMBStr(rgb2, szProvider);
  94. return(err);
  95. }
  96. //+-------------------------------------------------------------------------
  97. // Helper function to allocated the output buffer
  98. // and call CryptDecodeObject.
  99. //--------------------------------------------------------------------------
  100. BOOL
  101. WINAPI
  102. MDecodeObject(
  103. IN DWORD dwEncodingType,
  104. IN LPCSTR lpszStructureType,
  105. IN const PBYTE pbEncoded,
  106. IN DWORD cbEncoded,
  107. OUT PVOID * ppvoid
  108. )
  109. {
  110. DWORD cb = 0;
  111. assert(ppvoid != NULL);
  112. *ppvoid = NULL;
  113. // get the size
  114. if(!CryptDecodeObject(
  115. dwEncodingType,
  116. lpszStructureType,
  117. pbEncoded,
  118. cbEncoded,
  119. 0, // dwFlags
  120. NULL,
  121. &cb
  122. ))
  123. return(FALSE);
  124. // allocate the buffer
  125. if( (*ppvoid = malloc(cb)) == NULL )
  126. {
  127. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  128. return(FALSE);
  129. }
  130. // Decode the data
  131. if(!CryptDecodeObject(
  132. dwEncodingType,
  133. lpszStructureType,
  134. pbEncoded,
  135. cbEncoded,
  136. 0, // dwFlags
  137. *ppvoid,
  138. &cb
  139. ))
  140. {
  141. free(*ppvoid);
  142. *ppvoid = NULL;
  143. return(FALSE);
  144. }
  145. return(TRUE);
  146. }
  147. //+-------------------------------------------------------------------------
  148. // Helper function to allocated the output buffer
  149. // and call CertRDNValueToStr.
  150. //--------------------------------------------------------------------------
  151. DWORD
  152. WINAPI
  153. MCertRDNValueToStr(
  154. IN DWORD dwValueType,
  155. IN PCERT_RDN_VALUE_BLOB pValue,
  156. OUT OPTIONAL LPSTR * ppsz
  157. )
  158. {
  159. DWORD cb = 0;
  160. assert(ppsz != NULL);
  161. *ppsz = NULL;
  162. // get the size
  163. cb = CertRDNValueToStrA(
  164. dwValueType,
  165. pValue,
  166. NULL,
  167. 0);
  168. // allocate the buffer
  169. if( (*ppsz = (LPSTR) malloc(cb)) == NULL )
  170. {
  171. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  172. return(0);
  173. }
  174. // now convert the CERT_RDN Value to an
  175. // ascii string based on the specified
  176. // ASN value type.
  177. // This shouldn't fail.
  178. return(CertRDNValueToStrA(
  179. dwValueType,
  180. pValue,
  181. *ppsz,
  182. cb));
  183. }
  184. //+-------------------------------------------------------------------------
  185. // Helper function to get and allocate the exported public key info
  186. //--------------------------------------------------------------------------
  187. BOOL
  188. WINAPI
  189. MCryptExportPublicKeyInfo(
  190. HCRYPTPROV hProv,
  191. DWORD dwKeySpec,
  192. PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
  193. )
  194. {
  195. DWORD cbPubKeyInfo;
  196. assert(ppPubKeyInfo != NULL);
  197. *ppPubKeyInfo = NULL;
  198. // get the size
  199. if(!CryptExportPublicKeyInfo(
  200. hProv,
  201. dwKeySpec,
  202. X509_ASN_ENCODING,
  203. NULL, // pPubKeyInfo
  204. &cbPubKeyInfo
  205. )
  206. )
  207. return(FALSE);
  208. // allocate the buffer
  209. if( (*ppPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) malloc(cbPubKeyInfo)) == NULL )
  210. {
  211. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  212. return(FALSE);
  213. }
  214. if(!CryptExportPublicKeyInfo(
  215. hProv,
  216. dwKeySpec,
  217. X509_ASN_ENCODING,
  218. *ppPubKeyInfo,
  219. &cbPubKeyInfo
  220. )
  221. )
  222. {
  223. free(*ppPubKeyInfo);
  224. *ppPubKeyInfo = NULL;
  225. return(FALSE);
  226. }
  227. return(TRUE);
  228. }
  229. //+-------------------------------------------------------------------------
  230. // Helper function to allocated the output buffer
  231. // and call CertGetCertificateContextProperty.
  232. //--------------------------------------------------------------------------
  233. BOOL
  234. WINAPI
  235. MCertGetCertificateContextProperty(
  236. IN PCCERT_CONTEXT pCertContext,
  237. IN DWORD dwPropId,
  238. OUT void ** ppvData
  239. )
  240. {
  241. DWORD cb = 0;
  242. assert(ppvData != NULL);
  243. *ppvData = NULL;
  244. // get the size
  245. if( !CertGetCertificateContextProperty(
  246. pCertContext,
  247. dwPropId,
  248. NULL,
  249. &cb))
  250. return(FALSE);
  251. // allocate the buffer
  252. if( (*ppvData = malloc(cb)) == NULL )
  253. {
  254. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  255. return(FALSE);
  256. }
  257. // Get the property out of the cert
  258. if( !CertGetCertificateContextProperty(
  259. pCertContext,
  260. dwPropId,
  261. *ppvData,
  262. &cb))
  263. {
  264. free(*ppvData);
  265. *ppvData = NULL;
  266. return(FALSE);
  267. }
  268. return(TRUE);
  269. }
  270. //+-------------------------------------------------------------------------
  271. // Helper function to allocated the output buffer
  272. // and call CryptEncryptMessage.
  273. //--------------------------------------------------------------------------
  274. BOOL
  275. WINAPI
  276. MCryptEncryptMessage(
  277. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  278. IN DWORD cRecipientCert,
  279. IN PCCERT_CONTEXT rgpRecipientCert[],
  280. IN const BYTE *pbToBeEncrypted,
  281. IN DWORD cbToBeEncrypted,
  282. OUT BYTE **ppbEncryptedBlob,
  283. OUT DWORD *pcbEncryptedBlob
  284. )
  285. {
  286. assert(ppbEncryptedBlob != NULL);
  287. *ppbEncryptedBlob = NULL;
  288. assert(pcbEncryptedBlob != NULL);
  289. *pcbEncryptedBlob = 0;
  290. // get the size
  291. if(!CryptEncryptMessage(
  292. pEncryptPara,
  293. cRecipientCert,
  294. rgpRecipientCert,
  295. pbToBeEncrypted,
  296. cbToBeEncrypted,
  297. NULL,
  298. pcbEncryptedBlob
  299. ))
  300. return(FALSE);
  301. // allocate the buffer
  302. if( (*ppbEncryptedBlob = (BYTE *) malloc(*pcbEncryptedBlob)) == NULL )
  303. {
  304. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  305. return(FALSE);
  306. }
  307. // encrypt the data
  308. if(!CryptEncryptMessage(
  309. pEncryptPara,
  310. cRecipientCert,
  311. rgpRecipientCert,
  312. pbToBeEncrypted,
  313. cbToBeEncrypted,
  314. *ppbEncryptedBlob,
  315. pcbEncryptedBlob))
  316. {
  317. free(*ppbEncryptedBlob);
  318. *ppbEncryptedBlob = NULL;
  319. *pcbEncryptedBlob = 0;
  320. return(FALSE);
  321. }
  322. return(TRUE);
  323. }
  324. //+-------------------------------------------------------------------------
  325. // Display FEncrypt usage.
  326. //--------------------------------------------------------------------------
  327. void
  328. Usage(void)
  329. {
  330. printf("Usage: FEncrypt [options] <SubjectName> <ClearTextFileName> <EncryptedFileName>\n");
  331. printf("Options are:\n");
  332. printf(" -RC2 - RC2 encryption\n");
  333. printf(" -RC4 - RC4 encryption\n");
  334. printf(" -SP3 - SP3 compatible encryption\n");
  335. printf(" -FIX - Fix by loading sp3crmsg.dll\n");
  336. exit(1);
  337. }
  338. //+-------------------------------------------------------------------------
  339. // Generalized error routine
  340. //--------------------------------------------------------------------------
  341. #define PRINTERROR(psz, err) _PrintError((psz), (err), __LINE__)
  342. void
  343. _PrintError(char *pszMsg, DWORD err, DWORD line)
  344. {
  345. printf("%s failed on line %u: %u(%x)\n", pszMsg, line, err, err);
  346. }
  347. //+-------------------------------------------------------------------------
  348. // Grovels the cert store looking for a cert with the specified
  349. // subject common name. Then checks to see that there are private
  350. // and public exchange keys.
  351. //--------------------------------------------------------------------------
  352. PCCERT_CONTEXT GetSubjectCertFromStore(
  353. HCERTSTORE hMyStore,
  354. const char * szSubjectName,
  355. HCRYPTPROV * phProv
  356. )
  357. {
  358. DWORD i, j;
  359. PCCERT_CONTEXT pCertContext = NULL;
  360. PCCERT_CONTEXT pCertContextLast = NULL;
  361. PCERT_NAME_INFO pNameInfo = NULL;
  362. LPSTR sz = NULL;
  363. PCRYPT_KEY_PROV_INFO pProvInfo = NULL;
  364. HCRYPTPROV hProv = NULL;
  365. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  366. assert(hMyStore != NULL);
  367. assert(phProv != NULL);
  368. *phProv = NULL;
  369. // Enum all certs looking for the requested common
  370. // subject name that has private keys (so we know we can decrypt)
  371. while( hProv == NULL &&
  372. (pCertContext = CertEnumCertificatesInStore(
  373. hMyStore,
  374. pCertContextLast)) != NULL)
  375. {
  376. // decode the subject name into RDNs
  377. if(MDecodeObject(X509_ASN_ENCODING, X509_NAME,
  378. pCertContext->pCertInfo->Subject.pbData,
  379. pCertContext->pCertInfo->Subject.cbData,
  380. (void **) &pNameInfo)
  381. )
  382. {
  383. // loop thru looking for an CERT_RDN and COMMON Name that works
  384. for(i=0; i<pNameInfo->cRDN && hProv == NULL; i++)
  385. {
  386. for(j=0; j<pNameInfo->rgRDN[i].cRDNAttr && hProv == NULL; j++)
  387. {
  388. // check to see if this is the common name
  389. if( !strcmp(pNameInfo->rgRDN[i].rgRDNAttr[j].pszObjId,
  390. szOID_COMMON_NAME) )
  391. {
  392. // convert the string to something I can read
  393. MCertRDNValueToStr(
  394. pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType,
  395. &pNameInfo->rgRDN[i].rgRDNAttr[j].Value,
  396. &sz);
  397. // see if this is a viable certificate to use
  398. if( sz == NULL ||
  399. // see if it is the common name we are looking for
  400. _stricmp(sz, szSubjectName) ||
  401. // see if there are associated private keys
  402. // to ensure we can decrypt the data later
  403. !MCertGetCertificateContextProperty(
  404. pCertContext,
  405. CERT_KEY_PROV_INFO_PROP_ID,
  406. (void **) &pProvInfo) ||
  407. // Make sure it is an exchange key for encryption
  408. pProvInfo->dwKeySpec != AT_KEYEXCHANGE ||
  409. // see if the keys are really there
  410. !CryptAcquireContextU(
  411. &hProv,
  412. pProvInfo->pwszContainerName,
  413. pProvInfo->pwszProvName,
  414. pProvInfo->dwProvType,
  415. pProvInfo->dwFlags &
  416. ~CERT_SET_KEY_CONTEXT_PROP_ID)
  417. )
  418. {
  419. // On an error we didn't find a valid
  420. // key provider. Unfortunately, the CSP
  421. // may not leave the prov handle NULL
  422. // so clear it out
  423. hProv = NULL;
  424. }
  425. // Make sure the public keys in the
  426. // CSP match the public key in the certificate
  427. else if(
  428. // export the public key blob
  429. !MCryptExportPublicKeyInfo(
  430. hProv,
  431. pProvInfo->dwKeySpec,
  432. &pPubKeyInfo
  433. ) ||
  434. // see if the public keys compare with
  435. // what is in the certificate
  436. !CertComparePublicKeyInfo(
  437. X509_ASN_ENCODING,
  438. &pCertContext->pCertInfo->SubjectPublicKeyInfo,
  439. pPubKeyInfo
  440. )
  441. )
  442. // if the keys didn't compare, then we don't
  443. // want to use this ceritificate
  444. {
  445. // close the hProv, we didn't find a valid cert
  446. assert(hProv != NULL);
  447. CryptReleaseContext(hProv, 0);
  448. hProv = NULL;
  449. }
  450. // free public key info
  451. if(pPubKeyInfo != NULL)
  452. {
  453. free(pPubKeyInfo);
  454. pPubKeyInfo = NULL;
  455. }
  456. // clean up opened prov info
  457. if(pProvInfo != NULL)
  458. {
  459. free(pProvInfo);
  460. pProvInfo = NULL;
  461. }
  462. // free the space for the ascii common name
  463. if(sz != NULL)
  464. {
  465. free(sz);
  466. sz = NULL;
  467. }
  468. }
  469. }
  470. }
  471. // free the name info data
  472. if(pNameInfo != NULL)
  473. {
  474. free(pNameInfo);
  475. pNameInfo = NULL;
  476. }
  477. }
  478. // go to the next certificate
  479. pCertContextLast = pCertContext;
  480. }
  481. assert(pProvInfo == NULL);
  482. assert(sz == NULL);
  483. assert(pNameInfo == NULL);
  484. // There is a good cert in the store, return it
  485. if(hProv != NULL)
  486. {
  487. *phProv = hProv;
  488. assert(pCertContext != NULL);
  489. return(pCertContext);
  490. }
  491. return(NULL);
  492. }
  493. //+-------------------------------------------------------------------------
  494. // Main program. Open a file to encrypt,
  495. // encrypts it and then writes the encrypted
  496. // data to the output file.
  497. //--------------------------------------------------------------------------
  498. int __cdecl
  499. main(int argc, char * argv[])
  500. {
  501. DWORD dwExitValue = 0;
  502. HCERTSTORE hMyStore = NULL;
  503. PCCERT_CONTEXT pCertContext = NULL;
  504. HCRYPTPROV hProv = NULL;
  505. HANDLE hFileOut = INVALID_HANDLE_VALUE;
  506. HANDLE hFile = INVALID_HANDLE_VALUE;
  507. DWORD cbFile = 0;
  508. HANDLE hMap = NULL;
  509. PBYTE pbFile = NULL;
  510. BOOL fResult;
  511. HMODULE hDll = NULL;
  512. CMSG_SP3_COMPATIBLE_AUX_INFO SP3AuxInfo;
  513. BOOL fSP3 = FALSE;
  514. BOOL fFix = FALSE;
  515. CRYPT_ALGORITHM_IDENTIFIER encryptAlgId = {szOID_RSA_RC4, 0};
  516. CRYPT_ENCRYPT_MESSAGE_PARA encryptInfo;
  517. PBYTE pbEncryptedBlob = NULL;
  518. DWORD cbEncryptedBlob = 0;
  519. DWORD cb = 0;
  520. // Advance past fencrypt.exe and check for leading options
  521. while (--argc > 0) {
  522. if (**++argv != '-')
  523. break;
  524. if (0 == _stricmp(argv[0], "-RC2"))
  525. encryptAlgId.pszObjId = szOID_RSA_RC2CBC;
  526. else if (0 == _stricmp(argv[0], "-RC4"))
  527. encryptAlgId.pszObjId = szOID_RSA_RC4;
  528. else if (0 == _stricmp(argv[0], "-SP3"))
  529. fSP3 = TRUE;
  530. else if (0 == _stricmp(argv[0], "-FIX"))
  531. fFix = TRUE;
  532. else {
  533. printf("Bad option: %s\n", argv[0]);
  534. Usage();
  535. }
  536. }
  537. // must have the parameters
  538. if (argc != 3)
  539. Usage();
  540. if (fFix) {
  541. if (NULL == (hDll = LoadLibraryA("sp3crmsg.dll")))
  542. {
  543. PRINTERROR("LoadLibraryA(sp3crmsg.dll)", GetLastError());
  544. goto ErrCleanUp;
  545. }
  546. }
  547. // Open the MY store
  548. if( (hMyStore = CertOpenSystemStore(NULL, "My")) == NULL )
  549. {
  550. PRINTERROR("CertOpenSystemStore", GetLastError());
  551. goto ErrCleanUp;
  552. }
  553. // Find a certificate in the MY store that
  554. // matches the subject name and has private keys
  555. if( (pCertContext = GetSubjectCertFromStore(hMyStore, argv[0], &hProv)) == NULL)
  556. {
  557. printf("Unable to find certificate %s with valid keys.\n", argv[0]);
  558. goto ErrCleanUp;
  559. }
  560. // At this point we have a provider, Cert and a public key.
  561. // We should be able to encrypt
  562. // Read in the clear text file
  563. if(
  564. // read in the file to encrypt
  565. (hFile = CreateFileA(
  566. argv[1], // pointer to name of the file
  567. GENERIC_READ, // access (read-write) mode
  568. FILE_SHARE_READ, // share mode
  569. NULL, // pointer to security descriptor
  570. OPEN_EXISTING, // how to create
  571. FILE_ATTRIBUTE_NORMAL, // file attributes
  572. NULL // handle to file with attributes to copy
  573. )) == INVALID_HANDLE_VALUE ||
  574. // create a file mapping object
  575. (hMap = CreateFileMapping(
  576. hFile, // handle to file to map
  577. NULL, // optional security attributes
  578. PAGE_READONLY, // protection for mapping object
  579. 0, // high-order 32 bits of object size
  580. 0, // low-order 32 bits of object size
  581. NULL // name of file-mapping object
  582. )) == NULL ||
  583. // Map the file into the address space
  584. (pbFile = (PBYTE) MapViewOfFileEx(
  585. hMap, // file-mapping object to map into address space
  586. FILE_MAP_READ, // access mode
  587. 0, // high-order 32 bits of file offset
  588. 0, // low-order 32 bits of file offset
  589. 0, // number of bytes to map
  590. NULL // suggested starting address for mapped view
  591. )) == NULL
  592. )
  593. {
  594. PRINTERROR("File Open", GetLastError());
  595. goto ErrCleanUp;
  596. }
  597. // get the size of the file
  598. if( (cbFile = GetFileSize(
  599. hFile, // handle of file to get size of
  600. NULL // address of high-order word for file size
  601. )) == 0
  602. )
  603. {
  604. printf("File %s has a 0 length.\n", argv[1]);
  605. goto ErrCleanUp;
  606. }
  607. // at this point we have a file mapping, go ahead and encrypt the file
  608. // Do rc4 encryption
  609. memset(&encryptInfo, 0, sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
  610. encryptInfo.cbSize =
  611. sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
  612. encryptInfo.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  613. encryptInfo.hCryptProv = hProv;
  614. encryptInfo.ContentEncryptionAlgorithm = encryptAlgId;
  615. if (fSP3) {
  616. memset(&SP3AuxInfo, 0, sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO));
  617. SP3AuxInfo.cbSize = sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO);
  618. SP3AuxInfo.dwFlags = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  619. encryptInfo.pvEncryptionAuxInfo = &SP3AuxInfo;
  620. }
  621. // encrypt it
  622. fResult = MCryptEncryptMessage(
  623. &encryptInfo,
  624. 1,
  625. &pCertContext,
  626. pbFile,
  627. cbFile,
  628. &pbEncryptedBlob,
  629. &cbEncryptedBlob
  630. );
  631. if (!fResult && fSP3 && (DWORD) E_INVALIDARG == GetLastError()) {
  632. printf(
  633. "Non-NULL pvEncryptionAuxInfo not supported in SP3 crypt32.dll\n");
  634. encryptInfo.pvEncryptionAuxInfo = NULL;
  635. fResult = MCryptEncryptMessage(
  636. &encryptInfo,
  637. 1,
  638. &pCertContext,
  639. pbFile,
  640. cbFile,
  641. &pbEncryptedBlob,
  642. &cbEncryptedBlob
  643. );
  644. }
  645. if (!fResult) {
  646. PRINTERROR("MCryptEncryptMessage", GetLastError());
  647. goto ErrCleanUp;
  648. }
  649. // write the encrypted file out
  650. if(
  651. // open the output file
  652. (hFileOut = CreateFileA(
  653. argv[2], // pointer to name of the file
  654. GENERIC_WRITE, // access (read-write) mode
  655. FILE_SHARE_READ, // share mode
  656. NULL, // pointer to security descriptor
  657. CREATE_ALWAYS, // how to create
  658. FILE_ATTRIBUTE_NORMAL, // file attributes
  659. NULL // handle to file with attributes to copy
  660. )) == INVALID_HANDLE_VALUE ||
  661. //write to the file
  662. !WriteFile(
  663. hFileOut, // handle to file to write to
  664. pbEncryptedBlob, // pointer to data to write to file
  665. cbEncryptedBlob, // number of bytes to write
  666. &cb, // pointer to number of bytes written
  667. NULL // pointer to structure needed for overlapped I/O
  668. )
  669. )
  670. {
  671. PRINTERROR("File Write", GetLastError());
  672. goto ErrCleanUp;
  673. }
  674. CleanUp:
  675. if(hDll)
  676. FreeLibrary(hDll);
  677. if(hMap != NULL)
  678. CloseHandle(hMap);
  679. if(hFile != INVALID_HANDLE_VALUE && hFile != NULL)
  680. CloseHandle(hFile);
  681. if(hFileOut != INVALID_HANDLE_VALUE && hFile != NULL)
  682. CloseHandle(hFileOut);
  683. if(pCertContext != NULL)
  684. CertFreeCertificateContext(pCertContext);
  685. if(hProv != NULL)
  686. CryptReleaseContext(hProv, 0);
  687. if(hMyStore != NULL)
  688. CertCloseStore(hMyStore, 0);
  689. if(pbEncryptedBlob != NULL)
  690. free(pbEncryptedBlob);
  691. return(dwExitValue);
  692. ErrCleanUp:
  693. dwExitValue = 1;
  694. goto CleanUp;
  695. }