Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1196 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: signer.cpp
  8. //
  9. // Contents: Microsoft Internet Security Signing API
  10. //
  11. // History: June-25-97 xiaohs created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include <stdio.h>
  16. //--------------------------------------------------------------------------
  17. //
  18. // InternalSign:
  19. // The signing routine called by signer.dll internally. This is the
  20. // function that actually does the job.
  21. //
  22. //--------------------------------------------------------------------------
  23. HRESULT WINAPI
  24. InternalSign(IN DWORD dwEncodingType, // Encoding type
  25. IN HCRYPTPROV hCryptProv, // CAPI provider, opened for signing private key
  26. IN DWORD dwKeySpec, // Type of signing key, AT_SIGNATURE or AT_EXCHANGE
  27. IN LPCSTR pszAlgorithmOid, // Algorithm id used to create digest
  28. IN LPSIP_SUBJECTINFO pSipInfo, // SIP information
  29. IN DWORD *pdwIndex, // signer index
  30. IN PCCERT_CONTEXT psSigningContext, // Cert context to the signing certificate
  31. IN HCERTSTORE hSpcStore, // The credentials to use in the signing
  32. IN LPCWSTR pwszOpusName, // Optional, the name of the program to appear in
  33. IN LPCWSTR pwszOpusInfo, // Optional, the unparsed name of a link to more
  34. IN BOOL fIncludeCerts, // add the certificates to the signature
  35. IN BOOL fCommercial, // commerical signing
  36. IN BOOL fIndividual, // individual signing
  37. IN BOOL fAuthcode, // whether use fCommercial as an attributes
  38. IN PCRYPT_ATTRIBUTES psAuthenticated, // Optional, authenticated attributes added to signature
  39. IN PCRYPT_ATTRIBUTES psUnauthenticated, // Optional, unauthenticated attributes added to signature
  40. OUT PBYTE* ppbDigest, //Optional: return the Digest of the file
  41. OUT DWORD* pcbDigest, //Optional: return the size of the digest
  42. OUT PBYTE* ppbMessage, //Optional: return the encoded signed message
  43. OUT DWORD* pcbMessage) //Optional: return the size of encoded signed message
  44. {
  45. HRESULT hr = S_OK;
  46. SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
  47. PBYTE pbOpusAttribute = NULL; // Encoding for the opus attribute
  48. DWORD cbOpusAttribute = 0; // :
  49. PBYTE pbStatementAttribute = NULL; // Encoding for the statement attribute
  50. DWORD cbStatementAttribute = 0; // :
  51. PCRYPT_ATTRIBUTE rgpAuthAttributes = NULL;
  52. DWORD dwAuthAttributes = 0;
  53. PCRYPT_ATTRIBUTE rgpUnauthAttributes = NULL;
  54. DWORD dwUnauthAttributes = 0;
  55. PSIP_INDIRECT_DATA psIndirectData = NULL; // Indirect data structure
  56. DWORD dwIndirectData = 0;
  57. PBYTE pbIndirectBlob = NULL; // Encoding Indirect blob
  58. DWORD cbIndirectBlob = 0; // :
  59. PBYTE pbGetBlob=NULL;
  60. DWORD cbGetBlob=0;
  61. CRYPT_DATA_BLOB PKCS7Blob;
  62. HCERTSTORE hPKCS7CertStore=NULL;
  63. DWORD dwPKCS7Certs=0;
  64. PCERT_BLOB rgPKCS7Certs=NULL;
  65. PBYTE pbEncodedSignMsg = NULL; // Encoding for the statement attribute
  66. DWORD cbEncodedSignMsg = 0; // :
  67. HCRYPTMSG hMsg = NULL;
  68. CMSG_SIGNER_ENCODE_INFO sSignerInfo;
  69. CMSG_SIGNED_ENCODE_INFO sSignedInfo;
  70. PCERT_BLOB rgpCryptMsgCertificates = NULL;
  71. DWORD dwCryptMsgCertificates = 0;
  72. PCRL_BLOB rgpCryptMsgCrls = NULL;
  73. DWORD dwCryptMsgCrls = 0;
  74. PBYTE pbSignerData = NULL;
  75. DWORD cbSignerData = 0;
  76. BOOL fSignCommercial=FALSE;
  77. BOOL fCTLFile =FALSE;
  78. PCTL_CONTEXT pCTLContext=NULL;
  79. GUID CTLGuid=CRYPT_SUBJTYPE_CTL_IMAGE;
  80. GUID CATGuid=CRYPT_SUBJTYPE_CATALOG_IMAGE;
  81. DWORD dwCertIndex=0;
  82. BOOL fFound=FALSE;
  83. BOOL fNeedStatementType=FALSE;
  84. PKITRY {
  85. //init memory
  86. ZeroMemory(&sSignerInfo, sizeof(CMSG_SIGNER_ENCODE_INFO));
  87. ZeroMemory(&sSignedInfo, sizeof(CMSG_SIGNED_ENCODE_INFO));
  88. // Load up the sip functions.
  89. if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
  90. 0, // Reserved
  91. &sSip)) // Table of functions
  92. PKITHROW(SignError());
  93. // Set up the attributes (AUTHENTICODE Specific, replace with your attributes)
  94. // Encode the opus information up into an attribute
  95. if(fAuthcode)
  96. {
  97. hr = CreateOpusInfo(pwszOpusName,
  98. pwszOpusInfo,
  99. &pbOpusAttribute,
  100. &cbOpusAttribute);
  101. if(hr != S_OK) PKITHROW(hr);
  102. //Check to see if we need to put the statement type attributes
  103. if(NeedStatementTypeAttr(psSigningContext, fCommercial, fIndividual))
  104. {
  105. fNeedStatementType=TRUE;
  106. // Check signing certificate to see if its signing cabablity complies
  107. //with the request
  108. if(S_OK!=(hr=CheckCommercial(psSigningContext,fCommercial, fIndividual,
  109. &fSignCommercial)))
  110. PKITHROW(hr);
  111. if(S_OK !=(hr = CreateStatementType(fSignCommercial,
  112. &pbStatementAttribute,
  113. &cbStatementAttribute)))
  114. PKITHROW(hr);
  115. }
  116. else
  117. fNeedStatementType=FALSE;
  118. }
  119. // Create Authenticode attributes and append additional authenticated attributes.
  120. // Allocate and add StatementType and SpOpusInfo (add room for one blob per attribute, which we need)
  121. DWORD dwAttrSize = 0;
  122. //get the number of authenticated attributes
  123. if(fAuthcode)
  124. {
  125. if(fNeedStatementType)
  126. dwAuthAttributes = 2; // StatementType + opus
  127. else
  128. dwAuthAttributes= 1;
  129. }
  130. else
  131. dwAuthAttributes= 0;
  132. if(psAuthenticated)
  133. dwAuthAttributes += psAuthenticated->cAttr;
  134. dwAttrSize = sizeof(CRYPT_ATTRIBUTE) * dwAuthAttributes + 2 * sizeof(CRYPT_ATTR_BLOB);
  135. rgpAuthAttributes = (PCRYPT_ATTRIBUTE) malloc(dwAttrSize);
  136. if(!rgpAuthAttributes) PKITHROW(E_OUTOFMEMORY);
  137. ZeroMemory(rgpAuthAttributes, dwAttrSize);
  138. PCRYPT_ATTR_BLOB pValue = (PCRYPT_ATTR_BLOB) (rgpAuthAttributes + dwAuthAttributes);
  139. //the start of the authenticated attributes
  140. dwAttrSize=0;
  141. //add the authenticode specific attributes
  142. if(fAuthcode)
  143. {
  144. // Update SpOpusInfo
  145. rgpAuthAttributes[dwAttrSize].pszObjId = SPC_SP_OPUS_INFO_OBJID;
  146. rgpAuthAttributes[dwAttrSize].cValue = 1;
  147. rgpAuthAttributes[dwAttrSize].rgValue = &pValue[dwAttrSize];
  148. pValue[dwAttrSize].pbData = pbOpusAttribute;
  149. pValue[dwAttrSize].cbData = cbOpusAttribute;
  150. dwAttrSize++;
  151. // Update StatementType
  152. if(fNeedStatementType)
  153. {
  154. rgpAuthAttributes[dwAttrSize].pszObjId = SPC_STATEMENT_TYPE_OBJID;
  155. rgpAuthAttributes[dwAttrSize].cValue = 1;
  156. rgpAuthAttributes[dwAttrSize].rgValue = &pValue[dwAttrSize];
  157. pValue[dwAttrSize].pbData = pbStatementAttribute;
  158. pValue[dwAttrSize].cbData = cbStatementAttribute;
  159. dwAttrSize++;
  160. }
  161. }
  162. if(psAuthenticated) {
  163. for(DWORD i = dwAttrSize, ii = 0; ii < psAuthenticated->cAttr; ii++, i++)
  164. rgpAuthAttributes[i] = psAuthenticated->rgAttr[ii];
  165. }
  166. // Get the Unauthenticated attributes
  167. if(psUnauthenticated) {
  168. rgpUnauthAttributes = psUnauthenticated->rgAttr;
  169. dwUnauthAttributes = psUnauthenticated->cAttr;
  170. }
  171. //check to see if the file is either a catalog file or a CTL file
  172. if((CTLGuid == (*(pSipInfo->pgSubjectType))) ||
  173. (CATGuid == (*(pSipInfo->pgSubjectType)))
  174. )
  175. fCTLFile=TRUE;
  176. else
  177. {
  178. // Get the indirect data struct from the SIP
  179. if(!sSip.pfCreate(pSipInfo,
  180. &dwIndirectData,
  181. psIndirectData))
  182. PKITHROW(SignError());
  183. psIndirectData = (PSIP_INDIRECT_DATA) malloc(dwIndirectData);
  184. if(!psIndirectData)
  185. PKITHROW(E_OUTOFMEMORY);
  186. if(!sSip.pfCreate(pSipInfo,
  187. &dwIndirectData,
  188. psIndirectData))
  189. PKITHROW(SignError());
  190. // Encode the indirect data
  191. CryptEncodeObject(dwEncodingType,
  192. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  193. psIndirectData,
  194. pbIndirectBlob,
  195. &cbIndirectBlob);
  196. if (cbIndirectBlob == 0)
  197. PKITHROW(SignError());
  198. pbIndirectBlob = (PBYTE) malloc(cbIndirectBlob);
  199. if(!pbIndirectBlob)
  200. PKITHROW(E_OUTOFMEMORY);
  201. if (!CryptEncodeObject(dwEncodingType,
  202. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  203. psIndirectData,
  204. pbIndirectBlob,
  205. &cbIndirectBlob))
  206. PKITHROW(SignError());
  207. }
  208. // Encode the signed message
  209. // Setup the signing info
  210. ZeroMemory(&sSignerInfo, sizeof(CMSG_SIGNER_ENCODE_INFO));
  211. sSignerInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
  212. sSignerInfo.pCertInfo = psSigningContext->pCertInfo;
  213. sSignerInfo.hCryptProv = hCryptProv;
  214. sSignerInfo.dwKeySpec = dwKeySpec;
  215. sSignerInfo.HashAlgorithm.pszObjId = (char*) pszAlgorithmOid;
  216. sSignerInfo.cAuthAttr = dwAuthAttributes;
  217. sSignerInfo.rgAuthAttr = rgpAuthAttributes;
  218. sSignerInfo.cUnauthAttr = dwUnauthAttributes;
  219. sSignerInfo.rgUnauthAttr = rgpUnauthAttributes;
  220. // Setup the signing structures
  221. ZeroMemory(&sSignedInfo, sizeof(CMSG_SIGNED_ENCODE_INFO));
  222. sSignedInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
  223. sSignedInfo.cSigners = 1;
  224. sSignedInfo.rgSigners = &sSignerInfo;
  225. // if there are certificates to add change them to the
  226. // form required by CryptMsg... functions
  227. // load up the certificates into a vector
  228. // Count the number of certs in the store
  229. if(fIncludeCerts && hSpcStore) {
  230. PCCERT_CONTEXT pCert = NULL;
  231. while ((pCert = CertEnumCertificatesInStore(hSpcStore, pCert)))
  232. dwCryptMsgCertificates++;
  233. // Get the encoded blobs of the CERTS
  234. if (dwCryptMsgCertificates > 0) {
  235. rgpCryptMsgCertificates = (PCERT_BLOB) malloc(sizeof(CERT_BLOB) * dwCryptMsgCertificates);
  236. if(!rgpCryptMsgCertificates)
  237. PKITHROW(E_OUTOFMEMORY);
  238. ZeroMemory(rgpCryptMsgCertificates, sizeof(CERT_BLOB) * dwCryptMsgCertificates);
  239. PCERT_BLOB pCertPtr = rgpCryptMsgCertificates;
  240. pCert = NULL;
  241. DWORD c = 0;
  242. while ((pCert = CertEnumCertificatesInStore(hSpcStore, pCert)) && c < dwCryptMsgCertificates) {
  243. pCertPtr->pbData = pCert->pbCertEncoded;
  244. pCertPtr->cbData = pCert->cbCertEncoded;
  245. c++; pCertPtr++;
  246. }
  247. }
  248. sSignedInfo.cCertEncoded = dwCryptMsgCertificates;
  249. sSignedInfo.rgCertEncoded = rgpCryptMsgCertificates;
  250. rgpCryptMsgCertificates=NULL;
  251. // Get the encoded blobs of the CRLS
  252. DWORD crlFlag = 0;
  253. PCCRL_CONTEXT pCrl = NULL;
  254. while ((pCrl = CertGetCRLFromStore(hSpcStore, NULL, pCrl, &crlFlag)))
  255. dwCryptMsgCrls++;
  256. if (dwCryptMsgCrls > 0) {
  257. rgpCryptMsgCrls = (PCRL_BLOB) malloc(sizeof(CRL_BLOB) * dwCryptMsgCrls);
  258. if(!rgpCryptMsgCrls) PKITHROW(E_OUTOFMEMORY);
  259. ZeroMemory(rgpCryptMsgCrls, sizeof(CRL_BLOB) * dwCryptMsgCrls);
  260. PCRL_BLOB pCrlPtr = rgpCryptMsgCrls;
  261. pCrl = NULL;
  262. DWORD c = 0;
  263. while ((pCrl = CertGetCRLFromStore(hSpcStore, NULL, pCrl, &crlFlag)) && c < dwCryptMsgCrls) {
  264. pCrlPtr->pbData = pCrl->pbCrlEncoded;
  265. pCrlPtr->cbData = pCrl->cbCrlEncoded;
  266. c++; pCrlPtr++;
  267. }
  268. }
  269. sSignedInfo.cCrlEncoded = dwCryptMsgCrls;
  270. sSignedInfo.rgCrlEncoded = rgpCryptMsgCrls;
  271. rgpCryptMsgCrls=NULL;
  272. }
  273. //check to see if the subject is a CTL file. If it is, we need to preserve
  274. //all the certificates in the original signer Info
  275. if(CTLGuid == (*(pSipInfo->pgSubjectType)))
  276. {
  277. PCCERT_CONTEXT pCert = NULL;
  278. //call Get the get the original signer information
  279. sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, NULL);
  280. if (cbGetBlob < 1)
  281. {
  282. PKITHROW(SignError());
  283. }
  284. if (!(pbGetBlob = (BYTE *)malloc(cbGetBlob)))
  285. {
  286. PKITHROW(E_OUTOFMEMORY);
  287. }
  288. if (!(sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, pbGetBlob)))
  289. {
  290. PKITHROW(SignError());
  291. }
  292. //open the PKCS7 BLOB as a certificate store
  293. PKCS7Blob.cbData=cbGetBlob;
  294. PKCS7Blob.pbData=pbGetBlob;
  295. hPKCS7CertStore=CertOpenStore(CERT_STORE_PROV_PKCS7,
  296. dwEncodingType,
  297. NULL,
  298. 0,
  299. &PKCS7Blob);
  300. if(!hPKCS7CertStore)
  301. PKITHROW(SignError());
  302. //enum all the certificate in the store
  303. while ((pCert = CertEnumCertificatesInStore(hPKCS7CertStore, pCert)))
  304. dwPKCS7Certs++;
  305. //Get the encoded blobs of the CERTS
  306. if (dwPKCS7Certs > 0)
  307. {
  308. VOID *pvTemp;
  309. pvTemp = realloc(sSignedInfo.rgCertEncoded,
  310. sizeof(CERT_BLOB) * (sSignedInfo.cCertEncoded+dwPKCS7Certs));
  311. if(!pvTemp)
  312. PKITHROW(E_OUTOFMEMORY)
  313. else
  314. sSignedInfo.rgCertEncoded = (PCERT_BLOB) pvTemp;
  315. PCERT_BLOB pCertPtr = (sSignedInfo.rgCertEncoded + sSignedInfo.cCertEncoded);
  316. pCert = NULL;
  317. DWORD c = 0;
  318. while ((pCert = CertEnumCertificatesInStore(hPKCS7CertStore, pCert)) && c < dwPKCS7Certs)
  319. {
  320. fFound=FALSE;
  321. //we need to make sure that we do not add duplicated certificates
  322. for(dwCertIndex=0; dwCertIndex<sSignedInfo.cCertEncoded; dwCertIndex++)
  323. {
  324. if((sSignedInfo.rgCertEncoded[dwCertIndex]).cbData==pCert->cbCertEncoded)
  325. {
  326. if(0==memcmp((sSignedInfo.rgCertEncoded[dwCertIndex]).pbData,
  327. pCert->pbCertEncoded, pCert->cbCertEncoded))
  328. {
  329. fFound=TRUE;
  330. break;
  331. }
  332. }
  333. }
  334. //we only add the certificates that do not duplicates the signer's
  335. //certificates
  336. if(FALSE==fFound)
  337. {
  338. pCertPtr->pbData = pCert->pbCertEncoded;
  339. pCertPtr->cbData = pCert->cbCertEncoded;
  340. c++; pCertPtr++;
  341. }
  342. }
  343. sSignedInfo.cCertEncoded += c;
  344. }
  345. }
  346. if (fCTLFile)
  347. {
  348. //
  349. // get the signed message if we need to
  350. //
  351. if(NULL==pbGetBlob)
  352. {
  353. //
  354. sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, NULL);
  355. if (cbGetBlob < 1)
  356. {
  357. PKITHROW(SignError());
  358. }
  359. if (!(pbGetBlob = (BYTE *)malloc(cbGetBlob)))
  360. {
  361. PKITHROW(E_OUTOFMEMORY);
  362. }
  363. if (!(sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, pbGetBlob)))
  364. {
  365. PKITHROW(SignError());
  366. }
  367. }
  368. //
  369. // extract the inner content
  370. //
  371. pCTLContext = (PCTL_CONTEXT)CertCreateCTLContext(
  372. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  373. pbGetBlob,
  374. cbGetBlob);
  375. if (!(pCTLContext))
  376. {
  377. PKITHROW(SignError());
  378. }
  379. if (!(pCTLContext->pbCtlContent))
  380. {
  381. PKITHROW(SignError());
  382. }
  383. //
  384. // add singer info! (e.g.: sign it!)
  385. //
  386. cbEncodedSignMsg = 0;
  387. CryptMsgSignCTL(dwEncodingType, pCTLContext->pbCtlContent, pCTLContext->cbCtlContent,
  388. &sSignedInfo, 0, NULL, &cbEncodedSignMsg);
  389. if (cbEncodedSignMsg < 1)
  390. {
  391. PKITHROW(SignError());
  392. }
  393. if (!(pbEncodedSignMsg = (BYTE *)malloc(cbEncodedSignMsg)))
  394. {
  395. PKITHROW(E_OUTOFMEMORY);
  396. }
  397. if (!(CryptMsgSignCTL(dwEncodingType,
  398. pCTLContext->pbCtlContent, pCTLContext->cbCtlContent,
  399. &sSignedInfo, 0, pbEncodedSignMsg, &cbEncodedSignMsg)))
  400. {
  401. PKITHROW(SignError());
  402. }
  403. CertFreeCTLContext(pCTLContext);
  404. pCTLContext = NULL;
  405. }
  406. else
  407. {
  408. hMsg = CryptMsgOpenToEncode(dwEncodingType,
  409. 0, // dwFlags
  410. CMSG_SIGNED,
  411. &sSignedInfo,
  412. SPC_INDIRECT_DATA_OBJID,
  413. NULL);
  414. if(hMsg == NULL)
  415. PKITHROW(SignError());
  416. if (!CryptMsgUpdate(hMsg,
  417. pbIndirectBlob,
  418. cbIndirectBlob,
  419. TRUE)) // Final
  420. PKITHROW(SignError());
  421. CryptMsgGetParam(hMsg,
  422. CMSG_CONTENT_PARAM,
  423. 0, // dwIndex
  424. NULL, // pbSignedData
  425. &cbEncodedSignMsg);
  426. if (cbEncodedSignMsg == 0) PKITHROW(SignError());
  427. pbEncodedSignMsg = (PBYTE) malloc(cbEncodedSignMsg);
  428. if(!pbEncodedSignMsg) PKITHROW(E_OUTOFMEMORY);
  429. if (!CryptMsgGetParam(hMsg,
  430. CMSG_CONTENT_PARAM,
  431. 0, // dwIndex
  432. pbEncodedSignMsg,
  433. &cbEncodedSignMsg))
  434. PKITHROW(SignError());
  435. }
  436. //put the signatures if we are dealing with anything other than the BLOB
  437. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  438. {
  439. // Purge all the signatures in the subject
  440. sSip.pfRemove(pSipInfo, *pdwIndex);
  441. // Store the Signed Message in the sip
  442. if(!(sSip.pfPut( pSipInfo,
  443. dwEncodingType,
  444. pdwIndex,
  445. cbEncodedSignMsg,
  446. pbEncodedSignMsg)))
  447. {
  448. PKITHROW(SignError());
  449. }
  450. }
  451. if(ppbMessage && pcbMessage) {
  452. *ppbMessage = pbEncodedSignMsg;
  453. pbEncodedSignMsg = NULL;
  454. *pcbMessage = cbEncodedSignMsg;
  455. }
  456. if(ppbDigest && pcbDigest) {
  457. // Get the encrypted digest
  458. pbSignerData = NULL;
  459. CryptMsgGetParam(hMsg,
  460. CMSG_ENCRYPTED_DIGEST,
  461. 0, // dwIndex
  462. pbSignerData,
  463. &cbSignerData);
  464. if(cbSignerData == 0) PKITHROW(SignError());
  465. pbSignerData = (PBYTE) malloc(cbSignerData);
  466. if(!pbSignerData) PKITHROW(E_OUTOFMEMORY);
  467. if(!CryptMsgGetParam(hMsg,
  468. CMSG_ENCRYPTED_DIGEST,
  469. 0, // dwIndex
  470. pbSignerData,
  471. &cbSignerData))
  472. PKITHROW(SignError());
  473. *ppbDigest = pbSignerData;
  474. pbSignerData = NULL;
  475. *pcbDigest = cbSignerData;
  476. }
  477. }
  478. PKICATCH(err) {
  479. hr = err.pkiError;
  480. } PKIEND;
  481. if (pCTLContext)
  482. {
  483. CertFreeCTLContext(pCTLContext);
  484. }
  485. if (pbSignerData)
  486. free(pbSignerData);
  487. if(pbEncodedSignMsg)
  488. free(pbEncodedSignMsg);
  489. if(hMsg)
  490. CryptMsgClose(hMsg);
  491. if(sSignedInfo.rgCrlEncoded)
  492. free(sSignedInfo.rgCrlEncoded);
  493. if(sSignedInfo.rgCertEncoded)
  494. free(sSignedInfo.rgCertEncoded);
  495. if(pbIndirectBlob)
  496. free(pbIndirectBlob);
  497. if(pbGetBlob)
  498. free(pbGetBlob);
  499. if(hPKCS7CertStore)
  500. CertCloseStore(hPKCS7CertStore,0);
  501. if(psIndirectData)
  502. free(psIndirectData);
  503. if(rgpAuthAttributes)
  504. free(rgpAuthAttributes);
  505. if(pbStatementAttribute)
  506. free(pbStatementAttribute);
  507. if(pbOpusAttribute)
  508. free(pbOpusAttribute);
  509. return hr;
  510. }
  511. //--------------------------------------------------------------------------
  512. //
  513. // SignerTimeStamp:
  514. // Timestamp a file.
  515. //
  516. //--------------------------------------------------------------------------
  517. HRESULT WINAPI
  518. SignerTimeStamp(
  519. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be timestamped
  520. IN LPCWSTR pwszHttpTimeStamp, // Required: timestamp server HTTP address
  521. IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to the timestamp
  522. IN LPVOID pSipData // Optional: The additional data passed to sip funcitons
  523. )
  524. {
  525. return SignerTimeStampEx(0,
  526. pSubjectInfo,
  527. pwszHttpTimeStamp,
  528. psRequest,
  529. pSipData,
  530. NULL);
  531. }
  532. //--------------------------------------------------------------------------
  533. //
  534. // SignerTimeStampEx:
  535. // Timestamp a file.
  536. //
  537. //--------------------------------------------------------------------------
  538. HRESULT WINAPI
  539. SignerTimeStampEx(
  540. IN DWORD dwFlags, //Reserved: Has to be set to 0.
  541. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be timestamped
  542. IN LPCWSTR pwszHttpTimeStamp, // Required: timestamp server HTTP address
  543. IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to the timestamp
  544. IN LPVOID pSipData, // Optional: The additional data passed to sip funcitons
  545. OUT SIGNER_CONTEXT **ppSignerContext // Optional: The signed BLOB. User has to free
  546. // the context via SignerFreeSignerContext
  547. )
  548. {
  549. HRESULT hr=E_FAIL;
  550. DWORD dwTimeStampRequest=0;
  551. BYTE *pbTimeStampRequest=NULL;
  552. DWORD dwTimeStampResponse=0;
  553. BYTE *pbTimeStampResponse=NULL;
  554. CHttpTran cTran;
  555. BOOL fOpen=FALSE;
  556. DWORD err;
  557. LPSTR szURL=NULL;
  558. DWORD dwEncodingType=OCTET_ENCODING;
  559. CHAR *pEncodedRequest=NULL;
  560. DWORD dwEncodedRequest=0;
  561. CHAR *pEncodedResponse=NULL;
  562. DWORD dwEncodedResponse=0;
  563. //input parameter check
  564. if((!pwszHttpTimeStamp) ||(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
  565. return E_INVALIDARG;
  566. //request a time stamp
  567. hr=SignerCreateTimeStampRequest(pSubjectInfo,
  568. psRequest,
  569. pSipData,
  570. NULL,
  571. &dwTimeStampRequest);
  572. if(hr!=S_OK)
  573. goto CLEANUP;
  574. pbTimeStampRequest=(BYTE *)malloc(dwTimeStampRequest);
  575. if(!pbTimeStampRequest)
  576. {
  577. hr=E_OUTOFMEMORY;
  578. goto CLEANUP;
  579. }
  580. hr=SignerCreateTimeStampRequest(pSubjectInfo,
  581. psRequest,
  582. pSipData,
  583. pbTimeStampRequest,
  584. &dwTimeStampRequest);
  585. if(hr!=S_OK)
  586. goto CLEANUP;
  587. //conver the WSTR of URL to STR
  588. if((hr=WSZtoSZ((LPWSTR)pwszHttpTimeStamp,&szURL))!=S_OK)
  589. goto CLEANUP;
  590. //base64 encode the request
  591. if(S_OK!=(hr=BytesToBase64(pbTimeStampRequest,
  592. dwTimeStampRequest,
  593. &pEncodedRequest,
  594. &dwEncodedRequest)))
  595. goto CLEANUP;
  596. //estalish the connection between the http site
  597. err=cTran.Open( szURL, GTREAD|GTWRITE);
  598. if(err!=ERROR_SUCCESS)
  599. {
  600. hr=E_FAIL;
  601. goto CLEANUP;
  602. }
  603. //mark that we have open the connection successful
  604. fOpen=TRUE;
  605. //send the request
  606. err=cTran.Send(dwEncodingType,dwEncodedRequest,(BYTE *)pEncodedRequest);
  607. if(err!=ERROR_SUCCESS)
  608. {
  609. hr=HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  610. goto CLEANUP;
  611. }
  612. //send the request
  613. err=cTran.Receive(&dwEncodingType,&dwEncodedResponse,(BYTE **)&pEncodedResponse);
  614. if(err!=ERROR_SUCCESS)
  615. {
  616. hr=E_FAIL;
  617. goto CLEANUP;
  618. }
  619. //make sure the encoding type is correct
  620. // if(dwEncodingType!=OCTET_ENCODING)
  621. // {
  622. // hr=E_FAIL;
  623. // goto CLEANUP;
  624. // }
  625. //base64 decode the response
  626. if(S_OK != (hr=Base64ToBytes(
  627. pEncodedResponse,
  628. dwEncodedResponse,
  629. &pbTimeStampResponse,
  630. &dwTimeStampResponse)))
  631. goto CLEANUP;
  632. //add the timestamp response to the time
  633. hr=SignerAddTimeStampResponseEx(0, pSubjectInfo,pbTimeStampResponse,
  634. dwTimeStampResponse, pSipData,
  635. ppSignerContext);
  636. CLEANUP:
  637. if(pEncodedRequest)
  638. free(pEncodedRequest);
  639. if(pbTimeStampResponse)
  640. free(pbTimeStampResponse);
  641. if(pbTimeStampRequest)
  642. free(pbTimeStampRequest);
  643. if(szURL)
  644. free(szURL);
  645. if(fOpen)
  646. {
  647. if(pEncodedResponse)
  648. cTran.Free((BYTE *)pEncodedResponse);
  649. cTran.Close();
  650. }
  651. return hr;
  652. }
  653. //+-----------------------------------------------------------------------
  654. //
  655. // SignerSign:
  656. // Sign and/or timestamp a file.
  657. //
  658. //------------------------------------------------------------------------
  659. HRESULT WINAPI
  660. SignerSign(
  661. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be signed and/or timestamped
  662. IN SIGNER_CERT *pSignerCert, //Required: The signing certificate to use
  663. IN SIGNER_SIGNATURE_INFO *pSignatureInfo, //Required: The signature information during signing process
  664. IN SIGNER_PROVIDER_INFO *pProviderInfo, //Optional: The crypto security provider to use.
  665. // This parameter has to be set unless
  666. // certStoreInfo is set in *pSignerCert
  667. // and the signing certificate has provider
  668. // information associated with it
  669. IN LPCWSTR pwszHttpTimeStamp, //Optional: Timestamp server http address. If this parameter
  670. // is set, the file will be timestamped.
  671. IN PCRYPT_ATTRIBUTES psRequest, //Optional: Attributes added to Time stamp request. Ignored
  672. // unless pwszHttpTimeStamp is set
  673. IN LPVOID pSipData //Optional: The additional data passed to sip funcitons
  674. )
  675. {
  676. return SignerSignEx(
  677. 0,
  678. pSubjectInfo,
  679. pSignerCert,
  680. pSignatureInfo,
  681. pProviderInfo,
  682. pwszHttpTimeStamp,
  683. psRequest,
  684. pSipData,
  685. NULL);
  686. }
  687. //+-----------------------------------------------------------------------
  688. //
  689. // SignerSignEx:
  690. // Sign and/or timestamp a file.
  691. //
  692. //------------------------------------------------------------------------
  693. HRESULT WINAPI
  694. SignerSignEx(
  695. IN DWORD dwFlags, //Reserved: Has to be set to 0.
  696. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be signed and/or timestamped
  697. IN SIGNER_CERT *pSignerCert, //Required: The signing certificate to use
  698. IN SIGNER_SIGNATURE_INFO *pSignatureInfo, //Required: The signature information during signing process
  699. IN SIGNER_PROVIDER_INFO *pProviderInfo, //Optional: The crypto security provider to use.
  700. // This parameter has to be set unless
  701. // certStoreInfo is set in *pSignerCert
  702. // and the signing certificate has provider
  703. // information associated with it
  704. IN LPCWSTR pwszHttpTimeStamp, //Optional: Timestamp server http address. If this parameter
  705. // is set, the file will be timestamped.
  706. IN PCRYPT_ATTRIBUTES psRequest, //Optional: Attributes added to Time stamp request. Ignored
  707. // unless pwszHttpTimeStamp is set
  708. IN LPVOID pSipData, //Optional: The additional data passed to sip funcitons
  709. OUT SIGNER_CONTEXT **ppSignerContext //Optional: The signed BLOB. User has to free
  710. // the context via SignerFreeSignerContext
  711. )
  712. {
  713. HRESULT hr = S_OK;
  714. HANDLE hFile = NULL; // File to sign
  715. BOOL fFileOpen=FALSE;
  716. HCERTSTORE hSpcStore = NULL; // Certificates added to signature
  717. PCCERT_CONTEXT psSigningContext = NULL; // Cert context to the signing certificate
  718. GUID gSubjectGuid; // The subject guid used to load the sip
  719. SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
  720. MS_ADDINFO_BLOB sBlob;
  721. HCRYPTPROV hCryptProv = NULL; // Crypto provider, uses private key container
  722. HCRYPTPROV hMSBaseProv = NULL; //This is the MS base provider for hashing purpose
  723. LPWSTR pwszTmpContainer = NULL; // Pvk container (opened up pvk file)
  724. LPWSTR pwszProvName=NULL;
  725. DWORD dwProvType;
  726. BOOL fAcquired=FALSE;
  727. LPCWSTR pwszPvkFile = NULL;
  728. LPCWSTR pwszKeyContainerName = NULL;
  729. BOOL fAuthcode=FALSE;
  730. BOOL fCertAcquire=FALSE;
  731. //set dwKeySpec to 0. That is, we allow any key specification
  732. //for code signing
  733. DWORD dwKeySpec = 0;
  734. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
  735. LPCSTR pszAlgorithmOid = NULL;
  736. WCHAR wszPublisher[40];
  737. PBYTE pbEncodedMessage=NULL;
  738. DWORD cbEncodedMessage=0;
  739. //input parameter checking
  740. if(!CheckSigncodeParam(pSubjectInfo, pSignerCert, pSignatureInfo,
  741. pProviderInfo))
  742. return E_INVALIDARG;
  743. //determine if this is an authenticode specific signing
  744. if(pSignatureInfo->dwAttrChoice==SIGNER_AUTHCODE_ATTR)
  745. fAuthcode=TRUE;
  746. //init
  747. if(ppSignerContext)
  748. *ppSignerContext=NULL;
  749. // Acquire a context for the specified provider
  750. // First,try to acquire the provider context based on the properties on a cert
  751. if(pSignerCert->dwCertChoice==SIGNER_CERT_STORE)
  752. {
  753. if(GetCryptProvFromCert(pSignerCert->hwnd,
  754. (pSignerCert->pCertStoreInfo)->pSigningCert,
  755. &hCryptProv,
  756. &dwKeySpec,
  757. &fAcquired,
  758. &pwszTmpContainer,
  759. &pwszProvName,
  760. &dwProvType))
  761. //mark that we acquire the context via the cert's property
  762. fCertAcquire=TRUE;
  763. }
  764. // If the 1st failed, try to acquire the provider context based on
  765. //pPvkInfo
  766. if(hCryptProv==NULL)
  767. {
  768. //pProviderInfo has to be set
  769. if(!pProviderInfo)
  770. {
  771. hr=CRYPT_E_NO_PROVIDER;
  772. goto CLEANUP;
  773. }
  774. //decide the PVK file name or the key container name
  775. if(pProviderInfo->dwPvkChoice == PVK_TYPE_FILE_NAME)
  776. pwszPvkFile=pProviderInfo->pwszPvkFileName;
  777. else
  778. pwszKeyContainerName=pProviderInfo->pwszKeyContainer;
  779. //load from the resource of string L"publisher"
  780. if(0==LoadStringU(hInstance, IDS_Publisher, wszPublisher, 40))
  781. {
  782. hr=SignError();
  783. goto CLEANUP;
  784. }
  785. //acquire the context
  786. if(S_OK != (hr=PvkGetCryptProv(
  787. pSignerCert->hwnd,
  788. wszPublisher,
  789. pProviderInfo->pwszProviderName,
  790. pProviderInfo->dwProviderType,
  791. pwszPvkFile,
  792. pwszKeyContainerName,
  793. &(pProviderInfo->dwKeySpec),
  794. &pwszTmpContainer,
  795. &hCryptProv)))
  796. {
  797. hr=CRYPT_E_NO_PROVIDER;
  798. goto CLEANUP;
  799. }
  800. //mark the hCryptProv is acquired
  801. fAcquired=TRUE;
  802. //mark the key spec that we used
  803. dwKeySpec=pProviderInfo->dwKeySpec;
  804. }
  805. //now, acquire a MS base crypto provider for any operation other than
  806. //signing
  807. if(!CryptAcquireContext(&hMSBaseProv,
  808. NULL,
  809. MS_DEF_PROV,
  810. PROV_RSA_FULL,
  811. CRYPT_VERIFYCONTEXT))
  812. {
  813. hr=GetLastError();
  814. goto CLEANUP;
  815. }
  816. //build a certificate store, which includes the signing certificate,
  817. //and all the certs necessary in the signature
  818. //get the signing certificate
  819. if(S_OK != (hr = BuildCertStore(hCryptProv,
  820. dwKeySpec,
  821. hMSBaseProv,
  822. dwEncodingType,
  823. pSignerCert,
  824. &hSpcStore,
  825. &psSigningContext)))
  826. goto CLEANUP;
  827. //check the time validity of the signing certificate
  828. if(0!=CertVerifyTimeValidity(NULL, psSigningContext->pCertInfo))
  829. {
  830. hr=CERT_E_EXPIRED;
  831. goto CLEANUP;
  832. }
  833. // Determine the hashing algorithm
  834. pszAlgorithmOid = CertAlgIdToOID(pSignatureInfo->algidHash);
  835. // Set up the sip information
  836. sSubjInfo.hProv = hMSBaseProv;
  837. sSubjInfo.DigestAlgorithm.pszObjId = (char*) pszAlgorithmOid;
  838. sSubjInfo.dwEncodingType = dwEncodingType;
  839. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
  840. sSubjInfo.pClientData = pSipData;
  841. //set up file information
  842. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  843. {
  844. // Open up the file
  845. if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
  846. (pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
  847. {
  848. if(S_OK != (hr = SignOpenFile(
  849. pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
  850. goto CLEANUP;
  851. fFileOpen=TRUE;
  852. }
  853. else
  854. hFile=pSubjectInfo->pSignerFileInfo->hFile;
  855. // Get the subject type.
  856. if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
  857. goto CLEANUP;
  858. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  859. sSubjInfo.hFile = hFile;
  860. sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
  861. }
  862. else
  863. {
  864. memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
  865. sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
  866. sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
  867. sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
  868. sSubjInfo.psBlob=&sBlob;
  869. sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
  870. sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
  871. sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
  872. }
  873. //now call InternalSign to do the real work
  874. hr = InternalSign(dwEncodingType,
  875. hCryptProv,
  876. dwKeySpec,
  877. pszAlgorithmOid,
  878. &sSubjInfo,
  879. pSubjectInfo->pdwIndex,
  880. psSigningContext,
  881. hSpcStore,
  882. fAuthcode ? pSignatureInfo->pAttrAuthcode->pwszName : NULL,
  883. fAuthcode ? pSignatureInfo->pAttrAuthcode->pwszInfo : NULL,
  884. TRUE,
  885. fAuthcode ? pSignatureInfo->pAttrAuthcode->fCommercial : FALSE,
  886. fAuthcode ? pSignatureInfo->pAttrAuthcode->fIndividual : FALSE,
  887. fAuthcode,
  888. pSignatureInfo->psAuthenticated,
  889. pSignatureInfo->psUnauthenticated,
  890. NULL,
  891. NULL,
  892. &pbEncodedMessage,
  893. &cbEncodedMessage);
  894. if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
  895. {
  896. fFileOpen = FALSE; // we opened it, but, the SIP closed it!
  897. }
  898. if(hr != S_OK)
  899. goto CLEANUP;
  900. //timestamp the file if requested
  901. if(pwszHttpTimeStamp)
  902. {
  903. if(S_OK != (hr =SignerTimeStampEx(0,
  904. pSubjectInfo,pwszHttpTimeStamp,
  905. psRequest,pSipData,
  906. ppSignerContext)))
  907. goto CLEANUP;
  908. }
  909. else
  910. {
  911. if(ppSignerContext)
  912. {
  913. //set up the context information
  914. *ppSignerContext=(SIGNER_CONTEXT *)malloc(sizeof(SIGNER_CONTEXT));
  915. if(NULL==(*ppSignerContext))
  916. {
  917. hr=E_OUTOFMEMORY;
  918. goto CLEANUP;
  919. }
  920. (*ppSignerContext)->cbSize=sizeof(SIGNER_CONTEXT);
  921. (*ppSignerContext)->cbBlob=cbEncodedMessage;
  922. (*ppSignerContext)->pbBlob=pbEncodedMessage;
  923. pbEncodedMessage=NULL;
  924. }
  925. }
  926. hr=S_OK;
  927. CLEANUP:
  928. //free the memory.
  929. if(pbEncodedMessage)
  930. free(pbEncodedMessage);
  931. if(psSigningContext)
  932. CertFreeCertificateContext(psSigningContext);
  933. if(hSpcStore)
  934. CertCloseStore(hSpcStore, 0);
  935. //free the CryptProvider
  936. if(hCryptProv)
  937. {
  938. if(fCertAcquire)
  939. {
  940. FreeCryptProvFromCert(fAcquired,
  941. hCryptProv,
  942. pwszProvName,
  943. dwProvType,
  944. pwszTmpContainer);
  945. }
  946. else
  947. {
  948. PvkFreeCryptProv(hCryptProv,
  949. pProviderInfo? pProviderInfo->pwszProviderName : NULL,
  950. pProviderInfo? pProviderInfo->dwProviderType : 0,
  951. pwszTmpContainer);
  952. }
  953. }
  954. if(hMSBaseProv)
  955. {
  956. CryptReleaseContext(hMSBaseProv, 0);
  957. }
  958. if(hFile && (fFileOpen==TRUE))
  959. CloseHandle(hFile);
  960. #if (1) //DSIE: bug 306005.
  961. if (hr != S_OK && !HRESULT_SEVERITY(hr))
  962. {
  963. // Some CAPIs does not return HRESULT. They return Win API errors,
  964. // so need to convert to HRESULT so that caller using the FAILED
  965. // macro will catch the error.
  966. hr = HRESULT_FROM_WIN32((DWORD) hr);
  967. }
  968. #endif
  969. return hr;
  970. }
  971. //+-----------------------------------------------------------------------
  972. //
  973. // SignerFreeSignerContext
  974. //
  975. //------------------------------------------------------------------------
  976. HRESULT WINAPI
  977. SignerFreeSignerContext(
  978. IN SIGNER_CONTEXT *pSignerContext)
  979. {
  980. if(pSignerContext)
  981. {
  982. if(pSignerContext->pbBlob)
  983. free(pSignerContext->pbBlob);
  984. free(pSignerContext);
  985. }
  986. return S_OK;
  987. }