CodeSignVerify.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. #include "stdafx.h"
  2. #include <WinVer.h>
  3. //#pragma comment (lib, "Version.lib")
  4. #include <Wintrust.h.>
  5. #include<SoftPub.h>
  6. //#pragma comment (lib, "wintrust")
  7. //#pragma comment(lib, "crypt32.lib")
  8. #include "fileutil.h"
  9. #include "CodeSignVerify.h"
  10. CCodeSignVerify::CCodeSignVerify(DWORD dwCodePage, DWORD dwLangID)
  11. :m_dwCodePage(dwCodePage), m_dwLangID(dwLangID)
  12. {
  13. }
  14. CCodeSignVerify::~CCodeSignVerify()
  15. {
  16. }
  17. bool CCodeSignVerify::GetVersionInfo(const char *pszFileName, CVersionInfo &versionInfo)
  18. {
  19. DWORD dwZero(0);
  20. DWORD dwSize = ::GetFileVersionInfoSize(pszFileName, &dwZero);
  21. if (dwSize == 0)
  22. {
  23. SetLastErrMsg();
  24. return false;
  25. }
  26. void *pVersionInfo = new char[dwSize];
  27. bool bRet = ::GetFileVersionInfo(pszFileName, 0, dwSize, pVersionInfo) == TRUE;
  28. if (bRet)
  29. {
  30. // read fixed version info
  31. UINT nLen(0);
  32. VS_FIXEDFILEINFO* pFixedInfo = NULL;
  33. bRet = ::VerQueryValue(pVersionInfo, "\\", (LPVOID*)&pFixedInfo, &nLen) && pFixedInfo->dwSignature == VS_FFI_SIGNATURE;
  34. if (bRet)
  35. {
  36. // get file version & product version
  37. versionInfo.FileVersion = CVersion(HIWORD(pFixedInfo->dwFileVersionMS),
  38. LOWORD(pFixedInfo->dwFileVersionMS),
  39. HIWORD(pFixedInfo->dwFileVersionLS),
  40. LOWORD(pFixedInfo->dwFileVersionLS));
  41. versionInfo.ProductVersion = CVersion(HIWORD(pFixedInfo->dwProductVersionMS),
  42. LOWORD(pFixedInfo->dwProductVersionMS),
  43. HIWORD(pFixedInfo->dwProductVersionLS),
  44. LOWORD(pFixedInfo->dwProductVersionLS));
  45. }
  46. // get string file info
  47. bRet = bRet && GetStringFileInfo(pVersionInfo, "ProductName", versionInfo.strProductName);
  48. bRet = bRet && GetStringFileInfo(pVersionInfo, "CompanyName", versionInfo.strCompanyName);
  49. bRet = bRet && GetStringFileInfo(pVersionInfo, "FileDescription", versionInfo.strDescription);
  50. // custom info, possiblely not define
  51. GetStringFileInfo(pVersionInfo, "AuthorName", versionInfo.strAuthorName);
  52. }
  53. delete[] pVersionInfo;
  54. if (!bRet)
  55. SetLastErrMsg();
  56. return bRet;
  57. }
  58. bool CCodeSignVerify::VerifySignature(const char *pszFileName, CSignInfo &signInfo)
  59. {
  60. if (!IsSignFromTrust(pszFileName))
  61. return false;
  62. if (!GetSignInfo(pszFileName, signInfo))
  63. return false;
  64. /*
  65. if (signInfo.strSignCertSubject.Compare("China Merchants Bank Co., Ltd") != 0)
  66. {
  67. SetLastErrMsg(CSimpleStringA::Format("signer invalid: %s", (const char*)signInfo.strSignCertSubject));
  68. return false;
  69. }*/
  70. //if (signInfo.strSignCertSubject.Compare("CMB CCDG Signing") != 0)
  71. //{
  72. // SetLastErrMsg(CSimpleStringA::Format("strSignCertSubject invalid: %s", (const char*)signInfo.strSignCertSubject));
  73. // return false;
  74. //}
  75. return true;
  76. }
  77. bool CCodeSignVerify::IsSignFromTrust(const char *pszFileName)
  78. {
  79. // check if file exists
  80. if (!ExistsFileA(pszFileName))
  81. {
  82. SetLastErrMsg(CSimpleStringA::Format("file \"%s\" not exist", pszFileName));
  83. return false;
  84. }
  85. WCHAR wszFileName[MAX_PATH] = {};
  86. int nRet = MultiByteToWideChar(CP_ACP, 0, pszFileName, -1, wszFileName, MAX_PATH);
  87. if (nRet <= 0)
  88. {
  89. SetLastErrMsg("convert to wchar string fail");
  90. return false;
  91. }
  92. LONG lStatus;
  93. DWORD dwLastError;
  94. // Initialize the WINTRUST_FILE_INFO structure.
  95. bool bRet = false;
  96. WINTRUST_FILE_INFO FileData;
  97. memset(&FileData, 0, sizeof(FileData));
  98. FileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
  99. FileData.pcwszFilePath = wszFileName;
  100. FileData.hFile = NULL;
  101. FileData.pgKnownSubject = NULL;
  102. /*
  103. WVTPolicyGUID specifies the policy to apply on the file
  104. WINTRUST_ACTION_GENERIC_VERIFY_V2 policy checks:
  105. 1) The certificate used to sign the file chains up to a root
  106. certificate located in the trusted root certificate store. This
  107. implies that the identity of the publisher has been verified by
  108. a certification authority.
  109. 2) In cases where user interface is displayed (which this example
  110. does not do), WinVerifyTrust will check for whether the
  111. end entity certificate is stored in the trusted publisher store,
  112. implying that the user trusts content from this publisher.
  113. 3) The end entity certificate has sufficient permission to sign
  114. code, as indicated by the presence of a code signing EKU or no
  115. EKU. */
  116. GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  117. WINTRUST_DATA WinTrustData;
  118. // Initialize the WinVerifyTrust input data structure.
  119. // Default all fields to 0.
  120. memset(&WinTrustData, 0, sizeof(WinTrustData));
  121. WinTrustData.cbStruct = sizeof(WinTrustData);
  122. // Use default code signing EKU.
  123. WinTrustData.pPolicyCallbackData = NULL;
  124. // No data to pass to SIP.
  125. WinTrustData.pSIPClientData = NULL;
  126. // Disable WVT UI.
  127. WinTrustData.dwUIChoice = WTD_UI_NONE;
  128. // No revocation checking.
  129. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  130. // Verify an embedded signature on a file.
  131. WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
  132. // Default verification.
  133. WinTrustData.dwStateAction = 0;
  134. // Not applicable for default verification of embedded signature.
  135. WinTrustData.hWVTStateData = NULL;
  136. // Not used.
  137. WinTrustData.pwszURLReference = NULL;
  138. // Default.
  139. //WinTrustData.dwProvFlags = WTD_HASH_ONLY_FLAG; // xkm@20140904: 只验证Hash, 在准入时后台验证签名证书合法性
  140. WinTrustData.dwProvFlags = WTD_SAFER_FLAG;
  141. // This is not applicable if there is no UI because it changes
  142. // the UI to accommodate running applications instead of
  143. // installing applications.
  144. WinTrustData.dwUIContext = 0;
  145. // Set pFile.
  146. WinTrustData.pFile = &FileData;
  147. // WinVerifyTrust verifies signatures as specified by the GUID and Wintrust_Data.
  148. lStatus = WinVerifyTrust(
  149. NULL,
  150. &WVTPolicyGUID,
  151. &WinTrustData);
  152. switch (lStatus)
  153. {
  154. case ERROR_SUCCESS:
  155. /*Signed file:
  156. - Hash that represents the subject is trusted.
  157. - Trusted publisher without any verification errors.
  158. - UI was disabled in dwUIChoice. No publisher or time stamp chain errors.
  159. - UI was enabled in dwUIChoice and the user clicked "Yes" when asked to install and run the signed subject. */
  160. bRet = true;
  161. break;
  162. case CERT_E_CHAINING:
  163. // 非受信任的根证书颁发机构,此错误视为通过
  164. bRet = true;
  165. break;
  166. case TRUST_E_NOSIGNATURE:
  167. // The file was not signed or had a signature that was not valid.
  168. // Get the reason for no signature.
  169. dwLastError = GetLastError();
  170. if (TRUST_E_NOSIGNATURE == dwLastError ||
  171. TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError ||
  172. TRUST_E_PROVIDER_UNKNOWN == dwLastError)
  173. {
  174. // The file was not signed.
  175. SetLastErrMsg("file not signed or signature not valid");
  176. }
  177. else
  178. {
  179. // The signature was not valid or there was an error opening the file.
  180. SetLastErrMsg("unknown error occurred trying to verify the signature");
  181. }
  182. break;
  183. case TRUST_E_EXPLICIT_DISTRUST:
  184. // The hash that represents the subject or the publisher is not allowed by the admin or user.
  185. SetLastErrMsg("signature is present, but disallowed");
  186. break;
  187. case TRUST_E_SUBJECT_NOT_TRUSTED:
  188. // The user clicked "No" when asked to install and run.
  189. SetLastErrMsg("signature is present, but not trusted");
  190. break;
  191. case CRYPT_E_SECURITY_SETTINGS:
  192. /*The hash that represents the subject or the publisher
  193. was not explicitly trusted by the admin and the
  194. admin policy has disabled user trust. No signature,
  195. publisher or time stamp errors. */
  196. SetLastErrMsg("CRYPT_E_SECURITY_SETTINGS - The hash "
  197. "representing the subject or the publisher wasn't "
  198. "explicitly trusted by the admin and admin policy "
  199. "has disabled user trust. No signature, publisher "
  200. "or timestamp errors");
  201. break;
  202. default:
  203. // The UI was disabled in dwUIChoice or the admin policy
  204. // has disabled user trust. lStatus contains the
  205. // publisher or time stamp chain error.
  206. SetLastErrMsg("verify sign not pass");
  207. break;
  208. }
  209. return bRet;
  210. }
  211. bool CCodeSignVerify::GetSignInfo(const char *pszFileName, CSignInfo &signInfo)
  212. {
  213. HCERTSTORE hStore = NULL;
  214. HCRYPTMSG hMsg = NULL;
  215. PCMSG_SIGNER_INFO pSignerInfo = NULL;
  216. __try
  217. {
  218. // check if file exists
  219. if (!ExistsFileA(pszFileName))
  220. {
  221. SetLastErrMsg("file not exist");
  222. return false;
  223. }
  224. WCHAR wcsFileName[MAX_PATH] = {};
  225. int nRet = MultiByteToWideChar(CP_ACP, 0, pszFileName, -1, wcsFileName, MAX_PATH);
  226. if (nRet <= 0)
  227. {
  228. SetLastErrMsg("convert file name to wcstring fail");
  229. return false;
  230. }
  231. // Get message handle and store handle from the signed file.
  232. DWORD dwEncoding, dwContentType, dwFormatType;
  233. BOOL bRet = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
  234. wcsFileName,
  235. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
  236. CERT_QUERY_FORMAT_FLAG_BINARY,
  237. 0,
  238. &dwEncoding,
  239. &dwContentType,
  240. &dwFormatType,
  241. &hStore,
  242. &hMsg,
  243. NULL);
  244. if (!bRet)
  245. {
  246. SetLastErrMsg("get message and store handle fail");
  247. return false;
  248. }
  249. // Get signer information size.
  250. DWORD dwSignerInfoLen;
  251. bRet = CryptMsgGetParam(hMsg,
  252. CMSG_SIGNER_INFO_PARAM,
  253. 0,
  254. NULL,
  255. &dwSignerInfoLen);
  256. if (!bRet)
  257. {
  258. SetLastErrMsg("get signer info size fail");
  259. return false;
  260. }
  261. // Allocate memory for signer information.
  262. pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfoLen);
  263. if (pSignerInfo == NULL)
  264. {
  265. SetLastErrMsg("allocate memory for signer information of file fail");
  266. return false;
  267. }
  268. // Get Signer Information.
  269. bRet = CryptMsgGetParam(hMsg,
  270. CMSG_SIGNER_INFO_PARAM,
  271. 0,
  272. (PVOID)pSignerInfo,
  273. &dwSignerInfoLen);
  274. if (!bRet)
  275. {
  276. SetLastErrMsg("get signer info fail");
  277. return false;
  278. }
  279. // get programe name
  280. if (!GetProgramName(pSignerInfo, signInfo.strProgramName))
  281. return false;
  282. // get sign cert info
  283. if (!GetSignCertInfo(hStore, pSignerInfo, signInfo.strSignCertSerialNo, signInfo.strSignCertIssuer,
  284. signInfo.strSignCertSubject, signInfo.strSignCertHash))
  285. return false;
  286. // get timestamp info
  287. // 如果没有签名时间戳,也视为成功
  288. SYSTEMTIME st = {};
  289. if (GetTimeOfTimeStamp(hStore, pSignerInfo, &st))
  290. signInfo.dtSignTime.FromSystemTime(st);
  291. return true;
  292. }
  293. __finally
  294. {
  295. if (pSignerInfo != NULL)
  296. LocalFree(pSignerInfo);
  297. if (hStore != NULL)
  298. CertCloseStore(hStore, 0);
  299. if (hMsg != NULL)
  300. CryptMsgClose(hMsg);
  301. }
  302. return false;
  303. }
  304. bool CCodeSignVerify::Sha1Hash(BYTE *pData, int nDataLen, BYTE hash[20])
  305. {
  306. bool bRet = false;
  307. HCRYPTPROV hCryptProv;
  308. if (CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) {
  309. HCRYPTHASH hHash;
  310. if (CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
  311. {
  312. if (!CryptHashData(hHash, pData, nDataLen, 0))
  313. SetLastErrMsg("CryptHashData fail");
  314. else
  315. {
  316. DWORD dwLen = 20;
  317. if (CryptGetHashParam(hHash, HP_HASHVAL, (LPBYTE)&hash[0], &dwLen, 0))
  318. bRet = true;
  319. else
  320. SetLastErrMsg("CryptGetHashParam fail");
  321. }
  322. CryptDestroyHash(hHash);
  323. }
  324. else {
  325. SetLastErrMsg("CryptCreateHash failed");
  326. }
  327. CryptReleaseContext(hCryptProv, 0);
  328. }
  329. else {
  330. SetLastErrMsg("CryptAcquireContextA failed");
  331. }
  332. return bRet;
  333. }
  334. bool CCodeSignVerify::GetSignCertInfo(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo,
  335. CSimpleStringA &strSerialNum, CSimpleStringA &strIssuer, CSimpleStringA &strSubject, CSimpleStringA &strCertHash)
  336. {
  337. PCCERT_CONTEXT pCertContext = NULL;
  338. LPTSTR szName = NULL;
  339. __try
  340. {
  341. // Search for the signer certificate in the temporary certificate store.
  342. CERT_INFO certInfo = {};
  343. certInfo.Issuer = pSignerInfo->Issuer;
  344. certInfo.SerialNumber = pSignerInfo->SerialNumber;
  345. pCertContext = CertFindCertificateInStore(hStore,
  346. (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
  347. 0,
  348. CERT_FIND_SUBJECT_CERT,
  349. (PVOID)&certInfo,
  350. NULL);
  351. if (!pCertContext)
  352. {
  353. SetLastErrMsg("search for the signer certificate in the temporary certificate store fail");
  354. return false;
  355. }
  356. // compute cert hash
  357. BYTE hash[20] = {};
  358. if (!Sha1Hash(pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, hash))
  359. {
  360. SetLastErrMsg("compute sign cert sha1 hash fail");
  361. return false;
  362. }
  363. char szHash[64] = {};
  364. for (int i = 0; i < 20; i++)
  365. {
  366. sprintf(szHash, "%s%02x", szHash, hash[i]);
  367. }
  368. strCertHash = szHash;
  369. // Serial Number
  370. DWORD dwDataLen = pCertContext->pCertInfo->SerialNumber.cbData;
  371. for (DWORD n = 0; n < dwDataLen; n++)
  372. {
  373. char szTmp[32] = {};
  374. sprintf(szTmp, "%02X", pCertContext->pCertInfo->SerialNumber.pbData[dwDataLen - (n + 1)]);
  375. strSerialNum.Append(szTmp);
  376. }
  377. // Get Issuer name size.
  378. if (!(dwDataLen = CertGetNameString(pCertContext,
  379. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  380. CERT_NAME_ISSUER_FLAG,
  381. NULL,
  382. NULL,
  383. 0)))
  384. {
  385. SetLastErrMsg("CertGetNameString failed");
  386. return false;
  387. }
  388. // Allocate memory for Issuer name.
  389. LPTSTR szName = (LPTSTR)LocalAlloc(LPTR, dwDataLen * sizeof(TCHAR));
  390. if (!szName)
  391. {
  392. SetLastErrMsg("Unable to allocate memory for issuer name");
  393. return false;
  394. }
  395. // Get Issuer name.
  396. if (!(CertGetNameString(pCertContext,
  397. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  398. CERT_NAME_ISSUER_FLAG,
  399. NULL,
  400. szName,
  401. dwDataLen)))
  402. {
  403. SetLastErrMsg("CertGetNameString failed");
  404. return false;
  405. }
  406. // print Issuer name.
  407. strIssuer = szName;
  408. LocalFree(szName);
  409. szName = NULL;
  410. // Get Subject name size.
  411. if (!(dwDataLen = CertGetNameString(pCertContext,
  412. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  413. 0,
  414. NULL,
  415. NULL,
  416. 0)))
  417. {
  418. SetLastErrMsg("CertGetNameString failed");
  419. return false;
  420. }
  421. // Allocate memory for subject name.
  422. szName = (LPTSTR)LocalAlloc(LPTR, dwDataLen * sizeof(TCHAR));
  423. if (!szName)
  424. {
  425. SetLastErrMsg("Unable to allocate memory for subject name");
  426. return false;
  427. }
  428. // Get subject name.
  429. if (!(CertGetNameString(pCertContext,
  430. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  431. 0,
  432. NULL,
  433. szName,
  434. dwDataLen)))
  435. {
  436. SetLastErrMsg("CertGetNameString failed");
  437. return false;
  438. }
  439. // Print Subject Name.
  440. strSubject = szName;
  441. return true;
  442. }
  443. __finally
  444. {
  445. if (szName != NULL)
  446. LocalFree(szName);
  447. if (pCertContext != NULL)
  448. CertFreeCertificateContext(pCertContext);
  449. }
  450. SetLastErrMsg("get sign cert info failed");
  451. return false;
  452. }
  453. bool CCodeSignVerify::GetProgramName(PCMSG_SIGNER_INFO pSignerInfo, CSimpleStringA &strProgramName)
  454. {
  455. for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
  456. {
  457. if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
  458. pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
  459. {
  460. // Get Size of SPC_SP_OPUS_INFO structure.
  461. DWORD dwDataLen(0);
  462. if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  463. SPC_SP_OPUS_INFO_OBJID,
  464. pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
  465. pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
  466. 0,
  467. NULL,
  468. &dwDataLen))
  469. {
  470. SetLastErrMsg("CryptDecodeObject failed");
  471. return false;
  472. }
  473. // Allocate memory for SPC_SP_OPUS_INFO structure.
  474. PSPC_SP_OPUS_INFO pOpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwDataLen);
  475. if (!pOpusInfo)
  476. {
  477. SetLastErrMsg("Unable to allocate memory for Publisher Info");
  478. return false;
  479. }
  480. // Decode and get SPC_SP_OPUS_INFO structure.
  481. if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  482. SPC_SP_OPUS_INFO_OBJID,
  483. pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
  484. pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
  485. 0,
  486. pOpusInfo,
  487. &dwDataLen))
  488. {
  489. SetLastErrMsg("CryptDecodeObject failed");
  490. LocalFree(pOpusInfo);
  491. return false;
  492. }
  493. // Fill in Program Name if present.
  494. if (pOpusInfo->pwszProgramName)
  495. {
  496. CSimpleStringW str = pOpusInfo->pwszProgramName;
  497. strProgramName = CSimpleStringW2A(str);
  498. }
  499. LocalFree(pOpusInfo);
  500. pOpusInfo = NULL;
  501. return true;
  502. }
  503. }
  504. SetLastErrMsg("find SPC_SP_OPUS_INFO_OBJID struct failed");
  505. return false;
  506. }
  507. bool CCodeSignVerify::GetTimeOfTimeStamp(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st)
  508. {
  509. PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
  510. __try
  511. {
  512. // get timestamp sign info
  513. // Loop through unathenticated attributes for szOID_RSA_counterSign OID.
  514. for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
  515. {
  516. if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId,
  517. szOID_RSA_counterSign) == 0)
  518. {
  519. // Get size of CMSG_SIGNER_INFO structure.
  520. DWORD dwSize(0);
  521. if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  522. PKCS7_SIGNER_INFO,
  523. pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
  524. pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
  525. 0,
  526. NULL,
  527. &dwSize))
  528. {
  529. SetLastErrMsg("CryptDecodeObject failed");
  530. return false;
  531. }
  532. // Allocate memory for CMSG_SIGNER_INFO.
  533. pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
  534. if (!pCounterSignerInfo)
  535. {
  536. SetLastErrMsg("Unable to allocate memory for timestamp info");
  537. return false;
  538. }
  539. // Decode and get CMSG_SIGNER_INFO structure
  540. // for timestamp certificate.
  541. if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  542. PKCS7_SIGNER_INFO,
  543. pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
  544. pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
  545. 0,
  546. (PVOID)pCounterSignerInfo,
  547. &dwSize))
  548. {
  549. SetLastErrMsg("CryptDecodeObject failed");
  550. return false;
  551. }
  552. // Loop through authenticated attributes and find
  553. // szOID_RSA_signingTime OID.
  554. for (DWORD n = 0; n < pCounterSignerInfo->AuthAttrs.cAttr; n++)
  555. {
  556. if (lstrcmpA(szOID_RSA_signingTime,
  557. pCounterSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
  558. {
  559. // Decode and get FILETIME structure.
  560. FILETIME lft, ft;
  561. DWORD dwData = sizeof(ft);
  562. if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  563. szOID_RSA_signingTime,
  564. pCounterSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
  565. pCounterSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
  566. 0,
  567. (PVOID)&ft,
  568. &dwData))
  569. {
  570. SetLastErrMsg("CryptDecodeObject failed");
  571. return false;
  572. }
  573. // Convert to local time.
  574. FileTimeToLocalFileTime(&ft, &lft);
  575. FileTimeToSystemTime(&lft, st);
  576. return true;
  577. } //lstrcmp szOID_RSA_signingTime
  578. } // for
  579. break;
  580. }
  581. }
  582. }
  583. __finally
  584. {
  585. if (pCounterSignerInfo != NULL)
  586. LocalFree(pCounterSignerInfo);
  587. }
  588. SetLastErrMsg("find sign timestamp info fail");
  589. return false;
  590. }
  591. bool CCodeSignVerify::GetStringFileInfo(void *pVersionInfo, const char *pszKeyName, CSimpleStringA &strValue)
  592. {
  593. // get inherit string file info
  594. char *pszValue = NULL;
  595. UINT nLen(0);
  596. CSimpleString strStringInfoKey = CSimpleString::Format("\\StringFileInfo\\%04x%04x\\", m_dwLangID, m_dwCodePage);
  597. if (::VerQueryValue(pVersionInfo, strStringInfoKey + pszKeyName, (void**)&pszValue, &nLen))
  598. {
  599. strValue = pszValue;
  600. return true;
  601. }
  602. return false;
  603. }
  604. CSimpleStringA CCodeSignVerify::GetErrorMsg()
  605. {
  606. if (m_strLastErrMsg.IsNullOrEmpty()) // if null, string operation will crash
  607. return "";
  608. else
  609. return m_strLastErrMsg;
  610. }
  611. void CCodeSignVerify::SetLastErrMsg(const char *pErrMsg)
  612. {
  613. DWORD dwError = GetLastError();
  614. if (dwError == 0)
  615. m_strLastErrMsg = pErrMsg;
  616. else
  617. m_strLastErrMsg = CSimpleStringA::Format("%s %s(0x%X)",
  618. pErrMsg == NULL ? "" : pErrMsg,
  619. (const char*)GetSysErrMsg(dwError), dwError);
  620. }