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.

1209 lines
34 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : client.cxx //
  3. // DESCRIPTION : Crypto API interface //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // Mar 8 1996 larrys New //
  7. // dbarlow //
  8. // //
  9. // Copyright (C) 1996 Microsoft Corporation All Rights Reserved //
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <stddef.h>
  14. #include <stdio.h>
  15. #include "mainrpc.h" // header file generated by the MIDL compiler
  16. #include <imagehlp.h>
  17. #include "des.h"
  18. #include "modes.h"
  19. #include "skrpc.h"
  20. extern "C" {
  21. #include "md5.h"
  22. };
  23. // designatred resource for in file signatures
  24. #define CRYPT_SIG_RESOURCE_NUMBER "#666"
  25. // MAC in file
  26. #define MAC_RESOURCE_NUMBER "#667"
  27. static DWORD dwMACInFileVersion = 0x100;
  28. BYTE rgbDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
  29. BOOL HashTheFile(
  30. LPCSTR pszFile,
  31. DWORD dwCRCOffset,
  32. BYTE *pbHash,
  33. DWORD *pcbHash,
  34. DWORD cbImage
  35. );
  36. DWORD GetCRCOffset(
  37. LPCSTR szFile,
  38. DWORD cbImage,
  39. DWORD *pdwCRCOffset
  40. );
  41. static DWORD dwSigInFileVersion = 0x100;
  42. DWORD SetCryptSignatureResource(
  43. LPCSTR szFile,
  44. DWORD dwSigVersion,
  45. DWORD dwCRCOffset,
  46. PBYTE pbNewSig,
  47. DWORD cbNewSig,
  48. DWORD cbImage
  49. );
  50. void ShowHelp();
  51. BOOL DumpFile(LPCTSTR szFile, const BYTE *pb, UINT cb);
  52. void CallServer(void);
  53. BYTE pbSignature[256];
  54. BYTE pbDigest[80];
  55. DWORD cbDigestLen = sizeof(pbDigest);
  56. DWORD cbSignatureLen = sizeof(pbSignature);
  57. // The function MACs the given bytes.
  58. void MACBytes(
  59. IN DESTable *pDESKeyTable,
  60. IN BYTE *pbData,
  61. IN DWORD cbData,
  62. IN OUT BYTE *pbTmp,
  63. IN OUT DWORD *pcbTmp,
  64. IN OUT BYTE *pbMAC,
  65. IN BOOL fFinal
  66. )
  67. {
  68. DWORD cb = cbData;
  69. DWORD cbMACed = 0;
  70. while (cb)
  71. {
  72. if ((cb + *pcbTmp) < DES_BLOCKLEN)
  73. {
  74. memcpy(pbTmp + *pcbTmp, pbData + cbMACed, cb);
  75. *pcbTmp += cb;
  76. break;
  77. }
  78. else
  79. {
  80. memcpy(pbTmp + *pcbTmp, pbData + cbMACed, DES_BLOCKLEN - *pcbTmp);
  81. CBC(des, DES_BLOCKLEN, pbMAC, pbTmp, pDESKeyTable,
  82. ENCRYPT, pbMAC);
  83. cbMACed = cbMACed + (DES_BLOCKLEN - *pcbTmp);
  84. cb = cb - (DES_BLOCKLEN - *pcbTmp);
  85. *pcbTmp = 0;
  86. }
  87. }
  88. }
  89. // Given hInst, allocs and returns pointers to MAC pulled from
  90. // resource
  91. BOOL GetResourcePtr(
  92. IN HMODULE hInst,
  93. IN LPSTR pszRsrcName,
  94. OUT BYTE **ppbRsrcMAC,
  95. OUT DWORD *pcbRsrcMAC
  96. )
  97. {
  98. HRSRC hRsrc;
  99. BOOL fRet = FALSE;
  100. // Nab resource handle for our signature
  101. if (NULL == (hRsrc = FindResourceA(hInst, pszRsrcName,
  102. RT_RCDATA)))
  103. goto Ret;
  104. // get a pointer to the actual signature data
  105. if (NULL == (*ppbRsrcMAC = (PBYTE)LoadResource(hInst, hRsrc)))
  106. goto Ret;
  107. // determine the size of the resource
  108. if (0 == (*pcbRsrcMAC = SizeofResource(hInst, hRsrc)))
  109. goto Ret;
  110. fRet = TRUE;
  111. Ret:
  112. return fRet;
  113. }
  114. #define CSP_TO_BE_MACED_CHUNK 4096
  115. // Given hFile, reads the specified number of bytes (cbToBeMACed) from the file
  116. // and MACs these bytes. The function does this in chunks.
  117. BOOL MACBytesOfFile(
  118. IN HANDLE hFile,
  119. IN DWORD cbToBeMACed,
  120. IN DESTable *pDESKeyTable,
  121. IN BYTE *pbTmp,
  122. IN DWORD *pcbTmp,
  123. IN BYTE *pbMAC,
  124. IN BYTE fFinal
  125. )
  126. {
  127. BYTE rgbChunk[CSP_TO_BE_MACED_CHUNK];
  128. DWORD cbRemaining = cbToBeMACed;
  129. DWORD cbToRead;
  130. DWORD dwBytesRead;
  131. BOOL fRet = FALSE;
  132. //
  133. // loop over the file for the specified number of bytes
  134. // updating the hash as we go.
  135. //
  136. while (cbRemaining > 0)
  137. {
  138. if (cbRemaining < CSP_TO_BE_MACED_CHUNK)
  139. cbToRead = cbRemaining;
  140. else
  141. cbToRead = CSP_TO_BE_MACED_CHUNK;
  142. if(!ReadFile(hFile, rgbChunk, cbToRead, &dwBytesRead, NULL))
  143. goto Ret;
  144. if (dwBytesRead != cbToRead)
  145. goto Ret;
  146. MACBytes(pDESKeyTable, rgbChunk, dwBytesRead, pbTmp, pcbTmp,
  147. pbMAC, fFinal);
  148. cbRemaining -= cbToRead;
  149. }
  150. fRet = TRUE;
  151. Ret:
  152. return fRet;
  153. }
  154. BOOL MACTheFileWithSig(
  155. LPCSTR pszImage,
  156. DWORD cbImage,
  157. IN DWORD dwMACVersion,
  158. IN DWORD dwCRCOffset,
  159. OUT BYTE *pbMAC
  160. )
  161. {
  162. HMODULE hInst = 0;
  163. MEMORY_BASIC_INFORMATION MemInfo;
  164. BYTE *pbRsrcMAC;
  165. DWORD cbRsrcMAC;
  166. BYTE *pbRsrcSig;
  167. DWORD cbRsrcSig;
  168. BYTE *pbStart;
  169. BYTE rgbMAC[DES_BLOCKLEN];
  170. BYTE rgbZeroMAC[DES_BLOCKLEN + sizeof(DWORD) * 2];
  171. BYTE rgbZeroSig[144];
  172. BYTE *pbPostCRC; // pointer to just after CRC
  173. DWORD cbCRCToRsrc1; // number of bytes from CRC to first rsrc
  174. DWORD cbRsrc1ToRsrc2; // number of bytes from first rsrc to second
  175. DWORD cbPostRsrc; // size - (already hashed + signature size)
  176. BYTE *pbRsrc1ToRsrc2;
  177. BYTE *pbPostRsrc;
  178. BYTE *pbZeroRsrc1;
  179. BYTE *pbZeroRsrc2;
  180. DWORD cbZeroRsrc1;
  181. DWORD cbZeroRsrc2;
  182. DWORD dwZeroCRC = 0;
  183. DWORD dwBytesRead = 0;
  184. OFSTRUCT ImageInfoBuf;
  185. HFILE hFile = HFILE_ERROR;
  186. HANDLE hMapping = NULL;
  187. DESTable DESKeyTable;
  188. BYTE rgbTmp[DES_BLOCKLEN];
  189. DWORD cbTmp = 0;
  190. BOOL fRet = FALSE;
  191. memset(&MemInfo, 0, sizeof(MemInfo));
  192. memset(rgbMAC, 0, sizeof(rgbMAC));
  193. memset(rgbTmp, 0, sizeof(rgbTmp));
  194. // Load the file
  195. if (HFILE_ERROR == (hFile = OpenFile(pszImage, &ImageInfoBuf,
  196. OF_READ)))
  197. {
  198. goto Ret;
  199. }
  200. hMapping = CreateFileMapping((HANDLE)IntToPtr(hFile),
  201. NULL,
  202. PAGE_READONLY,
  203. 0,
  204. 0,
  205. NULL);
  206. if(hMapping == NULL)
  207. {
  208. goto Ret;
  209. }
  210. hInst = (HMODULE)MapViewOfFile(hMapping,
  211. FILE_MAP_READ,
  212. 0,
  213. 0,
  214. 0);
  215. if(hInst == NULL)
  216. {
  217. goto Ret;
  218. }
  219. pbStart = (BYTE*)hInst;
  220. // Convert pointer to HMODULE, using the same scheme as
  221. // LoadLibrary (windows\base\client\module.c).
  222. *((ULONG_PTR*)&hInst) |= 0x00000001;
  223. // the MAC resource
  224. if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbRsrcMAC, &cbRsrcMAC))
  225. goto Ret;
  226. // the MAC resource
  227. if (!GetResourcePtr(hInst, CRYPT_SIG_RESOURCE_NUMBER, &pbRsrcSig, &cbRsrcSig))
  228. goto Ret;
  229. if (cbRsrcMAC < (sizeof(DWORD) * 2))
  230. goto Ret;
  231. // create a zero byte MAC
  232. memset(rgbZeroMAC, 0, sizeof(rgbZeroMAC));
  233. // create a zero byte Sig
  234. memset(rgbZeroSig, 0, sizeof(rgbZeroSig));
  235. // set up the pointers
  236. pbPostCRC = pbStart + dwCRCOffset + sizeof(DWORD);
  237. if (pbRsrcSig > pbRsrcMAC) // MAC is first Rsrc
  238. {
  239. cbCRCToRsrc1 = (DWORD)(pbRsrcMAC - pbPostCRC);
  240. pbRsrc1ToRsrc2 = pbRsrcMAC + cbRsrcMAC;
  241. cbRsrc1ToRsrc2 = (DWORD)(pbRsrcSig - pbRsrc1ToRsrc2);
  242. pbPostRsrc = pbRsrcSig + cbRsrcSig;
  243. cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
  244. // zero pointers
  245. pbZeroRsrc1 = rgbZeroMAC;
  246. cbZeroRsrc1 = cbRsrcMAC;
  247. pbZeroRsrc2 = rgbZeroSig;
  248. cbZeroRsrc2 = cbRsrcSig;
  249. }
  250. else // Sig is first Rsrc
  251. {
  252. cbCRCToRsrc1 = (DWORD)(pbRsrcSig - pbPostCRC);
  253. pbRsrc1ToRsrc2 = pbRsrcSig + cbRsrcSig;
  254. cbRsrc1ToRsrc2 = (DWORD)(pbRsrcMAC - pbRsrc1ToRsrc2);
  255. pbPostRsrc = pbRsrcMAC + cbRsrcMAC;
  256. cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
  257. // zero pointers
  258. pbZeroRsrc1 = rgbZeroSig;
  259. cbZeroRsrc1 = cbRsrcSig;
  260. pbZeroRsrc2 = rgbZeroMAC;
  261. cbZeroRsrc2 = cbRsrcMAC;
  262. }
  263. // init the key table
  264. deskey(&DESKeyTable, rgbDESKey);
  265. // MAC up to the CRC
  266. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), dwCRCOffset, &DESKeyTable, rgbTmp,
  267. &cbTmp, rgbMAC, FALSE))
  268. {
  269. goto Ret;
  270. }
  271. // pretend CRC is zeroed
  272. MACBytes(&DESKeyTable, (BYTE*)&dwZeroCRC, sizeof(DWORD), rgbTmp, &cbTmp,
  273. rgbMAC, FALSE);
  274. if (!SetFilePointer((HANDLE)IntToPtr(hFile), sizeof(DWORD), NULL, FILE_CURRENT))
  275. {
  276. goto Ret;
  277. }
  278. // MAC from CRC to first resource
  279. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbCRCToRsrc1, &DESKeyTable, rgbTmp,
  280. &cbTmp, rgbMAC, FALSE))
  281. {
  282. goto Ret;
  283. }
  284. // pretend image has zeroed first resource
  285. MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc1, cbZeroRsrc1, rgbTmp, &cbTmp,
  286. rgbMAC, FALSE);
  287. if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc1, NULL, FILE_CURRENT))
  288. {
  289. goto Ret;
  290. }
  291. // MAC from first resource to second
  292. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbRsrc1ToRsrc2, &DESKeyTable, rgbTmp,
  293. &cbTmp, rgbMAC, FALSE))
  294. {
  295. goto Ret;
  296. }
  297. // pretend image has zeroed second Resource
  298. MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc2, cbZeroRsrc2, rgbTmp, &cbTmp,
  299. rgbMAC, FALSE);
  300. if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc2, NULL, FILE_CURRENT))
  301. {
  302. goto Ret;
  303. }
  304. // MAC after the resource
  305. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbPostRsrc, &DESKeyTable, rgbTmp, &cbTmp,
  306. rgbMAC, TRUE))
  307. {
  308. goto Ret;
  309. }
  310. memcpy(pbMAC, rgbMAC, DES_BLOCKLEN);
  311. fRet = TRUE;
  312. Ret:
  313. if(hInst)
  314. UnmapViewOfFile(hInst);
  315. if(hMapping)
  316. CloseHandle(hMapping);
  317. if (HFILE_ERROR != hFile)
  318. _lclose(hFile);
  319. return fRet;
  320. }
  321. // SetCryptMACResource
  322. //
  323. // slams MAC resource in file with the new MAC
  324. //
  325. DWORD SetCryptMACResource(
  326. IN LPCSTR szFile,
  327. IN DWORD dwMACVersion,
  328. IN DWORD dwCRCOffset,
  329. IN PBYTE pbNewMAC,
  330. IN DWORD cbImage
  331. )
  332. {
  333. DWORD dwErr = 0x1;
  334. HANDLE hFileProv = NULL;
  335. HMODULE hInst = NULL;
  336. PBYTE pbFilePtr = NULL;
  337. DWORD cbImageSize, cbMACOffset;
  338. PBYTE pbMAC;
  339. DWORD cbMAC;
  340. MEMORY_BASIC_INFORMATION MemInfo;
  341. BYTE *pbStart;
  342. DWORD OldCheckSum;
  343. DWORD NewCheckSum;
  344. PIMAGE_NT_HEADERS pImageNTHdrs;
  345. HANDLE hFileMap = NULL;
  346. memset(&MemInfo, 0, sizeof(MemInfo));
  347. // Load the file as a datafile
  348. if (NULL == (hInst = LoadLibraryEx(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  349. {
  350. printf("Couldn't load file\n");
  351. goto Ret;
  352. }
  353. if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbMAC, &cbMAC))
  354. {
  355. printf("Couldn't find MAC placeholder\n");
  356. goto Ret;
  357. }
  358. // get image start address
  359. VirtualQuery(hInst, &MemInfo, sizeof(MemInfo));
  360. pbStart = (BYTE*)MemInfo.BaseAddress;
  361. FreeLibrary(hInst); hInst = NULL;
  362. cbMACOffset = (DWORD)(pbMAC - pbStart);
  363. if (cbMAC != (DES_BLOCKLEN + sizeof(DWORD) * 2))
  364. {
  365. printf("Attempt to replace %d zeros with new MAC!\n", cbMAC);
  366. goto Ret;
  367. }
  368. if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile,
  369. GENERIC_READ | GENERIC_WRITE,
  370. 0, // don't share
  371. NULL,
  372. OPEN_EXISTING,
  373. FILE_ATTRIBUTE_NORMAL,
  374. 0)))
  375. {
  376. printf("Couldn't CreateFile: 0x%x\n", GetLastError());
  377. goto Ret;
  378. }
  379. if (NULL == (hFileMap = CreateFileMapping(
  380. hFileProv,
  381. NULL,
  382. PAGE_READWRITE,
  383. 0,
  384. 0,
  385. NULL)))
  386. {
  387. printf("Couldn't map file\n");
  388. goto Ret;
  389. }
  390. if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile(
  391. hFileMap,
  392. FILE_MAP_ALL_ACCESS,
  393. 0,
  394. 0,
  395. 0)))
  396. {
  397. printf("Couldn't create view\n");
  398. goto Ret;
  399. }
  400. // copy version, CRC offset and new sig
  401. CopyMemory(pbFilePtr+cbMACOffset, &dwMACVersion, sizeof(dwMACVersion));
  402. cbMACOffset += sizeof(dwMACVersion);
  403. CopyMemory(pbFilePtr+cbMACOffset, &dwCRCOffset, sizeof(dwCRCOffset));
  404. cbMACOffset += sizeof(dwCRCOffset);
  405. CopyMemory(pbFilePtr+cbMACOffset, pbNewMAC, DES_BLOCKLEN);
  406. // compute a new checksum
  407. if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage,
  408. &OldCheckSum, &NewCheckSum)))
  409. goto Ret;
  410. CopyMemory(&pImageNTHdrs->OptionalHeader.CheckSum, &NewCheckSum, sizeof(DWORD));
  411. if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage,
  412. &OldCheckSum, &NewCheckSum)))
  413. goto Ret;
  414. if (OldCheckSum != NewCheckSum)
  415. goto Ret;
  416. dwErr = ERROR_SUCCESS;
  417. Ret:
  418. if (pbFilePtr)
  419. UnmapViewOfFile(pbFilePtr);
  420. if (hFileMap)
  421. CloseHandle(hFileMap);
  422. if (hInst)
  423. FreeLibrary(hInst);
  424. if (hFileProv)
  425. CloseHandle(hFileProv);
  426. return dwErr;
  427. }
  428. void MacCSP(
  429. LPCSTR pszInFile
  430. )
  431. {
  432. DWORD cbImage;
  433. DWORD dwCRCOffset;
  434. HANDLE hFileProv = INVALID_HANDLE_VALUE;
  435. BYTE rgbMAC[DES_BLOCKLEN];
  436. HMODULE hInst = NULL;
  437. PBYTE pbFilePtr = NULL;
  438. DWORD cbImageSize, cbMACOffset;
  439. PBYTE pbMAC;
  440. DWORD cbMAC;
  441. memset(rgbMAC, 0, sizeof(rgbMAC));
  442. // check if the MAC resource is in the CSP and exit if not
  443. // Load the file as a datafile
  444. if (NULL == (hInst = LoadLibraryEx(pszInFile,
  445. NULL,
  446. LOAD_LIBRARY_AS_DATAFILE)))
  447. {
  448. printf("Couldn't load file\n");
  449. goto Ret;
  450. }
  451. if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbMAC, &cbMAC))
  452. {
  453. goto Ret;
  454. }
  455. FreeLibrary(hInst);
  456. hInst = NULL;
  457. // get the file size
  458. if ((hFileProv = CreateFile(pszInFile,
  459. GENERIC_READ,
  460. FILE_SHARE_READ,
  461. NULL,
  462. OPEN_EXISTING,
  463. FILE_ATTRIBUTE_NORMAL,
  464. 0)) == INVALID_HANDLE_VALUE)
  465. {
  466. printf("CSP specified was not found!\n");
  467. goto Ret;
  468. }
  469. if (0xffffffff == (cbImage = GetFileSize(hFileProv, NULL)))
  470. {
  471. printf("CSP specified was not found!\n");
  472. goto Ret;
  473. }
  474. CloseHandle(hFileProv);
  475. hFileProv = NULL;
  476. if (0 != GetCRCOffset(pszInFile, cbImage, &dwCRCOffset))
  477. {
  478. printf("Unable to get CRC!\n");
  479. goto Ret;
  480. }
  481. // calculate the MAC
  482. if (!MACTheFileWithSig(pszInFile,
  483. cbImage,
  484. dwMACInFileVersion,
  485. dwCRCOffset,
  486. rgbMAC))
  487. {
  488. printf("MAC failed!\n");
  489. goto Ret;
  490. }
  491. //
  492. // Place the MAC into the resource in the file
  493. //
  494. if (ERROR_SUCCESS != SetCryptMACResource(pszInFile,
  495. dwMACInFileVersion,
  496. dwCRCOffset,
  497. rgbMAC,
  498. cbImage))
  499. {
  500. printf("Unable to set the MAC into the file resource!\n");
  501. goto Ret;
  502. }
  503. Ret:
  504. if (hInst)
  505. {
  506. FreeLibrary(hInst);
  507. }
  508. if (INVALID_HANDLE_VALUE != hFileProv)
  509. {
  510. CloseHandle(hFileProv);
  511. }
  512. return;
  513. }
  514. /*++
  515. main:
  516. This is the main entry point of the application.
  517. Arguments:
  518. argc - Count of arguments
  519. argv - array of arguments
  520. Return Value:
  521. 0 - Success
  522. 1 - Error
  523. Author:
  524. Doug Barlow (dbarlow) 1/25/1996
  525. --*/
  526. extern "C" void __cdecl
  527. main(
  528. int argc,
  529. char *argv[])
  530. {
  531. DWORD exStatus = 1;
  532. DWORD index;
  533. LPCTSTR szBinFile = NULL;
  534. LPCTSTR szInFile = NULL;
  535. BOOL fOutput = FALSE;
  536. int status;
  537. DWORD ThreadId;
  538. HANDLE hThread;
  539. // RPC Specific variables.
  540. RPC_STATUS rpcStatus;
  541. unsigned char * pszUuid = NULL;
  542. char * pszProtocolSequence = "ncacn_np";
  543. unsigned char * pszNetworkAddress = (LPBYTE)"\\\\enigma.ntdev.microsoft.com";
  544. char * pszEndpoint = "\\pipe\\sign";
  545. unsigned char * pszOptions = NULL;
  546. unsigned char * pszStringBinding = NULL;
  547. DWORD dwrt;
  548. DWORD i;
  549. DWORD cbImage;
  550. DWORD dwCRCOffset;
  551. HANDLE hFileProv = 0;
  552. //
  553. // Parse the command line.
  554. //
  555. if ((argc != 2) || (argv[1][0] == '?'))
  556. {
  557. ShowHelp();
  558. exStatus = 0;
  559. goto ErrorExit;
  560. }
  561. szInFile = &argv[1][0];
  562. //
  563. // Command consistency checks.
  564. //
  565. if (NULL == szInFile)
  566. {
  567. printf("No input file specified.\n");
  568. goto ErrorExit;
  569. }
  570. MacCSP(szInFile);
  571. // get the file size
  572. if ((hFileProv = CreateFile(szInFile,
  573. GENERIC_READ,
  574. FILE_SHARE_READ,
  575. NULL,
  576. OPEN_EXISTING,
  577. FILE_ATTRIBUTE_NORMAL,
  578. 0)) == INVALID_HANDLE_VALUE)
  579. {
  580. printf("CSP specified was not found!\n");
  581. goto ErrorExit;
  582. }
  583. if (0xffffffff == (cbImage = GetFileSize(hFileProv, NULL)))
  584. {
  585. printf("CSP specified was not found!\n");
  586. goto ErrorExit;
  587. }
  588. CloseHandle(hFileProv);
  589. hFileProv = NULL;
  590. if (ERROR_SUCCESS != GetCRCOffset(szInFile, cbImage, &dwCRCOffset))
  591. {
  592. printf("Unable to get the CRC offset on the file!\n");
  593. goto ErrorExit;
  594. }
  595. //
  596. // Compute the hash.
  597. //
  598. if (!HashTheFile(szInFile, dwCRCOffset, pbDigest, &cbDigestLen, cbImage))
  599. {
  600. printf("Unable to hash the file!\n");
  601. goto ErrorExit;
  602. }
  603. //
  604. // Get the signature.
  605. //
  606. // Try to make rpc connection
  607. rpcStatus = RpcStringBindingCompose(pszUuid,
  608. (unsigned char *) pszProtocolSequence,
  609. pszNetworkAddress,
  610. (unsigned char *) pszEndpoint,
  611. pszOptions,
  612. &pszStringBinding);
  613. #ifdef DEBUG
  614. printf("RpcStringBindingCompose returned 0x%x\n", rpcStatus);
  615. printf("pszStringBinding = %s\n", pszStringBinding);
  616. #endif
  617. if (0 != rpcStatus)
  618. {
  619. printf("Failed to compose binding string for target RPC server.\n");
  620. goto ErrorExit;
  621. }
  622. /* Set the binding handle that will */
  623. /* be used to bind to the server */
  624. rpcStatus = RpcBindingFromStringBinding(pszStringBinding,
  625. &hello_IfHandle);
  626. #ifdef DEBUG
  627. printf("RpcBindingFromStringBinding returned 0x%x\n", rpcStatus);
  628. #endif
  629. if (0 != rpcStatus)
  630. {
  631. printf("Failed to bind to target RPC server.\n");
  632. goto ErrorExit;
  633. }
  634. if ((hThread = CreateThread(NULL,
  635. 0,
  636. (LPTHREAD_START_ROUTINE) CallServer,
  637. NULL,
  638. 0,
  639. &ThreadId)) == NULL)
  640. {
  641. printf("Call to CreateThread failed\n");
  642. goto ErrorExit;
  643. }
  644. printf("Sending request to be signed, will wait 5 minutes\n");
  645. for (i = 0; i < 20; i++)
  646. {
  647. printf("Waited %d seconds\n", i*30);
  648. dwrt = WaitForSingleObject(hThread, 15000);
  649. if (dwrt == WAIT_OBJECT_0)
  650. {
  651. break;
  652. }
  653. }
  654. if (i == 20)
  655. {
  656. printf("Call to Server timed out\n");
  657. goto ErrorExit;
  658. }
  659. GetExitCodeThread(hThread, &dwrt);
  660. if (dwrt)
  661. {
  662. goto ErrorExit;
  663. }
  664. //
  665. // Place the signature into the resource in the file
  666. //
  667. if (ERROR_SUCCESS != SetCryptSignatureResource(szInFile, dwSigInFileVersion,
  668. dwCRCOffset, pbSignature,
  669. cbSignatureLen, cbImage))
  670. {
  671. printf("Unable to set the signature into the file resource!\n");
  672. goto ErrorExit;
  673. }
  674. //
  675. // Clean up and return.
  676. //
  677. exStatus = 0;
  678. ErrorExit:
  679. exit(exStatus);
  680. }
  681. void CallServer(void)
  682. {
  683. RpcTryExcept
  684. {
  685. cbSignatureLen = sizeof(pbSignature);
  686. if (GenSignature(pbDigest, &cbSignatureLen, pbSignature))
  687. {
  688. printf("GenSignature returned an error \n");
  689. ExitThread(TRUE);
  690. }
  691. }
  692. RpcExcept(1)
  693. {
  694. printf("RPC error -- exception code is 0x%X\n", RpcExceptionCode());
  695. ExitThread(RpcExceptionCode());
  696. }
  697. RpcEndExcept
  698. ExitThread(FALSE);
  699. }
  700. // Given hInst, allocs and returns pointers to signature pulled from
  701. // resource
  702. BOOL GetCryptSigResourcePtr(
  703. HMODULE hInst,
  704. BYTE **ppbRsrcSig,
  705. DWORD *pcbRsrcSig
  706. )
  707. {
  708. HRSRC hRsrc;
  709. BOOL fRet = FALSE;
  710. // Nab resource handle for our signature
  711. if (NULL == (hRsrc = FindResource(hInst, CRYPT_SIG_RESOURCE_NUMBER,
  712. RT_RCDATA)))
  713. goto Ret;
  714. // get a pointer to the actual signature data
  715. if (NULL == (*ppbRsrcSig = (PBYTE)LoadResource(hInst, hRsrc)))
  716. goto Ret;
  717. // determine the size of the resource
  718. if (0 == (*pcbRsrcSig = SizeofResource(hInst, hRsrc)))
  719. goto Ret;
  720. fRet = TRUE;
  721. Ret:
  722. return fRet;
  723. }
  724. // Given hInst, hashes over the file skipping, hashing zero bytes where the
  725. // resource is
  726. BOOL HashTheFile(
  727. LPCSTR pszFile,
  728. DWORD dwCRCOffset,
  729. BYTE *pbHash,
  730. DWORD *pcbHash,
  731. DWORD cbImage
  732. )
  733. {
  734. MEMORY_BASIC_INFORMATION MemInfo;
  735. BYTE *pbRsrcSig;
  736. DWORD cbRsrcSig;
  737. BYTE *pbStart;
  738. BYTE *pbZeroSig = NULL;
  739. MD5_CTX MD5Hash;
  740. DWORD dwZeroCRC = 0;
  741. DWORD cbPreCRC; // start of CRC
  742. DWORD cbCRCToSig; // end of CRC to start of sig
  743. BYTE *pbPostCRC; // just after CRC
  744. DWORD cbPostSig; // size - (already hashed + signature size)
  745. BYTE *pbPostSig;
  746. HMODULE hInst = 0;
  747. BOOL fRet = FALSE;
  748. memset(&MD5Hash, 0, sizeof(MD5Hash));
  749. memset(&MemInfo, 0, sizeof(MemInfo));
  750. // Load the file as a datafile
  751. if (NULL == (hInst = LoadLibraryEx(pszFile, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  752. goto Ret;
  753. // get image start address
  754. VirtualQuery(hInst, &MemInfo, sizeof(MemInfo));
  755. pbStart = (BYTE*)MemInfo.BaseAddress;
  756. // the resources signature
  757. if (!GetCryptSigResourcePtr(hInst, &pbRsrcSig, &cbRsrcSig))
  758. goto Ret;
  759. // create a zero byte signature
  760. if (NULL == (pbZeroSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, cbRsrcSig)))
  761. goto Ret;
  762. // want to hash the version and the CRC offset
  763. CopyMemory(pbZeroSig, &dwSigInFileVersion, sizeof(dwSigInFileVersion));
  764. CopyMemory(pbZeroSig + sizeof(dwSigInFileVersion), &dwCRCOffset,
  765. sizeof(dwCRCOffset));
  766. // hash over the relevant data
  767. {
  768. pbPostCRC = pbStart + dwCRCOffset + sizeof(dwZeroCRC);
  769. cbCRCToSig = (DWORD)(pbRsrcSig - pbPostCRC);
  770. pbPostSig = pbRsrcSig + cbRsrcSig;
  771. cbPostSig = (cbImage - (DWORD)(pbPostSig - pbStart));
  772. MD5Init(&MD5Hash);
  773. MD5Update(&MD5Hash, pbStart, dwCRCOffset);
  774. // pretend CRC is zeroed
  775. MD5Update(&MD5Hash, (BYTE*)&dwZeroCRC, sizeof(dwZeroCRC));
  776. // pretend image has zeroed sig
  777. MD5Update(&MD5Hash, pbPostCRC, cbCRCToSig);
  778. // pretend image has zeroed sig
  779. MD5Update(&MD5Hash, pbZeroSig, cbRsrcSig);
  780. MD5Update(&MD5Hash, pbPostSig, cbPostSig);
  781. // Finish the hash
  782. MD5Final(&MD5Hash);
  783. *pcbHash = MD5DIGESTLEN;
  784. memcpy(pbHash, MD5Hash.digest, MD5DIGESTLEN);
  785. }
  786. fRet = TRUE;
  787. Ret:
  788. if (hInst)
  789. FreeLibrary(hInst);
  790. if (pbZeroSig)
  791. LocalFree(pbZeroSig);
  792. return fRet;
  793. }
  794. DWORD GetCRCOffset(
  795. LPCSTR szFile,
  796. DWORD cbImage,
  797. DWORD *pdwCRCOffset
  798. )
  799. {
  800. DWORD dwErr = 0x1;
  801. HANDLE hFileProv = NULL;
  802. PBYTE pbFilePtr = NULL;
  803. DWORD OldCheckSum;
  804. DWORD NewCheckSum;
  805. PIMAGE_NT_HEADERS pImageNTHdrs;
  806. HANDLE hFileMap = NULL;
  807. if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile,
  808. GENERIC_READ | GENERIC_WRITE,
  809. 0, // don't share
  810. NULL,
  811. OPEN_EXISTING,
  812. FILE_ATTRIBUTE_NORMAL,
  813. 0)))
  814. {
  815. printf("Couldn't CreateFile: 0x%x\n", GetLastError());
  816. goto Ret;
  817. }
  818. if (NULL == (hFileMap = CreateFileMapping(
  819. hFileProv,
  820. NULL,
  821. PAGE_READWRITE,
  822. 0,
  823. 0,
  824. NULL)))
  825. {
  826. printf("Couldn't map file\n");
  827. goto Ret;
  828. }
  829. if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile(
  830. hFileMap,
  831. FILE_MAP_ALL_ACCESS,
  832. 0,
  833. 0,
  834. 0)))
  835. {
  836. printf("Couldn't create view\n");
  837. goto Ret;
  838. }
  839. // compute a new checksum
  840. if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage,
  841. &OldCheckSum, &NewCheckSum)))
  842. goto Ret;
  843. *pdwCRCOffset = (DWORD)((BYTE*)&pImageNTHdrs->OptionalHeader.CheckSum - pbFilePtr);
  844. dwErr = ERROR_SUCCESS;
  845. Ret:
  846. if (pbFilePtr)
  847. UnmapViewOfFile(pbFilePtr);
  848. if (hFileMap)
  849. CloseHandle(hFileMap);
  850. if (hFileProv)
  851. CloseHandle(hFileProv);
  852. return dwErr;
  853. }
  854. // SetCryptSignatureResource
  855. //
  856. // slams signature resource in file with the new signature
  857. //
  858. // szFile is file to modify
  859. // pbNewSig is new signature
  860. // cbNewSig is new signature length
  861. DWORD SetCryptSignatureResource(
  862. LPCSTR szFile,
  863. DWORD dwSigVersion,
  864. DWORD dwCRCOffset,
  865. PBYTE pbNewSig,
  866. DWORD cbNewSig,
  867. DWORD cbImage
  868. )
  869. {
  870. DWORD dwErr = 0x1;
  871. HANDLE hFileProv = NULL;
  872. HMODULE hInst = NULL;
  873. PBYTE pbFilePtr = NULL;
  874. DWORD cbImageSize, cbSigOffset;
  875. PBYTE pbSig;
  876. DWORD cbSig;
  877. MEMORY_BASIC_INFORMATION MemInfo;
  878. BYTE *pbStart;
  879. DWORD OldCheckSum;
  880. DWORD NewCheckSum;
  881. PIMAGE_NT_HEADERS pImageNTHdrs;
  882. HANDLE hFileMap = NULL;
  883. memset(&MemInfo, 0, sizeof(MemInfo));
  884. // Load the file as a datafile
  885. if (NULL == (hInst = LoadLibraryEx(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  886. {
  887. printf("Couldn't load file\n");
  888. goto Ret;
  889. }
  890. if (!GetCryptSigResourcePtr(hInst,
  891. &pbSig,
  892. &cbSig))
  893. {
  894. printf("Couldn't find signature placeholder\n");
  895. goto Ret;
  896. }
  897. // get image start address
  898. VirtualQuery(hInst, &MemInfo, sizeof(MemInfo));
  899. pbStart = (BYTE*)MemInfo.BaseAddress;
  900. FreeLibrary(hInst); hInst = NULL;
  901. cbSigOffset = (DWORD)(pbSig - pbStart);
  902. if (cbSig < (cbNewSig + (sizeof(DWORD) * 2)))
  903. {
  904. printf("Attempt to replace %d zeros with %d byte signature!\n", cbSig, cbNewSig);
  905. goto Ret;
  906. }
  907. if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile,
  908. GENERIC_READ | GENERIC_WRITE,
  909. 0, // don't share
  910. NULL,
  911. OPEN_EXISTING,
  912. FILE_ATTRIBUTE_NORMAL,
  913. 0)))
  914. {
  915. printf("Couldn't CreateFile: 0x%x\n", GetLastError());
  916. goto Ret;
  917. }
  918. if (NULL == (hFileMap = CreateFileMapping(
  919. hFileProv,
  920. NULL,
  921. PAGE_READWRITE,
  922. 0,
  923. 0,
  924. NULL)))
  925. {
  926. printf("Couldn't map file\n");
  927. goto Ret;
  928. }
  929. if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile(
  930. hFileMap,
  931. FILE_MAP_ALL_ACCESS,
  932. 0,
  933. 0,
  934. 0)))
  935. {
  936. printf("Couldn't create view\n");
  937. goto Ret;
  938. }
  939. // copy version, CRC offset and new sig
  940. CopyMemory(pbFilePtr+cbSigOffset, &dwSigVersion, sizeof(dwSigVersion));
  941. cbSigOffset += sizeof(dwSigVersion);
  942. CopyMemory(pbFilePtr+cbSigOffset, &dwCRCOffset, sizeof(dwCRCOffset));
  943. cbSigOffset += sizeof(dwCRCOffset);
  944. CopyMemory(pbFilePtr+cbSigOffset, pbNewSig, cbNewSig);
  945. if (cbSig > (cbNewSig + (sizeof(DWORD) * 2)))
  946. {
  947. ZeroMemory(pbFilePtr+cbSigOffset+cbNewSig,
  948. cbSig - (cbNewSig + (sizeof(DWORD) * 2)));
  949. }
  950. // compute a new checksum
  951. if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage,
  952. &OldCheckSum, &NewCheckSum)))
  953. goto Ret;
  954. CopyMemory(&pImageNTHdrs->OptionalHeader.CheckSum, &NewCheckSum, sizeof(DWORD));
  955. if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage,
  956. &OldCheckSum, &NewCheckSum)))
  957. goto Ret;
  958. if (OldCheckSum != NewCheckSum)
  959. goto Ret;
  960. dwErr = ERROR_SUCCESS;
  961. Ret:
  962. if (pbFilePtr)
  963. UnmapViewOfFile(pbFilePtr);
  964. if (hFileMap)
  965. CloseHandle(hFileMap);
  966. if (hInst)
  967. FreeLibrary(hInst);
  968. if (hFileProv)
  969. CloseHandle(hFileProv);
  970. return dwErr;
  971. }
  972. /*++
  973. ShowHelp:
  974. This routine displays a short help message to the given output stream.
  975. Arguments:
  976. ostr - The output stream to receive the help message.
  977. Return Value:
  978. None
  979. Author:
  980. Doug Barlow (dbarlow) 7/21/1995
  981. --*/
  982. void
  983. ShowHelp()
  984. {
  985. printf("CryptoAPI Internal CSP Signing Utility\n");
  986. printf("signcsp <filename>\n");
  987. }
  988. /* MIDL allocate and free */
  989. void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
  990. {
  991. return(malloc(len));
  992. }
  993. void __RPC_API midl_user_free(void __RPC_FAR * ptr)
  994. {
  995. free(ptr);
  996. }