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