Source code of Windows XP (NT5)
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.

1196 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: timereq.cpp
  7. //
  8. // Contents: Digital Timestamping APIs
  9. //
  10. // History: June-25-1997 Xiaohs Created
  11. //----------------------------------------------------------------------------
  12. #include "global.hxx"
  13. #include <stdio.h>
  14. static char szCrypt32[]="crypt32.dll";
  15. //The version for crtyp32.dll which shipped with NT sp3: "4.0.1381.4"
  16. static DWORD dwLowVersion=0x05650004;
  17. static DWORD dwHighVersion=0x00040000;
  18. HRESULT WINAPI
  19. GetSignedMessageSignerInfoSubj(IN DWORD dwEncodingType,
  20. IN HCRYPTPROV hCryptProv,
  21. IN LPSIP_SUBJECTINFO pSipInfo,
  22. IN DWORD* pdwIndex,
  23. IN OUT PBYTE* ppbSignerInfo,
  24. IN OUT DWORD* pcbSignerInfo)
  25. {
  26. HRESULT hr = S_OK;
  27. SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
  28. DWORD cbSignedMsg = 0;
  29. PBYTE pbSignedMsg = 0;
  30. DWORD dwCertEncoding = 0;
  31. DWORD dwMsgType = 0;
  32. HCRYPTMSG hMsg = NULL;
  33. DWORD cbSignerInfo=0;
  34. BYTE *pbSignerInfo=NULL;
  35. PKITRY {
  36. if(!pcbSignerInfo || !ppbSignerInfo)
  37. PKITHROW(E_INVALIDARG);
  38. //init
  39. *pcbSignerInfo=0;
  40. *ppbSignerInfo=NULL;
  41. // Load up the sip functions.
  42. if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
  43. 0, // Reserved
  44. &sSip)) // Table of functions
  45. PKITHROW(SignError());
  46. sSip.pfGet(pSipInfo,
  47. &dwCertEncoding,
  48. *pdwIndex,
  49. &cbSignedMsg,
  50. NULL);
  51. if(cbSignedMsg == 0) PKITHROW(SignError());
  52. pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
  53. if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
  54. if(!sSip.pfGet(pSipInfo,
  55. &dwCertEncoding,
  56. *pdwIndex,
  57. &cbSignedMsg,
  58. pbSignedMsg))
  59. PKITHROW(SignError()); // Real error.
  60. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  61. {
  62. if(dwCertEncoding != dwEncodingType)
  63. PKITHROW(TRUST_E_NOSIGNATURE);
  64. }
  65. if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
  66. SignNoContentWrap(pbSignedMsg, cbSignedMsg))
  67. dwMsgType = CMSG_SIGNED;
  68. // Use CryptMsg to crack the encoded PKCS7 Signed Message
  69. if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
  70. 0, // dwFlags
  71. dwMsgType,
  72. hCryptProv,
  73. NULL, // pRecipientInfo
  74. NULL)))
  75. PKITHROW(E_UNEXPECTED);
  76. if (!CryptMsgUpdate(hMsg,
  77. pbSignedMsg,
  78. cbSignedMsg,
  79. TRUE)) // fFinal
  80. PKITHROW(SignError());
  81. if(!CryptMsgGetParam(hMsg,
  82. CMSG_ENCODED_SIGNER,
  83. 0, // First signer
  84. NULL,
  85. &cbSignerInfo))
  86. PKITHROW(SignError());
  87. pbSignerInfo=(PBYTE)malloc(cbSignerInfo);
  88. if(!pbSignerInfo)
  89. PKITHROW(E_OUTOFMEMORY);
  90. if(!CryptMsgGetParam(hMsg,
  91. CMSG_ENCODED_SIGNER,
  92. 0, // First signer
  93. pbSignerInfo,
  94. &cbSignerInfo))
  95. PKITHROW(SignError());
  96. //copy to the out put
  97. *ppbSignerInfo=pbSignerInfo;
  98. *pcbSignerInfo=cbSignerInfo;
  99. hr=S_OK;
  100. }
  101. PKICATCH(err) {
  102. hr = err.pkiError;
  103. } PKIEND;
  104. if (hMsg)
  105. CryptMsgClose(hMsg);
  106. if(pbSignedMsg)
  107. free(pbSignedMsg);
  108. if( (hr!=S_OK) && (pbSignerInfo))
  109. free(pbSignerInfo);
  110. return hr;
  111. }
  112. HRESULT WINAPI
  113. GetSignedMessageSignerInfo(IN HCRYPTPROV hCryptProv,
  114. IN SIGNER_SUBJECT_INFO *pSubjectInfo,
  115. IN LPVOID pSipInfo,
  116. IN OUT PBYTE* ppbSignerInfo,
  117. IN OUT DWORD* pcbSignerInfo)
  118. {
  119. HRESULT hr = S_OK;
  120. HANDLE hFile = NULL;
  121. BOOL fFileOpen=FALSE;
  122. GUID gSubjectGuid; // The subject guid used to load the sip
  123. MS_ADDINFO_BLOB sBlob;
  124. SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
  125. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
  126. PKITRY {
  127. if(!pcbSignerInfo || !ppbSignerInfo)
  128. PKITHROW(E_INVALIDARG);
  129. sSubjInfo.dwEncodingType = dwEncodingType;
  130. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
  131. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  132. sSubjInfo.hProv=hCryptProv;
  133. //set up file information
  134. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  135. {
  136. // Open up the file
  137. if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
  138. (pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
  139. {
  140. if(S_OK != (hr = SignOpenFile(
  141. pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
  142. PKITHROW(hr);
  143. fFileOpen=TRUE;
  144. }
  145. else
  146. hFile=pSubjectInfo->pSignerFileInfo->hFile;
  147. // Get the subject type.
  148. if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
  149. PKITHROW(hr);
  150. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  151. sSubjInfo.hFile = hFile;
  152. sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
  153. }
  154. else
  155. {
  156. memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
  157. sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
  158. sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
  159. sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
  160. sSubjInfo.psBlob=&sBlob;
  161. sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
  162. sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
  163. sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
  164. }
  165. hr = GetSignedMessageSignerInfoSubj(
  166. dwEncodingType,
  167. hCryptProv,
  168. &sSubjInfo,
  169. pSubjectInfo->pdwIndex,
  170. ppbSignerInfo,
  171. pcbSignerInfo);
  172. if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
  173. {
  174. fFileOpen = FALSE; // we opened it, but, the SIP closed it!
  175. }
  176. if(hr != S_OK) PKITHROW(hr);
  177. }
  178. PKICATCH(err) {
  179. hr = err.pkiError;
  180. } PKIEND;
  181. if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
  182. return hr;
  183. }
  184. HRESULT WINAPI
  185. SignerAddTimeStampResponse(
  186. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to which the timestamp request should be added
  187. IN PBYTE pbTimeStampResponse,
  188. IN DWORD cbTimeStampResponse,
  189. IN LPVOID pSipData)
  190. {
  191. return SignerAddTimeStampResponseEx(
  192. 0,
  193. pSubjectInfo,
  194. pbTimeStampResponse,
  195. cbTimeStampResponse,
  196. pSipData,
  197. NULL);
  198. }
  199. HRESULT WINAPI
  200. SignerAddTimeStampResponseEx(
  201. IN DWORD dwFlags, //Reserved: Has to be set to 0.
  202. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to which the timestamp request should be added
  203. IN PBYTE pbTimeStampResponse,
  204. IN DWORD cbTimeStampResponse,
  205. IN LPVOID pSipData,
  206. OUT SIGNER_CONTEXT **ppSignerContext
  207. )
  208. {
  209. HRESULT hr = S_OK;
  210. HANDLE hFile = NULL;
  211. BOOL fFileOpen=FALSE;
  212. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  213. GUID gSubjectGuid; // The subject guid used to load the sip
  214. SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
  215. MS_ADDINFO_BLOB sBlob;
  216. HCRYPTPROV hCryptProv = NULL;
  217. DWORD cbSignerInfo=0;
  218. BYTE *pbSignerInfo=NULL;
  219. PBYTE pbEncodedMessage=NULL;
  220. DWORD cbEncodedMessage=0;
  221. PKITRY {
  222. //init
  223. if(ppSignerContext)
  224. *ppSignerContext=NULL;
  225. if(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo))
  226. PKITHROW(E_INVALIDARG);
  227. // Use the default provider
  228. if(!CryptAcquireContext(&hCryptProv,
  229. NULL,
  230. MS_DEF_PROV,
  231. PROV_RSA_FULL,
  232. CRYPT_VERIFYCONTEXT))
  233. PKITHROW(SignError());
  234. //retrieve the enccoded signer info
  235. hr = GetSignedMessageSignerInfo(hCryptProv,
  236. pSubjectInfo,
  237. pSipData,
  238. &pbSignerInfo,
  239. &cbSignerInfo);
  240. if(hr != S_OK) PKITHROW(hr);
  241. sSubjInfo.hProv = hCryptProv;
  242. sSubjInfo.DigestAlgorithm.pszObjId = NULL;
  243. sSubjInfo.dwEncodingType = dwEncodingType;
  244. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
  245. sSubjInfo.pClientData = pSipData;
  246. //set up file information
  247. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  248. {
  249. // Open up the file
  250. if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
  251. (pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
  252. {
  253. if(S_OK != (hr = SignOpenFile(
  254. pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
  255. PKITHROW(hr);
  256. fFileOpen=TRUE;
  257. }
  258. else
  259. hFile=pSubjectInfo->pSignerFileInfo->hFile;
  260. // Get the subject type.
  261. if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
  262. PKITHROW(hr);
  263. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  264. sSubjInfo.hFile = hFile;
  265. sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
  266. }
  267. else
  268. {
  269. memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
  270. sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
  271. sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
  272. sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
  273. sSubjInfo.psBlob=&sBlob;
  274. sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
  275. sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
  276. sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
  277. }
  278. hr = AddTimeStampSubj(dwEncodingType,
  279. hCryptProv,
  280. &sSubjInfo,
  281. pSubjectInfo->pdwIndex,
  282. pbTimeStampResponse,
  283. cbTimeStampResponse,
  284. pbSignerInfo,
  285. cbSignerInfo,
  286. &pbEncodedMessage,
  287. &cbEncodedMessage);
  288. if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
  289. {
  290. fFileOpen = FALSE; // we opened it, but, the SIP closed it!
  291. }
  292. if(hr != S_OK) PKITHROW(hr);
  293. //set up the signer context
  294. if(ppSignerContext)
  295. {
  296. //set up the context information
  297. *ppSignerContext=(SIGNER_CONTEXT *)malloc(sizeof(SIGNER_CONTEXT));
  298. if(NULL==(*ppSignerContext))
  299. {
  300. hr=E_OUTOFMEMORY;
  301. PKITHROW(hr);
  302. }
  303. (*ppSignerContext)->cbSize=sizeof(SIGNER_CONTEXT);
  304. (*ppSignerContext)->cbBlob=cbEncodedMessage;
  305. (*ppSignerContext)->pbBlob=pbEncodedMessage;
  306. pbEncodedMessage=NULL;
  307. }
  308. hr=S_OK;
  309. }
  310. PKICATCH(err) {
  311. hr = err.pkiError;
  312. } PKIEND;
  313. if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
  314. if(hCryptProv) CryptReleaseContext(hCryptProv, 0);
  315. if(pbSignerInfo) free(pbSignerInfo);
  316. if(pbEncodedMessage)
  317. free(pbEncodedMessage);
  318. return hr;
  319. }
  320. HRESULT WINAPI
  321. AddTimeStampSubj(IN DWORD dwEncodingType,
  322. IN HCRYPTPROV hCryptProv,
  323. IN LPSIP_SUBJECTINFO pSipInfo,
  324. IN DWORD *pdwIndex,
  325. IN PBYTE pbTimeStampResponse,
  326. IN DWORD cbTimeStampResponse,
  327. IN PBYTE pbEncodedSignerInfo,
  328. IN DWORD cbEncodedSignerInfo,
  329. OUT PBYTE* ppbMessage,
  330. OUT DWORD* pcbMessage
  331. )
  332. {
  333. HRESULT hr = S_OK;
  334. SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
  335. DWORD cbSignedMsg = 0;
  336. PBYTE pbSignedMsg = 0;
  337. DWORD dwCertEncoding = 0;
  338. DWORD dwMsgType = 0;
  339. HCRYPTMSG hMsg = NULL;
  340. PBYTE pbEncodedSigner = NULL;
  341. DWORD cbEncodedSigner = 0;
  342. PBYTE pbEncodedSignMsg = NULL; // Encoding for the statement attribute
  343. DWORD cbEncodedSignMsg = 0; // :
  344. PBYTE pbCounterSign = NULL;
  345. DWORD cbCounterSign = 0;
  346. CERT_INFO *pbCertInfo = NULL;
  347. DWORD cbCertInfo = 0;
  348. HCERTSTORE hTmpCertStore=NULL;
  349. PCCERT_CONTEXT pCert = NULL;
  350. PCCRL_CONTEXT pCrl = NULL;
  351. PCRYPT_ATTRIBUTES pbUnauth = NULL;
  352. DWORD cbUnauth = 0;
  353. DWORD dwFileVersionSize=0;
  354. DWORD dwFile=0;
  355. BYTE *pVersionInfo=NULL;
  356. VS_FIXEDFILEINFO *pFixedFileInfo=NULL;
  357. UINT unitFixedFileInfo=0;
  358. PKITRY {
  359. // Use CryptMsg to crack the encoded PKCS7 Signed Message
  360. if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
  361. 0, // dwFlags
  362. dwMsgType,
  363. hCryptProv,
  364. NULL, // pRecipientInfo
  365. NULL)))
  366. PKITHROW(E_UNEXPECTED);
  367. if (!CryptMsgUpdate(hMsg,
  368. pbTimeStampResponse,
  369. cbTimeStampResponse,
  370. TRUE)) // fFinal
  371. PKITHROW(SignError());
  372. //get the encoded signer BLOB
  373. CryptMsgGetParam(hMsg,
  374. CMSG_ENCODED_SIGNER,
  375. 0,
  376. NULL,
  377. &cbEncodedSigner);
  378. if (cbEncodedSigner == 0) PKITHROW(S_FALSE); // no attributes
  379. pbEncodedSigner = (PBYTE) malloc(cbEncodedSigner);
  380. if(!pbEncodedSigner) PKITHROW(E_OUTOFMEMORY);
  381. if (!CryptMsgGetParam(hMsg,
  382. CMSG_ENCODED_SIGNER,
  383. 0,
  384. pbEncodedSigner,
  385. &cbEncodedSigner))
  386. PKITHROW(SignError());
  387. //get the timestamp signer's cert info
  388. if(!CryptMsgGetParam(hMsg,
  389. CMSG_SIGNER_CERT_INFO_PARAM,
  390. 0,
  391. NULL,
  392. &cbCertInfo))
  393. PKITHROW(SignError());
  394. if (cbCertInfo == 0) PKITHROW(SignError());
  395. pbCertInfo = (CERT_INFO *) malloc(cbCertInfo);
  396. if(!pbCertInfo) PKITHROW(E_OUTOFMEMORY);
  397. if (!CryptMsgGetParam(hMsg,
  398. CMSG_SIGNER_CERT_INFO_PARAM,
  399. 0,
  400. pbCertInfo,
  401. &cbCertInfo))
  402. PKITHROW(SignError());
  403. // get the cert store from the timestamp response
  404. hTmpCertStore = CertOpenStore(CERT_STORE_PROV_MSG,
  405. dwEncodingType,
  406. hCryptProv,
  407. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  408. hMsg);
  409. if (hTmpCertStore == NULL) PKITHROW(SignError());
  410. //find the timestamper's certificate
  411. pCert = CertGetSubjectCertificateFromStore(
  412. hTmpCertStore,
  413. X509_ASN_ENCODING,
  414. pbCertInfo);
  415. if(NULL == pCert)
  416. {
  417. hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  418. PKITHROW(hr);
  419. }
  420. //make sure the timestamper's certiricate is either from verisign,
  421. // or has the correct key usage
  422. /* if(!ValidTimestampCert(pCert))
  423. {
  424. hr=TRUST_E_TIME_STAMP;
  425. PKITHROW(hr);
  426. } */
  427. //Compare hashed signature of the orinigal signed message
  428. //with the authenticated attribute from the timestamp respoonse.
  429. //they have to match
  430. if(pbEncodedSignerInfo!=NULL && cbEncodedSignerInfo!=0)
  431. {
  432. //verify the signature of the timestamp
  433. if(0==CryptMsgControl(hMsg,0,CMSG_CTRL_VERIFY_SIGNATURE,
  434. pCert->pCertInfo))
  435. {
  436. hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  437. PKITHROW(hr);
  438. }
  439. //verify the signatures
  440. if(!CryptMsgVerifyCountersignatureEncoded(
  441. hCryptProv,
  442. dwEncodingType,
  443. pbEncodedSignerInfo,
  444. cbEncodedSignerInfo,
  445. pbEncodedSigner,
  446. cbEncodedSigner,
  447. pCert->pCertInfo))
  448. {
  449. hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  450. PKITHROW(hr);
  451. }
  452. }//end of the counter signature verificate
  453. //release the cert context
  454. if(pCert)
  455. {
  456. CertFreeCertificateContext(pCert);
  457. pCert=NULL;
  458. }
  459. //close the certstore
  460. if(hTmpCertStore)
  461. {
  462. CertCloseStore(hTmpCertStore, 0);
  463. hTmpCertStore=NULL;
  464. }
  465. // get the cert store from the file
  466. hTmpCertStore = CertOpenStore(CERT_STORE_PROV_MSG,
  467. dwEncodingType,
  468. hCryptProv,
  469. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  470. hMsg);
  471. if (hTmpCertStore == NULL) PKITHROW(SignError());
  472. CryptMsgClose(hMsg);
  473. hMsg = NULL;
  474. // Load up the sip functions.
  475. if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
  476. 0, // Reserved
  477. &sSip)) // Table of functions
  478. PKITHROW(SignError());
  479. sSip.pfGet(pSipInfo,
  480. &dwCertEncoding,
  481. *pdwIndex,
  482. &cbSignedMsg,
  483. NULL);
  484. if(cbSignedMsg == 0) PKITHROW(SignError());
  485. pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
  486. if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
  487. if(!sSip.pfGet(pSipInfo,
  488. &dwCertEncoding,
  489. *pdwIndex,
  490. &cbSignedMsg,
  491. pbSignedMsg))
  492. PKITHROW(SignError()); // Real error.
  493. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  494. {
  495. if(dwCertEncoding != dwEncodingType)
  496. PKITHROW(TRUST_E_NOSIGNATURE);
  497. }
  498. if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
  499. SignNoContentWrap(pbSignedMsg, cbSignedMsg))
  500. dwMsgType = CMSG_SIGNED;
  501. // Use CryptMsg to crack the encoded PKCS7 Signed Message
  502. if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
  503. 0, // dwFlags
  504. dwMsgType,
  505. hCryptProv,
  506. NULL, // pRecipientInfo
  507. NULL)))
  508. PKITHROW(E_UNEXPECTED);
  509. if (!CryptMsgUpdate(hMsg,
  510. pbSignedMsg,
  511. cbSignedMsg,
  512. TRUE)) // fFinal
  513. PKITHROW(SignError());
  514. // Encode up the signer info from the timestamp response and
  515. // add it as an unauthenticated attribute.
  516. CRYPT_ATTRIBUTE sAttr;
  517. CRYPT_ATTR_BLOB sSig;
  518. sSig.pbData = pbEncodedSigner;
  519. sSig.cbData = cbEncodedSigner;
  520. sAttr.pszObjId = szOID_RSA_counterSign;
  521. sAttr.cValue = 1;
  522. sAttr.rgValue = &sSig;
  523. CryptEncodeObject(dwEncodingType,
  524. PKCS_ATTRIBUTE,
  525. &sAttr,
  526. pbCounterSign,
  527. &cbCounterSign);
  528. if(cbCounterSign == 0) PKITHROW(SignError());
  529. pbCounterSign = (PBYTE) malloc(cbCounterSign);
  530. if(!pbCounterSign) PKITHROW(E_OUTOFMEMORY);
  531. if(!CryptEncodeObject(dwEncodingType,
  532. PKCS_ATTRIBUTE,
  533. &sAttr,
  534. pbCounterSign,
  535. &cbCounterSign))
  536. PKITHROW(SignError());
  537. CryptMsgGetParam(hMsg,
  538. CMSG_SIGNER_UNAUTH_ATTR_PARAM,
  539. 0,
  540. NULL,
  541. &cbUnauth);
  542. if(cbUnauth)
  543. {
  544. //check the version of "crytp32.dll". If it is more than
  545. //"4.0.1381.4", we should be able to timestamp a timestamped
  546. //file
  547. dwFileVersionSize=GetFileVersionInfoSize(szCrypt32,&dwFile);
  548. if(!dwFileVersionSize)
  549. PKITHROW(SignError());
  550. pVersionInfo=(BYTE *)malloc(dwFileVersionSize);
  551. if(!pVersionInfo)
  552. PKITHROW(SignError());
  553. if(!GetFileVersionInfo(szCrypt32, NULL,dwFileVersionSize,
  554. pVersionInfo))
  555. PKITHROW(SignError());
  556. if(!VerQueryValue(pVersionInfo, "\\", (LPVOID *)&pFixedFileInfo,
  557. &unitFixedFileInfo))
  558. PKITHROW(SignError());
  559. if(pFixedFileInfo->dwFileVersionMS <= dwHighVersion &&
  560. pFixedFileInfo->dwFileVersionLS <= dwLowVersion)
  561. PKITHROW(SignError());
  562. // we delete any existing time stamps since our policy provider
  563. //only support one timestamp per file
  564. pbUnauth = (PCRYPT_ATTRIBUTES) malloc(cbUnauth);
  565. if(!pbUnauth) PKITHROW(E_OUTOFMEMORY);
  566. if(!CryptMsgGetParam(hMsg,
  567. CMSG_SIGNER_UNAUTH_ATTR_PARAM,
  568. 0,
  569. pbUnauth,
  570. &cbUnauth))
  571. PKITHROW(SignError());
  572. CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA sAttrDel; ZERO(sAttrDel);
  573. sAttrDel.cbSize = sizeof(CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA);
  574. //we always assume there is only one signer
  575. sAttrDel.dwSignerIndex = 0;
  576. for(DWORD ii = 0; ii < pbUnauth->cAttr; ii++)
  577. {
  578. if(strcmp(pbUnauth->rgAttr[ii].pszObjId, szOID_RSA_counterSign) == 0)
  579. {
  580. sAttrDel.dwUnauthAttrIndex = ii;
  581. if (!CryptMsgControl(hMsg,
  582. 0,
  583. CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR,
  584. &sAttrDel))
  585. PKITHROW(SignError());
  586. }
  587. }
  588. }
  589. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA sAttrPara; ZERO(sAttrPara);
  590. sAttrPara.cbSize = sizeof(CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA);
  591. sAttrPara.dwSignerIndex = 0;
  592. sAttrPara.blob.pbData = pbCounterSign;
  593. sAttrPara.blob.cbData = cbCounterSign;
  594. if (!CryptMsgControl(hMsg,
  595. 0,
  596. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
  597. &sAttrPara))
  598. PKITHROW(SignError());
  599. // merge all the certificates from the time stamp response
  600. DWORD dwFlags = 0;
  601. while ((pCert = CertEnumCertificatesInStore(hTmpCertStore, pCert))) {
  602. CRYPT_DATA_BLOB blob;
  603. blob.pbData = pCert->pbCertEncoded;
  604. blob.cbData = pCert->cbCertEncoded;
  605. if (!CryptMsgControl(hMsg,
  606. 0,
  607. CMSG_CTRL_ADD_CERT,
  608. &blob))
  609. PKITHROW(SignError());
  610. }
  611. while ((pCrl = CertGetCRLFromStore(hTmpCertStore, NULL, pCrl, &dwFlags))) {
  612. CRYPT_DATA_BLOB blob;
  613. blob.pbData = pCrl->pbCrlEncoded;
  614. blob.cbData = pCrl->cbCrlEncoded;
  615. if (!CryptMsgControl(hMsg,
  616. 0,
  617. CMSG_CTRL_ADD_CRL,
  618. &blob))
  619. PKITHROW(SignError());
  620. }
  621. // Re-encode up the message and away we go.
  622. CryptMsgGetParam(hMsg,
  623. CMSG_ENCODED_MESSAGE,
  624. 0, // dwIndex
  625. NULL, // pbSignedData
  626. &cbEncodedSignMsg);
  627. if (cbEncodedSignMsg == 0) PKITHROW(SignError());
  628. pbEncodedSignMsg = (PBYTE) malloc(cbEncodedSignMsg);
  629. if(!pbEncodedSignMsg) PKITHROW(E_OUTOFMEMORY);
  630. if (!CryptMsgGetParam(hMsg,
  631. CMSG_ENCODED_MESSAGE,
  632. 0, // dwIndex
  633. pbEncodedSignMsg,
  634. &cbEncodedSignMsg))
  635. PKITHROW(SignError());
  636. //put the signatures if we are dealing with anything other than the BLOB
  637. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  638. {
  639. // Purge all the signatures in the subject
  640. sSip.pfRemove(pSipInfo, *pdwIndex);
  641. // Store the Signed Message in the sip
  642. if(!sSip.pfPut(pSipInfo,
  643. dwEncodingType,
  644. pdwIndex,
  645. cbEncodedSignMsg,
  646. pbEncodedSignMsg))
  647. PKITHROW(SignError());
  648. }
  649. if(ppbMessage && pcbMessage)
  650. {
  651. *ppbMessage = pbEncodedSignMsg;
  652. pbEncodedSignMsg = NULL;
  653. *pcbMessage = cbEncodedSignMsg;
  654. }
  655. }
  656. PKICATCH(err) {
  657. hr = err.pkiError;
  658. } PKIEND;
  659. if(pbUnauth)
  660. free(pbUnauth);
  661. if(pCert)
  662. CertFreeCertificateContext(pCert);
  663. if(pCrl)
  664. CertFreeCRLContext(pCrl);
  665. if(hTmpCertStore)
  666. CertCloseStore(hTmpCertStore, 0);
  667. if(pbCounterSign)
  668. free(pbCounterSign);
  669. if(pbEncodedSignMsg)
  670. free(pbEncodedSignMsg);
  671. if (hMsg)
  672. CryptMsgClose(hMsg);
  673. if(pbEncodedSigner)
  674. free(pbEncodedSigner);
  675. if(pbSignedMsg)
  676. free(pbSignedMsg);
  677. if(pVersionInfo)
  678. free(pVersionInfo);
  679. if(pbCertInfo)
  680. free(pbCertInfo);
  681. return hr;
  682. }
  683. HRESULT WINAPI
  684. SignerCreateTimeStampRequest(
  685. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject based on which to create a timestamp request
  686. IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to Time stamp request
  687. IN LPVOID pSipData,
  688. OUT PBYTE pbTimeStampRequest,
  689. IN OUT DWORD* pcbTimeStampRequest)
  690. {
  691. HRESULT hr = S_OK;
  692. BOOL fResult=FALSE;
  693. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
  694. PBYTE pbDigest = NULL;
  695. DWORD cbDigest = 0;
  696. PKITRY {
  697. if((!pcbTimeStampRequest) ||(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
  698. PKITHROW(E_INVALIDARG);
  699. if(*pcbTimeStampRequest == 0)
  700. pbTimeStampRequest = NULL;
  701. // Retrieve the digest from the signature on the file.
  702. hr = GetSignedMessageDigest(pSubjectInfo,
  703. pSipData,
  704. &pbDigest,
  705. &cbDigest);
  706. if(hr != S_OK) PKITHROW(hr);
  707. hr = TimeStampRequest(dwEncodingType,
  708. psRequest,
  709. pbDigest,
  710. cbDigest,
  711. pbTimeStampRequest,
  712. pcbTimeStampRequest);
  713. if(hr != S_OK) PKITHROW(hr);
  714. }
  715. PKICATCH(err) {
  716. hr = err.pkiError;
  717. } PKIEND;
  718. if(pbDigest) free(pbDigest);
  719. return hr;
  720. }
  721. HRESULT WINAPI
  722. GetSignedMessageDigest(IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject based on which to create a timestamp request
  723. IN LPVOID pSipData,
  724. IN OUT PBYTE* ppbDigest,
  725. IN OUT DWORD* pcbDigest)
  726. {
  727. HRESULT hr = S_OK;
  728. HANDLE hFile = NULL;
  729. BOOL fFileOpen=FALSE;
  730. GUID gSubjectGuid; // The subject guid used to load the sip
  731. MS_ADDINFO_BLOB sBlob;
  732. SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
  733. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
  734. PKITRY {
  735. if((!pcbDigest) || (!ppbDigest) || (FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
  736. PKITHROW(E_INVALIDARG);
  737. *ppbDigest = NULL;
  738. // Set up the sip information (this is based on mssip.h)
  739. sSubjInfo.dwEncodingType = dwEncodingType;
  740. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
  741. sSubjInfo.pClientData = pSipData;
  742. //set up file information
  743. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  744. {
  745. // Open up the file
  746. if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
  747. (pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
  748. {
  749. if(S_OK != (hr = SignOpenFile(
  750. pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
  751. PKITHROW(hr);
  752. fFileOpen=TRUE;
  753. }
  754. else
  755. hFile=pSubjectInfo->pSignerFileInfo->hFile;
  756. // Get the subject type.
  757. if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
  758. PKITHROW(hr);
  759. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  760. sSubjInfo.hFile = hFile;
  761. sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
  762. }
  763. else
  764. {
  765. memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
  766. sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
  767. sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
  768. sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
  769. sSubjInfo.psBlob=&sBlob;
  770. sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
  771. sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
  772. sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
  773. }
  774. hr = GetSignedMessageDigestSubj(dwEncodingType,
  775. NULL,
  776. &sSubjInfo,
  777. pSubjectInfo->pdwIndex,
  778. ppbDigest,
  779. pcbDigest);
  780. if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
  781. {
  782. fFileOpen = FALSE; // we opened it, but, the SIP closed it!
  783. }
  784. if(hr != S_OK) PKITHROW(hr);
  785. }
  786. PKICATCH(err) {
  787. hr = err.pkiError;
  788. } PKIEND;
  789. if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
  790. return hr;
  791. }
  792. HRESULT WINAPI
  793. GetSignedMessageDigestSubj(IN DWORD dwEncodingType,
  794. IN HCRYPTPROV hCryptProv,
  795. IN LPSIP_SUBJECTINFO pSipInfo,
  796. IN DWORD *pdwIndex,
  797. IN OUT PBYTE* ppbTimeDigest,
  798. IN OUT DWORD* pcbTimeDigest)
  799. {
  800. HRESULT hr = S_OK;
  801. SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
  802. DWORD cbSignedMsg = 0;
  803. PBYTE pbSignedMsg = 0;
  804. DWORD dwCertEncoding = 0;
  805. DWORD dwMsgType = 0;
  806. HCRYPTMSG hMsg = NULL;
  807. BOOL fAcquiredCryptProv = FALSE;
  808. DWORD cbTimeDigest=0;
  809. BYTE *pbTimeDigest=NULL;
  810. PKITRY {
  811. if(!pcbTimeDigest || !ppbTimeDigest)
  812. PKITHROW(E_INVALIDARG);
  813. *ppbTimeDigest=NULL;
  814. *pcbTimeDigest=0;
  815. if(hCryptProv == NULL)
  816. {
  817. if(!CryptAcquireContext(&hCryptProv,
  818. NULL,
  819. MS_DEF_PROV,
  820. PROV_RSA_FULL,
  821. CRYPT_VERIFYCONTEXT))
  822. PKITHROW(SignError());
  823. fAcquiredCryptProv = TRUE;
  824. //update the subject Info
  825. if(NULL==(pSipInfo->hProv))
  826. pSipInfo->hProv=hCryptProv;
  827. }
  828. // Load up the sip functions.
  829. if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
  830. 0, // Reserved
  831. &sSip)) // Table of functions
  832. PKITHROW(SignError());
  833. sSip.pfGet(pSipInfo,
  834. &dwCertEncoding,
  835. *pdwIndex,
  836. &cbSignedMsg,
  837. NULL);
  838. if(cbSignedMsg == 0) PKITHROW(SignError());
  839. pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
  840. if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
  841. if(!sSip.pfGet(pSipInfo,
  842. &dwCertEncoding,
  843. *pdwIndex,
  844. &cbSignedMsg,
  845. pbSignedMsg))
  846. PKITHROW(SignError()); // Real error.
  847. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  848. {
  849. if(dwCertEncoding != dwEncodingType)
  850. PKITHROW(TRUST_E_NOSIGNATURE);
  851. }
  852. if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
  853. SignNoContentWrap(pbSignedMsg, cbSignedMsg))
  854. dwMsgType = CMSG_SIGNED;
  855. // Use CryptMsg to crack the encoded PKCS7 Signed Message
  856. if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
  857. 0, // dwFlags
  858. dwMsgType,
  859. hCryptProv,
  860. NULL, // pRecipientInfo
  861. NULL)))
  862. PKITHROW(E_UNEXPECTED);
  863. if (!CryptMsgUpdate(hMsg,
  864. pbSignedMsg,
  865. cbSignedMsg,
  866. TRUE)) // fFinal
  867. PKITHROW(SignError());
  868. if(!CryptMsgGetParam(hMsg,
  869. CMSG_ENCRYPTED_DIGEST,
  870. 0,
  871. NULL,
  872. &cbTimeDigest))
  873. PKITHROW(SignError());
  874. //allocate memory
  875. pbTimeDigest = (PBYTE)malloc(cbTimeDigest);
  876. if(!pbTimeDigest)
  877. PKITHROW(E_OUTOFMEMORY);
  878. if(!CryptMsgGetParam(hMsg,
  879. CMSG_ENCRYPTED_DIGEST,
  880. 0,
  881. pbTimeDigest,
  882. &cbTimeDigest))
  883. PKITHROW(SignError());
  884. //copy the information
  885. *ppbTimeDigest=pbTimeDigest;
  886. *pcbTimeDigest=cbTimeDigest;
  887. hr=S_OK;
  888. }
  889. PKICATCH(err) {
  890. hr = err.pkiError;
  891. } PKIEND;
  892. if (hMsg)
  893. CryptMsgClose(hMsg);
  894. if(pbSignedMsg)
  895. free(pbSignedMsg);
  896. if((hr!=S_OK) && (pbTimeDigest))
  897. free(pbTimeDigest);
  898. if(fAcquiredCryptProv)
  899. CryptReleaseContext(hCryptProv, 0);
  900. return hr;
  901. }
  902. HRESULT WINAPI
  903. TimeStampRequest(IN DWORD dwEncodingType,
  904. IN PCRYPT_ATTRIBUTES psRequest,
  905. IN PBYTE pbDigest,
  906. IN DWORD cbDigest,
  907. OUT PBYTE pbTimeRequest,
  908. IN OUT DWORD* pcbTimeRequest)
  909. {
  910. HRESULT hr = S_OK;
  911. CRYPT_TIME_STAMP_REQUEST_INFO sTimeRequest; ZERO(sTimeRequest);
  912. PBYTE pbEncodedRequest = NULL;
  913. DWORD cbEncodedRequest = 0;
  914. PKITRY {
  915. if(!pcbTimeRequest)
  916. PKITHROW(E_INVALIDARG);
  917. if(*pcbTimeRequest == 0)
  918. pbTimeRequest = NULL;
  919. sTimeRequest.pszTimeStampAlgorithm = SPC_TIME_STAMP_REQUEST_OBJID;
  920. sTimeRequest.pszContentType = szOID_RSA_data;
  921. sTimeRequest.Content.pbData = pbDigest;
  922. sTimeRequest.Content.cbData = cbDigest;
  923. if(psRequest) {
  924. sTimeRequest.cAttribute = psRequest->cAttr;
  925. sTimeRequest.rgAttribute = psRequest->rgAttr;
  926. }
  927. CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  928. PKCS_TIME_REQUEST,
  929. &sTimeRequest,
  930. pbEncodedRequest,
  931. &cbEncodedRequest);
  932. if(cbEncodedRequest == 0) PKITHROW(SignError());
  933. pbEncodedRequest = (PBYTE) malloc(cbEncodedRequest);
  934. if(!pbEncodedRequest) PKITHROW(E_OUTOFMEMORY);
  935. if(!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  936. PKCS_TIME_REQUEST,
  937. &sTimeRequest,
  938. pbEncodedRequest,
  939. &cbEncodedRequest))
  940. PKITHROW(SignError());
  941. //return the infomation
  942. if(*pcbTimeRequest==0)
  943. {
  944. *pcbTimeRequest=cbEncodedRequest;
  945. hr=S_OK;
  946. }
  947. else
  948. {
  949. if(*pcbTimeRequest < cbEncodedRequest)
  950. {
  951. hr=ERROR_MORE_DATA;
  952. PKITHROW(SignError());
  953. }
  954. else
  955. {
  956. memcpy(pbTimeRequest, pbEncodedRequest, cbEncodedRequest);
  957. hr=S_OK;
  958. }
  959. }
  960. }
  961. PKICATCH(err) {
  962. hr = err.pkiError;
  963. } PKIEND;
  964. if(pbEncodedRequest)
  965. free(pbEncodedRequest);
  966. return hr;
  967. }