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.

1567 lines
43 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : showsig.cpp //
  3. // DESCRIPTION : Crypto API interface //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // May 4 1998 jeffspel //
  7. // //
  8. // Copyright (C) 1998 Microsoft Corporation All Rights Reserved //
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include <windows.h>
  11. #include <stdlib.h>
  12. #include <stddef.h>
  13. #include <stdio.h>
  14. #include <rsa.h>
  15. #include <md5.h>
  16. #include <rc4.h>
  17. #include <des.h>
  18. #include <modes.h>
  19. #define MS_INTERNAL_KEY
  20. #define RC4_KEYSIZE 5
  21. #define KEYSIZE512 0x48
  22. #define KEYSIZE1024 0x88
  23. #define SIG_RESOURCE_NUM 1
  24. // designatred resource for in file signatures
  25. #define CRYPT_SIG_RESOURCE_NUMBER "#666"
  26. // MAC in file
  27. #define MAC_RESOURCE_NUMBER "#667"
  28. typedef struct _SECONDTIER_SIG
  29. {
  30. DWORD dwMagic;
  31. DWORD cbSig;
  32. BSAFE_PUB_KEY Pub;
  33. } SECOND_TIER_SIG, *PSECOND_TIER_SIG;
  34. BOOL g_fUseTestKey = TRUE;
  35. #ifdef TEST_BUILD_EXPONENT
  36. #pragma message("WARNING: building showsig.exe with TESTKEY enabled!")
  37. static struct _TESTKEY
  38. {
  39. BSAFE_PUB_KEY PUB;
  40. unsigned char pubmodulus[KEYSIZE512];
  41. } TESTKEY = {
  42. {
  43. 0x66b8443b,
  44. 0x6f5fc900,
  45. 0xa12132fe,
  46. 0xff1b06cf,
  47. 0x2f4826eb,
  48. },
  49. {
  50. 0x3e, 0x69, 0x4f, 0x45, 0x31, 0x95, 0x60, 0x6c,
  51. 0x80, 0xa5, 0x41, 0x99, 0x3e, 0xfc, 0x92, 0x2c,
  52. 0x93, 0xf9, 0x86, 0x23, 0x3d, 0x48, 0x35, 0x81,
  53. 0x19, 0xb6, 0x7c, 0x04, 0x43, 0xe6, 0x3e, 0xd4,
  54. 0xd5, 0x43, 0xaf, 0x52, 0xdd, 0x51, 0x20, 0xac,
  55. 0xc3, 0xca, 0xee, 0x21, 0x9b, 0x4a, 0x2d, 0xf7,
  56. 0xd8, 0x5f, 0x32, 0xeb, 0x49, 0x72, 0xb9, 0x8d,
  57. 0x2e, 0x1a, 0x76, 0x7f, 0xde, 0xc6, 0x75, 0xab,
  58. 0xaf, 0x67, 0xe0, 0xf0, 0x8b, 0x30, 0x20, 0x92,
  59. }
  60. };
  61. #endif
  62. static struct _mskey
  63. {
  64. BSAFE_PUB_KEY PUB;
  65. unsigned char pubmodulus[KEYSIZE1024];
  66. } MSKEY = {
  67. {
  68. 0x2bad85ae,
  69. 0x883adacc,
  70. 0xb32ebd68,
  71. 0xa7ec8b06,
  72. 0x58dbeb81,
  73. },
  74. {
  75. 0x42, 0x34, 0xb7, 0xab, 0x45, 0x0f, 0x60, 0xcd,
  76. 0x8f, 0x77, 0xb5, 0xd1, 0x79, 0x18, 0x34, 0xbe,
  77. 0x66, 0xcb, 0x5c, 0x66, 0x4a, 0x9f, 0x03, 0x18,
  78. 0x13, 0x36, 0x8e, 0x88, 0x21, 0x78, 0xb1, 0x94,
  79. 0xa1, 0xd5, 0x8f, 0x8c, 0xa5, 0xd3, 0x9f, 0x86,
  80. 0x43, 0x89, 0x05, 0xa0, 0xe3, 0xee, 0xe2, 0xd0,
  81. 0xe5, 0x1d, 0x5f, 0xaf, 0xff, 0x85, 0x71, 0x7a,
  82. 0x0a, 0xdb, 0x2e, 0xd8, 0xc3, 0x5f, 0x2f, 0xb1,
  83. 0xf0, 0x53, 0x98, 0x3b, 0x44, 0xee, 0x7f, 0xc9,
  84. 0x54, 0x26, 0xdb, 0xdd, 0xfe, 0x1f, 0xd0, 0xda,
  85. 0x96, 0x89, 0xc8, 0x9e, 0x2b, 0x5d, 0x96, 0xd1,
  86. 0xf7, 0x52, 0x14, 0x04, 0xfb, 0xf8, 0xee, 0x4d,
  87. 0x92, 0xd1, 0xb6, 0x37, 0x6a, 0xe0, 0xaf, 0xde,
  88. 0xc7, 0x41, 0x06, 0x7a, 0xe5, 0x6e, 0xb1, 0x8c,
  89. 0x8f, 0x17, 0xf0, 0x63, 0x8d, 0xaf, 0x63, 0xfd,
  90. 0x22, 0xc5, 0xad, 0x1a, 0xb1, 0xe4, 0x7a, 0x6b,
  91. 0x1e, 0x0e, 0xea, 0x60, 0x56, 0xbd, 0x49, 0xd0,
  92. }
  93. };
  94. static struct _key
  95. {
  96. BSAFE_PUB_KEY PUB;
  97. unsigned char pubmodulus[KEYSIZE1024];
  98. } KEY = {
  99. {
  100. 0x3fcbf1a9,
  101. 0x08f597db,
  102. 0xe4aecab4,
  103. 0x75360f90,
  104. 0x9d6c0f00,
  105. },
  106. {
  107. 0x85, 0xdd, 0x9b, 0xf4, 0x4d, 0x0b, 0xc4, 0x96,
  108. 0x3e, 0x79, 0x86, 0x30, 0x6d, 0x27, 0x31, 0xee,
  109. 0x4a, 0x85, 0xf5, 0xff, 0xbb, 0xa9, 0xbd, 0x81,
  110. 0x86, 0xf2, 0x4f, 0x87, 0x6c, 0x57, 0x55, 0x19,
  111. 0xe4, 0xf4, 0x49, 0xa3, 0x19, 0x27, 0x08, 0x82,
  112. 0x9e, 0xf9, 0x8a, 0x8e, 0x41, 0xd6, 0x91, 0x71,
  113. 0x47, 0x48, 0xee, 0xd6, 0x24, 0x2d, 0xdd, 0x22,
  114. 0x72, 0x08, 0xc6, 0xa7, 0x34, 0x6f, 0x93, 0xd2,
  115. 0xe7, 0x72, 0x57, 0x78, 0x7a, 0x96, 0xc1, 0xe1,
  116. 0x47, 0x38, 0x78, 0x43, 0x53, 0xea, 0xf3, 0x88,
  117. 0x82, 0x66, 0x41, 0x43, 0xd4, 0x62, 0x44, 0x01,
  118. 0x7d, 0xb2, 0x16, 0xb3, 0x50, 0x89, 0xdb, 0x0a,
  119. 0x93, 0x17, 0x02, 0x02, 0x46, 0x49, 0x79, 0x76,
  120. 0x59, 0xb6, 0xb1, 0x2b, 0xfc, 0xb0, 0x9a, 0x21,
  121. 0xe6, 0xfa, 0x2d, 0x56, 0x07, 0x36, 0xbc, 0x13,
  122. 0x7f, 0x1c, 0xde, 0x55, 0xfb, 0x0d, 0x67, 0x0f,
  123. 0xc2, 0x17, 0x45, 0x8a, 0x14, 0x2b, 0xba, 0x55,
  124. }
  125. };
  126. static struct _key2
  127. {
  128. BSAFE_PUB_KEY PUB;
  129. unsigned char pubmodulus[KEYSIZE1024];
  130. } KEY2 = {
  131. {
  132. 0x685fc690,
  133. 0x97d49b6b,
  134. 0x1dccd9d2,
  135. 0xa5ec9b52,
  136. 0x64fd29d7,
  137. },
  138. {
  139. 0x03, 0x8c, 0xa3, 0x9e, 0xfb, 0x93, 0xb6, 0x72,
  140. 0x2a, 0xda, 0x6f, 0xa5, 0xec, 0x26, 0x39, 0x58,
  141. 0x41, 0xcd, 0x3f, 0x49, 0x10, 0x4c, 0xcc, 0x7e,
  142. 0x23, 0x94, 0xf9, 0x5d, 0x9b, 0x2b, 0xa3, 0x6b,
  143. 0xe8, 0xec, 0x52, 0xd9, 0x56, 0x64, 0x74, 0x7c,
  144. 0x44, 0x6f, 0x36, 0xb7, 0x14, 0x9d, 0x02, 0x3c,
  145. 0x0e, 0x32, 0xb6, 0x38, 0x20, 0x25, 0xbd, 0x8c,
  146. 0x9b, 0xd1, 0x46, 0xa7, 0xb3, 0x58, 0x4a, 0xb7,
  147. 0xdd, 0x0e, 0x38, 0xb6, 0x16, 0x44, 0xbf, 0xc1,
  148. 0xca, 0x4d, 0x6a, 0x9f, 0xcb, 0x6f, 0x3c, 0x5f,
  149. 0x03, 0xab, 0x7a, 0xb8, 0x16, 0x70, 0xcf, 0x98,
  150. 0xd0, 0xca, 0x8d, 0x25, 0x57, 0x3a, 0x22, 0x8b,
  151. 0x44, 0x96, 0x37, 0x51, 0x30, 0x00, 0x92, 0x1b,
  152. 0x03, 0xb9, 0xf9, 0x0d, 0xb3, 0x1a, 0xe2, 0xb4,
  153. 0xc5, 0x7b, 0xc9, 0x4b, 0xe2, 0x42, 0x25, 0xfe,
  154. 0x3d, 0x42, 0xfa, 0x45, 0xc6, 0x94, 0xc9, 0x8e,
  155. 0x87, 0x7e, 0xf6, 0x68, 0x90, 0x30, 0x65, 0x10,
  156. }
  157. };
  158. void
  159. EncryptKey(
  160. BYTE *pdata,
  161. DWORD size,
  162. BYTE val)
  163. {
  164. RC4_KEYSTRUCT key;
  165. BYTE RealKey[RC4_KEYSIZE] = {0xa2, 0x17, 0x9c, 0x98, 0xca};
  166. DWORD index;
  167. for (index = 0; index < RC4_KEYSIZE; index++)
  168. {
  169. RealKey[index] = RealKey[index] ^ val;
  170. }
  171. rc4_key(&key, RC4_KEYSIZE, RealKey);
  172. rc4(&key, size, pdata);
  173. }
  174. void
  175. MD5HashData(
  176. BYTE *pb,
  177. DWORD cb,
  178. BYTE *pbHash)
  179. {
  180. MD5_CTX HashState;
  181. MD5Init(&HashState);
  182. MD5Update(&HashState, pb, cb);
  183. // Finish the hash
  184. MD5Final(&HashState);
  185. memcpy(pbHash, HashState.digest, 16);
  186. }
  187. BOOL
  188. CheckSignature(
  189. BYTE *pbKey,
  190. DWORD cbKey,
  191. BYTE *pbSig,
  192. DWORD cbSig,
  193. BYTE *pbHash,
  194. BOOL fUnknownLen)
  195. {
  196. BYTE rgbResult[KEYSIZE1024];
  197. BYTE rgbSig[KEYSIZE1024];
  198. BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  199. BYTE rgbKeyHash[16];
  200. BYTE *pbSecondKey;
  201. DWORD cbSecondKey;
  202. BYTE *pbKeySig;
  203. PSECOND_TIER_SIG pSecondTierSig;
  204. LPBSAFE_PUB_KEY pTmp;
  205. BOOL fRet = FALSE;
  206. memset(rgbResult, 0, KEYSIZE1024);
  207. memset(rgbSig, 0, KEYSIZE1024);
  208. // just check the straight signature if version is 1
  209. pTmp = (LPBSAFE_PUB_KEY)pbKey;
  210. // check if sig length is the same as the key length
  211. if (fUnknownLen || (cbSig == pTmp->keylen))
  212. {
  213. memcpy(rgbSig, pbSig, pTmp->keylen);
  214. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  215. if (RtlEqualMemory(pbHash, rgbResult, 16) &&
  216. rgbResult[cbKey-1] == 0 &&
  217. rgbResult[cbKey-2] == 1 &&
  218. rgbResult[16] == 0 &&
  219. rgbResult[17] == 0xFF)
  220. {
  221. fRet = TRUE;
  222. goto Ret;
  223. }
  224. }
  225. // check the the second tier signature if the magic equals 2
  226. pSecondTierSig = (PSECOND_TIER_SIG)pbSig;
  227. if (0x00000002 != pSecondTierSig->dwMagic)
  228. goto Ret;
  229. if (0x31415352 != pSecondTierSig->Pub.magic)
  230. goto Ret;
  231. // assign the pointers
  232. cbSecondKey = sizeof(BSAFE_PUB_KEY) + pSecondTierSig->Pub.keylen;
  233. pbSecondKey = pbSig + (sizeof(SECOND_TIER_SIG) - sizeof(BSAFE_PUB_KEY));
  234. pbKeySig = pbSecondKey + cbSecondKey;
  235. // hash the second tier key
  236. MD5HashData(pbSecondKey, cbSecondKey, rgbKeyHash);
  237. // Decrypt the signature data on the second tier key
  238. memset(rgbResult, 0, sizeof(rgbResult));
  239. memset(rgbSig, 0, sizeof(rgbSig));
  240. memcpy(rgbSig, pbKeySig, pSecondTierSig->cbSig);
  241. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  242. if ((FALSE == RtlEqualMemory(rgbKeyHash, rgbResult, 16)) ||
  243. rgbResult[cbKey-1] != 0 ||
  244. rgbResult[cbKey-2] != 1 ||
  245. rgbResult[16] != 0 ||
  246. rgbResult[17] != 0)
  247. {
  248. goto Ret;
  249. }
  250. // Decrypt the signature data on the CSP
  251. memset(rgbResult, 0, sizeof(rgbResult));
  252. memset(rgbSig, 0, sizeof(rgbSig));
  253. memset(rgbKey, 0, sizeof(rgbKey));
  254. memcpy(rgbSig, pbKeySig + pSecondTierSig->cbSig, pSecondTierSig->cbSig);
  255. memcpy(rgbKey, pbSecondKey, cbSecondKey);
  256. pTmp = (LPBSAFE_PUB_KEY)rgbKey;
  257. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  258. if (RtlEqualMemory(pbHash, rgbResult, 16) &&
  259. rgbResult[cbKey-1] == 0 &&
  260. rgbResult[cbKey-2] == 1 &&
  261. rgbResult[16] == 0)
  262. {
  263. fRet = TRUE;
  264. if (0xff != rgbResult[18])
  265. {
  266. DWORD dwI;
  267. printf("2nd Tier signature performed by ");
  268. for (dwI = 18; 0xff != rgbResult[dwI]; dwI += 1)
  269. printf("%c", rgbResult[dwI]);
  270. printf(".\n");
  271. }
  272. }
  273. Ret:
  274. return fRet;
  275. }
  276. // Given hInst, allocs and returns pointers to SIG and MAC pulled from
  277. // resource
  278. BOOL
  279. GetResourcePtr(
  280. IN HMODULE hInst,
  281. IN LPSTR pszRsrcName,
  282. OUT BYTE **ppbRsrcMAC,
  283. OUT DWORD *pcbRsrcMAC)
  284. {
  285. HRSRC hRsrc;
  286. BOOL fRet = FALSE;
  287. // Nab resource handle for our signature
  288. if (NULL == (hRsrc = FindResourceA(hInst, pszRsrcName,
  289. RT_RCDATA)))
  290. goto Ret;
  291. // get a pointer to the actual signature data
  292. if (NULL == (*ppbRsrcMAC = (PBYTE)LoadResource(hInst, hRsrc)))
  293. goto Ret;
  294. // determine the size of the resource
  295. if (0 == (*pcbRsrcMAC = SizeofResource(hInst, hRsrc)))
  296. goto Ret;
  297. fRet = TRUE;
  298. Ret:
  299. return fRet;
  300. }
  301. // GetCryptSignatureResource
  302. //
  303. DWORD
  304. GetCryptSignatureResource(
  305. LPCSTR szFile,
  306. PBYTE *ppbNewSig,
  307. DWORD *pcbNewSig)
  308. {
  309. DWORD dwErr = 0x1;
  310. BYTE *pbSig;
  311. HMODULE hInst = NULL;
  312. // Load the file as a datafile
  313. if (NULL == (hInst = LoadLibraryEx(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  314. {
  315. printf("Couldn't load file\n");
  316. goto Ret;
  317. }
  318. if (!GetResourcePtr(hInst,
  319. CRYPT_SIG_RESOURCE_NUMBER,
  320. &pbSig,
  321. pcbNewSig))
  322. {
  323. printf("Couldn't find signature placeholder\n");
  324. goto Ret;
  325. }
  326. if (NULL == (*ppbNewSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, *pcbNewSig)))
  327. goto Ret;
  328. memcpy(*ppbNewSig, pbSig, *pcbNewSig);
  329. dwErr = ERROR_SUCCESS;
  330. Ret:
  331. if (hInst)
  332. FreeLibrary(hInst);
  333. return dwErr;
  334. }
  335. #define CSP_TO_BE_MACED_CHUNK 4096
  336. // The function MACs the given bytes.
  337. void
  338. MACBytes(
  339. IN DESTable *pDESKeyTable,
  340. IN BYTE *pbData,
  341. IN DWORD cbData,
  342. IN OUT BYTE *pbTmp,
  343. IN OUT DWORD *pcbTmp,
  344. IN OUT BYTE *pbMAC,
  345. IN BOOL fFinal)
  346. {
  347. DWORD cb = cbData;
  348. DWORD cbMACed = 0;
  349. while (cb)
  350. {
  351. if ((cb + *pcbTmp) < DES_BLOCKLEN)
  352. {
  353. memcpy(pbTmp + *pcbTmp, pbData + cbMACed, cb);
  354. *pcbTmp += cb;
  355. break;
  356. }
  357. else
  358. {
  359. memcpy(pbTmp + *pcbTmp, pbData + cbMACed, DES_BLOCKLEN - *pcbTmp);
  360. CBC(des, DES_BLOCKLEN, pbMAC, pbTmp, pDESKeyTable,
  361. ENCRYPT, pbMAC);
  362. cbMACed = cbMACed + (DES_BLOCKLEN - *pcbTmp);
  363. cb = cb - (DES_BLOCKLEN - *pcbTmp);
  364. *pcbTmp = 0;
  365. }
  366. }
  367. }
  368. // Given hFile, reads the specified number of bytes (cbToBeMACed) from the file
  369. // and MACs these bytes. The function does this in chunks.
  370. BOOL
  371. MACBytesOfFile(
  372. IN HANDLE hFile,
  373. IN DWORD cbToBeMACed,
  374. IN DESTable *pDESKeyTable,
  375. IN BYTE *pbTmp,
  376. IN DWORD *pcbTmp,
  377. IN BYTE *pbMAC,
  378. IN BYTE fFinal)
  379. {
  380. BYTE rgbChunk[CSP_TO_BE_MACED_CHUNK];
  381. DWORD cbRemaining = cbToBeMACed;
  382. DWORD cbToRead;
  383. DWORD dwBytesRead;
  384. BOOL fRet = FALSE;
  385. //
  386. // loop over the file for the specified number of bytes
  387. // updating the hash as we go.
  388. //
  389. while (cbRemaining > 0)
  390. {
  391. if (cbRemaining < CSP_TO_BE_MACED_CHUNK)
  392. cbToRead = cbRemaining;
  393. else
  394. cbToRead = CSP_TO_BE_MACED_CHUNK;
  395. if (!ReadFile(hFile, rgbChunk, cbToRead, &dwBytesRead, NULL))
  396. goto Ret;
  397. if (dwBytesRead != cbToRead)
  398. goto Ret;
  399. MACBytes(pDESKeyTable, rgbChunk, dwBytesRead, pbTmp, pcbTmp,
  400. pbMAC, fFinal);
  401. cbRemaining -= cbToRead;
  402. }
  403. fRet = TRUE;
  404. Ret:
  405. return fRet;
  406. }
  407. BYTE rgbMACDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
  408. BOOL
  409. MACTheFile(
  410. LPCSTR pszImage,
  411. DWORD cbImage)
  412. {
  413. HMODULE hInst = 0;
  414. MEMORY_BASIC_INFORMATION MemInfo;
  415. BYTE *pbRsrcMAC;
  416. DWORD cbRsrcMAC;
  417. BYTE *pbRsrcSig;
  418. DWORD cbRsrcSig;
  419. BYTE *pbStart;
  420. BYTE rgbMAC[DES_BLOCKLEN];
  421. BYTE *pbZeroRsrc = NULL;
  422. BYTE *pbPostCRC; // pointer to just after CRC
  423. DWORD cbCRCToRsrc1; // number of bytes from CRC to first rsrc
  424. DWORD cbRsrc1ToRsrc2; // number of bytes from first rsrc to second
  425. DWORD cbPostRsrc; // size - (already hashed + signature size)
  426. BYTE *pbRsrc1ToRsrc2;
  427. BYTE *pbPostRsrc;
  428. BYTE *pbZeroRsrc1;
  429. BYTE *pbZeroRsrc2;
  430. DWORD cbZeroRsrc1;
  431. DWORD cbZeroRsrc2;
  432. DWORD *pdwMACInFileVer;
  433. DWORD *pdwCRCOffset;
  434. DWORD dwCRCOffset;
  435. DWORD dwZeroCRC = 0;
  436. DWORD dwBytesRead = 0;
  437. OFSTRUCT ImageInfoBuf;
  438. HFILE hFile = HFILE_ERROR;
  439. HANDLE hMapping = NULL;
  440. DESTable DESKeyTable;
  441. BYTE rgbTmp[DES_BLOCKLEN];
  442. DWORD cbTmp = 0;
  443. BOOL fRet = FALSE;
  444. DWORD i;
  445. memset(&MemInfo, 0, sizeof(MemInfo));
  446. memset(rgbMAC, 0, sizeof(rgbMAC));
  447. memset(rgbTmp, 0, sizeof(rgbTmp));
  448. // Load the file
  449. if (HFILE_ERROR == (hFile = OpenFile(pszImage, &ImageInfoBuf,
  450. OF_READ)))
  451. {
  452. goto Ret;
  453. }
  454. hMapping = CreateFileMapping((HANDLE)IntToPtr(hFile),
  455. NULL,
  456. PAGE_READONLY,
  457. 0,
  458. 0,
  459. NULL);
  460. if (hMapping == NULL)
  461. {
  462. goto Ret;
  463. }
  464. hInst = (HMODULE)MapViewOfFile(hMapping,
  465. FILE_MAP_READ,
  466. 0,
  467. 0,
  468. 0);
  469. if (hInst == NULL)
  470. {
  471. goto Ret;
  472. }
  473. pbStart = (BYTE*)hInst;
  474. // Convert pointer to HMODULE, using the same scheme as
  475. // LoadLibrary (windows\base\client\module.c).
  476. *((ULONG_PTR*)&hInst) |= 0x00000001;
  477. // the MAC resource
  478. if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbRsrcMAC, &cbRsrcMAC))
  479. goto Ret;
  480. // display the MAC
  481. printf("--- MAC Resource ---\n");
  482. for (i = 0; i < cbRsrcMAC; i++)
  483. {
  484. printf("0x%02X ", pbRsrcMAC[i]);
  485. if (((i + 1) % 8) == 0)
  486. printf("\n");
  487. }
  488. if (0 != (i % 8))
  489. printf("\n");
  490. // the Signature resource
  491. if (!GetResourcePtr(hInst, CRYPT_SIG_RESOURCE_NUMBER, &pbRsrcSig, &cbRsrcSig))
  492. {
  493. pbRsrcSig = NULL;
  494. cbRsrcSig = 0;
  495. }
  496. if (cbRsrcMAC < (sizeof(DWORD) * 2))
  497. goto Ret;
  498. // check the MAC in file version and get the CRC offset
  499. pdwMACInFileVer = (DWORD*)pbRsrcMAC;
  500. pdwCRCOffset = (DWORD*)(pbRsrcMAC + sizeof(DWORD));
  501. dwCRCOffset = *pdwCRCOffset;
  502. if ((0x00000100 != *pdwMACInFileVer) || (dwCRCOffset > cbImage))
  503. goto Ret;
  504. if (DES_BLOCKLEN != (cbRsrcMAC - (sizeof(DWORD) * 2)))
  505. {
  506. goto Ret;
  507. }
  508. // create a zero byte Sig
  509. pbZeroRsrc = (LPBYTE)LocalAlloc(LPTR, max(cbRsrcMAC, cbRsrcSig));
  510. // set up the pointers
  511. pbPostCRC = pbStart + *pdwCRCOffset + sizeof(DWORD);
  512. if (NULL == pbRsrcSig) // No sig resource
  513. {
  514. cbCRCToRsrc1 = (DWORD)(pbRsrcMAC - pbPostCRC);
  515. pbRsrc1ToRsrc2 = pbRsrcMAC + cbRsrcMAC;
  516. cbRsrc1ToRsrc2 = 0;
  517. pbPostRsrc = pbRsrcMAC + cbRsrcMAC;
  518. cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
  519. // zero pointers
  520. pbZeroRsrc1 = pbZeroRsrc;
  521. cbZeroRsrc1 = cbRsrcMAC;
  522. pbZeroRsrc2 = pbZeroRsrc;
  523. cbZeroRsrc2 = 0;
  524. }
  525. else if (pbRsrcSig > pbRsrcMAC) // MAC is first Rsrc
  526. {
  527. cbCRCToRsrc1 = (DWORD)(pbRsrcMAC - pbPostCRC);
  528. pbRsrc1ToRsrc2 = pbRsrcMAC + cbRsrcMAC;
  529. cbRsrc1ToRsrc2 = (DWORD)(pbRsrcSig - pbRsrc1ToRsrc2);
  530. pbPostRsrc = pbRsrcSig + cbRsrcSig;
  531. cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
  532. // zero pointers
  533. pbZeroRsrc1 = pbZeroRsrc;
  534. cbZeroRsrc1 = cbRsrcMAC;
  535. pbZeroRsrc2 = pbZeroRsrc;
  536. cbZeroRsrc2 = cbRsrcSig;
  537. }
  538. else // Sig is first Rsrc
  539. {
  540. cbCRCToRsrc1 = (DWORD)(pbRsrcSig - pbPostCRC);
  541. pbRsrc1ToRsrc2 = pbRsrcSig + cbRsrcSig;
  542. cbRsrc1ToRsrc2 = (DWORD)(pbRsrcMAC - pbRsrc1ToRsrc2);
  543. pbPostRsrc = pbRsrcMAC + cbRsrcMAC;
  544. cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
  545. // zero pointers
  546. pbZeroRsrc1 = pbZeroRsrc;
  547. cbZeroRsrc1 = cbRsrcSig;
  548. pbZeroRsrc2 = pbZeroRsrc;
  549. cbZeroRsrc2 = cbRsrcMAC;
  550. }
  551. // init the key table
  552. deskey(&DESKeyTable, rgbMACDESKey);
  553. // MAC up to the CRC
  554. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), dwCRCOffset, &DESKeyTable, rgbTmp,
  555. &cbTmp, rgbMAC, FALSE))
  556. {
  557. goto Ret;
  558. }
  559. // pretend CRC is zeroed
  560. MACBytes(&DESKeyTable, (BYTE*)&dwZeroCRC, sizeof(DWORD), rgbTmp, &cbTmp,
  561. rgbMAC, FALSE);
  562. if (!SetFilePointer((HANDLE)IntToPtr(hFile), sizeof(DWORD), NULL, FILE_CURRENT))
  563. {
  564. goto Ret;
  565. }
  566. // MAC from CRC to first resource
  567. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbCRCToRsrc1, &DESKeyTable, rgbTmp,
  568. &cbTmp, rgbMAC, FALSE))
  569. {
  570. goto Ret;
  571. }
  572. // pretend image has zeroed first resource
  573. MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc1, cbZeroRsrc1, rgbTmp, &cbTmp,
  574. rgbMAC, FALSE);
  575. if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc1, NULL, FILE_CURRENT))
  576. {
  577. goto Ret;
  578. }
  579. // MAC from first resource to second
  580. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbRsrc1ToRsrc2, &DESKeyTable, rgbTmp,
  581. &cbTmp, rgbMAC, FALSE))
  582. {
  583. goto Ret;
  584. }
  585. // pretend image has zeroed second Resource
  586. MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc2, cbZeroRsrc2, rgbTmp, &cbTmp,
  587. rgbMAC, FALSE);
  588. if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc2, NULL, FILE_CURRENT))
  589. {
  590. goto Ret;
  591. }
  592. // MAC after the resource
  593. if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbPostRsrc, &DESKeyTable, rgbTmp, &cbTmp,
  594. rgbMAC, TRUE))
  595. {
  596. goto Ret;
  597. }
  598. if (0 != memcmp(rgbMAC, pbRsrcMAC + sizeof(DWORD) * 2, DES_BLOCKLEN))
  599. goto Ret;
  600. fRet = TRUE;
  601. Ret:
  602. if (hInst)
  603. UnmapViewOfFile(hInst);
  604. if (hMapping)
  605. CloseHandle(hMapping);
  606. if (HFILE_ERROR != hFile)
  607. _lclose(hFile);
  608. if (NULL != pbZeroRsrc)
  609. LocalFree(pbZeroRsrc);
  610. return fRet;
  611. }
  612. // **********************************************************************
  613. // SelfMACCheck performs a DES MAC on the binary image of this DLL
  614. // **********************************************************************
  615. BOOL
  616. SelfMACCheck(
  617. IN LPCSTR pszImage)
  618. {
  619. HFILE hFileProv = HFILE_ERROR;
  620. DWORD cbImage;
  621. OFSTRUCT ImageInfoBuf;
  622. HMODULE hInst = NULL;
  623. PBYTE pbMAC;
  624. DWORD cbMAC;
  625. BOOL fRet = FALSE;
  626. // check if the MAC resource is in the CSP and exit if not
  627. // Load the file as a datafile
  628. if (NULL == (hInst = LoadLibraryEx(pszImage,
  629. NULL,
  630. LOAD_LIBRARY_AS_DATAFILE)))
  631. {
  632. fRet = TRUE;
  633. goto Ret;
  634. }
  635. if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbMAC, &cbMAC))
  636. {
  637. fRet = TRUE;
  638. goto Ret;
  639. }
  640. FreeLibrary(hInst);
  641. hInst = NULL;
  642. // Check file size
  643. if (HFILE_ERROR == (hFileProv = OpenFile(pszImage, &ImageInfoBuf, OF_READ)))
  644. {
  645. printf("FAILURE - Unable to open the requested file\n");
  646. goto Ret;
  647. }
  648. if (0xffffffff == (cbImage = GetFileSize((HANDLE)IntToPtr(hFileProv), NULL)))
  649. {
  650. printf("FAILURE - Unable to open the requested file\n");
  651. goto Ret;
  652. }
  653. _lclose(hFileProv);
  654. hFileProv = HFILE_ERROR;
  655. if (!MACTheFile(pszImage, cbImage))
  656. {
  657. printf("FAILURE - The MAC resource does not verify!\n");
  658. goto Ret;
  659. }
  660. else
  661. printf("MAC Verifies.\n\n");
  662. fRet = TRUE;
  663. Ret:
  664. if (hInst)
  665. {
  666. FreeLibrary(hInst);
  667. }
  668. if (HFILE_ERROR != hFileProv)
  669. _lclose(hFileProv);
  670. return fRet;
  671. }
  672. #define CSP_TO_BE_HASHED_CHUNK 4096
  673. // Given hFile, reads the specified number of bytes (cbToBeHashed) from the file
  674. // and hashes these bytes. The function does this in chunks.
  675. BOOL
  676. HashBytesOfFile(
  677. IN HFILE hFile,
  678. IN DWORD cbToBeHashed,
  679. IN OUT MD5_CTX *pMD5Hash)
  680. {
  681. BYTE rgbChunk[CSP_TO_BE_HASHED_CHUNK];
  682. DWORD cbRemaining = cbToBeHashed;
  683. DWORD cbToRead;
  684. DWORD dwBytesRead;
  685. BOOL fRet = FALSE;
  686. //
  687. // loop over the file for the specified number of bytes
  688. // updating the hash as we go.
  689. //
  690. while (cbRemaining > 0)
  691. {
  692. if (cbRemaining < CSP_TO_BE_HASHED_CHUNK)
  693. cbToRead = cbRemaining;
  694. else
  695. cbToRead = CSP_TO_BE_HASHED_CHUNK;
  696. if (!ReadFile((HANDLE)IntToPtr(hFile), rgbChunk, cbToRead, &dwBytesRead, NULL))
  697. goto Ret;
  698. if (dwBytesRead != cbToRead)
  699. goto Ret;
  700. MD5Update(pMD5Hash, rgbChunk, dwBytesRead);
  701. cbRemaining -= cbToRead;
  702. }
  703. fRet = TRUE;
  704. Ret:
  705. return fRet;
  706. }
  707. BOOL
  708. HashTheFile(
  709. LPCSTR pszImage,
  710. DWORD cbImage,
  711. BYTE **ppbSig,
  712. DWORD *pcbSig,
  713. BYTE *pbHash)
  714. {
  715. HMODULE hInst = 0;
  716. MEMORY_BASIC_INFORMATION MemInfo;
  717. BYTE *pbRsrcSig;
  718. DWORD cbRsrcSig;
  719. BYTE *pbStart;
  720. BYTE *pbZeroRsrc = NULL;
  721. MD5_CTX MD5Hash;
  722. BYTE *pbPostCRC; // pointer to just after CRC
  723. DWORD cbCRCToSig; // number of bytes from CRC to sig
  724. DWORD cbPostSig; // size - (already hashed + signature size)
  725. BYTE *pbPostSig;
  726. DWORD *pdwSigInFileVer;
  727. DWORD *pdwCRCOffset;
  728. DWORD dwCRCOffset;
  729. DWORD dwZeroCRC = 0;
  730. DWORD dwBytesRead = 0;
  731. OFSTRUCT ImageInfoBuf;
  732. HFILE hFile = HFILE_ERROR;
  733. BOOL fRet = FALSE;
  734. memset(&MD5Hash, 0, sizeof(MD5Hash));
  735. memset(&MemInfo, 0, sizeof(MemInfo));
  736. // Load the file as a datafile
  737. if (NULL == (hInst = LoadLibraryEx(pszImage, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  738. goto Ret;
  739. // get image start address
  740. VirtualQuery(hInst, &MemInfo, sizeof(MemInfo));
  741. pbStart = (BYTE*)MemInfo.BaseAddress;
  742. // the resources signature
  743. if ((NULL == ppbSig) || !GetResourcePtr(hInst, CRYPT_SIG_RESOURCE_NUMBER, &pbRsrcSig, &cbRsrcSig))
  744. {
  745. dwCRCOffset = 0;
  746. pbPostCRC = NULL;
  747. cbCRCToSig = 0;
  748. pbPostSig = NULL;
  749. cbPostSig = cbImage;
  750. cbRsrcSig = 0;
  751. if (NULL != pcbSig)
  752. *pcbSig = 0;
  753. }
  754. else
  755. {
  756. if (cbRsrcSig < (sizeof(DWORD) * 2))
  757. goto Ret;
  758. // check the sig in file version and get the CRC offset
  759. pdwSigInFileVer = (DWORD*)pbRsrcSig;
  760. pdwCRCOffset = (DWORD*)(pbRsrcSig + sizeof(DWORD));
  761. dwCRCOffset = *pdwCRCOffset;
  762. if ((0x00000100 != *pdwSigInFileVer) || (dwCRCOffset > cbImage))
  763. goto Ret;
  764. // create a zero byte signature
  765. if (NULL == (pbZeroRsrc = (BYTE*)LocalAlloc(LMEM_ZEROINIT, cbRsrcSig)))
  766. goto Ret;
  767. memcpy(pbZeroRsrc, pbRsrcSig, sizeof(DWORD) * 2);
  768. pbPostCRC = pbStart + *pdwCRCOffset + sizeof(DWORD);
  769. cbCRCToSig = (DWORD)(pbRsrcSig - pbPostCRC);
  770. pbPostSig = pbRsrcSig + cbRsrcSig;
  771. cbPostSig = (cbImage - (DWORD)(pbPostSig - pbStart));
  772. // allocate the real signature and copy the resource sig into the real sig
  773. *pcbSig = cbRsrcSig - (sizeof(DWORD) * 2);
  774. if (NULL == (*ppbSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, *pcbSig)))
  775. goto Ret;
  776. memcpy(*ppbSig, pbRsrcSig + (sizeof(DWORD) * 2), *pcbSig);
  777. }
  778. FreeLibrary(hInst);
  779. hInst = 0;
  780. // hash over the relevant data
  781. {
  782. if (HFILE_ERROR == (hFile = OpenFile(pszImage, &ImageInfoBuf, OF_READ)))
  783. {
  784. goto Ret;
  785. }
  786. MD5Init(&MD5Hash);
  787. if (0 != dwCRCOffset)
  788. {
  789. // hash up to the CRC
  790. if (!HashBytesOfFile(hFile, dwCRCOffset, &MD5Hash))
  791. goto Ret;
  792. // pretend CRC is zeroed
  793. MD5Update(&MD5Hash, (BYTE*)&dwZeroCRC, sizeof(DWORD));
  794. if (!ReadFile((HANDLE)IntToPtr(hFile), (BYTE*)&dwZeroCRC, sizeof(DWORD),
  795. &dwBytesRead, NULL))
  796. {
  797. goto Ret;
  798. }
  799. }
  800. if (0 != cbRsrcSig)
  801. {
  802. // hash from CRC to sig resource
  803. if (!HashBytesOfFile(hFile, cbCRCToSig, &MD5Hash))
  804. goto Ret;
  805. // pretend image has zeroed sig
  806. MD5Update(&MD5Hash, pbZeroRsrc, cbRsrcSig);
  807. if (!ReadFile((HANDLE)IntToPtr(hFile), (BYTE*)pbZeroRsrc, cbRsrcSig,
  808. &dwBytesRead, NULL))
  809. {
  810. goto Ret;
  811. }
  812. }
  813. // hash after the sig resource
  814. if (!HashBytesOfFile(hFile, cbPostSig, &MD5Hash))
  815. goto Ret;
  816. // Finish the hash
  817. MD5Final(&MD5Hash);
  818. memcpy(pbHash, MD5Hash.digest, MD5DIGESTLEN);
  819. }
  820. fRet = TRUE;
  821. Ret:
  822. if (pbZeroRsrc)
  823. LocalFree(pbZeroRsrc);
  824. if (hInst)
  825. FreeLibrary(hInst);
  826. if (HFILE_ERROR != hFile)
  827. _lclose(hFile);
  828. return fRet;
  829. }
  830. /*
  831. - CheckAllSignatures
  832. -
  833. * Purpose:
  834. * Check signature against all keys
  835. *
  836. *
  837. * Returns:
  838. * BOOL
  839. */
  840. BOOL
  841. CheckAllSignatures(
  842. BYTE *pbSig,
  843. DWORD cbSig,
  844. BYTE *pbHash,
  845. BOOL fUnknownLen)
  846. {
  847. BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  848. BYTE rgbKey2[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  849. BYTE rgbMSKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  850. #ifdef TEST_BUILD_EXPONENT
  851. BYTE rgbTestKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE512];
  852. HMODULE hMod;
  853. HRSRC hRes;
  854. HGLOBAL pRes;
  855. DWORD dwSize;
  856. #endif
  857. BOOL fRet = FALSE;
  858. // decrypt the keys once for each process
  859. #ifdef TEST_BUILD_EXPONENT
  860. hMod = GetModuleHandle("advapi32.dll");
  861. if (hRes = FindResource(hMod, (LPCTSTR) IDR_PUBKEY1, RT_RCDATA))
  862. {
  863. if (pRes = LoadResource(hMod, hRes))
  864. {
  865. dwSize = SizeofResource(hMod, hRes);
  866. memcpy(&TESTKEY, (CHAR *) pRes, dwSize);
  867. }
  868. }
  869. #endif
  870. memcpy(rgbKey, (BYTE*)&KEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  871. EncryptKey(rgbKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 0);
  872. memcpy(rgbMSKey, (BYTE*)&MSKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  873. EncryptKey(rgbMSKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 1);
  874. memcpy(rgbKey2, (BYTE*)&KEY2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  875. EncryptKey(rgbKey2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 2);
  876. #ifdef TEST_BUILD_EXPONENT
  877. memcpy(rgbTestKey, (BYTE*)&TESTKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE512);
  878. EncryptKey(rgbTestKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE512, 3);
  879. #ifdef WIN95
  880. TESTKEY.PUB.pubexp = TEST_BUILD_EXPONENT;
  881. #else
  882. TESTKEY.PUB.pubexp = USER_SHARED_DATA->CryptoExponent;
  883. #endif // WIN95
  884. #endif // TEST_BUILD_EXPONENT
  885. if (TRUE == (fRet = CheckSignature(rgbKey, 128, pbSig,
  886. cbSig, pbHash, fUnknownLen)))
  887. {
  888. printf("Checked against the retail CSP key\n" );
  889. fRet = TRUE;
  890. goto Ret;
  891. }
  892. if (g_fUseTestKey)
  893. {
  894. if (TRUE == (fRet = CheckSignature(rgbMSKey, 128, pbSig,
  895. cbSig, pbHash, fUnknownLen)))
  896. {
  897. printf("Checked against the Internal Only \"Enigma\" Key\n" );
  898. fRet = TRUE;
  899. goto Ret;
  900. }
  901. }
  902. if (TRUE == (fRet = CheckSignature(rgbKey2, 128, pbSig,
  903. cbSig, pbHash, fUnknownLen)))
  904. {
  905. printf("Checked against retail Key2\n" );
  906. fRet = TRUE;
  907. goto Ret;
  908. }
  909. #ifdef TEST_BUILD_EXPONENT
  910. if (TRUE == (fRet = CheckSignature(rgbTestKey, 64, pbSig,
  911. cbSig, pbHash, fUnknownLen)))
  912. {
  913. printf("Checked against Test key\n" );
  914. fRet = TRUE;
  915. goto Ret;
  916. }
  917. #endif // TEST_BUILD_EXPONENT
  918. Ret:
  919. return fRet;
  920. }
  921. /*
  922. - CheckSignatureInFile
  923. -
  924. * Purpose:
  925. * Check signature which is in the resource in the file
  926. *
  927. *
  928. * Parameters:
  929. * IN pszImage - address of file
  930. *
  931. * Returns:
  932. * BOOL
  933. */
  934. BOOL
  935. CheckSignatureInFile(
  936. LPCSTR pszImage)
  937. {
  938. HFILE hFileProv = HFILE_ERROR;
  939. DWORD cbImage;
  940. BYTE *pbSig = NULL;
  941. DWORD cbSig;
  942. BYTE rgbHash[MD5DIGESTLEN];
  943. OFSTRUCT ImageInfoBuf;
  944. BOOL fRet = FALSE;
  945. // Check file size
  946. {
  947. if (HFILE_ERROR == (hFileProv = OpenFile(pszImage, &ImageInfoBuf, OF_READ)))
  948. {
  949. SetLastError((DWORD) NTE_PROV_DLL_NOT_FOUND);
  950. goto Ret;
  951. }
  952. if (0xffffffff == (cbImage = GetFileSize((HANDLE)IntToPtr(hFileProv), NULL)))
  953. goto Ret;
  954. _lclose(hFileProv);
  955. hFileProv = HFILE_ERROR;
  956. }
  957. if (!HashTheFile(pszImage, cbImage, &pbSig, &cbSig, rgbHash))
  958. goto Ret;
  959. // check signature against all public keys
  960. if (!CheckAllSignatures(pbSig, cbSig, rgbHash, FALSE))
  961. goto Ret;
  962. fRet = TRUE;
  963. Ret:
  964. if (HFILE_ERROR != hFileProv)
  965. _lclose(hFileProv);
  966. if (pbSig)
  967. LocalFree(pbSig);
  968. return fRet;
  969. }
  970. /*++
  971. ShowHelp:
  972. This routine displays a short help message to the given output stream.
  973. Arguments:
  974. ostr - The output stream to receive the help message.
  975. Return Value:
  976. None
  977. Author:
  978. Jeff Spelman
  979. --*/
  980. void
  981. ShowHelp(
  982. void)
  983. {
  984. printf("CryptoAPI Display Signature Utility\n");
  985. printf(" showsig <filename>\n");
  986. printf("or\n");
  987. printf(" showsig -s <rsrcfile> <filename>\n");
  988. printf("or\n");
  989. printf(" showsig -b <sigfile> <filename>\n");
  990. printf("Other options:\n");
  991. printf(" +t - Enable the use of the Enigma key\n");
  992. printf(" (On by default).\n");
  993. printf(" -t - Disable the use of the Enigma key\n");
  994. }
  995. /*++
  996. main:
  997. This is the main entry point of the application.
  998. Arguments:
  999. argc - Count of arguments
  1000. argv - array of arguments
  1001. Return Value:
  1002. 0 - Success
  1003. 1 - Error
  1004. Author:
  1005. Jeff Spelman
  1006. --*/
  1007. extern "C" void __cdecl
  1008. main(
  1009. int argc,
  1010. char *argv[])
  1011. {
  1012. TCHAR szFullPath[MAX_PATH];
  1013. HANDLE hFile = INVALID_HANDLE_VALUE;
  1014. HMODULE hResFile = NULL;
  1015. DWORD exStatus = 1;
  1016. LPCTSTR szInFile = NULL;
  1017. LPCTSTR szResFile = NULL;
  1018. LPCTSTR szSigFile = NULL;
  1019. LPTSTR szTail;
  1020. BOOL fOutput = FALSE;
  1021. DWORD i;
  1022. HRSRC hRes;
  1023. DWORD cbImage;
  1024. BOOL fFreeSignature = FALSE;
  1025. BYTE rgbHash[MD5DIGESTLEN];
  1026. LPBYTE pbSignature = NULL;
  1027. DWORD cbSignatureLen;
  1028. //
  1029. // Parse the command line.
  1030. //
  1031. for (i = 1; i < (DWORD)argc; i++)
  1032. {
  1033. if (0 == _stricmp("-h", argv[i]))
  1034. {
  1035. ShowHelp();
  1036. exStatus = 1;
  1037. goto ErrorExit;
  1038. }
  1039. else if (0 == _stricmp("-s", argv[i]))
  1040. {
  1041. i += 1;
  1042. if ((NULL != szResFile) || (i >= (DWORD)argc))
  1043. {
  1044. ShowHelp();
  1045. exStatus = 1;
  1046. goto ErrorExit;
  1047. }
  1048. szResFile = argv[i];
  1049. }
  1050. else if (0 == _stricmp("-b", argv[i]))
  1051. {
  1052. i += 1;
  1053. if ((NULL != szSigFile) || (i >= (DWORD)argc))
  1054. {
  1055. ShowHelp();
  1056. exStatus = 1;
  1057. goto ErrorExit;
  1058. }
  1059. szSigFile = argv[i];
  1060. }
  1061. else if (0 == _stricmp("-t", argv[i]))
  1062. {
  1063. g_fUseTestKey = FALSE;
  1064. }
  1065. else if (0 == _stricmp("+t", argv[i]))
  1066. {
  1067. g_fUseTestKey = TRUE;
  1068. }
  1069. else
  1070. {
  1071. if (NULL != szInFile)
  1072. {
  1073. ShowHelp();
  1074. exStatus = 1;
  1075. goto ErrorExit;
  1076. }
  1077. szInFile = argv[i];
  1078. }
  1079. }
  1080. //
  1081. // Command consistency checks.
  1082. //
  1083. if (NULL == szInFile)
  1084. {
  1085. printf("No input file specified.\n");
  1086. ShowHelp();
  1087. exStatus = 4 ;
  1088. goto ErrorExit;
  1089. }
  1090. i = GetFullPathName(szInFile,
  1091. sizeof(szFullPath) / sizeof(TCHAR),
  1092. szFullPath,
  1093. &szTail);
  1094. if (0 == i)
  1095. {
  1096. printf("Can't expand file name.\n");
  1097. exStatus = 4;
  1098. goto ErrorExit;
  1099. }
  1100. else if (sizeof(szFullPath) / sizeof(TCHAR) < i)
  1101. {
  1102. printf("File path too long.\n");
  1103. exStatus = 4;
  1104. goto ErrorExit;
  1105. }
  1106. szInFile = szFullPath;
  1107. //
  1108. // If the DLL has a FIPS 140-1 MAC resource then check it
  1109. //
  1110. if (!SelfMACCheck(szInFile))
  1111. exStatus = 3 ;
  1112. //
  1113. // Where's our signature?
  1114. //
  1115. if (NULL != szSigFile)
  1116. {
  1117. //
  1118. // This file has an accompanying binary signature file.
  1119. // Verify the file, and get its length.
  1120. //
  1121. hFile = CreateFile(szInFile,
  1122. GENERIC_READ,
  1123. FILE_SHARE_READ,
  1124. NULL,
  1125. OPEN_EXISTING,
  1126. FILE_ATTRIBUTE_NORMAL,
  1127. NULL);
  1128. if (INVALID_HANDLE_VALUE == hFile)
  1129. {
  1130. printf("Unable to open the CSP file!\n");
  1131. exStatus = 2 ;
  1132. goto ErrorExit;
  1133. }
  1134. cbImage = GetFileSize(hFile, NULL);
  1135. if (0 == cbImage)
  1136. {
  1137. printf("Unable to get size of CSP file!\n");
  1138. exStatus = 2 ;
  1139. goto ErrorExit;
  1140. }
  1141. CloseHandle(hFile);
  1142. hFile = INVALID_HANDLE_VALUE;
  1143. //
  1144. // Get the signature from the file.
  1145. //
  1146. hFile = CreateFile(szSigFile,
  1147. GENERIC_READ,
  1148. FILE_SHARE_READ,
  1149. NULL,
  1150. OPEN_EXISTING,
  1151. FILE_ATTRIBUTE_NORMAL,
  1152. NULL);
  1153. if (INVALID_HANDLE_VALUE == hFile)
  1154. {
  1155. printf("Unable to open the Signature file!\n");
  1156. exStatus = 2 ;
  1157. goto ErrorExit;
  1158. }
  1159. cbSignatureLen = GetFileSize(hFile, NULL);
  1160. if (0 == cbImage)
  1161. {
  1162. printf("Unable to get size of the Signature file!\n");
  1163. exStatus = 2 ;
  1164. goto ErrorExit;
  1165. }
  1166. pbSignature = (LPBYTE)LocalAlloc(LPTR, cbSignatureLen);
  1167. if (NULL == pbSignature)
  1168. {
  1169. printf("No memory!\n");
  1170. exStatus = 2;
  1171. goto ErrorExit;
  1172. }
  1173. fFreeSignature = TRUE;
  1174. if (!ReadFile(hFile,
  1175. pbSignature,
  1176. cbSignatureLen,
  1177. &cbSignatureLen,
  1178. NULL))
  1179. {
  1180. printf("Unable to read the Signature file!\n");
  1181. exStatus = 2 ;
  1182. goto ErrorExit;
  1183. }
  1184. CloseHandle(hFile);
  1185. hFile = INVALID_HANDLE_VALUE;
  1186. // display the signature
  1187. printf("--- Signature ---\n");
  1188. for (i = 0; i < cbSignatureLen; i++)
  1189. {
  1190. printf("0x%02X ", pbSignature[i]);
  1191. if (((i + 1) % 8) == 0)
  1192. printf("\n");
  1193. }
  1194. if (0 != (i % 8))
  1195. printf("\n");
  1196. if (!HashTheFile(szInFile, cbImage, NULL, NULL, rgbHash))
  1197. {
  1198. printf("Unable to hash the CSP file!\n");
  1199. exStatus = 2 ;
  1200. goto ErrorExit;
  1201. }
  1202. // check signature against all public keys
  1203. if (!CheckAllSignatures(pbSignature, cbSignatureLen, rgbHash, FALSE))
  1204. {
  1205. printf("The signature on %s FAILED to verify!\n", szInFile);
  1206. exStatus = 1 ;
  1207. }
  1208. else
  1209. {
  1210. printf("The signature on %s VERIFIED!\n", szInFile);
  1211. exStatus = 0;
  1212. }
  1213. }
  1214. else if (NULL != szResFile)
  1215. {
  1216. //
  1217. // This file has an accompanying signature resource file.
  1218. // Verify the file, and get its length.
  1219. //
  1220. hFile = CreateFile(szInFile,
  1221. GENERIC_READ,
  1222. FILE_SHARE_READ,
  1223. NULL,
  1224. OPEN_EXISTING,
  1225. FILE_ATTRIBUTE_NORMAL,
  1226. NULL);
  1227. if (INVALID_HANDLE_VALUE == hFile)
  1228. {
  1229. printf("Unable to open the CSP file!\n");
  1230. exStatus = 2 ;
  1231. goto ErrorExit;
  1232. }
  1233. cbImage = GetFileSize(hFile, NULL);
  1234. if (0 == cbImage)
  1235. {
  1236. printf("Unable to get size of CSP file!\n");
  1237. exStatus = 2 ;
  1238. goto ErrorExit;
  1239. }
  1240. CloseHandle(hFile);
  1241. hFile = INVALID_HANDLE_VALUE;
  1242. //
  1243. // Load the resource from the associated resource file.
  1244. //
  1245. hResFile = LoadLibraryEx(szResFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1246. if (NULL == hResFile)
  1247. {
  1248. printf("Unable to load the resource file!\n");
  1249. exStatus = 2 ;
  1250. goto ErrorExit;
  1251. }
  1252. hRes = FindResource(hResFile, (LPCTSTR)SIG_RESOURCE_NUM, RT_RCDATA);
  1253. if (NULL == hRes)
  1254. {
  1255. printf("Unable to find the signature in the resource file!\n");
  1256. exStatus = 2 ;
  1257. goto ErrorExit;
  1258. }
  1259. pbSignature = (LPBYTE)LoadResource(hResFile, hRes);
  1260. if (NULL == pbSignature)
  1261. {
  1262. printf("Unable to find the signature in the resource file!\n");
  1263. exStatus = 2 ;
  1264. goto ErrorExit;
  1265. }
  1266. cbSignatureLen = SizeofResource(hResFile, hRes);
  1267. // display the signature
  1268. printf("--- Signature ---\n");
  1269. for (i = 0; i < cbSignatureLen; i++)
  1270. {
  1271. printf("0x%02X ", pbSignature[i]);
  1272. if (((i + 1) % 8) == 0)
  1273. printf("\n");
  1274. }
  1275. if (0 != (i % 8))
  1276. printf("\n");
  1277. if (!HashTheFile(szInFile, cbImage, NULL, NULL, rgbHash))
  1278. {
  1279. printf("Unable to hash the CSP file!\n");
  1280. exStatus = 2 ;
  1281. goto ErrorExit;
  1282. }
  1283. // check signature against all public keys
  1284. if (!CheckAllSignatures(pbSignature, cbSignatureLen, rgbHash, FALSE))
  1285. {
  1286. printf("The signature on %s FAILED to verify!\n", szInFile);
  1287. exStatus = 1 ;
  1288. }
  1289. else
  1290. {
  1291. printf("The signature on %s VERIFIED!\n", szInFile);
  1292. exStatus = 0;
  1293. }
  1294. }
  1295. else
  1296. {
  1297. //
  1298. // Get the signature from the resource in the file
  1299. //
  1300. if (ERROR_SUCCESS != GetCryptSignatureResource(szInFile,
  1301. &pbSignature,
  1302. &cbSignatureLen))
  1303. {
  1304. printf("Unable to get the signature from the file resource!\n");
  1305. exStatus = 2 ;
  1306. goto ErrorExit;
  1307. }
  1308. // display the signature
  1309. printf("--- Signature ---\n");
  1310. for (i = 0; i < cbSignatureLen; i++)
  1311. {
  1312. printf("0x%02X ", pbSignature[i]);
  1313. if (((i + 1) % 8) == 0)
  1314. printf("\n");
  1315. }
  1316. if (0 != (i % 8))
  1317. printf("\n");
  1318. //
  1319. // check the signature against the file
  1320. //
  1321. if (CheckSignatureInFile(szInFile))
  1322. {
  1323. printf("The signature on %s VERIFIED!\n", szInFile);
  1324. exStatus = 0;
  1325. }
  1326. else
  1327. {
  1328. printf("The signature on %s FAILED to verify!\n", szInFile);
  1329. exStatus = 1 ;
  1330. }
  1331. }
  1332. //
  1333. // Clean up and return.
  1334. //
  1335. ErrorExit:
  1336. if (fFreeSignature && (NULL != pbSignature))
  1337. LocalFree(pbSignature);
  1338. if (INVALID_HANDLE_VALUE != hFile)
  1339. CloseHandle(hFile);
  1340. if (NULL != hResFile)
  1341. FreeLibrary(hResFile);
  1342. exit(exStatus);
  1343. }