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.

1195 lines
38 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. sSignedInfo.rgCertEncoded = (PCERT_BLOB)
  309. realloc(sSignedInfo.rgCertEncoded,
  310. sizeof(CERT_BLOB) * (sSignedInfo.cCertEncoded+dwPKCS7Certs));
  311. if(!sSignedInfo.rgCertEncoded)
  312. PKITHROW(E_OUTOFMEMORY);
  313. PCERT_BLOB pCertPtr = (sSignedInfo.rgCertEncoded + sSignedInfo.cCertEncoded);
  314. pCert = NULL;
  315. DWORD c = 0;
  316. while ((pCert = CertEnumCertificatesInStore(hPKCS7CertStore, pCert)) && c < dwPKCS7Certs)
  317. {
  318. fFound=FALSE;
  319. //we need to make sure that we do not add duplicated certificates
  320. for(dwCertIndex=0; dwCertIndex<sSignedInfo.cCertEncoded; dwCertIndex++)
  321. {
  322. if((sSignedInfo.rgCertEncoded[dwCertIndex]).cbData==pCert->cbCertEncoded)
  323. {
  324. if(0==memcmp((sSignedInfo.rgCertEncoded[dwCertIndex]).pbData,
  325. pCert->pbCertEncoded, pCert->cbCertEncoded))
  326. {
  327. fFound=TRUE;
  328. break;
  329. }
  330. }
  331. }
  332. //we only add the certificates that do not duplicates the signer's
  333. //certificates
  334. if(FALSE==fFound)
  335. {
  336. pCertPtr->pbData = pCert->pbCertEncoded;
  337. pCertPtr->cbData = pCert->cbCertEncoded;
  338. c++; pCertPtr++;
  339. }
  340. }
  341. sSignedInfo.cCertEncoded += c;
  342. }
  343. }
  344. if (fCTLFile)
  345. {
  346. //
  347. // get the signed message if we need to
  348. //
  349. if(NULL==pbGetBlob)
  350. {
  351. //
  352. sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, NULL);
  353. if (cbGetBlob < 1)
  354. {
  355. PKITHROW(SignError());
  356. }
  357. if (!(pbGetBlob = (BYTE *)malloc(cbGetBlob)))
  358. {
  359. PKITHROW(E_OUTOFMEMORY);
  360. }
  361. if (!(sSip.pfGet(pSipInfo, &dwEncodingType, *pdwIndex, &cbGetBlob, pbGetBlob)))
  362. {
  363. PKITHROW(SignError());
  364. }
  365. }
  366. //
  367. // extract the inner content
  368. //
  369. pCTLContext = (PCTL_CONTEXT)CertCreateCTLContext(
  370. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  371. pbGetBlob,
  372. cbGetBlob);
  373. if (!(pCTLContext))
  374. {
  375. PKITHROW(SignError());
  376. }
  377. if (!(pCTLContext->pbCtlContent))
  378. {
  379. PKITHROW(SignError());
  380. }
  381. //
  382. // add singer info! (e.g.: sign it!)
  383. //
  384. cbEncodedSignMsg = 0;
  385. CryptMsgSignCTL(dwEncodingType, pCTLContext->pbCtlContent, pCTLContext->cbCtlContent,
  386. &sSignedInfo, 0, NULL, &cbEncodedSignMsg);
  387. if (cbEncodedSignMsg < 1)
  388. {
  389. PKITHROW(SignError());
  390. }
  391. if (!(pbEncodedSignMsg = (BYTE *)malloc(cbEncodedSignMsg)))
  392. {
  393. PKITHROW(E_OUTOFMEMORY);
  394. }
  395. if (!(CryptMsgSignCTL(dwEncodingType,
  396. pCTLContext->pbCtlContent, pCTLContext->cbCtlContent,
  397. &sSignedInfo, 0, pbEncodedSignMsg, &cbEncodedSignMsg)))
  398. {
  399. PKITHROW(SignError());
  400. }
  401. CertFreeCTLContext(pCTLContext);
  402. pCTLContext = NULL;
  403. }
  404. else
  405. {
  406. hMsg = CryptMsgOpenToEncode(dwEncodingType,
  407. 0, // dwFlags
  408. CMSG_SIGNED,
  409. &sSignedInfo,
  410. SPC_INDIRECT_DATA_OBJID,
  411. NULL);
  412. if(hMsg == NULL)
  413. PKITHROW(SignError());
  414. if (!CryptMsgUpdate(hMsg,
  415. pbIndirectBlob,
  416. cbIndirectBlob,
  417. TRUE)) // Final
  418. PKITHROW(SignError());
  419. CryptMsgGetParam(hMsg,
  420. CMSG_CONTENT_PARAM,
  421. 0, // dwIndex
  422. NULL, // pbSignedData
  423. &cbEncodedSignMsg);
  424. if (cbEncodedSignMsg == 0) PKITHROW(SignError());
  425. pbEncodedSignMsg = (PBYTE) malloc(cbEncodedSignMsg);
  426. if(!pbEncodedSignMsg) PKITHROW(E_OUTOFMEMORY);
  427. if (!CryptMsgGetParam(hMsg,
  428. CMSG_CONTENT_PARAM,
  429. 0, // dwIndex
  430. pbEncodedSignMsg,
  431. &cbEncodedSignMsg))
  432. PKITHROW(SignError());
  433. }
  434. //put the signatures if we are dealing with anything other than the BLOB
  435. if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
  436. {
  437. // Purge all the signatures in the subject
  438. sSip.pfRemove(pSipInfo, *pdwIndex);
  439. // Store the Signed Message in the sip
  440. if(!(sSip.pfPut( pSipInfo,
  441. dwEncodingType,
  442. pdwIndex,
  443. cbEncodedSignMsg,
  444. pbEncodedSignMsg)))
  445. {
  446. PKITHROW(SignError());
  447. }
  448. }
  449. if(ppbMessage && pcbMessage) {
  450. *ppbMessage = pbEncodedSignMsg;
  451. pbEncodedSignMsg = NULL;
  452. *pcbMessage = cbEncodedSignMsg;
  453. }
  454. if(ppbDigest && pcbDigest) {
  455. // Get the encrypted digest
  456. pbSignerData = NULL;
  457. CryptMsgGetParam(hMsg,
  458. CMSG_ENCRYPTED_DIGEST,
  459. 0, // dwIndex
  460. pbSignerData,
  461. &cbSignerData);
  462. if(cbSignerData == 0) PKITHROW(SignError());
  463. pbSignerData = (PBYTE) malloc(cbSignerData);
  464. if(!pbSignerData) PKITHROW(E_OUTOFMEMORY);
  465. if(!CryptMsgGetParam(hMsg,
  466. CMSG_ENCRYPTED_DIGEST,
  467. 0, // dwIndex
  468. pbSignerData,
  469. &cbSignerData))
  470. PKITHROW(SignError());
  471. *ppbDigest = pbSignerData;
  472. pbSignerData = NULL;
  473. *pcbDigest = cbSignerData;
  474. }
  475. }
  476. PKICATCH(err) {
  477. hr = err.pkiError;
  478. } PKIEND;
  479. if (pCTLContext)
  480. {
  481. CertFreeCTLContext(pCTLContext);
  482. }
  483. if (pbSignerData)
  484. free(pbSignerData);
  485. if(pbEncodedSignMsg)
  486. free(pbEncodedSignMsg);
  487. if(hMsg)
  488. CryptMsgClose(hMsg);
  489. if(sSignedInfo.rgCrlEncoded)
  490. free(sSignedInfo.rgCrlEncoded);
  491. if(sSignedInfo.rgCertEncoded)
  492. free(sSignedInfo.rgCertEncoded);
  493. if(pbIndirectBlob)
  494. free(pbIndirectBlob);
  495. if(pbGetBlob)
  496. free(pbGetBlob);
  497. if(hPKCS7CertStore)
  498. CertCloseStore(hPKCS7CertStore,0);
  499. if(psIndirectData)
  500. free(psIndirectData);
  501. if(rgpAuthAttributes)
  502. free(rgpAuthAttributes);
  503. if(pbStatementAttribute)
  504. free(pbStatementAttribute);
  505. if(pbOpusAttribute)
  506. free(pbOpusAttribute);
  507. return hr;
  508. }
  509. //--------------------------------------------------------------------------
  510. //
  511. // SignerTimeStamp:
  512. // Timestamp a file.
  513. //
  514. //--------------------------------------------------------------------------
  515. HRESULT WINAPI
  516. SignerTimeStamp(
  517. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be timestamped
  518. IN LPCWSTR pwszHttpTimeStamp, // Required: timestamp server HTTP address
  519. IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to the timestamp
  520. IN LPVOID pSipData // Optional: The additional data passed to sip funcitons
  521. )
  522. {
  523. return SignerTimeStampEx(0,
  524. pSubjectInfo,
  525. pwszHttpTimeStamp,
  526. psRequest,
  527. pSipData,
  528. NULL);
  529. }
  530. //--------------------------------------------------------------------------
  531. //
  532. // SignerTimeStampEx:
  533. // Timestamp a file.
  534. //
  535. //--------------------------------------------------------------------------
  536. HRESULT WINAPI
  537. SignerTimeStampEx(
  538. IN DWORD dwFlags, //Reserved: Has to be set to 0.
  539. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be timestamped
  540. IN LPCWSTR pwszHttpTimeStamp, // Required: timestamp server HTTP address
  541. IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to the timestamp
  542. IN LPVOID pSipData, // Optional: The additional data passed to sip funcitons
  543. OUT SIGNER_CONTEXT **ppSignerContext // Optional: The signed BLOB. User has to free
  544. // the context via SignerFreeSignerContext
  545. )
  546. {
  547. HRESULT hr=E_FAIL;
  548. DWORD dwTimeStampRequest=0;
  549. BYTE *pbTimeStampRequest=NULL;
  550. DWORD dwTimeStampResponse=0;
  551. BYTE *pbTimeStampResponse=NULL;
  552. CHttpTran cTran;
  553. BOOL fOpen=FALSE;
  554. DWORD err;
  555. LPSTR szURL=NULL;
  556. DWORD dwEncodingType=OCTET_ENCODING;
  557. CHAR *pEncodedRequest=NULL;
  558. DWORD dwEncodedRequest=0;
  559. CHAR *pEncodedResponse=NULL;
  560. DWORD dwEncodedResponse=0;
  561. //input parameter check
  562. if((!pwszHttpTimeStamp) ||(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
  563. return E_INVALIDARG;
  564. //request a time stamp
  565. hr=SignerCreateTimeStampRequest(pSubjectInfo,
  566. psRequest,
  567. pSipData,
  568. NULL,
  569. &dwTimeStampRequest);
  570. if(hr!=S_OK)
  571. goto CLEANUP;
  572. pbTimeStampRequest=(BYTE *)malloc(dwTimeStampRequest);
  573. if(!pbTimeStampRequest)
  574. {
  575. hr=E_OUTOFMEMORY;
  576. goto CLEANUP;
  577. }
  578. hr=SignerCreateTimeStampRequest(pSubjectInfo,
  579. psRequest,
  580. pSipData,
  581. pbTimeStampRequest,
  582. &dwTimeStampRequest);
  583. if(hr!=S_OK)
  584. goto CLEANUP;
  585. //conver the WSTR of URL to STR
  586. if((hr=WSZtoSZ((LPWSTR)pwszHttpTimeStamp,&szURL))!=S_OK)
  587. goto CLEANUP;
  588. //base64 encode the request
  589. if(S_OK!=(hr=BytesToBase64(pbTimeStampRequest,
  590. dwTimeStampRequest,
  591. &pEncodedRequest,
  592. &dwEncodedRequest)))
  593. goto CLEANUP;
  594. //estalish the connection between the http site
  595. err=cTran.Open( szURL, GTREAD|GTWRITE);
  596. if(err!=ERROR_SUCCESS)
  597. {
  598. hr=E_FAIL;
  599. goto CLEANUP;
  600. }
  601. //mark that we have open the connection successful
  602. fOpen=TRUE;
  603. //send the request
  604. err=cTran.Send(dwEncodingType,dwEncodedRequest,(BYTE *)pEncodedRequest);
  605. if(err!=ERROR_SUCCESS)
  606. {
  607. hr=HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  608. goto CLEANUP;
  609. }
  610. //send the request
  611. err=cTran.Receive(&dwEncodingType,&dwEncodedResponse,(BYTE **)&pEncodedResponse);
  612. if(err!=ERROR_SUCCESS)
  613. {
  614. hr=E_FAIL;
  615. goto CLEANUP;
  616. }
  617. //make sure the encoding type is correct
  618. // if(dwEncodingType!=OCTET_ENCODING)
  619. // {
  620. // hr=E_FAIL;
  621. // goto CLEANUP;
  622. // }
  623. //base64 decode the response
  624. if(S_OK != (hr=Base64ToBytes(
  625. pEncodedResponse,
  626. dwEncodedResponse,
  627. &pbTimeStampResponse,
  628. &dwTimeStampResponse)))
  629. goto CLEANUP;
  630. //add the timestamp response to the time
  631. hr=SignerAddTimeStampResponseEx(0, pSubjectInfo,pbTimeStampResponse,
  632. dwTimeStampResponse, pSipData,
  633. ppSignerContext);
  634. CLEANUP:
  635. if(pEncodedRequest)
  636. free(pEncodedRequest);
  637. if(pbTimeStampResponse)
  638. free(pbTimeStampResponse);
  639. if(pbTimeStampRequest)
  640. free(pbTimeStampRequest);
  641. if(szURL)
  642. free(szURL);
  643. if(fOpen)
  644. {
  645. if(pEncodedResponse)
  646. cTran.Free((BYTE *)pEncodedResponse);
  647. cTran.Close();
  648. }
  649. return hr;
  650. }
  651. //+-----------------------------------------------------------------------
  652. //
  653. // SignerSign:
  654. // Sign and/or timestamp a file.
  655. //
  656. //------------------------------------------------------------------------
  657. HRESULT WINAPI
  658. SignerSign(
  659. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be signed and/or timestamped
  660. IN SIGNER_CERT *pSignerCert, //Required: The signing certificate to use
  661. IN SIGNER_SIGNATURE_INFO *pSignatureInfo, //Required: The signature information during signing process
  662. IN SIGNER_PROVIDER_INFO *pProviderInfo, //Optional: The crypto security provider to use.
  663. // This parameter has to be set unless
  664. // certStoreInfo is set in *pSignerCert
  665. // and the signing certificate has provider
  666. // information associated with it
  667. IN LPCWSTR pwszHttpTimeStamp, //Optional: Timestamp server http address. If this parameter
  668. // is set, the file will be timestamped.
  669. IN PCRYPT_ATTRIBUTES psRequest, //Optional: Attributes added to Time stamp request. Ignored
  670. // unless pwszHttpTimeStamp is set
  671. IN LPVOID pSipData //Optional: The additional data passed to sip funcitons
  672. )
  673. {
  674. return SignerSignEx(
  675. 0,
  676. pSubjectInfo,
  677. pSignerCert,
  678. pSignatureInfo,
  679. pProviderInfo,
  680. pwszHttpTimeStamp,
  681. psRequest,
  682. pSipData,
  683. NULL);
  684. }
  685. //+-----------------------------------------------------------------------
  686. //
  687. // SignerSignEx:
  688. // Sign and/or timestamp a file.
  689. //
  690. //------------------------------------------------------------------------
  691. HRESULT WINAPI
  692. SignerSignEx(
  693. IN DWORD dwFlags, //Reserved: Has to be set to 0.
  694. IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to be signed and/or timestamped
  695. IN SIGNER_CERT *pSignerCert, //Required: The signing certificate to use
  696. IN SIGNER_SIGNATURE_INFO *pSignatureInfo, //Required: The signature information during signing process
  697. IN SIGNER_PROVIDER_INFO *pProviderInfo, //Optional: The crypto security provider to use.
  698. // This parameter has to be set unless
  699. // certStoreInfo is set in *pSignerCert
  700. // and the signing certificate has provider
  701. // information associated with it
  702. IN LPCWSTR pwszHttpTimeStamp, //Optional: Timestamp server http address. If this parameter
  703. // is set, the file will be timestamped.
  704. IN PCRYPT_ATTRIBUTES psRequest, //Optional: Attributes added to Time stamp request. Ignored
  705. // unless pwszHttpTimeStamp is set
  706. IN LPVOID pSipData, //Optional: The additional data passed to sip funcitons
  707. OUT SIGNER_CONTEXT **ppSignerContext //Optional: The signed BLOB. User has to free
  708. // the context via SignerFreeSignerContext
  709. )
  710. {
  711. HRESULT hr = S_OK;
  712. HANDLE hFile = NULL; // File to sign
  713. BOOL fFileOpen=FALSE;
  714. HCERTSTORE hSpcStore = NULL; // Certificates added to signature
  715. PCCERT_CONTEXT psSigningContext = NULL; // Cert context to the signing certificate
  716. GUID gSubjectGuid; // The subject guid used to load the sip
  717. SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
  718. MS_ADDINFO_BLOB sBlob;
  719. HCRYPTPROV hCryptProv = NULL; // Crypto provider, uses private key container
  720. HCRYPTPROV hMSBaseProv = NULL; //This is the MS base provider for hashing purpose
  721. LPWSTR pwszTmpContainer = NULL; // Pvk container (opened up pvk file)
  722. LPWSTR pwszProvName=NULL;
  723. DWORD dwProvType;
  724. BOOL fAcquired=FALSE;
  725. LPCWSTR pwszPvkFile = NULL;
  726. LPCWSTR pwszKeyContainerName = NULL;
  727. BOOL fAuthcode=FALSE;
  728. BOOL fCertAcquire=FALSE;
  729. //set dwKeySpec to 0. That is, we allow any key specification
  730. //for code signing
  731. DWORD dwKeySpec = 0;
  732. DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
  733. LPCSTR pszAlgorithmOid = NULL;
  734. WCHAR wszPublisher[40];
  735. PBYTE pbEncodedMessage=NULL;
  736. DWORD cbEncodedMessage=0;
  737. //input parameter checking
  738. if(!CheckSigncodeParam(pSubjectInfo, pSignerCert, pSignatureInfo,
  739. pProviderInfo))
  740. return E_INVALIDARG;
  741. //determine if this is an authenticode specific signing
  742. if(pSignatureInfo->dwAttrChoice==SIGNER_AUTHCODE_ATTR)
  743. fAuthcode=TRUE;
  744. //init
  745. if(ppSignerContext)
  746. *ppSignerContext=NULL;
  747. // Acquire a context for the specified provider
  748. // First,try to acquire the provider context based on the properties on a cert
  749. if(pSignerCert->dwCertChoice==SIGNER_CERT_STORE)
  750. {
  751. if(GetCryptProvFromCert(pSignerCert->hwnd,
  752. (pSignerCert->pCertStoreInfo)->pSigningCert,
  753. &hCryptProv,
  754. &dwKeySpec,
  755. &fAcquired,
  756. &pwszTmpContainer,
  757. &pwszProvName,
  758. &dwProvType))
  759. //mark that we acquire the context via the cert's property
  760. fCertAcquire=TRUE;
  761. }
  762. // If the 1st failed, try to acquire the provider context based on
  763. //pPvkInfo
  764. if(hCryptProv==NULL)
  765. {
  766. //pProviderInfo has to be set
  767. if(!pProviderInfo)
  768. {
  769. hr=CRYPT_E_NO_PROVIDER;
  770. goto CLEANUP;
  771. }
  772. //decide the PVK file name or the key container name
  773. if(pProviderInfo->dwPvkChoice == PVK_TYPE_FILE_NAME)
  774. pwszPvkFile=pProviderInfo->pwszPvkFileName;
  775. else
  776. pwszKeyContainerName=pProviderInfo->pwszKeyContainer;
  777. //load from the resource of string L"publisher"
  778. if(0==LoadStringU(hInstance, IDS_Publisher, wszPublisher, 40))
  779. {
  780. hr=SignError();
  781. goto CLEANUP;
  782. }
  783. //acquire the context
  784. if(S_OK != (hr=PvkGetCryptProv(
  785. pSignerCert->hwnd,
  786. wszPublisher,
  787. pProviderInfo->pwszProviderName,
  788. pProviderInfo->dwProviderType,
  789. pwszPvkFile,
  790. pwszKeyContainerName,
  791. &(pProviderInfo->dwKeySpec),
  792. &pwszTmpContainer,
  793. &hCryptProv)))
  794. {
  795. hr=CRYPT_E_NO_PROVIDER;
  796. goto CLEANUP;
  797. }
  798. //mark the hCryptProv is acquired
  799. fAcquired=TRUE;
  800. //mark the key spec that we used
  801. dwKeySpec=pProviderInfo->dwKeySpec;
  802. }
  803. //now, acquire a MS base crypto provider for any operation other than
  804. //signing
  805. if(!CryptAcquireContext(&hMSBaseProv,
  806. NULL,
  807. MS_DEF_PROV,
  808. PROV_RSA_FULL,
  809. CRYPT_VERIFYCONTEXT))
  810. {
  811. hr=GetLastError();
  812. goto CLEANUP;
  813. }
  814. //build a certificate store, which includes the signing certificate,
  815. //and all the certs necessary in the signature
  816. //get the signing certificate
  817. if(S_OK != (hr = BuildCertStore(hCryptProv,
  818. dwKeySpec,
  819. hMSBaseProv,
  820. dwEncodingType,
  821. pSignerCert,
  822. &hSpcStore,
  823. &psSigningContext)))
  824. goto CLEANUP;
  825. //check the time validity of the signing certificate
  826. if(0!=CertVerifyTimeValidity(NULL, psSigningContext->pCertInfo))
  827. {
  828. hr=CERT_E_EXPIRED;
  829. goto CLEANUP;
  830. }
  831. // Determine the hashing algorithm
  832. pszAlgorithmOid = CertAlgIdToOID(pSignatureInfo->algidHash);
  833. // Set up the sip information
  834. sSubjInfo.hProv = hMSBaseProv;
  835. sSubjInfo.DigestAlgorithm.pszObjId = (char*) pszAlgorithmOid;
  836. sSubjInfo.dwEncodingType = dwEncodingType;
  837. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
  838. sSubjInfo.pClientData = pSipData;
  839. //set up file information
  840. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  841. {
  842. // Open up the file
  843. if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
  844. (pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
  845. {
  846. if(S_OK != (hr = SignOpenFile(
  847. pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
  848. goto CLEANUP;
  849. fFileOpen=TRUE;
  850. }
  851. else
  852. hFile=pSubjectInfo->pSignerFileInfo->hFile;
  853. // Get the subject type.
  854. if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
  855. goto CLEANUP;
  856. sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
  857. sSubjInfo.hFile = hFile;
  858. sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
  859. }
  860. else
  861. {
  862. memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
  863. sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
  864. sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
  865. sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
  866. sSubjInfo.psBlob=&sBlob;
  867. sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
  868. sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
  869. sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
  870. }
  871. //now call InternalSign to do the real work
  872. hr = InternalSign(dwEncodingType,
  873. hCryptProv,
  874. dwKeySpec,
  875. pszAlgorithmOid,
  876. &sSubjInfo,
  877. pSubjectInfo->pdwIndex,
  878. psSigningContext,
  879. hSpcStore,
  880. fAuthcode ? pSignatureInfo->pAttrAuthcode->pwszName : NULL,
  881. fAuthcode ? pSignatureInfo->pAttrAuthcode->pwszInfo : NULL,
  882. TRUE,
  883. fAuthcode ? pSignatureInfo->pAttrAuthcode->fCommercial : FALSE,
  884. fAuthcode ? pSignatureInfo->pAttrAuthcode->fIndividual : FALSE,
  885. fAuthcode,
  886. pSignatureInfo->psAuthenticated,
  887. pSignatureInfo->psUnauthenticated,
  888. NULL,
  889. NULL,
  890. &pbEncodedMessage,
  891. &cbEncodedMessage);
  892. if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
  893. {
  894. fFileOpen = FALSE; // we opened it, but, the SIP closed it!
  895. }
  896. if(hr != S_OK)
  897. goto CLEANUP;
  898. //timestamp the file if requested
  899. if(pwszHttpTimeStamp)
  900. {
  901. if(S_OK != (hr =SignerTimeStampEx(0,
  902. pSubjectInfo,pwszHttpTimeStamp,
  903. psRequest,pSipData,
  904. ppSignerContext)))
  905. goto CLEANUP;
  906. }
  907. else
  908. {
  909. if(ppSignerContext)
  910. {
  911. //set up the context information
  912. *ppSignerContext=(SIGNER_CONTEXT *)malloc(sizeof(SIGNER_CONTEXT));
  913. if(NULL==(*ppSignerContext))
  914. {
  915. hr=E_OUTOFMEMORY;
  916. goto CLEANUP;
  917. }
  918. (*ppSignerContext)->cbSize=sizeof(SIGNER_CONTEXT);
  919. (*ppSignerContext)->cbBlob=cbEncodedMessage;
  920. (*ppSignerContext)->pbBlob=pbEncodedMessage;
  921. pbEncodedMessage=NULL;
  922. }
  923. }
  924. hr=S_OK;
  925. CLEANUP:
  926. //free the memory.
  927. if(pbEncodedMessage)
  928. free(pbEncodedMessage);
  929. if(psSigningContext)
  930. CertFreeCertificateContext(psSigningContext);
  931. if(hSpcStore)
  932. CertCloseStore(hSpcStore, 0);
  933. //free the CryptProvider
  934. if(hCryptProv)
  935. {
  936. if(fCertAcquire)
  937. {
  938. FreeCryptProvFromCert(fAcquired,
  939. hCryptProv,
  940. pwszProvName,
  941. dwProvType,
  942. pwszTmpContainer);
  943. }
  944. else
  945. {
  946. PvkFreeCryptProv(hCryptProv,
  947. pProviderInfo? pProviderInfo->pwszProviderName : NULL,
  948. pProviderInfo? pProviderInfo->dwProviderType : 0,
  949. pwszTmpContainer);
  950. }
  951. }
  952. if(hMSBaseProv)
  953. {
  954. CryptReleaseContext(hMSBaseProv, 0);
  955. }
  956. if(hFile && (fFileOpen==TRUE))
  957. CloseHandle(hFile);
  958. #if (1) //DSIE: bug 306005.
  959. if (hr != S_OK && !HRESULT_SEVERITY(hr))
  960. {
  961. // Some CAPIs does not return HRESULT. They return Win API errors,
  962. // so need to convert to HRESULT so that caller using the FAILED
  963. // macro will catch the error.
  964. hr = HRESULT_FROM_WIN32((DWORD) hr);
  965. }
  966. #endif
  967. return hr;
  968. }
  969. //+-----------------------------------------------------------------------
  970. //
  971. // SignerFreeSignerContext
  972. //
  973. //------------------------------------------------------------------------
  974. HRESULT WINAPI
  975. SignerFreeSignerContext(
  976. IN SIGNER_CONTEXT *pSignerContext)
  977. {
  978. if(pSignerContext)
  979. {
  980. if(pSignerContext->pbBlob)
  981. free(pSignerContext->pbBlob);
  982. free(pSignerContext);
  983. }
  984. return S_OK;
  985. }