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.

3664 lines
120 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: sca.cpp
  8. //
  9. // Contents: Simplified Cryptographic APIs (SCA)
  10. //
  11. // This implementation layers upon the CryptMsg and CertStore
  12. // APIs.
  13. //
  14. // Functions:
  15. // CryptSignMessage
  16. // CryptVerifyMessageSignature
  17. // CryptVerifyDetachedMessageSignature
  18. // CryptGetMessageSignerCount
  19. // CryptGetMessageCertificates
  20. // CryptDecodeMessage
  21. // CryptEncryptMessage
  22. // CryptDecryptMessage
  23. // CryptSignAndEncryptMessage
  24. // CryptDecryptAndVerifyMessageSignature
  25. // CryptHashMessage
  26. // CryptVerifyMessageHash
  27. // CryptVerifyDetachedMessageHash
  28. // CryptSignMessageWithKey
  29. // CryptVerifyMessageSignatureWithKey
  30. //
  31. // History: 14-Feb-96 philh created
  32. // 21-Feb-96 phil redid to reflect changes made to sca.h
  33. // 19-Jan-97 philh removed SET stuff
  34. //
  35. //--------------------------------------------------------------------------
  36. #include "global.hxx"
  37. #include <dbgdef.h>
  38. // #define ENABLE_SCA_STREAM_TEST 1
  39. #define SCA_STREAM_ENABLE_FLAG 0x80000000
  40. #define SCA_INDEFINITE_STREAM_FLAG 0x40000000
  41. static const CRYPT_OBJID_TABLE MsgTypeObjIdTable[] = {
  42. CMSG_DATA, szOID_RSA_data ,
  43. CMSG_SIGNED, szOID_RSA_signedData ,
  44. CMSG_ENVELOPED, szOID_RSA_envelopedData ,
  45. CMSG_SIGNED_AND_ENVELOPED, szOID_RSA_signEnvData ,
  46. CMSG_HASHED, szOID_RSA_digestedData ,
  47. CMSG_ENCRYPTED, szOID_RSA_encryptedData
  48. };
  49. #define MSG_TYPE_OBJID_CNT (sizeof(MsgTypeObjIdTable)/sizeof(MsgTypeObjIdTable[0]))
  50. //+-------------------------------------------------------------------------
  51. // Convert the MsgType to the ASN.1 Object Identifier string
  52. //
  53. // Returns NULL if there isn't an ObjId corresponding to the MsgType.
  54. //--------------------------------------------------------------------------
  55. static LPCSTR MsgTypeToOID(
  56. IN DWORD dwMsgType
  57. )
  58. {
  59. int i;
  60. for (i = 0; i < MSG_TYPE_OBJID_CNT; i++)
  61. if (MsgTypeObjIdTable[i].dwAlgId == dwMsgType)
  62. return MsgTypeObjIdTable[i].pszObjId;
  63. return NULL;
  64. }
  65. //+-------------------------------------------------------------------------
  66. // Convert the ASN.1 Object Identifier string to the MsgType
  67. //
  68. // Returns 0 if there isn't a MsgType corresponding to the ObjId.
  69. //--------------------------------------------------------------------------
  70. static DWORD OIDToMsgType(
  71. IN LPCSTR pszObjId
  72. )
  73. {
  74. int i;
  75. for (i = 0; i < MSG_TYPE_OBJID_CNT; i++)
  76. if (_stricmp(pszObjId, MsgTypeObjIdTable[i].pszObjId) == 0)
  77. return MsgTypeObjIdTable[i].dwAlgId;
  78. return 0;
  79. }
  80. //+-------------------------------------------------------------------------
  81. // SCA allocation and free routines
  82. //--------------------------------------------------------------------------
  83. static void *SCAAlloc(
  84. IN size_t cbBytes
  85. );
  86. static void SCAFree(
  87. IN void *pv
  88. );
  89. //+-------------------------------------------------------------------------
  90. // Null implementation of the get signer certificate
  91. //--------------------------------------------------------------------------
  92. static PCCERT_CONTEXT WINAPI NullGetSignerCertificate(
  93. IN void *pvGetArg,
  94. IN DWORD dwCertEncodingType,
  95. IN PCERT_INFO pSignerId,
  96. IN HCERTSTORE hMsgCertStore
  97. );
  98. //+-------------------------------------------------------------------------
  99. // Functions for initializing message encode information
  100. //--------------------------------------------------------------------------
  101. static PCMSG_SIGNER_ENCODE_INFO InitSignerEncodeInfo(
  102. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara
  103. );
  104. static void FreeSignerEncodeInfo(
  105. IN PCMSG_SIGNER_ENCODE_INFO pSigner
  106. );
  107. static BOOL InitSignedCertAndCrl(
  108. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  109. OUT PCERT_BLOB *ppCertEncoded,
  110. OUT PCRL_BLOB *ppCrlEncoded
  111. );
  112. static void FreeSignedCertAndCrl(
  113. IN PCERT_BLOB pCertEncoded,
  114. IN PCRL_BLOB pCrlEncoded
  115. );
  116. static BOOL InitSignedMsgEncodeInfo(
  117. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  118. OUT PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  119. );
  120. static void FreeSignedMsgEncodeInfo(
  121. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  122. IN PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  123. );
  124. #ifdef CMS_PKCS7
  125. // Returned array of CMSG_RECIPIENT_ENCODE_INFOs needs to be SCAFree'd
  126. static PCMSG_RECIPIENT_ENCODE_INFO InitCmsRecipientEncodeInfo(
  127. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  128. IN DWORD cRecipientCert,
  129. IN PCCERT_CONTEXT rgpRecipientCert[],
  130. IN DWORD dwFlags
  131. );
  132. #else
  133. // Returned array of PCERT_INFOs needs to be SCAFree'd
  134. static PCERT_INFO *InitRecipientEncodeInfo(
  135. IN DWORD cRecipientCert,
  136. IN PCCERT_CONTEXT rgpRecipientCert[]
  137. );
  138. #endif // CMS_PKCS7
  139. static BOOL InitEnvelopedMsgEncodeInfo(
  140. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  141. IN DWORD cRecipientCert,
  142. IN PCCERT_CONTEXT rgpRecipientCert[],
  143. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  144. );
  145. static void FreeEnvelopedMsgEncodeInfo(
  146. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  147. IN PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  148. );
  149. //+-------------------------------------------------------------------------
  150. // Encodes the message.
  151. //--------------------------------------------------------------------------
  152. static BOOL EncodeMsg(
  153. IN DWORD dwMsgEncodingType,
  154. IN DWORD dwFlags,
  155. IN DWORD dwMsgType,
  156. IN void *pvMsgEncodeInfo,
  157. IN DWORD cToBeEncoded,
  158. IN const BYTE *rgpbToBeEncoded[],
  159. IN DWORD rgcbToBeEncoded[],
  160. IN BOOL fBareContent,
  161. IN DWORD dwInnerContentType,
  162. OUT BYTE *pbEncodedBlob,
  163. IN OUT DWORD *pcbEncodedBlob
  164. );
  165. //+-------------------------------------------------------------------------
  166. // Decodes the message types:
  167. // CMSG_SIGNED
  168. // CMSG_ENVELOPED
  169. // CMSG_SIGNED_AND_ENVELOPED
  170. // CMSG_HASHED
  171. //--------------------------------------------------------------------------
  172. static BOOL DecodeMsg(
  173. IN DWORD dwMsgTypeFlags,
  174. IN OPTIONAL PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  175. IN OPTIONAL PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  176. IN DWORD dwSignerIndex,
  177. IN const BYTE *pbEncodedBlob,
  178. IN DWORD cbEncodedBlob,
  179. IN DWORD cToBeEncoded,
  180. IN OPTIONAL const BYTE *rgpbToBeEncoded[],
  181. IN OPTIONAL DWORD rgcbToBeEncoded[],
  182. IN DWORD dwPrevInnerContentType,
  183. OUT OPTIONAL DWORD *pdwMsgType,
  184. OUT OPTIONAL DWORD *pdwInnerContentType,
  185. OUT OPTIONAL BYTE *pbDecoded,
  186. IN OUT OPTIONAL DWORD *pcbDecoded,
  187. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  188. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  189. );
  190. #ifdef ENABLE_SCA_STREAM_TEST
  191. //+-------------------------------------------------------------------------
  192. // Encodes the message using streaming.
  193. //--------------------------------------------------------------------------
  194. static BOOL StreamEncodeMsg(
  195. IN DWORD dwMsgEncodingType,
  196. IN DWORD dwFlags,
  197. IN DWORD dwMsgType,
  198. IN void *pvMsgEncodeInfo,
  199. IN DWORD cToBeEncoded,
  200. IN const BYTE *rgpbToBeEncoded[],
  201. IN DWORD rgcbToBeEncoded[],
  202. IN BOOL fBareContent,
  203. IN DWORD dwInnerContentType,
  204. OUT BYTE *pbEncodedBlob,
  205. IN OUT DWORD *pcbEncodedBlob
  206. );
  207. //+-------------------------------------------------------------------------
  208. // Decodes the message types:
  209. // CMSG_SIGNED
  210. // CMSG_ENVELOPED
  211. // CMSG_SIGNED_AND_ENVELOPED
  212. // CMSG_HASHED
  213. //
  214. // Uses streaming.
  215. //--------------------------------------------------------------------------
  216. static BOOL StreamDecodeMsg(
  217. IN DWORD dwMsgTypeFlags,
  218. IN OPTIONAL PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  219. IN OPTIONAL PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  220. IN DWORD dwSignerIndex,
  221. IN const BYTE *pbEncodedBlob,
  222. IN DWORD cbEncodedBlob,
  223. IN DWORD cToBeEncoded,
  224. IN OPTIONAL const BYTE *rgpbToBeEncoded[],
  225. IN OPTIONAL DWORD rgcbToBeEncoded[],
  226. IN DWORD dwPrevInnerContentType,
  227. OUT OPTIONAL DWORD *pdwMsgType,
  228. OUT OPTIONAL DWORD *pdwInnerContentType,
  229. OUT OPTIONAL BYTE *pbDecoded,
  230. IN OUT OPTIONAL DWORD *pcbDecoded,
  231. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  232. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  233. );
  234. #endif
  235. //+-------------------------------------------------------------------------
  236. // Decodes the HASHED message type
  237. //--------------------------------------------------------------------------
  238. static BOOL DecodeHashMsg(
  239. IN PCRYPT_HASH_MESSAGE_PARA pHashPara,
  240. IN const BYTE *pbEncodedBlob,
  241. IN DWORD cbEncodedBlob,
  242. IN DWORD cToBeHashed,
  243. IN OPTIONAL const BYTE *rgpbToBeHashed[],
  244. IN OPTIONAL DWORD rgcbToBeHashed[],
  245. OUT OPTIONAL BYTE *pbDecoded,
  246. IN OUT OPTIONAL DWORD *pcbDecoded,
  247. OUT OPTIONAL BYTE *pbComputedHash,
  248. IN OUT OPTIONAL DWORD *pcbComputedHash
  249. );
  250. //+-------------------------------------------------------------------------
  251. // Get certificate for and verify the message's signer.
  252. //--------------------------------------------------------------------------
  253. static BOOL GetSignerCertAndVerify(
  254. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  255. IN DWORD dwSignerIndex,
  256. IN HCRYPTMSG hMsg,
  257. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  258. );
  259. //+-------------------------------------------------------------------------
  260. // Get a certificate with a key provider property for one of the message's
  261. // recipients and use to decrypt the message.
  262. //--------------------------------------------------------------------------
  263. static BOOL GetXchgCertAndDecrypt(
  264. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  265. IN HCRYPTMSG hMsg,
  266. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert
  267. );
  268. //+-------------------------------------------------------------------------
  269. // Allocate and get message parameter
  270. //--------------------------------------------------------------------------
  271. static void * AllocAndMsgGetParam(
  272. IN HCRYPTMSG hMsg,
  273. IN DWORD dwParamType,
  274. IN DWORD dwIndex
  275. );
  276. //+-------------------------------------------------------------------------
  277. // Sign the message.
  278. //
  279. // If fDetachedSignature is TRUE, the "to be signed" content isn't included
  280. // in the encoded signed blob.
  281. //--------------------------------------------------------------------------
  282. BOOL
  283. WINAPI
  284. CryptSignMessage(
  285. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  286. IN BOOL fDetachedSignature,
  287. IN DWORD cToBeSigned,
  288. IN const BYTE *rgpbToBeSigned[],
  289. IN DWORD rgcbToBeSigned[],
  290. OUT BYTE *pbSignedBlob,
  291. IN OUT DWORD *pcbSignedBlob
  292. )
  293. {
  294. BOOL fResult;
  295. CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
  296. fResult = InitSignedMsgEncodeInfo(
  297. pSignPara,
  298. &SignedMsgEncodeInfo
  299. );
  300. if (fResult) {
  301. BOOL fBareContent;
  302. DWORD dwInnerContentType;
  303. DWORD dwFlags = 0;
  304. if (fDetachedSignature)
  305. dwFlags |= CMSG_DETACHED_FLAG;
  306. if (pSignPara->cbSize >= STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA,
  307. dwInnerContentType)) {
  308. fBareContent =
  309. pSignPara->dwFlags & CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG;
  310. dwInnerContentType =
  311. pSignPara->dwInnerContentType;
  312. #ifdef CMS_PKCS7
  313. if (pSignPara->dwFlags &
  314. CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG)
  315. dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  316. #endif // CMS_PKCS7
  317. } else {
  318. fBareContent = FALSE;
  319. dwInnerContentType = 0;
  320. }
  321. #ifdef ENABLE_SCA_STREAM_TEST
  322. if (pSignPara->cbSize >= STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA,
  323. dwFlags) &&
  324. (pSignPara->dwFlags & SCA_STREAM_ENABLE_FLAG)) {
  325. dwFlags |= pSignPara->dwFlags & SCA_INDEFINITE_STREAM_FLAG;
  326. fResult = StreamEncodeMsg(
  327. pSignPara->dwMsgEncodingType,
  328. dwFlags,
  329. CMSG_SIGNED,
  330. &SignedMsgEncodeInfo,
  331. cToBeSigned,
  332. rgpbToBeSigned,
  333. rgcbToBeSigned,
  334. fBareContent,
  335. dwInnerContentType,
  336. pbSignedBlob,
  337. pcbSignedBlob
  338. );
  339. } else
  340. #endif
  341. fResult = EncodeMsg(
  342. pSignPara->dwMsgEncodingType,
  343. dwFlags,
  344. CMSG_SIGNED,
  345. &SignedMsgEncodeInfo,
  346. cToBeSigned,
  347. rgpbToBeSigned,
  348. rgcbToBeSigned,
  349. fBareContent,
  350. dwInnerContentType,
  351. pbSignedBlob,
  352. pcbSignedBlob
  353. );
  354. FreeSignedMsgEncodeInfo(pSignPara, &SignedMsgEncodeInfo);
  355. } else
  356. *pcbSignedBlob = 0;
  357. return fResult;
  358. }
  359. //+-------------------------------------------------------------------------
  360. // Verify a signed message.
  361. //
  362. // For *pcbDecoded == 0 on input, the signer isn't verified.
  363. //
  364. // A message might have more than one signer. Set dwSignerIndex to iterate
  365. // through all the signers. dwSignerIndex == 0 selects the first signer.
  366. //
  367. // pVerifyPara's pfnGetSignerCertificate is called to get the signer's
  368. // certificate.
  369. //
  370. // For a verified signer and message, *ppSignerCert is updated
  371. // with the CertContext of the signer. It must be freed by calling
  372. // CertFreeCertificateContext. Otherwise, *ppSignerCert is set to NULL.
  373. // For *pbcbDecoded == 0 on input, *ppSignerCert is always set to
  374. // NULL.
  375. //
  376. // ppSignerCert can be NULL, indicating the caller isn't interested
  377. // in getting the CertContext of the signer.
  378. //
  379. // pcbDecoded can be NULL, indicating the caller isn't interested in getting
  380. // the decoded content. Furthermore, if the message doesn't contain any
  381. // content or signers, then, pcbDecoded must be set to NULL, to allow the
  382. // pVerifyPara->pfnGetSignerCertificate to be called. Normally, this would be
  383. // the case when the signed message contains only certficates and CRLs.
  384. // If pcbDecoded is NULL and the message doesn't have the indicated signer,
  385. // pfnGetSignerCertificate is called with pSignerId set to NULL.
  386. //--------------------------------------------------------------------------
  387. BOOL
  388. WINAPI
  389. CryptVerifyMessageSignature(
  390. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  391. IN DWORD dwSignerIndex,
  392. IN const BYTE *pbSignedBlob,
  393. IN DWORD cbSignedBlob,
  394. OUT OPTIONAL BYTE *pbDecoded,
  395. IN OUT OPTIONAL DWORD *pcbDecoded,
  396. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  397. )
  398. {
  399. #ifdef ENABLE_SCA_STREAM_TEST
  400. if (pVerifyPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG)
  401. return StreamDecodeMsg(
  402. CMSG_SIGNED_FLAG,
  403. NULL, // pDecryptPara
  404. pVerifyPara,
  405. dwSignerIndex,
  406. pbSignedBlob,
  407. cbSignedBlob,
  408. 0, // cToBeEncoded
  409. NULL, // rgpbToBeEncoded
  410. NULL, // rgcbToBeEncoded
  411. 0, // dwPrevInnerContentType
  412. NULL, // pdwMsgType
  413. NULL, // pdwInnerContentType
  414. pbDecoded,
  415. pcbDecoded,
  416. NULL, // ppXchgCert
  417. ppSignerCert
  418. );
  419. else
  420. #endif
  421. return DecodeMsg(
  422. CMSG_SIGNED_FLAG,
  423. NULL, // pDecryptPara
  424. pVerifyPara,
  425. dwSignerIndex,
  426. pbSignedBlob,
  427. cbSignedBlob,
  428. 0, // cToBeEncoded
  429. NULL, // rgpbToBeEncoded
  430. NULL, // rgcbToBeEncoded
  431. 0, // dwPrevInnerContentType
  432. NULL, // pdwMsgType
  433. NULL, // pdwInnerContentType
  434. pbDecoded,
  435. pcbDecoded,
  436. NULL, // ppXchgCert
  437. ppSignerCert
  438. );
  439. }
  440. //+-------------------------------------------------------------------------
  441. // Verify a signed message containing detached signature(s).
  442. // The "to be signed" content is passed in separately. No
  443. // decoded output. Otherwise, identical to CryptVerifyMessageSignature.
  444. //--------------------------------------------------------------------------
  445. BOOL
  446. WINAPI
  447. CryptVerifyDetachedMessageSignature(
  448. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  449. IN DWORD dwSignerIndex,
  450. IN const BYTE *pbDetachedSignBlob,
  451. IN DWORD cbDetachedSignBlob,
  452. IN DWORD cToBeSigned,
  453. IN const BYTE *rgpbToBeSigned[],
  454. IN DWORD rgcbToBeSigned[],
  455. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  456. )
  457. {
  458. #ifdef ENABLE_SCA_STREAM_TEST
  459. if (pVerifyPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG)
  460. return StreamDecodeMsg(
  461. CMSG_SIGNED_FLAG,
  462. NULL, // pDecryptPara
  463. pVerifyPara,
  464. dwSignerIndex,
  465. pbDetachedSignBlob,
  466. cbDetachedSignBlob,
  467. cToBeSigned,
  468. rgpbToBeSigned,
  469. rgcbToBeSigned,
  470. 0, // dwPrevInnerContentType
  471. NULL, // pdwMsgType
  472. NULL, // pdwInnerContentType
  473. NULL, // pbDecoded
  474. NULL, // pcbDecoded
  475. NULL, // ppXchgCert
  476. ppSignerCert
  477. );
  478. else
  479. #endif
  480. return DecodeMsg(
  481. CMSG_SIGNED_FLAG,
  482. NULL, // pDecryptPara
  483. pVerifyPara,
  484. dwSignerIndex,
  485. pbDetachedSignBlob,
  486. cbDetachedSignBlob,
  487. cToBeSigned,
  488. rgpbToBeSigned,
  489. rgcbToBeSigned,
  490. 0, // dwPrevInnerContentType
  491. NULL, // pdwMsgType
  492. NULL, // pdwInnerContentType
  493. NULL, // pbDecoded
  494. NULL, // pcbDecoded
  495. NULL, // ppXchgCert
  496. ppSignerCert
  497. );
  498. }
  499. //+-------------------------------------------------------------------------
  500. // Returns the count of signers in the signed message. For no signers, returns
  501. // 0. For an error returns -1 with LastError updated accordingly.
  502. //--------------------------------------------------------------------------
  503. LONG
  504. WINAPI
  505. CryptGetMessageSignerCount(
  506. IN DWORD dwMsgEncodingType,
  507. IN const BYTE *pbSignedBlob,
  508. IN DWORD cbSignedBlob
  509. )
  510. {
  511. HCRYPTMSG hMsg = NULL;
  512. LONG lSignerCount;
  513. DWORD cbData;
  514. if (NULL == (hMsg = CryptMsgOpenToDecode(
  515. dwMsgEncodingType,
  516. 0, // dwFlags
  517. 0, // dwMsgType
  518. 0, // hCryptProv,
  519. NULL, // pRecipientInfo
  520. NULL // pStreamInfo
  521. ))) goto ErrorReturn;
  522. if (!CryptMsgUpdate(
  523. hMsg,
  524. pbSignedBlob,
  525. cbSignedBlob,
  526. TRUE // fFinal
  527. )) goto ErrorReturn;
  528. lSignerCount = 0;
  529. cbData = sizeof(lSignerCount);
  530. if (!CryptMsgGetParam(
  531. hMsg,
  532. CMSG_SIGNER_COUNT_PARAM,
  533. 0, // dwIndex
  534. &lSignerCount,
  535. &cbData
  536. )) goto ErrorReturn;
  537. goto CommonReturn;
  538. ErrorReturn:
  539. lSignerCount = -1;
  540. CommonReturn:
  541. if (hMsg)
  542. CryptMsgClose(hMsg);
  543. return lSignerCount;
  544. }
  545. //+-------------------------------------------------------------------------
  546. // Returns the cert store containing the message's certs and CRLs.
  547. // For an error, returns NULL with LastError updated.
  548. //--------------------------------------------------------------------------
  549. HCERTSTORE
  550. WINAPI
  551. CryptGetMessageCertificates(
  552. IN DWORD dwMsgAndCertEncodingType,
  553. IN HCRYPTPROV hCryptProv, // passed to CertOpenStore
  554. IN DWORD dwFlags, // passed to CertOpenStore
  555. IN const BYTE *pbSignedBlob,
  556. IN DWORD cbSignedBlob
  557. )
  558. {
  559. CRYPT_DATA_BLOB SignedBlob;
  560. SignedBlob.pbData = (BYTE *) pbSignedBlob;
  561. SignedBlob.cbData = cbSignedBlob;
  562. return CertOpenStore(
  563. CERT_STORE_PROV_PKCS7,
  564. dwMsgAndCertEncodingType,
  565. hCryptProv,
  566. dwFlags,
  567. (const void *) &SignedBlob
  568. );
  569. }
  570. //+-------------------------------------------------------------------------
  571. // Encrypts the message for the recipient(s).
  572. //--------------------------------------------------------------------------
  573. BOOL
  574. WINAPI
  575. CryptEncryptMessage(
  576. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  577. IN DWORD cRecipientCert,
  578. IN PCCERT_CONTEXT rgpRecipientCert[],
  579. IN const BYTE *pbToBeEncrypted,
  580. IN DWORD cbToBeEncrypted,
  581. OUT BYTE *pbEncryptedBlob,
  582. IN OUT DWORD *pcbEncryptedBlob
  583. )
  584. {
  585. BOOL fResult;
  586. CMSG_ENVELOPED_ENCODE_INFO EnvelopedMsgEncodeInfo;
  587. fResult = InitEnvelopedMsgEncodeInfo(
  588. pEncryptPara,
  589. cRecipientCert,
  590. rgpRecipientCert,
  591. &EnvelopedMsgEncodeInfo
  592. );
  593. if (fResult) {
  594. BOOL fBareContent;
  595. DWORD dwInnerContentType;
  596. DWORD dwFlags = 0;
  597. if (pEncryptPara->cbSize >= sizeof(CRYPT_ENCRYPT_MESSAGE_PARA)) {
  598. fBareContent =
  599. pEncryptPara->dwFlags & CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG;
  600. dwInnerContentType =
  601. pEncryptPara->dwInnerContentType;
  602. #ifdef CMS_PKCS7
  603. if (pEncryptPara->dwFlags &
  604. CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG)
  605. dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  606. #endif // CMS_PKCS7
  607. } else {
  608. fBareContent = FALSE;
  609. dwInnerContentType = 0;
  610. }
  611. #ifdef ENABLE_SCA_STREAM_TEST
  612. if (pEncryptPara->cbSize >= STRUCT_CBSIZE(CRYPT_ENCRYPT_MESSAGE_PARA,
  613. dwFlags) &&
  614. (pEncryptPara->dwFlags & SCA_STREAM_ENABLE_FLAG)) {
  615. dwFlags |= pEncryptPara->dwFlags & SCA_INDEFINITE_STREAM_FLAG;
  616. fResult = StreamEncodeMsg(
  617. pEncryptPara->dwMsgEncodingType,
  618. dwFlags,
  619. CMSG_ENVELOPED,
  620. &EnvelopedMsgEncodeInfo,
  621. 1, // cToBeEncrypted
  622. &pbToBeEncrypted,
  623. &cbToBeEncrypted,
  624. fBareContent,
  625. dwInnerContentType,
  626. pbEncryptedBlob,
  627. pcbEncryptedBlob
  628. );
  629. } else
  630. #endif
  631. fResult = EncodeMsg(
  632. pEncryptPara->dwMsgEncodingType,
  633. dwFlags,
  634. CMSG_ENVELOPED,
  635. &EnvelopedMsgEncodeInfo,
  636. 1, // cToBeEncrypted
  637. &pbToBeEncrypted,
  638. &cbToBeEncrypted,
  639. fBareContent,
  640. dwInnerContentType,
  641. pbEncryptedBlob,
  642. pcbEncryptedBlob
  643. );
  644. FreeEnvelopedMsgEncodeInfo(pEncryptPara, &EnvelopedMsgEncodeInfo);
  645. } else
  646. *pcbEncryptedBlob = 0;
  647. return fResult;
  648. }
  649. //+-------------------------------------------------------------------------
  650. // Decrypts the message.
  651. //
  652. // For *pcbDecrypted == 0 on input, the message isn't decrypted.
  653. //
  654. // For a successfully decrypted message, *ppXchgCert is updated
  655. // with the CertContext used to decrypt. It must be freed by calling
  656. // CertFreeCertificateContext. Otherwise, *ppXchgCert is set to NULL.
  657. // For *pbcbDecrypted == 0 on input, *ppXchgCert is always set to
  658. // NULL.
  659. //
  660. // ppXchgCert can be NULL, indicating the caller isn't interested
  661. // in getting the CertContext used to decrypt.
  662. //
  663. // pcbDecrypted can be NULL, indicating the caller isn't interested in
  664. // getting the decrypted content. However, when pcbDecrypted is NULL,
  665. // the message is still decrypted.
  666. //--------------------------------------------------------------------------
  667. BOOL
  668. WINAPI
  669. CryptDecryptMessage(
  670. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  671. IN const BYTE *pbEncryptedBlob,
  672. IN DWORD cbEncryptedBlob,
  673. OUT OPTIONAL BYTE *pbDecrypted,
  674. IN OUT OPTIONAL DWORD *pcbDecrypted,
  675. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert
  676. )
  677. {
  678. #ifdef ENABLE_SCA_STREAM_TEST
  679. if (pDecryptPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG)
  680. return StreamDecodeMsg(
  681. CMSG_ENVELOPED_FLAG,
  682. pDecryptPara,
  683. NULL, // pVerifyPara
  684. 0, // dwSignerIndex
  685. pbEncryptedBlob,
  686. cbEncryptedBlob,
  687. 0, // cToBeEncoded
  688. NULL, // rgpbToBeEncoded
  689. NULL, // rgcbToBeEncoded
  690. 0, // dwPrevInnerContentType
  691. NULL, // pdwMsgType
  692. NULL, // pdwInnerContentType
  693. pbDecrypted,
  694. pcbDecrypted,
  695. ppXchgCert,
  696. NULL // ppSignerCert
  697. );
  698. else
  699. #endif
  700. return DecodeMsg(
  701. CMSG_ENVELOPED_FLAG,
  702. pDecryptPara,
  703. NULL, // pVerifyPara
  704. 0, // dwSignerIndex
  705. pbEncryptedBlob,
  706. cbEncryptedBlob,
  707. 0, // cToBeEncoded
  708. NULL, // rgpbToBeEncoded
  709. NULL, // rgcbToBeEncoded
  710. 0, // dwPrevInnerContentType
  711. NULL, // pdwMsgType
  712. NULL, // pdwInnerContentType
  713. pbDecrypted,
  714. pcbDecrypted,
  715. ppXchgCert,
  716. NULL // ppSignerCert
  717. );
  718. }
  719. //+-------------------------------------------------------------------------
  720. // Sign the message and encrypt for the recipient(s)
  721. //--------------------------------------------------------------------------
  722. BOOL
  723. WINAPI
  724. CryptSignAndEncryptMessage(
  725. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  726. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  727. IN DWORD cRecipientCert,
  728. IN PCCERT_CONTEXT rgpRecipientCert[],
  729. IN const BYTE *pbToBeSignedAndEncrypted,
  730. IN DWORD cbToBeSignedAndEncrypted,
  731. OUT BYTE *pbSignedAndEncryptedBlob,
  732. IN OUT DWORD *pcbSignedAndEncryptedBlob
  733. )
  734. {
  735. #if 1
  736. BOOL fResult;
  737. DWORD cbSigned;
  738. DWORD cbSignedDelta = 0;
  739. BYTE *pbSigned = NULL;
  740. if (pbSignedAndEncryptedBlob == NULL)
  741. *pcbSignedAndEncryptedBlob = 0;
  742. cbSigned = 0;
  743. CryptSignMessage(
  744. pSignPara,
  745. FALSE, // fDetachedSignature
  746. 1, // cToBeSigned
  747. &pbToBeSignedAndEncrypted,
  748. &cbToBeSignedAndEncrypted,
  749. NULL, // pbSignedBlob
  750. &cbSigned
  751. );
  752. if (cbSigned == 0) goto ErrorReturn;
  753. if (*pcbSignedAndEncryptedBlob) {
  754. DWORD cbSignedMax;
  755. pbSigned = (BYTE *) SCAAlloc(cbSigned);
  756. if (pbSigned == NULL) goto ErrorReturn;
  757. cbSignedMax = cbSigned;
  758. if (!CryptSignMessage(
  759. pSignPara,
  760. FALSE, // fDetachedSignature
  761. 1, // cToBeSigned
  762. &pbToBeSignedAndEncrypted,
  763. &cbToBeSignedAndEncrypted,
  764. pbSigned,
  765. &cbSigned
  766. )) goto ErrorReturn;
  767. if (cbSignedMax > cbSigned)
  768. // For DSS, the signature length varies since it consists of
  769. // a sequence of unsigned integers.
  770. cbSignedDelta = cbSignedMax - cbSigned;
  771. }
  772. fResult = CryptEncryptMessage(
  773. pEncryptPara,
  774. cRecipientCert,
  775. rgpRecipientCert,
  776. pbSigned,
  777. cbSigned,
  778. pbSignedAndEncryptedBlob,
  779. pcbSignedAndEncryptedBlob
  780. );
  781. if (!fResult && 0 != *pcbSignedAndEncryptedBlob)
  782. // Adjust if necessary for DSS signature length
  783. *pcbSignedAndEncryptedBlob += cbSignedDelta;
  784. goto CommonReturn;
  785. ErrorReturn:
  786. *pcbSignedAndEncryptedBlob = 0;
  787. fResult = FALSE;
  788. CommonReturn:
  789. if (pbSigned)
  790. SCAFree(pbSigned);
  791. return fResult;
  792. #else
  793. BOOL fResult;
  794. CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO SignedAndEnvelopedMsgEncodeInfo;
  795. SignedAndEnvelopedMsgEncodeInfo.cbSize =
  796. sizeof(CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO);
  797. fResult = InitSignedMsgEncodeInfo(
  798. pSignPara,
  799. &SignedAndEnvelopedMsgEncodeInfo.SignedInfo
  800. );
  801. if (fResult) {
  802. fResult = InitEnvelopedMsgEncodeInfo(
  803. pEncryptPara,
  804. cRecipientCert,
  805. rgpRecipientCert,
  806. &SignedAndEnvelopedMsgEncodeInfo.EnvelopedInfo
  807. );
  808. if (fResult) {
  809. fResult = EncodeMsg(
  810. pSignPara->dwMsgEncodingType,
  811. CMSG_SIGNED_AND_ENVELOPED,
  812. &SignedAndEnvelopedMsgEncodeInfo,
  813. pbToBeSignedAndEncrypted,
  814. cbToBeSignedAndEncrypted,
  815. FALSE, // fBareContent
  816. 0, // dwInnerContentType
  817. pbSignedAndEncryptedBlob,
  818. pcbSignedAndEncryptedBlob
  819. );
  820. FreeEnvelopedMsgEncodeInfo(pEncryptPara,
  821. &SignedAndEnvelopedMsgEncodeInfo.EnvelopedInfo);
  822. }
  823. FreeSignedMsgEncodeInfo(pSignPara,
  824. &SignedAndEnvelopedMsgEncodeInfo.SignedInfo);
  825. }
  826. return fResult;
  827. #endif
  828. }
  829. //+-------------------------------------------------------------------------
  830. // Decrypts the message and verifies the signer.
  831. //
  832. // For *pcbDecrypted == 0 on input, the message isn't decrypted and the
  833. // signer isn't verified.
  834. //
  835. // A message might have more than one signer. Set dwSignerIndex to iterate
  836. // through all the signers. dwSignerIndex == 0 selects the first signer.
  837. //
  838. // The hVerify's GetSignerCertificate is called to verify the signer's
  839. // certificate.
  840. //
  841. // For a successfully decrypted and verified message, *ppXchgCert and
  842. // *ppSignerCert are updated. They must be freed by calling
  843. // CertFreeCertificateContext. Otherwise, they are set to NULL.
  844. // For *pbcbDecrypted == 0 on input, both are always set to NULL.
  845. //
  846. // ppXchgCert and/or ppSignerCert can be NULL, indicating the
  847. // caller isn't interested in getting the CertContext.
  848. //
  849. // pcbDecrypted can be NULL, indicating the caller isn't interested in
  850. // getting the decrypted content. However, when pcbDecrypted is NULL,
  851. // the message is still decrypted and verified.
  852. //--------------------------------------------------------------------------
  853. BOOL
  854. WINAPI
  855. CryptDecryptAndVerifyMessageSignature(
  856. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  857. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  858. IN DWORD dwSignerIndex,
  859. IN const BYTE *pbEncryptedBlob,
  860. IN DWORD cbEncryptedBlob,
  861. OUT OPTIONAL BYTE *pbDecrypted,
  862. IN OUT OPTIONAL DWORD *pcbDecrypted,
  863. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  864. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  865. )
  866. {
  867. #if 1
  868. BOOL fResult;
  869. DWORD cbSignedBlob;
  870. BYTE *pbSignedBlob = NULL;
  871. DWORD dwEnvelopeInnerContentType;
  872. if (ppXchgCert)
  873. *ppXchgCert = NULL;
  874. if (ppSignerCert)
  875. *ppSignerCert = NULL;
  876. #ifdef ENABLE_SCA_STREAM_TEST
  877. if (pDecryptPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG) {
  878. cbSignedBlob = 0;
  879. StreamDecodeMsg(
  880. CMSG_ENVELOPED_FLAG,
  881. pDecryptPara,
  882. NULL, // pVerifyPara
  883. 0, // dwSignerIndex
  884. pbEncryptedBlob,
  885. cbEncryptedBlob,
  886. 0, // cToBeEncoded
  887. NULL, // rgpbToBeEncoded
  888. NULL, // rgcbToBeEncoded
  889. 0, // dwPrevInnerContentType
  890. NULL, // pdwMsgType
  891. NULL, // pdwInnerContentType
  892. NULL, // pbDecrypted
  893. &cbSignedBlob,
  894. NULL, // ppXchgCert
  895. NULL // ppSignerCert
  896. );
  897. if (cbSignedBlob == 0) goto ErrorReturn;
  898. pbSignedBlob = (BYTE *) SCAAlloc(cbSignedBlob);
  899. if (pbSignedBlob == NULL) goto ErrorReturn;
  900. if (!StreamDecodeMsg(
  901. CMSG_ENVELOPED_FLAG,
  902. pDecryptPara,
  903. NULL, // pVerifyPara
  904. 0, // dwSignerIndex
  905. pbEncryptedBlob,
  906. cbEncryptedBlob,
  907. 0, // cToBeEncoded
  908. NULL, // rgpbToBeEncoded
  909. NULL, // rgcbToBeEncoded
  910. 0, // dwPrevInnerContentType
  911. NULL, // pdwMsgType
  912. &dwEnvelopeInnerContentType,
  913. pbSignedBlob,
  914. &cbSignedBlob,
  915. ppXchgCert,
  916. NULL // ppSignerCert
  917. )) goto ErrorReturn;
  918. } else {
  919. #endif
  920. cbSignedBlob = 0;
  921. DecodeMsg(
  922. CMSG_ENVELOPED_FLAG,
  923. pDecryptPara,
  924. NULL, // pVerifyPara
  925. 0, // dwSignerIndex
  926. pbEncryptedBlob,
  927. cbEncryptedBlob,
  928. 0, // cToBeEncoded
  929. NULL, // rgpbToBeEncoded
  930. NULL, // rgcbToBeEncoded
  931. 0, // dwPrevInnerContentType
  932. NULL, // pdwMsgType
  933. NULL, // pdwInnerContentType
  934. NULL, // pbDecrypted
  935. &cbSignedBlob,
  936. NULL, // ppXchgCert
  937. NULL // ppSignerCert
  938. );
  939. if (cbSignedBlob == 0) goto ErrorReturn;
  940. pbSignedBlob = (BYTE *) SCAAlloc(cbSignedBlob);
  941. if (pbSignedBlob == NULL) goto ErrorReturn;
  942. if (!DecodeMsg(
  943. CMSG_ENVELOPED_FLAG,
  944. pDecryptPara,
  945. NULL, // pVerifyPara
  946. 0, // dwSignerIndex
  947. pbEncryptedBlob,
  948. cbEncryptedBlob,
  949. 0, // cToBeEncoded
  950. NULL, // rgpbToBeEncoded
  951. NULL, // rgcbToBeEncoded
  952. 0, // dwPrevInnerContentType
  953. NULL, // pdwMsgType
  954. &dwEnvelopeInnerContentType,
  955. pbSignedBlob,
  956. &cbSignedBlob,
  957. ppXchgCert,
  958. NULL // ppSignerCert
  959. )) goto ErrorReturn;
  960. #ifdef ENABLE_SCA_STREAM_TEST
  961. }
  962. #endif
  963. #ifdef ENABLE_SCA_STREAM_TEST
  964. if (pVerifyPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG)
  965. fResult = StreamDecodeMsg(
  966. CMSG_SIGNED_FLAG,
  967. NULL, // pDecryptPara
  968. pVerifyPara,
  969. dwSignerIndex,
  970. pbSignedBlob,
  971. cbSignedBlob,
  972. 0, // cToBeEncoded
  973. NULL, // rgpbToBeEncoded
  974. NULL, // rgcbToBeEncoded
  975. dwEnvelopeInnerContentType,
  976. NULL, // pdwMsgType
  977. NULL, // pdwInnerContentType
  978. pbDecrypted,
  979. pcbDecrypted,
  980. NULL, // ppXchgCert
  981. ppSignerCert
  982. );
  983. else
  984. #endif
  985. fResult = DecodeMsg(
  986. CMSG_SIGNED_FLAG,
  987. NULL, // pDecryptPara
  988. pVerifyPara,
  989. dwSignerIndex,
  990. pbSignedBlob,
  991. cbSignedBlob,
  992. 0, // cToBeEncoded
  993. NULL, // rgpbToBeEncoded
  994. NULL, // rgcbToBeEncoded
  995. dwEnvelopeInnerContentType,
  996. NULL, // pdwMsgType
  997. NULL, // pdwInnerContentType
  998. pbDecrypted,
  999. pcbDecrypted,
  1000. NULL, // ppXchgCert
  1001. ppSignerCert
  1002. );
  1003. if (!fResult) goto VerifyError;
  1004. goto CommonReturn;
  1005. ErrorReturn:
  1006. if (pcbDecrypted)
  1007. *pcbDecrypted = 0;
  1008. VerifyError:
  1009. if (ppXchgCert && *ppXchgCert) {
  1010. CertFreeCertificateContext(*ppXchgCert);
  1011. *ppXchgCert = NULL;
  1012. }
  1013. if (ppSignerCert && *ppSignerCert) {
  1014. CertFreeCertificateContext(*ppSignerCert);
  1015. *ppSignerCert = NULL;
  1016. }
  1017. fResult = FALSE;
  1018. CommonReturn:
  1019. if (pbSignedBlob)
  1020. SCAFree(pbSignedBlob);
  1021. return fResult;
  1022. #else
  1023. // This needs to be updated if we switch back to this option
  1024. return DecodeMsg(
  1025. CMSG_SIGNED_AND_ENVELOPED_FLAG,
  1026. pDecryptPara,
  1027. pVerifyPara,
  1028. dwSignerIndex,
  1029. pbEncryptedBlob,
  1030. cbEncryptedBlob,
  1031. 0, // dwPrevInnerContentType
  1032. NULL, // pdwMsgType
  1033. NULL, // pdwInnerContentType
  1034. pbDecrypted,
  1035. pcbDecrypted,
  1036. ppXchgCert,
  1037. ppSignerCert
  1038. );
  1039. #endif
  1040. }
  1041. //+-------------------------------------------------------------------------
  1042. // Get the hash length for the specified algorithm identifier.
  1043. //
  1044. // Returns 0 for an unknown identifier.
  1045. //--------------------------------------------------------------------------
  1046. static DWORD GetComputedHashLength(PCRYPT_ALGORITHM_IDENTIFIER pAlgId)
  1047. {
  1048. DWORD cbHash;
  1049. DWORD dwAlgId;
  1050. dwAlgId = CertOIDToAlgId(pAlgId->pszObjId);
  1051. switch (dwAlgId) {
  1052. case CALG_SHA:
  1053. cbHash = 20;
  1054. break;
  1055. case CALG_MD2:
  1056. case CALG_MD4:
  1057. case CALG_MD5:
  1058. cbHash = 16;
  1059. break;
  1060. default:
  1061. cbHash = 0;
  1062. }
  1063. return cbHash;
  1064. }
  1065. //+-------------------------------------------------------------------------
  1066. // Hash the message.
  1067. //
  1068. // If fDetachedHash is TRUE, only the ComputedHash is encoded in the
  1069. // pbHashedBlob. Otherwise, both the ToBeHashed and ComputedHash
  1070. // are encoded.
  1071. //
  1072. // pcbHashedBlob or pcbComputedHash can be NULL, indicating the caller
  1073. // isn't interested in getting the output.
  1074. //--------------------------------------------------------------------------
  1075. BOOL
  1076. WINAPI
  1077. CryptHashMessage(
  1078. IN PCRYPT_HASH_MESSAGE_PARA pHashPara,
  1079. IN BOOL fDetachedHash,
  1080. IN DWORD cToBeHashed,
  1081. IN const BYTE *rgpbToBeHashed[],
  1082. IN DWORD rgcbToBeHashed[],
  1083. OUT OPTIONAL BYTE *pbHashedBlob,
  1084. IN OUT OPTIONAL DWORD *pcbHashedBlob,
  1085. OUT OPTIONAL BYTE *pbComputedHash,
  1086. IN OUT OPTIONAL DWORD *pcbComputedHash
  1087. )
  1088. {
  1089. BOOL fResult;
  1090. DWORD dwFlags = fDetachedHash ? CMSG_DETACHED_FLAG : 0;
  1091. HCRYPTMSG hMsg = NULL;
  1092. CMSG_HASHED_ENCODE_INFO HashedMsgEncodeInfo;
  1093. DWORD cbHashedBlob;
  1094. DWORD cbComputedHash;
  1095. // Get input lengths and default return lengths to 0
  1096. cbHashedBlob = 0;
  1097. if (pcbHashedBlob) {
  1098. if (pbHashedBlob)
  1099. cbHashedBlob = *pcbHashedBlob;
  1100. *pcbHashedBlob = 0;
  1101. }
  1102. cbComputedHash = 0;
  1103. if (pcbComputedHash) {
  1104. if (pbComputedHash)
  1105. cbComputedHash = *pcbComputedHash;
  1106. *pcbComputedHash = 0;
  1107. }
  1108. assert(pHashPara->cbSize == sizeof(CRYPT_HASH_MESSAGE_PARA));
  1109. if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
  1110. goto InvalidArg;
  1111. HashedMsgEncodeInfo.cbSize = sizeof(CMSG_HASHED_ENCODE_INFO);
  1112. HashedMsgEncodeInfo.hCryptProv = pHashPara->hCryptProv;
  1113. HashedMsgEncodeInfo.HashAlgorithm = pHashPara->HashAlgorithm;
  1114. HashedMsgEncodeInfo.pvHashAuxInfo = pHashPara->pvHashAuxInfo;
  1115. fResult = TRUE;
  1116. if (0 == cbHashedBlob && 0 == cbComputedHash &&
  1117. (NULL == pcbComputedHash ||
  1118. 0 != (*pcbComputedHash = GetComputedHashLength(
  1119. &pHashPara->HashAlgorithm)))) {
  1120. // Length only
  1121. if (pcbHashedBlob) {
  1122. DWORD c;
  1123. DWORD cbTotal = 0;
  1124. DWORD *pcb;
  1125. for (c = cToBeHashed, pcb = rgcbToBeHashed; c > 0; c--, pcb++)
  1126. cbTotal += *pcb;
  1127. if (0 == (*pcbHashedBlob = CryptMsgCalculateEncodedLength(
  1128. pHashPara->dwMsgEncodingType,
  1129. dwFlags,
  1130. CMSG_HASHED,
  1131. &HashedMsgEncodeInfo,
  1132. NULL, // pszInnerContentObjID
  1133. cbTotal
  1134. ))) goto CalculateEncodedLengthError;
  1135. if (pbHashedBlob) goto LengthError;
  1136. }
  1137. if (pcbComputedHash && pbComputedHash)
  1138. goto LengthError;
  1139. } else {
  1140. if (NULL == (hMsg = CryptMsgOpenToEncode(
  1141. pHashPara->dwMsgEncodingType,
  1142. dwFlags,
  1143. CMSG_HASHED,
  1144. &HashedMsgEncodeInfo,
  1145. NULL, // pszInnerContentObjID
  1146. NULL // pStreamInfo
  1147. ))) goto OpenToEncodeError;
  1148. if (0 == cToBeHashed) {
  1149. if (!CryptMsgUpdate(
  1150. hMsg,
  1151. NULL, // pbData
  1152. 0, // cbData
  1153. TRUE // fFinal
  1154. )) goto UpdateError;
  1155. } else {
  1156. DWORD c;
  1157. DWORD *pcb;
  1158. const BYTE **ppb;
  1159. for (c = cToBeHashed,
  1160. pcb = rgcbToBeHashed,
  1161. ppb = rgpbToBeHashed; c > 0; c--, pcb++, ppb++) {
  1162. if (!CryptMsgUpdate(
  1163. hMsg,
  1164. *ppb,
  1165. *pcb,
  1166. c == 1 // fFinal
  1167. )) goto UpdateError;
  1168. }
  1169. }
  1170. if (pcbHashedBlob) {
  1171. fResult = CryptMsgGetParam(
  1172. hMsg,
  1173. CMSG_CONTENT_PARAM,
  1174. 0, // dwIndex
  1175. pbHashedBlob,
  1176. &cbHashedBlob
  1177. );
  1178. *pcbHashedBlob = cbHashedBlob;
  1179. }
  1180. if (pcbComputedHash) {
  1181. DWORD dwErr = 0;
  1182. BOOL fResult2;
  1183. if (!fResult)
  1184. dwErr = GetLastError();
  1185. fResult2 = CryptMsgGetParam(
  1186. hMsg,
  1187. CMSG_COMPUTED_HASH_PARAM,
  1188. 0, // dwIndex
  1189. pbComputedHash,
  1190. &cbComputedHash
  1191. );
  1192. *pcbComputedHash = cbComputedHash;
  1193. if (!fResult2)
  1194. fResult = FALSE;
  1195. else if (!fResult)
  1196. SetLastError(dwErr);
  1197. }
  1198. if (!fResult)
  1199. goto ErrorReturn; // NO_TRACE
  1200. }
  1201. CommonReturn:
  1202. if (hMsg)
  1203. CryptMsgClose(hMsg); // for success, preserves LastError
  1204. return fResult;
  1205. ErrorReturn:
  1206. fResult = FALSE;
  1207. goto CommonReturn;
  1208. SET_ERROR(InvalidArg, E_INVALIDARG)
  1209. SET_ERROR(LengthError, ERROR_MORE_DATA)
  1210. TRACE_ERROR(CalculateEncodedLengthError)
  1211. TRACE_ERROR(OpenToEncodeError)
  1212. TRACE_ERROR(UpdateError)
  1213. }
  1214. //+-------------------------------------------------------------------------
  1215. // Verify a hashed message.
  1216. //
  1217. // pcbToBeHashed or pcbComputedHash can be NULL,
  1218. // indicating the caller isn't interested in getting the output.
  1219. //--------------------------------------------------------------------------
  1220. BOOL
  1221. WINAPI
  1222. CryptVerifyMessageHash(
  1223. IN PCRYPT_HASH_MESSAGE_PARA pHashPara,
  1224. IN BYTE *pbHashedBlob,
  1225. IN DWORD cbHashedBlob,
  1226. OUT OPTIONAL BYTE *pbToBeHashed,
  1227. IN OUT OPTIONAL DWORD *pcbToBeHashed,
  1228. OUT OPTIONAL BYTE *pbComputedHash,
  1229. IN OUT OPTIONAL DWORD *pcbComputedHash
  1230. )
  1231. {
  1232. return DecodeHashMsg(
  1233. pHashPara,
  1234. pbHashedBlob,
  1235. cbHashedBlob,
  1236. NULL, // cToBeHashed
  1237. NULL, // rgpbToBeHashed
  1238. NULL, // rgcbToBeHashed
  1239. pbToBeHashed,
  1240. pcbToBeHashed,
  1241. pbComputedHash,
  1242. pcbComputedHash
  1243. );
  1244. }
  1245. //+-------------------------------------------------------------------------
  1246. // Verify a hashed message containing a detached hash.
  1247. // The "to be hashed" content is passed in separately. No
  1248. // decoded output. Otherwise, identical to CryptVerifyMessageHash.
  1249. //
  1250. // pcbComputedHash can be NULL, indicating the caller isn't interested
  1251. // in getting the output.
  1252. //--------------------------------------------------------------------------
  1253. BOOL
  1254. WINAPI
  1255. CryptVerifyDetachedMessageHash(
  1256. IN PCRYPT_HASH_MESSAGE_PARA pHashPara,
  1257. IN BYTE *pbDetachedHashBlob,
  1258. IN DWORD cbDetachedHashBlob,
  1259. IN DWORD cToBeHashed,
  1260. IN const BYTE *rgpbToBeHashed[],
  1261. IN DWORD rgcbToBeHashed[],
  1262. OUT OPTIONAL BYTE *pbComputedHash,
  1263. IN OUT OPTIONAL DWORD *pcbComputedHash
  1264. )
  1265. {
  1266. return DecodeHashMsg(
  1267. pHashPara,
  1268. pbDetachedHashBlob,
  1269. cbDetachedHashBlob,
  1270. cToBeHashed,
  1271. rgpbToBeHashed,
  1272. rgcbToBeHashed,
  1273. NULL, // pbDecoded
  1274. NULL, // pcbDecoded
  1275. pbComputedHash,
  1276. pcbComputedHash
  1277. );
  1278. }
  1279. //+-------------------------------------------------------------------------
  1280. // Decodes a cryptographic message which may be one of the following types:
  1281. // CMSG_DATA
  1282. // CMSG_SIGNED
  1283. // CMSG_ENVELOPED
  1284. // CMSG_SIGNED_AND_ENVELOPED
  1285. // CMSG_HASHED
  1286. //
  1287. // dwMsgTypeFlags specifies the set of allowable messages. For example, to
  1288. // decode either SIGNED or ENVELOPED messages, set dwMsgTypeFlags to:
  1289. // CMSG_SIGNED_FLAG | CMSG_ENVELOPED_FLAG.
  1290. //
  1291. // dwProvInnerContentType is only applicable when processing nested
  1292. // crytographic messages. When processing an outer crytographic message
  1293. // it must be set to 0. When decoding a nested cryptographic message
  1294. // its the dwInnerContentType returned by a previous CryptDecodeMessage
  1295. // of the outer message. The InnerContentType can be any of the CMSG types,
  1296. // for example, CMSG_DATA, CMSG_SIGNED, ...
  1297. //
  1298. // The optional *pdwMsgType is updated with the type of message.
  1299. //
  1300. // The optional *pdwInnerContentType is updated with the type of the inner
  1301. // message. Unless there is cryptographic message nesting, CMSG_DATA
  1302. // is returned.
  1303. //
  1304. // For CMSG_DATA: returns decoded content.
  1305. // For CMSG_SIGNED: same as CryptVerifyMessageSignature.
  1306. // For CMSG_ENVELOPED: same as CryptDecryptMessage.
  1307. // For CMSG_SIGNED_AND_ENVELOPED: same as CryptDecryptMessage plus
  1308. // CryptVerifyMessageSignature.
  1309. // For CMSG_HASHED: verifies the hash and returns decoded content.
  1310. //--------------------------------------------------------------------------
  1311. BOOL
  1312. WINAPI
  1313. CryptDecodeMessage(
  1314. IN DWORD dwMsgTypeFlags,
  1315. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  1316. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  1317. IN DWORD dwSignerIndex,
  1318. IN const BYTE *pbEncodedBlob,
  1319. IN DWORD cbEncodedBlob,
  1320. IN DWORD dwPrevInnerContentType,
  1321. OUT OPTIONAL DWORD *pdwMsgType,
  1322. OUT OPTIONAL DWORD *pdwInnerContentType,
  1323. OUT OPTIONAL BYTE *pbDecoded,
  1324. IN OUT OPTIONAL DWORD *pcbDecoded,
  1325. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  1326. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  1327. )
  1328. {
  1329. #ifdef ENABLE_SCA_STREAM_TEST
  1330. if ((pVerifyPara &&
  1331. (pVerifyPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG))
  1332. ||
  1333. (pDecryptPara &&
  1334. (pDecryptPara->dwMsgAndCertEncodingType & SCA_STREAM_ENABLE_FLAG)))
  1335. return StreamDecodeMsg(
  1336. dwMsgTypeFlags,
  1337. pDecryptPara,
  1338. pVerifyPara,
  1339. dwSignerIndex,
  1340. pbEncodedBlob,
  1341. cbEncodedBlob,
  1342. 0, // cToBeEncoded
  1343. NULL, // rgpbToBeEncoded
  1344. NULL, // rgcbToBeEncoded
  1345. dwPrevInnerContentType,
  1346. pdwMsgType,
  1347. pdwInnerContentType,
  1348. pbDecoded,
  1349. pcbDecoded,
  1350. ppXchgCert,
  1351. ppSignerCert
  1352. );
  1353. else
  1354. #endif
  1355. return DecodeMsg(
  1356. dwMsgTypeFlags,
  1357. pDecryptPara,
  1358. pVerifyPara,
  1359. dwSignerIndex,
  1360. pbEncodedBlob,
  1361. cbEncodedBlob,
  1362. 0, // cToBeEncoded
  1363. NULL, // rgpbToBeEncoded
  1364. NULL, // rgcbToBeEncoded
  1365. dwPrevInnerContentType,
  1366. pdwMsgType,
  1367. pdwInnerContentType,
  1368. pbDecoded,
  1369. pcbDecoded,
  1370. ppXchgCert,
  1371. ppSignerCert
  1372. );
  1373. }
  1374. //+-------------------------------------------------------------------------
  1375. // Sign the message using the provider's private key specified in the
  1376. // parameters. A dummy SignerId is created and stored in the message.
  1377. //
  1378. // Normally used until a certificate has been created for the key.
  1379. //--------------------------------------------------------------------------
  1380. BOOL
  1381. WINAPI
  1382. CryptSignMessageWithKey(
  1383. IN PCRYPT_KEY_SIGN_MESSAGE_PARA pSignPara,
  1384. IN const BYTE *pbToBeSigned,
  1385. IN DWORD cbToBeSigned,
  1386. OUT BYTE *pbSignedBlob,
  1387. IN OUT DWORD *pcbSignedBlob
  1388. )
  1389. {
  1390. BOOL fResult;
  1391. CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
  1392. CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
  1393. CERT_INFO CertInfo;
  1394. DWORD dwSerialNumber = 0x12345678;
  1395. #define NO_CERT_COMMON_NAME "NO CERT SIGNATURE"
  1396. CERT_RDN rgRDN[1];
  1397. CERT_RDN_ATTR rgAttr[1];
  1398. CERT_NAME_INFO NameInfo;
  1399. BYTE *pbNameEncoded = NULL;
  1400. DWORD cbNameEncoded;
  1401. assert(pSignPara->cbSize >= offsetof(CRYPT_KEY_SIGN_MESSAGE_PARA,
  1402. pvHashAuxInfo) + sizeof(pSignPara->pvHashAuxInfo));
  1403. if (pSignPara->cbSize < offsetof(CRYPT_KEY_SIGN_MESSAGE_PARA,
  1404. pvHashAuxInfo) + sizeof(pSignPara->pvHashAuxInfo))
  1405. goto InvalidArg;
  1406. // Create a dummy issuer name
  1407. NameInfo.cRDN = 1;
  1408. NameInfo.rgRDN = rgRDN;
  1409. rgRDN[0].cRDNAttr = 1;
  1410. rgRDN[0].rgRDNAttr = rgAttr;
  1411. rgAttr[0].pszObjId = szOID_COMMON_NAME;
  1412. rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
  1413. rgAttr[0].Value.pbData = (BYTE *) NO_CERT_COMMON_NAME;
  1414. rgAttr[0].Value.cbData = strlen(NO_CERT_COMMON_NAME);
  1415. cbNameEncoded = 0;
  1416. CryptEncodeObject(
  1417. pSignPara->dwMsgAndCertEncodingType,
  1418. X509_NAME,
  1419. &NameInfo,
  1420. NULL, // pbEncoded
  1421. &cbNameEncoded
  1422. );
  1423. if (cbNameEncoded == 0) goto ErrorReturn;
  1424. pbNameEncoded = (BYTE *) SCAAlloc(cbNameEncoded);
  1425. if (pbNameEncoded == NULL) goto ErrorReturn;
  1426. if (!CryptEncodeObject(
  1427. pSignPara->dwMsgAndCertEncodingType,
  1428. X509_NAME,
  1429. &NameInfo,
  1430. pbNameEncoded,
  1431. &cbNameEncoded
  1432. )) goto ErrorReturn;
  1433. // CertInfo needs to only be initialized with issuer, serial number
  1434. // and public key algorithm
  1435. memset(&CertInfo, 0, sizeof(CertInfo));
  1436. CertInfo.Issuer.pbData = pbNameEncoded;
  1437. CertInfo.Issuer.cbData = cbNameEncoded;
  1438. CertInfo.SerialNumber.pbData = (BYTE *) &dwSerialNumber;
  1439. CertInfo.SerialNumber.cbData = sizeof(dwSerialNumber);
  1440. if (pSignPara->cbSize >= offsetof(CRYPT_KEY_SIGN_MESSAGE_PARA,
  1441. PubKeyAlgorithm) + sizeof(pSignPara->PubKeyAlgorithm) &&
  1442. pSignPara->PubKeyAlgorithm.pszObjId &&
  1443. '\0' != *pSignPara->PubKeyAlgorithm.pszObjId)
  1444. CertInfo.SubjectPublicKeyInfo.Algorithm = pSignPara->PubKeyAlgorithm;
  1445. else
  1446. CertInfo.SubjectPublicKeyInfo.Algorithm.pszObjId =
  1447. CERT_DEFAULT_OID_PUBLIC_KEY_SIGN;
  1448. memset(&SignerEncodeInfo, 0, sizeof(SignerEncodeInfo));
  1449. SignerEncodeInfo.cbSize = sizeof(SignerEncodeInfo);
  1450. SignerEncodeInfo.pCertInfo = &CertInfo;
  1451. SignerEncodeInfo.hCryptProv = pSignPara->hCryptProv;
  1452. SignerEncodeInfo.dwKeySpec = pSignPara->dwKeySpec;
  1453. SignerEncodeInfo.HashAlgorithm = pSignPara->HashAlgorithm;
  1454. SignerEncodeInfo.pvHashAuxInfo = pSignPara->pvHashAuxInfo;
  1455. memset(&SignedMsgEncodeInfo, 0, sizeof(SignedMsgEncodeInfo));
  1456. SignedMsgEncodeInfo.cbSize = sizeof(SignedMsgEncodeInfo);
  1457. SignedMsgEncodeInfo.cSigners = 1;
  1458. SignedMsgEncodeInfo.rgSigners = &SignerEncodeInfo;
  1459. fResult = EncodeMsg(
  1460. pSignPara->dwMsgAndCertEncodingType,
  1461. 0, // dwFlags
  1462. CMSG_SIGNED,
  1463. &SignedMsgEncodeInfo,
  1464. 1, // cToBeSigned
  1465. &pbToBeSigned,
  1466. &cbToBeSigned,
  1467. FALSE, // fBareContent
  1468. 0, // dwInnerContentType
  1469. pbSignedBlob,
  1470. pcbSignedBlob
  1471. );
  1472. goto CommonReturn;
  1473. InvalidArg:
  1474. SetLastError((DWORD) E_INVALIDARG);
  1475. ErrorReturn:
  1476. fResult = FALSE;
  1477. *pcbSignedBlob = 0;
  1478. CommonReturn:
  1479. if (pbNameEncoded)
  1480. SCAFree(pbNameEncoded);
  1481. return fResult;
  1482. }
  1483. //+-------------------------------------------------------------------------
  1484. // Verify a signed message using the specified public key info.
  1485. //
  1486. // Normally called by a CA until it has created a certificate for the
  1487. // key.
  1488. //
  1489. // pPublicKeyInfo contains the public key to use to verify the signed
  1490. // message. If NULL, the signature isn't verified (for instance, the decoded
  1491. // content may contain the PublicKeyInfo).
  1492. //
  1493. // pcbDecoded can be NULL, indicating the caller isn't interested
  1494. // in getting the decoded content.
  1495. //--------------------------------------------------------------------------
  1496. BOOL
  1497. WINAPI
  1498. CryptVerifyMessageSignatureWithKey(
  1499. IN PCRYPT_KEY_VERIFY_MESSAGE_PARA pVerifyPara,
  1500. IN OPTIONAL PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  1501. IN const BYTE *pbSignedBlob,
  1502. IN DWORD cbSignedBlob,
  1503. OUT OPTIONAL BYTE *pbDecoded,
  1504. IN OUT OPTIONAL DWORD *pcbDecoded
  1505. )
  1506. {
  1507. BOOL fResult = TRUE;
  1508. HCRYPTMSG hMsg = NULL;
  1509. PCERT_INFO pCertInfo = NULL;
  1510. DWORD cbData;
  1511. DWORD dwMsgType;
  1512. DWORD dwFlags;
  1513. assert(pVerifyPara->cbSize == sizeof(CRYPT_KEY_VERIFY_MESSAGE_PARA));
  1514. if (pVerifyPara->cbSize != sizeof(CRYPT_KEY_VERIFY_MESSAGE_PARA))
  1515. goto InvalidArg;
  1516. if (pbDecoded == NULL && pcbDecoded)
  1517. *pcbDecoded = 0;
  1518. if (pcbDecoded && *pcbDecoded == 0 && pPublicKeyInfo == NULL)
  1519. dwFlags = CMSG_LENGTH_ONLY_FLAG;
  1520. else
  1521. dwFlags = 0;
  1522. hMsg = CryptMsgOpenToDecode(
  1523. pVerifyPara->dwMsgEncodingType,
  1524. dwFlags,
  1525. 0, // dwMsgType
  1526. pVerifyPara->hCryptProv,
  1527. NULL, // pRecipientInfo
  1528. NULL // pStreamInfo
  1529. );
  1530. if (hMsg == NULL) goto ErrorReturn;
  1531. fResult = CryptMsgUpdate(
  1532. hMsg,
  1533. pbSignedBlob,
  1534. cbSignedBlob,
  1535. TRUE // fFinal
  1536. );
  1537. if (!fResult) goto ErrorReturn;
  1538. cbData = sizeof(dwMsgType);
  1539. dwMsgType = 0;
  1540. fResult = CryptMsgGetParam(
  1541. hMsg,
  1542. CMSG_TYPE_PARAM,
  1543. 0, // dwIndex
  1544. &dwMsgType,
  1545. &cbData
  1546. );
  1547. if (!fResult) goto ErrorReturn;
  1548. if (dwMsgType != CMSG_SIGNED)
  1549. {
  1550. SetLastError((DWORD) CRYPT_E_UNEXPECTED_MSG_TYPE);
  1551. goto ErrorReturn;
  1552. }
  1553. if (pPublicKeyInfo) {
  1554. // Allocate and get the CERT_INFO containing the SignerId
  1555. // (Issuer and SerialNumber)
  1556. pCertInfo = (PCERT_INFO) AllocAndMsgGetParam(
  1557. hMsg,
  1558. CMSG_SIGNER_CERT_INFO_PARAM,
  1559. 0 // dwSignerIndex
  1560. );
  1561. if (pCertInfo == NULL) goto ErrorReturn;
  1562. pCertInfo->SubjectPublicKeyInfo = *pPublicKeyInfo;
  1563. fResult = CryptMsgControl(
  1564. hMsg,
  1565. 0, // dwFlags
  1566. CMSG_CTRL_VERIFY_SIGNATURE,
  1567. pCertInfo
  1568. );
  1569. if (!fResult) goto ErrorReturn;
  1570. }
  1571. if (pcbDecoded) {
  1572. fResult = CryptMsgGetParam(
  1573. hMsg,
  1574. CMSG_CONTENT_PARAM,
  1575. 0, // dwIndex
  1576. pbDecoded,
  1577. pcbDecoded
  1578. );
  1579. }
  1580. goto CommonReturn;
  1581. InvalidArg:
  1582. SetLastError((DWORD) E_INVALIDARG);
  1583. ErrorReturn:
  1584. if (pcbDecoded)
  1585. *pcbDecoded = 0;
  1586. fResult = FALSE;
  1587. CommonReturn:
  1588. if (pCertInfo)
  1589. SCAFree(pCertInfo);
  1590. if (hMsg)
  1591. CryptMsgClose(hMsg); // for success, preserves LastError
  1592. return fResult;
  1593. }
  1594. //+-------------------------------------------------------------------------
  1595. // SCA allocation and free routines
  1596. //--------------------------------------------------------------------------
  1597. static void *SCAAlloc(
  1598. IN size_t cbBytes
  1599. )
  1600. {
  1601. void *pv;
  1602. pv = malloc(cbBytes);
  1603. if (pv == NULL)
  1604. SetLastError((DWORD) E_OUTOFMEMORY);
  1605. return pv;
  1606. }
  1607. static void SCAFree(
  1608. IN void *pv
  1609. )
  1610. {
  1611. if (pv)
  1612. free(pv);
  1613. }
  1614. //+-------------------------------------------------------------------------
  1615. // Null implementation of the callback get and verify signer certificate
  1616. //--------------------------------------------------------------------------
  1617. static PCCERT_CONTEXT WINAPI NullGetSignerCertificate(
  1618. IN void *pvGetArg,
  1619. IN DWORD dwCertEncodingType,
  1620. IN PCERT_INFO pSignerId, // Only the Issuer and SerialNumber
  1621. // fields are used
  1622. IN HCERTSTORE hMsgCertStore
  1623. )
  1624. {
  1625. return CertGetSubjectCertificateFromStore(hMsgCertStore, dwCertEncodingType,
  1626. pSignerId);
  1627. }
  1628. //+-------------------------------------------------------------------------
  1629. // Functions for initializing message encode information
  1630. //--------------------------------------------------------------------------
  1631. static PCMSG_SIGNER_ENCODE_INFO InitSignerEncodeInfo(
  1632. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara
  1633. )
  1634. {
  1635. BOOL fResult;
  1636. PCMSG_SIGNER_ENCODE_INFO pSigner = NULL;
  1637. BOOL *pfDidCryptAcquire;
  1638. DWORD cbSigner;
  1639. #ifdef CMS_PKCS7
  1640. BYTE *pbHash; // not allocated
  1641. #endif // CMS_PKCS7
  1642. DWORD dwAcquireFlags;
  1643. if (pSignPara->pSigningCert == NULL)
  1644. return NULL;
  1645. // The flag indicating we did a CryptAcquireContext
  1646. // follows the CMSG_SIGNER_ENCODE_INFO. If set, the HCRYPTPROV will need to be
  1647. // released when SignerEncodeInfo is freed.
  1648. cbSigner = sizeof(CMSG_SIGNER_ENCODE_INFO) + sizeof(BOOL);
  1649. #ifdef CMS_PKCS7
  1650. if (pSignPara->dwFlags & CRYPT_MESSAGE_KEYID_SIGNER_FLAG)
  1651. cbSigner += MAX_HASH_LEN;
  1652. #endif // CMS_PKCS7
  1653. pSigner = (PCMSG_SIGNER_ENCODE_INFO) SCAAlloc(cbSigner);
  1654. if (pSigner == NULL) goto ErrorReturn;
  1655. memset(pSigner, 0, cbSigner);
  1656. pSigner->cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
  1657. pfDidCryptAcquire =
  1658. (BOOL *) (((BYTE *) pSigner) + sizeof(CMSG_SIGNER_ENCODE_INFO));
  1659. pSigner->pCertInfo = pSignPara->pSigningCert->pCertInfo;
  1660. pSigner->HashAlgorithm = pSignPara->HashAlgorithm;
  1661. pSigner->pvHashAuxInfo = pSignPara->pvHashAuxInfo;
  1662. dwAcquireFlags = CRYPT_ACQUIRE_USE_PROV_INFO_FLAG;
  1663. if (pSignPara->dwFlags & CRYPT_MESSAGE_SILENT_KEYSET_FLAG)
  1664. dwAcquireFlags |= CRYPT_ACQUIRE_SILENT_FLAG;
  1665. fResult = CryptAcquireCertificatePrivateKey(
  1666. pSignPara->pSigningCert,
  1667. dwAcquireFlags,
  1668. NULL, // pvReserved
  1669. &pSigner->hCryptProv,
  1670. &pSigner->dwKeySpec,
  1671. pfDidCryptAcquire
  1672. );
  1673. if (!fResult) goto ErrorReturn;
  1674. if (pSignPara->cbSize >= STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA,
  1675. rgUnauthAttr)) {
  1676. pSigner->cAuthAttr = pSignPara->cAuthAttr;
  1677. pSigner->rgAuthAttr = pSignPara->rgAuthAttr;
  1678. pSigner->cUnauthAttr = pSignPara->cUnauthAttr;
  1679. pSigner->rgUnauthAttr = pSignPara->rgUnauthAttr;
  1680. }
  1681. #ifdef CMS_PKCS7
  1682. if (pSignPara->dwFlags & CRYPT_MESSAGE_KEYID_SIGNER_FLAG) {
  1683. pbHash = (BYTE *) pfDidCryptAcquire + sizeof(*pfDidCryptAcquire);
  1684. pSigner->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1685. pSigner->SignerId.KeyId.pbData = pbHash;
  1686. pSigner->SignerId.KeyId.cbData = MAX_HASH_LEN;
  1687. if (!CertGetCertificateContextProperty(
  1688. pSignPara->pSigningCert,
  1689. CERT_KEY_IDENTIFIER_PROP_ID,
  1690. pbHash,
  1691. &pSigner->SignerId.KeyId.cbData
  1692. ))
  1693. goto ErrorReturn;
  1694. }
  1695. if (pSignPara->cbSize >= STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA,
  1696. pvHashEncryptionAuxInfo)) {
  1697. pSigner->HashEncryptionAlgorithm = pSignPara->HashEncryptionAlgorithm;
  1698. pSigner->pvHashEncryptionAuxInfo = pSignPara->pvHashEncryptionAuxInfo;
  1699. }
  1700. #endif // CMS_PKCS7
  1701. goto CommonReturn;
  1702. ErrorReturn:
  1703. if (pSigner) {
  1704. FreeSignerEncodeInfo(pSigner);
  1705. pSigner = NULL;
  1706. }
  1707. CommonReturn:
  1708. return pSigner;
  1709. }
  1710. static void FreeSignerEncodeInfo(
  1711. IN PCMSG_SIGNER_ENCODE_INFO pSigner
  1712. )
  1713. {
  1714. BOOL *pfDidCryptAcquire;
  1715. if (pSigner == NULL)
  1716. return;
  1717. // The flag indicating we did a CryptAcquireContext
  1718. // follows the CMSG_SIGNER_ENCODE_INFO.
  1719. pfDidCryptAcquire =
  1720. (BOOL *) (((BYTE *) pSigner) + sizeof(CMSG_SIGNER_ENCODE_INFO));
  1721. if (*pfDidCryptAcquire) {
  1722. DWORD dwErr = GetLastError();
  1723. CryptReleaseContext(pSigner->hCryptProv, 0);
  1724. SetLastError(dwErr);
  1725. }
  1726. SCAFree(pSigner);
  1727. }
  1728. static BOOL InitSignedCertAndCrl(
  1729. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  1730. OUT PCERT_BLOB *ppCertEncoded,
  1731. OUT PCRL_BLOB *ppCrlEncoded
  1732. )
  1733. {
  1734. PCERT_BLOB pCertEncoded = NULL;
  1735. PCRL_BLOB pCrlEncoded = NULL;
  1736. DWORD cMsgCert = pSignPara->cMsgCert;
  1737. DWORD cMsgCrl = pSignPara->cMsgCrl;
  1738. BOOL fResult;
  1739. DWORD dwIdx;
  1740. if (cMsgCert) {
  1741. pCertEncoded = (PCERT_BLOB) SCAAlloc(sizeof(CERT_BLOB) * cMsgCert);
  1742. if (pCertEncoded == NULL) goto ErrorReturn;
  1743. for (dwIdx = 0; dwIdx < cMsgCert; dwIdx++) {
  1744. pCertEncoded[dwIdx].pbData = pSignPara->rgpMsgCert[dwIdx]->pbCertEncoded;
  1745. pCertEncoded[dwIdx].cbData = pSignPara->rgpMsgCert[dwIdx]->cbCertEncoded;
  1746. }
  1747. }
  1748. if (cMsgCrl) {
  1749. pCrlEncoded = (PCRL_BLOB) SCAAlloc(sizeof(CRL_BLOB) * cMsgCrl);
  1750. if (pCrlEncoded == NULL) goto ErrorReturn;
  1751. for (dwIdx = 0; dwIdx < cMsgCrl; dwIdx++) {
  1752. pCrlEncoded[dwIdx].pbData = pSignPara->rgpMsgCrl[dwIdx]->pbCrlEncoded;
  1753. pCrlEncoded[dwIdx].cbData = pSignPara->rgpMsgCrl[dwIdx]->cbCrlEncoded;
  1754. }
  1755. }
  1756. fResult = TRUE;
  1757. goto CommonReturn;
  1758. ErrorReturn:
  1759. FreeSignedCertAndCrl(pCertEncoded, pCrlEncoded);
  1760. pCertEncoded = NULL;
  1761. pCrlEncoded = NULL;
  1762. fResult = FALSE;
  1763. CommonReturn:
  1764. *ppCertEncoded = pCertEncoded;
  1765. *ppCrlEncoded = pCrlEncoded;
  1766. return fResult;
  1767. }
  1768. static void FreeSignedCertAndCrl(
  1769. IN PCERT_BLOB pCertEncoded,
  1770. IN PCRL_BLOB pCrlEncoded
  1771. )
  1772. {
  1773. if (pCertEncoded)
  1774. SCAFree(pCertEncoded);
  1775. if (pCrlEncoded)
  1776. SCAFree(pCrlEncoded);
  1777. }
  1778. static BOOL InitSignedMsgEncodeInfo(
  1779. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  1780. OUT PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  1781. )
  1782. {
  1783. BOOL fResult = FALSE;
  1784. assert(pSignPara->cbSize >=
  1785. STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA, rgpMsgCrl));
  1786. if (pSignPara->cbSize < STRUCT_CBSIZE(CRYPT_SIGN_MESSAGE_PARA, rgpMsgCrl))
  1787. SetLastError((DWORD) E_INVALIDARG);
  1788. else {
  1789. memset(pSignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
  1790. pSignedMsgEncodeInfo->cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
  1791. pSignedMsgEncodeInfo->cSigners =
  1792. (pSignPara->pSigningCert != NULL) ? 1 : 0;
  1793. pSignedMsgEncodeInfo->rgSigners = InitSignerEncodeInfo(pSignPara);
  1794. if (pSignedMsgEncodeInfo->rgSigners ||
  1795. pSignedMsgEncodeInfo->cSigners == 0) {
  1796. pSignedMsgEncodeInfo->cCertEncoded = pSignPara->cMsgCert;
  1797. pSignedMsgEncodeInfo->cCrlEncoded = pSignPara->cMsgCrl;
  1798. fResult = InitSignedCertAndCrl(
  1799. pSignPara,
  1800. &pSignedMsgEncodeInfo->rgCertEncoded,
  1801. &pSignedMsgEncodeInfo->rgCrlEncoded
  1802. );
  1803. if(!fResult)
  1804. FreeSignerEncodeInfo(pSignedMsgEncodeInfo->rgSigners);
  1805. }
  1806. }
  1807. if (!fResult)
  1808. memset(pSignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
  1809. return fResult;
  1810. }
  1811. static void FreeSignedMsgEncodeInfo(
  1812. IN PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  1813. IN PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  1814. )
  1815. {
  1816. FreeSignerEncodeInfo(pSignedMsgEncodeInfo->rgSigners);
  1817. FreeSignedCertAndCrl(
  1818. pSignedMsgEncodeInfo->rgCertEncoded,
  1819. pSignedMsgEncodeInfo->rgCrlEncoded
  1820. );
  1821. }
  1822. #ifdef CMS_PKCS7
  1823. // Returned array of CMSG_RECIPIENT_ENCODE_INFOs needs to be SCAFree'd
  1824. //
  1825. // KeyAgree recipients use RC2 or 3DES wrap according
  1826. // to the EncryptPara's ContentEncryptionAlgorithm
  1827. static PCMSG_RECIPIENT_ENCODE_INFO InitCmsRecipientEncodeInfo(
  1828. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  1829. IN DWORD cRecipientCert,
  1830. IN PCCERT_CONTEXT rgpRecipientCert[],
  1831. IN DWORD dwFlags
  1832. )
  1833. {
  1834. PCMSG_RECIPIENT_ENCODE_INFO pCmsRecipientEncodeInfo = NULL;
  1835. DWORD cbCmsRecipientEncodeInfo;
  1836. PCMSG_RECIPIENT_ENCODE_INFO pEncodeInfo; // not allocated
  1837. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTrans; // not allocated
  1838. PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgree; // not allocated
  1839. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *ppEncryptedKey; // not allocated
  1840. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO pEncryptedKey; // not allocated
  1841. PCCERT_CONTEXT *ppRecipientCert; // not allocated
  1842. BYTE *pbHash = NULL; // not allocated
  1843. assert(cRecipientCert);
  1844. cbCmsRecipientEncodeInfo =
  1845. sizeof(CMSG_RECIPIENT_ENCODE_INFO) * cRecipientCert +
  1846. sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO) * cRecipientCert +
  1847. sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO) * cRecipientCert +
  1848. sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *) * cRecipientCert +
  1849. sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO) * cRecipientCert;
  1850. if (dwFlags & CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG)
  1851. cbCmsRecipientEncodeInfo += MAX_HASH_LEN * cRecipientCert;
  1852. pCmsRecipientEncodeInfo =
  1853. (PCMSG_RECIPIENT_ENCODE_INFO) SCAAlloc(cbCmsRecipientEncodeInfo);
  1854. if (NULL == pCmsRecipientEncodeInfo)
  1855. goto OutOfMemory;
  1856. memset(pCmsRecipientEncodeInfo, 0, cbCmsRecipientEncodeInfo);
  1857. pEncodeInfo = pCmsRecipientEncodeInfo;
  1858. pKeyTrans = (PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)
  1859. &pEncodeInfo[cRecipientCert];
  1860. pKeyAgree = (PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)
  1861. &pKeyTrans[cRecipientCert];
  1862. ppEncryptedKey = (PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)
  1863. &pKeyAgree[cRecipientCert];
  1864. pEncryptedKey = (PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO)
  1865. &ppEncryptedKey[cRecipientCert];
  1866. if (dwFlags & CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG)
  1867. pbHash = (BYTE *) &pEncryptedKey[cRecipientCert];
  1868. ppRecipientCert = rgpRecipientCert;
  1869. for ( ; 0 < cRecipientCert; cRecipientCert--,
  1870. pEncodeInfo++,
  1871. pKeyTrans++,
  1872. pKeyAgree++,
  1873. ppEncryptedKey++,
  1874. pEncryptedKey++,
  1875. ppRecipientCert++) {
  1876. PCERT_INFO pCertInfo = (*ppRecipientCert)->pCertInfo;
  1877. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo =
  1878. &pCertInfo->SubjectPublicKeyInfo;
  1879. PCCRYPT_OID_INFO pOIDInfo;
  1880. PCERT_ID pRecipientId;
  1881. ALG_ID aiPubKey;
  1882. if (pOIDInfo = CryptFindOIDInfo(
  1883. CRYPT_OID_INFO_OID_KEY,
  1884. pPublicKeyInfo->Algorithm.pszObjId,
  1885. CRYPT_PUBKEY_ALG_OID_GROUP_ID))
  1886. aiPubKey = pOIDInfo->Algid;
  1887. else
  1888. aiPubKey = 0;
  1889. if (aiPubKey == CALG_DH_SF || aiPubKey == CALG_DH_EPHEM) {
  1890. pEncodeInfo->dwRecipientChoice = CMSG_KEY_AGREE_RECIPIENT;
  1891. pEncodeInfo->pKeyAgree = pKeyAgree;
  1892. ALG_ID aiSymKey;
  1893. pKeyAgree->cbSize = sizeof(*pKeyAgree);
  1894. pKeyAgree->KeyEncryptionAlgorithm.pszObjId =
  1895. szOID_RSA_SMIMEalgESDH;
  1896. // pKeyAgree->pvKeyEncryptionAuxInfo =
  1897. if (pOIDInfo = CryptFindOIDInfo(
  1898. CRYPT_OID_INFO_OID_KEY,
  1899. pEncryptPara->ContentEncryptionAlgorithm.pszObjId,
  1900. CRYPT_ENCRYPT_ALG_OID_GROUP_ID))
  1901. aiSymKey = pOIDInfo->Algid;
  1902. else
  1903. aiSymKey = 0;
  1904. if (CALG_3DES == aiSymKey)
  1905. pKeyAgree->KeyWrapAlgorithm.pszObjId =
  1906. szOID_RSA_SMIMEalgCMS3DESwrap;
  1907. else {
  1908. pKeyAgree->KeyWrapAlgorithm.pszObjId =
  1909. szOID_RSA_SMIMEalgCMSRC2wrap;
  1910. if (CALG_RC2 == aiSymKey)
  1911. pKeyAgree->pvKeyWrapAuxInfo =
  1912. pEncryptPara->pvEncryptionAuxInfo;
  1913. }
  1914. // pKeyAgree->hCryptProv =
  1915. pKeyAgree->dwKeyChoice = CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE;
  1916. pKeyAgree->pEphemeralAlgorithm = &pPublicKeyInfo->Algorithm;
  1917. // pKeyAgree->UserKeyingMaterial =
  1918. pKeyAgree->cRecipientEncryptedKeys = 1;
  1919. pKeyAgree->rgpRecipientEncryptedKeys = ppEncryptedKey;
  1920. *ppEncryptedKey = pEncryptedKey;
  1921. pEncryptedKey->cbSize = sizeof(*pEncryptedKey);
  1922. pEncryptedKey->RecipientPublicKey = pPublicKeyInfo->PublicKey;
  1923. pRecipientId = &pEncryptedKey->RecipientId;
  1924. // pEncryptedKey->Date =
  1925. // pEncryptedKey->pOtherAttr =
  1926. } else {
  1927. pEncodeInfo->dwRecipientChoice = CMSG_KEY_TRANS_RECIPIENT;
  1928. pEncodeInfo->pKeyTrans = pKeyTrans;
  1929. pKeyTrans->cbSize = sizeof(*pKeyTrans);
  1930. pKeyTrans->KeyEncryptionAlgorithm = pPublicKeyInfo->Algorithm;
  1931. // pKeyTrans->pvKeyEncryptionAuxInfo =
  1932. // pKeyTrans->hCryptProv =
  1933. pKeyTrans->RecipientPublicKey = pPublicKeyInfo->PublicKey;
  1934. pRecipientId = &pKeyTrans->RecipientId;
  1935. }
  1936. if (dwFlags & CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG) {
  1937. pRecipientId->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1938. pRecipientId->KeyId.pbData = pbHash;
  1939. pRecipientId->KeyId.cbData = MAX_HASH_LEN;
  1940. if (!CertGetCertificateContextProperty(
  1941. *ppRecipientCert,
  1942. CERT_KEY_IDENTIFIER_PROP_ID,
  1943. pbHash,
  1944. &pRecipientId->KeyId.cbData
  1945. ))
  1946. goto GetKeyIdPropError;
  1947. pbHash += MAX_HASH_LEN;
  1948. } else {
  1949. pRecipientId->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1950. pRecipientId->IssuerSerialNumber.Issuer =
  1951. pCertInfo->Issuer;
  1952. pRecipientId->IssuerSerialNumber.SerialNumber =
  1953. pCertInfo->SerialNumber;
  1954. }
  1955. }
  1956. CommonReturn:
  1957. return pCmsRecipientEncodeInfo;
  1958. ErrorReturn:
  1959. SCAFree(pCmsRecipientEncodeInfo);
  1960. pCmsRecipientEncodeInfo = NULL;
  1961. goto CommonReturn;
  1962. TRACE_ERROR(OutOfMemory)
  1963. TRACE_ERROR(GetKeyIdPropError)
  1964. }
  1965. #else
  1966. // Returned array of PCERT_INFOs needs to be SCAFree'd
  1967. static PCERT_INFO *InitRecipientEncodeInfo(
  1968. IN DWORD cRecipientCert,
  1969. IN PCCERT_CONTEXT rgpRecipientCert[]
  1970. )
  1971. {
  1972. DWORD dwIdx;
  1973. PCERT_INFO *ppRecipientEncodeInfo;
  1974. if (cRecipientCert == 0) {
  1975. SetLastError((DWORD) E_INVALIDARG);
  1976. return NULL;
  1977. }
  1978. ppRecipientEncodeInfo = (PCERT_INFO *)
  1979. SCAAlloc(sizeof(PCERT_INFO) * cRecipientCert);
  1980. if (ppRecipientEncodeInfo != NULL) {
  1981. for (dwIdx = 0; dwIdx < cRecipientCert; dwIdx++)
  1982. ppRecipientEncodeInfo[dwIdx] = rgpRecipientCert[dwIdx]->pCertInfo;
  1983. }
  1984. return ppRecipientEncodeInfo;
  1985. }
  1986. #endif // CMS_PKCS7
  1987. static BOOL InitEnvelopedMsgEncodeInfo(
  1988. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  1989. IN DWORD cRecipientCert,
  1990. IN PCCERT_CONTEXT rgpRecipientCert[],
  1991. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  1992. )
  1993. {
  1994. BOOL fResult = FALSE;
  1995. #ifdef CMS_PKCS7
  1996. PCMSG_RECIPIENT_ENCODE_INFO pCmsRecipientEncodeInfo = NULL;
  1997. #else
  1998. PCERT_INFO *ppRecipientEncodeInfo;
  1999. #endif // CMS_PKCS7
  2000. assert(pEncryptPara->cbSize == sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) ||
  2001. pEncryptPara->cbSize == offsetof(CRYPT_ENCRYPT_MESSAGE_PARA, dwFlags));
  2002. if (pEncryptPara->cbSize < offsetof(CRYPT_ENCRYPT_MESSAGE_PARA, dwFlags))
  2003. SetLastError((DWORD) E_INVALIDARG);
  2004. else {
  2005. #ifdef CMS_PKCS7
  2006. if (0 == cRecipientCert || (pCmsRecipientEncodeInfo =
  2007. InitCmsRecipientEncodeInfo(
  2008. pEncryptPara,
  2009. cRecipientCert,
  2010. rgpRecipientCert,
  2011. pEncryptPara->cbSize >= sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) ?
  2012. pEncryptPara->dwFlags : 0
  2013. ))) {
  2014. #else
  2015. ppRecipientEncodeInfo = InitRecipientEncodeInfo(
  2016. cRecipientCert,
  2017. rgpRecipientCert
  2018. );
  2019. if (ppRecipientEncodeInfo) {
  2020. #endif // CMS_PKCS7
  2021. memset(pEnvelopedMsgEncodeInfo, 0,
  2022. sizeof(CMSG_ENVELOPED_ENCODE_INFO));
  2023. pEnvelopedMsgEncodeInfo->cbSize =
  2024. sizeof(CMSG_ENVELOPED_ENCODE_INFO);
  2025. pEnvelopedMsgEncodeInfo->hCryptProv = pEncryptPara->hCryptProv;
  2026. pEnvelopedMsgEncodeInfo->ContentEncryptionAlgorithm =
  2027. pEncryptPara->ContentEncryptionAlgorithm;
  2028. pEnvelopedMsgEncodeInfo->pvEncryptionAuxInfo =
  2029. pEncryptPara->pvEncryptionAuxInfo;
  2030. pEnvelopedMsgEncodeInfo->cRecipients = cRecipientCert;
  2031. #ifdef CMS_PKCS7
  2032. pEnvelopedMsgEncodeInfo->rgCmsRecipients = pCmsRecipientEncodeInfo;
  2033. #else
  2034. pEnvelopedMsgEncodeInfo->rgpRecipients = ppRecipientEncodeInfo;
  2035. #endif // CMS_PKCS7
  2036. fResult = TRUE;
  2037. } else
  2038. fResult = FALSE;
  2039. }
  2040. if (!fResult)
  2041. memset(pEnvelopedMsgEncodeInfo, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO));
  2042. return fResult;
  2043. }
  2044. static void FreeEnvelopedMsgEncodeInfo(
  2045. IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
  2046. IN PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  2047. )
  2048. {
  2049. #ifdef CMS_PKCS7
  2050. if (pEnvelopedMsgEncodeInfo->rgCmsRecipients)
  2051. SCAFree(pEnvelopedMsgEncodeInfo->rgCmsRecipients);
  2052. #else
  2053. if (pEnvelopedMsgEncodeInfo->rgpRecipients)
  2054. SCAFree(pEnvelopedMsgEncodeInfo->rgpRecipients);
  2055. #endif // CMS_PKCS7
  2056. }
  2057. //+-------------------------------------------------------------------------
  2058. // Encode the message.
  2059. //--------------------------------------------------------------------------
  2060. static BOOL EncodeMsg(
  2061. IN DWORD dwMsgEncodingType,
  2062. IN DWORD dwFlags,
  2063. IN DWORD dwMsgType,
  2064. IN void *pvMsgEncodeInfo,
  2065. IN DWORD cToBeEncoded,
  2066. IN const BYTE *rgpbToBeEncoded[],
  2067. IN DWORD rgcbToBeEncoded[],
  2068. IN BOOL fBareContent,
  2069. IN DWORD dwInnerContentType,
  2070. OUT BYTE *pbEncodedBlob,
  2071. IN OUT DWORD *pcbEncodedBlob
  2072. )
  2073. {
  2074. BOOL fResult;
  2075. HCRYPTMSG hMsg = NULL;
  2076. DWORD cbEncodedBlob;
  2077. LPCSTR pszInnerContentOID;
  2078. // Get input length and default return length to 0
  2079. if (pbEncodedBlob == NULL)
  2080. cbEncodedBlob = 0;
  2081. else
  2082. cbEncodedBlob = *pcbEncodedBlob;
  2083. *pcbEncodedBlob = 0;
  2084. if (dwInnerContentType)
  2085. pszInnerContentOID = MsgTypeToOID(dwInnerContentType);
  2086. else
  2087. pszInnerContentOID = NULL;
  2088. if (0 == cbEncodedBlob) {
  2089. DWORD c;
  2090. DWORD cbTotal = 0;
  2091. DWORD *pcb;
  2092. for (c = cToBeEncoded, pcb = rgcbToBeEncoded; c > 0; c--, pcb++)
  2093. cbTotal += *pcb;
  2094. if (fBareContent)
  2095. dwFlags |= CMSG_BARE_CONTENT_FLAG;
  2096. if (0 == (*pcbEncodedBlob = CryptMsgCalculateEncodedLength(
  2097. dwMsgEncodingType,
  2098. dwFlags,
  2099. dwMsgType,
  2100. pvMsgEncodeInfo,
  2101. (LPSTR) pszInnerContentOID,
  2102. cbTotal
  2103. ))) goto CalculateEncodedLengthError;
  2104. if (pbEncodedBlob) goto LengthError;
  2105. } else {
  2106. if (NULL == (hMsg = CryptMsgOpenToEncode(
  2107. dwMsgEncodingType,
  2108. dwFlags,
  2109. dwMsgType,
  2110. pvMsgEncodeInfo,
  2111. (LPSTR) pszInnerContentOID,
  2112. NULL // pStreamInfo
  2113. ))) goto OpenToEncodeError;
  2114. if (0 == cToBeEncoded) {
  2115. if (!CryptMsgUpdate(
  2116. hMsg,
  2117. NULL, // pbData
  2118. 0, // cbData
  2119. TRUE // fFinal
  2120. )) goto UpdateError;
  2121. } else {
  2122. DWORD c;
  2123. DWORD *pcb;
  2124. const BYTE **ppb;
  2125. for (c = cToBeEncoded,
  2126. pcb = rgcbToBeEncoded,
  2127. ppb = rgpbToBeEncoded; c > 0; c--, pcb++, ppb++) {
  2128. if (!CryptMsgUpdate(
  2129. hMsg,
  2130. *ppb,
  2131. *pcb,
  2132. c == 1 // fFinal
  2133. )) goto UpdateError;
  2134. }
  2135. }
  2136. fResult = CryptMsgGetParam(
  2137. hMsg,
  2138. fBareContent ? CMSG_BARE_CONTENT_PARAM : CMSG_CONTENT_PARAM,
  2139. 0, // dwIndex
  2140. pbEncodedBlob,
  2141. &cbEncodedBlob
  2142. );
  2143. *pcbEncodedBlob = cbEncodedBlob;
  2144. if (!fResult) goto ErrorReturn; // NO_TRACE
  2145. }
  2146. fResult = TRUE;
  2147. CommonReturn:
  2148. if (hMsg)
  2149. CryptMsgClose(hMsg); // for success, preserves LastError
  2150. return fResult;
  2151. ErrorReturn:
  2152. fResult = FALSE;
  2153. goto CommonReturn;
  2154. SET_ERROR(LengthError, ERROR_MORE_DATA)
  2155. TRACE_ERROR(CalculateEncodedLengthError)
  2156. TRACE_ERROR(OpenToEncodeError)
  2157. TRACE_ERROR(UpdateError)
  2158. }
  2159. //+-------------------------------------------------------------------------
  2160. // Decodes the message types:
  2161. // CMSG_SIGNED
  2162. // CMSG_ENVELOPED
  2163. // CMSG_SIGNED_AND_ENVELOPED
  2164. // CMSG_HASHED
  2165. //
  2166. // For detached signature (cToBeEncoded != 0), then, pcbDecoded == NULL.
  2167. //--------------------------------------------------------------------------
  2168. static BOOL DecodeMsg(
  2169. IN DWORD dwMsgTypeFlags,
  2170. IN OPTIONAL PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  2171. IN OPTIONAL PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  2172. IN DWORD dwSignerIndex,
  2173. IN const BYTE *pbEncodedBlob,
  2174. IN DWORD cbEncodedBlob,
  2175. IN DWORD cToBeEncoded,
  2176. IN OPTIONAL const BYTE *rgpbToBeEncoded[],
  2177. IN OPTIONAL DWORD rgcbToBeEncoded[],
  2178. IN DWORD dwPrevInnerContentType,
  2179. OUT OPTIONAL DWORD *pdwMsgType,
  2180. OUT OPTIONAL DWORD *pdwInnerContentType,
  2181. OUT OPTIONAL BYTE *pbDecoded,
  2182. IN OUT OPTIONAL DWORD *pcbDecoded,
  2183. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  2184. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  2185. )
  2186. {
  2187. BOOL fResult;
  2188. HCRYPTMSG hMsg = NULL;
  2189. DWORD cbData;
  2190. DWORD dwMsgType;
  2191. DWORD dwFlags;
  2192. HCRYPTPROV hCryptProv;
  2193. DWORD dwMsgEncodingType;
  2194. DWORD cbDecoded;
  2195. // Get input length and default return length to 0
  2196. cbDecoded = 0;
  2197. if (pcbDecoded) {
  2198. if (pbDecoded)
  2199. cbDecoded = *pcbDecoded;
  2200. *pcbDecoded = 0;
  2201. }
  2202. // Default optional return values to 0
  2203. if (pdwMsgType)
  2204. *pdwMsgType = 0;
  2205. if (pdwInnerContentType)
  2206. *pdwInnerContentType = 0;
  2207. if (ppXchgCert)
  2208. *ppXchgCert = NULL;
  2209. if (ppSignerCert)
  2210. *ppSignerCert = NULL;
  2211. if (pDecryptPara) {
  2212. assert(pDecryptPara->cbSize >=
  2213. STRUCT_CBSIZE(CRYPT_DECRYPT_MESSAGE_PARA, rghCertStore));
  2214. if (pDecryptPara->cbSize <
  2215. STRUCT_CBSIZE(CRYPT_DECRYPT_MESSAGE_PARA, rghCertStore))
  2216. goto InvalidArg;
  2217. }
  2218. if (pVerifyPara) {
  2219. assert(pVerifyPara->cbSize == sizeof(CRYPT_VERIFY_MESSAGE_PARA));
  2220. if (pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA))
  2221. goto InvalidArg;
  2222. hCryptProv = pVerifyPara->hCryptProv;
  2223. dwMsgEncodingType = pVerifyPara->dwMsgAndCertEncodingType;
  2224. } else {
  2225. hCryptProv = 0;
  2226. if (NULL == pDecryptPara) goto InvalidArg;
  2227. dwMsgEncodingType = pDecryptPara->dwMsgAndCertEncodingType;
  2228. }
  2229. if (cToBeEncoded)
  2230. dwFlags = CMSG_DETACHED_FLAG;
  2231. else if (pcbDecoded && 0 == cbDecoded &&
  2232. NULL == ppXchgCert && NULL == ppSignerCert)
  2233. dwFlags = CMSG_LENGTH_ONLY_FLAG;
  2234. else
  2235. dwFlags = 0;
  2236. if (dwPrevInnerContentType) {
  2237. dwMsgType = dwPrevInnerContentType;
  2238. if (CMSG_DATA == dwMsgType)
  2239. dwMsgType = 0;
  2240. } else
  2241. dwMsgType = 0;
  2242. if (NULL == (hMsg = CryptMsgOpenToDecode(
  2243. dwMsgEncodingType,
  2244. dwFlags,
  2245. dwMsgType,
  2246. hCryptProv,
  2247. NULL, // pRecipientInfo
  2248. NULL // pStreamInfo
  2249. ))) goto OpenToDecodeError;
  2250. if (!CryptMsgUpdate(
  2251. hMsg,
  2252. pbEncodedBlob,
  2253. cbEncodedBlob,
  2254. TRUE // fFinal
  2255. )) goto UpdateError;
  2256. if (cToBeEncoded) {
  2257. // Detached signature
  2258. DWORD c;
  2259. DWORD *pcb;
  2260. const BYTE **ppb;
  2261. for (c = cToBeEncoded,
  2262. pcb = rgcbToBeEncoded,
  2263. ppb = rgpbToBeEncoded; c > 0; c--, pcb++, ppb++) {
  2264. if (!CryptMsgUpdate(
  2265. hMsg,
  2266. *ppb,
  2267. *pcb,
  2268. c == 1 // fFinal
  2269. )) goto UpdateError;
  2270. }
  2271. }
  2272. cbData = sizeof(dwMsgType);
  2273. dwMsgType = 0;
  2274. if (!CryptMsgGetParam(
  2275. hMsg,
  2276. CMSG_TYPE_PARAM,
  2277. 0, // dwIndex
  2278. &dwMsgType,
  2279. &cbData
  2280. )) goto GetTypeError;
  2281. if (pdwMsgType)
  2282. *pdwMsgType = dwMsgType;
  2283. if (0 == ((1 << dwMsgType) & dwMsgTypeFlags))
  2284. goto UnexpectedMsgTypeError;
  2285. if (pdwInnerContentType) {
  2286. char szInnerContentType[128];
  2287. cbData = sizeof(szInnerContentType);
  2288. if (!CryptMsgGetParam(
  2289. hMsg,
  2290. CMSG_INNER_CONTENT_TYPE_PARAM,
  2291. 0, // dwIndex
  2292. szInnerContentType,
  2293. &cbData
  2294. )) goto GetInnerContentTypeError;
  2295. *pdwInnerContentType = OIDToMsgType(szInnerContentType);
  2296. }
  2297. if (0 == (dwFlags & CMSG_LENGTH_ONLY_FLAG)) {
  2298. if (dwMsgType == CMSG_ENVELOPED ||
  2299. dwMsgType == CMSG_SIGNED_AND_ENVELOPED) {
  2300. if (pDecryptPara == NULL) goto InvalidArg;
  2301. if (!GetXchgCertAndDecrypt(
  2302. pDecryptPara,
  2303. hMsg,
  2304. ppXchgCert
  2305. )) goto GetXchgCertAndDecryptError;
  2306. }
  2307. if (dwMsgType == CMSG_SIGNED ||
  2308. dwMsgType == CMSG_SIGNED_AND_ENVELOPED) {
  2309. if (pVerifyPara == NULL) goto InvalidArg;
  2310. if (!GetSignerCertAndVerify(
  2311. pVerifyPara,
  2312. dwSignerIndex,
  2313. hMsg,
  2314. ppSignerCert
  2315. )) goto GetSignerCertAndVerifyError;
  2316. }
  2317. }
  2318. if (pcbDecoded) {
  2319. fResult = CryptMsgGetParam(
  2320. hMsg,
  2321. CMSG_CONTENT_PARAM,
  2322. 0, // dwIndex
  2323. pbDecoded,
  2324. &cbDecoded
  2325. );
  2326. *pcbDecoded = cbDecoded;
  2327. if (!fResult) goto ErrorReturn; // NO_TRACE
  2328. }
  2329. fResult = TRUE;
  2330. CommonReturn:
  2331. if (hMsg)
  2332. CryptMsgClose(hMsg); // for success, preserves LastError
  2333. return fResult;
  2334. ErrorReturn:
  2335. if (ppXchgCert && *ppXchgCert) {
  2336. CertFreeCertificateContext(*ppXchgCert);
  2337. *ppXchgCert = NULL;
  2338. }
  2339. if (ppSignerCert && *ppSignerCert) {
  2340. CertFreeCertificateContext(*ppSignerCert);
  2341. *ppSignerCert = NULL;
  2342. }
  2343. fResult = FALSE;
  2344. goto CommonReturn;
  2345. SET_ERROR(InvalidArg, E_INVALIDARG)
  2346. TRACE_ERROR(OpenToDecodeError)
  2347. TRACE_ERROR(UpdateError)
  2348. TRACE_ERROR(GetTypeError)
  2349. TRACE_ERROR(GetInnerContentTypeError)
  2350. SET_ERROR(UnexpectedMsgTypeError, CRYPT_E_UNEXPECTED_MSG_TYPE)
  2351. TRACE_ERROR(GetXchgCertAndDecryptError)
  2352. TRACE_ERROR(GetSignerCertAndVerifyError)
  2353. }
  2354. #ifdef ENABLE_SCA_STREAM_TEST
  2355. typedef struct _STREAM_OUTPUT_INFO {
  2356. BYTE *pbData;
  2357. DWORD cbData;
  2358. DWORD cFinal;
  2359. } STREAM_OUTPUT_INFO, *PSTREAM_OUTPUT_INFO;
  2360. static void *SCARealloc(
  2361. IN void *pvOrg,
  2362. IN size_t cbBytes
  2363. )
  2364. {
  2365. void *pv;
  2366. if (NULL == (pv = pvOrg ? realloc(pvOrg, cbBytes) : malloc(cbBytes)))
  2367. SetLastError((DWORD) E_OUTOFMEMORY);
  2368. return pv;
  2369. }
  2370. static BOOL WINAPI StreamOutputCallback(
  2371. IN const void *pvArg,
  2372. IN BYTE *pbData,
  2373. IN DWORD cbData,
  2374. IN BOOL fFinal
  2375. )
  2376. {
  2377. BOOL fResult = TRUE;
  2378. PSTREAM_OUTPUT_INFO pInfo = (PSTREAM_OUTPUT_INFO) pvArg;
  2379. if (fFinal)
  2380. pInfo->cFinal++;
  2381. if (cbData) {
  2382. BYTE *pb;
  2383. if (NULL == (pb = (BYTE *) SCARealloc(pInfo->pbData,
  2384. pInfo->cbData + cbData)))
  2385. fResult = FALSE;
  2386. else {
  2387. memcpy(pb + pInfo->cbData, pbData, cbData);
  2388. pInfo->pbData = pb;
  2389. pInfo->cbData += cbData;
  2390. }
  2391. }
  2392. return fResult;
  2393. }
  2394. //+-------------------------------------------------------------------------
  2395. // Encodes the message using streaming.
  2396. //--------------------------------------------------------------------------
  2397. static BOOL StreamEncodeMsg(
  2398. IN DWORD dwMsgEncodingType,
  2399. IN DWORD dwFlags,
  2400. IN DWORD dwMsgType,
  2401. IN void *pvMsgEncodeInfo,
  2402. IN DWORD cToBeEncoded,
  2403. IN const BYTE *rgpbToBeEncoded[],
  2404. IN DWORD rgcbToBeEncoded[],
  2405. IN BOOL fBareContent,
  2406. IN DWORD dwInnerContentType,
  2407. OUT BYTE *pbEncodedBlob,
  2408. IN OUT DWORD *pcbEncodedBlob
  2409. )
  2410. {
  2411. BOOL fResult;
  2412. HCRYPTMSG hMsg = NULL;
  2413. DWORD cbEncodedBlob;
  2414. LPCSTR pszInnerContentOID;
  2415. STREAM_OUTPUT_INFO OutputInfo;
  2416. memset(&OutputInfo, 0, sizeof(OutputInfo));
  2417. CMSG_STREAM_INFO StreamInfo;
  2418. memset(&StreamInfo, 0, sizeof(StreamInfo));
  2419. StreamInfo.pfnStreamOutput = StreamOutputCallback;
  2420. StreamInfo.pvArg = (void *) &OutputInfo;
  2421. if (dwFlags & SCA_INDEFINITE_STREAM_FLAG)
  2422. StreamInfo.cbContent = CMSG_INDEFINITE_LENGTH;
  2423. else {
  2424. DWORD c;
  2425. DWORD cbTotal = 0;
  2426. DWORD *pcb;
  2427. for (c = cToBeEncoded, pcb = rgcbToBeEncoded; c > 0; c--, pcb++)
  2428. cbTotal += *pcb;
  2429. StreamInfo.cbContent = cbTotal;
  2430. }
  2431. dwFlags &= ~(SCA_STREAM_ENABLE_FLAG | SCA_INDEFINITE_STREAM_FLAG);
  2432. // Get input length and default return length to 0
  2433. if (pbEncodedBlob == NULL)
  2434. cbEncodedBlob = 0;
  2435. else
  2436. cbEncodedBlob = *pcbEncodedBlob;
  2437. *pcbEncodedBlob = 0;
  2438. if (dwInnerContentType)
  2439. pszInnerContentOID = MsgTypeToOID(dwInnerContentType);
  2440. else
  2441. pszInnerContentOID = NULL;
  2442. {
  2443. if (fBareContent)
  2444. dwFlags |= CMSG_BARE_CONTENT_FLAG;
  2445. if (NULL == (hMsg = CryptMsgOpenToEncode(
  2446. dwMsgEncodingType,
  2447. dwFlags,
  2448. dwMsgType,
  2449. pvMsgEncodeInfo,
  2450. (LPSTR) pszInnerContentOID,
  2451. &StreamInfo
  2452. ))) goto OpenToEncodeError;
  2453. if (0 == cToBeEncoded) {
  2454. if (!CryptMsgUpdate(
  2455. hMsg,
  2456. NULL, // pbData
  2457. 0, // cbData
  2458. TRUE // fFinal
  2459. )) goto UpdateError;
  2460. } else {
  2461. DWORD c;
  2462. DWORD *pcb;
  2463. const BYTE **ppb;
  2464. for (c = cToBeEncoded,
  2465. pcb = rgcbToBeEncoded,
  2466. ppb = rgpbToBeEncoded; c > 0; c--, pcb++, ppb++) {
  2467. BYTE *pbAlloc = NULL;
  2468. const BYTE *pb = *ppb;
  2469. if (NULL == pb) {
  2470. pbAlloc = (BYTE *) SCAAlloc(*pcb);
  2471. pb = pbAlloc;
  2472. }
  2473. fResult = CryptMsgUpdate(
  2474. hMsg,
  2475. pb,
  2476. *pcb,
  2477. c == 1 // fFinal
  2478. );
  2479. if (pbAlloc)
  2480. SCAFree(pbAlloc);
  2481. if (!fResult)
  2482. goto UpdateError;
  2483. }
  2484. }
  2485. if (1 != OutputInfo.cFinal)
  2486. goto BadStreamFinalCountError;
  2487. *pcbEncodedBlob = OutputInfo.cbData;
  2488. if (pbEncodedBlob) {
  2489. if (cbEncodedBlob < OutputInfo.cbData) {
  2490. SetLastError((DWORD) ERROR_MORE_DATA);
  2491. goto ErrorReturn; // no trace
  2492. }
  2493. if (OutputInfo.cbData > 0)
  2494. memcpy(pbEncodedBlob, OutputInfo.pbData, OutputInfo.cbData);
  2495. }
  2496. }
  2497. fResult = TRUE;
  2498. CommonReturn:
  2499. SCAFree(OutputInfo.pbData);
  2500. if (hMsg)
  2501. CryptMsgClose(hMsg); // for success, preserves LastError
  2502. return fResult;
  2503. ErrorReturn:
  2504. fResult = FALSE;
  2505. goto CommonReturn;
  2506. TRACE_ERROR(OpenToEncodeError)
  2507. TRACE_ERROR(UpdateError)
  2508. SET_ERROR(BadStreamFinalCountError, E_UNEXPECTED)
  2509. }
  2510. //+-------------------------------------------------------------------------
  2511. // Decodes the message types:
  2512. // CMSG_SIGNED
  2513. // CMSG_ENVELOPED
  2514. // CMSG_SIGNED_AND_ENVELOPED
  2515. // CMSG_HASHED
  2516. //
  2517. // Uses streaming.
  2518. //--------------------------------------------------------------------------
  2519. static BOOL StreamDecodeMsg(
  2520. IN DWORD dwMsgTypeFlags,
  2521. IN OPTIONAL PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  2522. IN OPTIONAL PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  2523. IN DWORD dwSignerIndex,
  2524. IN const BYTE *pbEncodedBlob,
  2525. IN DWORD cbEncodedBlob,
  2526. IN DWORD cToBeEncoded,
  2527. IN OPTIONAL const BYTE *rgpbToBeEncoded[],
  2528. IN OPTIONAL DWORD rgcbToBeEncoded[],
  2529. IN DWORD dwPrevInnerContentType,
  2530. OUT OPTIONAL DWORD *pdwMsgType,
  2531. OUT OPTIONAL DWORD *pdwInnerContentType,
  2532. OUT OPTIONAL BYTE *pbDecoded,
  2533. IN OUT OPTIONAL DWORD *pcbDecoded,
  2534. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert,
  2535. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  2536. )
  2537. {
  2538. BOOL fResult;
  2539. HCRYPTMSG hMsg = NULL;
  2540. DWORD cbData;
  2541. DWORD dwMsgType;
  2542. DWORD dwFlags;
  2543. HCRYPTPROV hCryptProv;
  2544. DWORD dwMsgEncodingType;
  2545. DWORD cbDecoded;
  2546. STREAM_OUTPUT_INFO OutputInfo;
  2547. memset(&OutputInfo, 0, sizeof(OutputInfo));
  2548. CMSG_STREAM_INFO StreamInfo;
  2549. memset(&StreamInfo, 0, sizeof(StreamInfo));
  2550. StreamInfo.pfnStreamOutput = StreamOutputCallback;
  2551. StreamInfo.pvArg = (void *) &OutputInfo;
  2552. StreamInfo.cbContent = CMSG_INDEFINITE_LENGTH;
  2553. // Get input length and default return length to 0
  2554. cbDecoded = 0;
  2555. if (pcbDecoded) {
  2556. if (pbDecoded)
  2557. cbDecoded = *pcbDecoded;
  2558. *pcbDecoded = 0;
  2559. }
  2560. // Default optional return values to 0
  2561. if (pdwMsgType)
  2562. *pdwMsgType = 0;
  2563. if (pdwInnerContentType)
  2564. *pdwInnerContentType = 0;
  2565. if (ppXchgCert)
  2566. *ppXchgCert = NULL;
  2567. if (ppSignerCert)
  2568. *ppSignerCert = NULL;
  2569. if (pDecryptPara) {
  2570. assert(pDecryptPara->cbSize >=
  2571. STRUCT_CBSIZE(CRYPT_DECRYPT_MESSAGE_PARA, rghCertStore));
  2572. if (pDecryptPara->cbSize <
  2573. STRUCT_CBSIZE(CRYPT_DECRYPT_MESSAGE_PARA, rghCertStore))
  2574. goto InvalidArg;
  2575. }
  2576. if (pVerifyPara) {
  2577. assert(pVerifyPara->cbSize == sizeof(CRYPT_VERIFY_MESSAGE_PARA));
  2578. if (pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA))
  2579. goto InvalidArg;
  2580. hCryptProv = pVerifyPara->hCryptProv;
  2581. dwMsgEncodingType = pVerifyPara->dwMsgAndCertEncodingType;
  2582. } else {
  2583. hCryptProv = 0;
  2584. if (NULL == pDecryptPara) goto InvalidArg;
  2585. dwMsgEncodingType = pDecryptPara->dwMsgAndCertEncodingType;
  2586. }
  2587. dwMsgEncodingType &= ~SCA_STREAM_ENABLE_FLAG;
  2588. if (cToBeEncoded)
  2589. dwFlags = CMSG_DETACHED_FLAG;
  2590. else
  2591. dwFlags = 0;
  2592. if (dwPrevInnerContentType) {
  2593. dwMsgType = dwPrevInnerContentType;
  2594. if (CMSG_DATA == dwMsgType)
  2595. dwMsgType = 0;
  2596. } else
  2597. dwMsgType = 0;
  2598. if (NULL == (hMsg = CryptMsgOpenToDecode(
  2599. dwMsgEncodingType,
  2600. dwFlags,
  2601. dwMsgType,
  2602. hCryptProv,
  2603. NULL, // pRecipientInfo
  2604. &StreamInfo
  2605. ))) goto OpenToDecodeError;
  2606. {
  2607. #if 1
  2608. DWORD cbDelta = cbEncodedBlob / 10;
  2609. #else
  2610. DWORD cbDelta = 1;
  2611. #endif
  2612. DWORD cbRemain = cbEncodedBlob;
  2613. const BYTE *pb = pbEncodedBlob;
  2614. do {
  2615. DWORD cb;
  2616. if (cbRemain > cbDelta)
  2617. cb = cbDelta;
  2618. else
  2619. cb = cbRemain;
  2620. if (!CryptMsgUpdate(
  2621. hMsg,
  2622. pb,
  2623. cb,
  2624. cbRemain == cb // fFinal
  2625. )) goto UpdateError;
  2626. pb += cb;
  2627. cbRemain -= cb;
  2628. } while (0 != cbRemain);
  2629. }
  2630. if (cToBeEncoded) {
  2631. // Detached signature
  2632. DWORD c;
  2633. DWORD *pcb;
  2634. const BYTE **ppb;
  2635. for (c = cToBeEncoded,
  2636. pcb = rgcbToBeEncoded,
  2637. ppb = rgpbToBeEncoded; c > 0; c--, pcb++, ppb++) {
  2638. if (!CryptMsgUpdate(
  2639. hMsg,
  2640. *ppb,
  2641. *pcb,
  2642. c == 1 // fFinal
  2643. )) goto UpdateError;
  2644. }
  2645. }
  2646. cbData = sizeof(dwMsgType);
  2647. dwMsgType = 0;
  2648. if (!CryptMsgGetParam(
  2649. hMsg,
  2650. CMSG_TYPE_PARAM,
  2651. 0, // dwIndex
  2652. &dwMsgType,
  2653. &cbData
  2654. )) goto GetTypeError;
  2655. if (pdwMsgType)
  2656. *pdwMsgType = dwMsgType;
  2657. if (0 == ((1 << dwMsgType) & dwMsgTypeFlags))
  2658. goto UnexpectedMsgTypeError;
  2659. if (pdwInnerContentType) {
  2660. char szInnerContentType[128];
  2661. cbData = sizeof(szInnerContentType);
  2662. if (!CryptMsgGetParam(
  2663. hMsg,
  2664. CMSG_INNER_CONTENT_TYPE_PARAM,
  2665. 0, // dwIndex
  2666. szInnerContentType,
  2667. &cbData
  2668. )) goto GetInnerContentTypeError;
  2669. *pdwInnerContentType = OIDToMsgType(szInnerContentType);
  2670. }
  2671. if (pcbDecoded && 0 == cbDecoded &&
  2672. NULL == ppXchgCert && NULL == ppSignerCert &&
  2673. dwMsgType != CMSG_ENVELOPED)
  2674. ; // Length only
  2675. else {
  2676. if (dwMsgType == CMSG_ENVELOPED ||
  2677. dwMsgType == CMSG_SIGNED_AND_ENVELOPED) {
  2678. if (pDecryptPara == NULL) goto InvalidArg;
  2679. if (!GetXchgCertAndDecrypt(
  2680. pDecryptPara,
  2681. hMsg,
  2682. ppXchgCert
  2683. )) goto GetXchgCertAndDecryptError;
  2684. }
  2685. if (dwMsgType == CMSG_SIGNED ||
  2686. dwMsgType == CMSG_SIGNED_AND_ENVELOPED) {
  2687. if (pVerifyPara == NULL) goto InvalidArg;
  2688. if (!GetSignerCertAndVerify(
  2689. pVerifyPara,
  2690. dwSignerIndex,
  2691. hMsg,
  2692. ppSignerCert
  2693. )) goto GetSignerCertAndVerifyError;
  2694. }
  2695. }
  2696. if (1 != OutputInfo.cFinal)
  2697. goto BadStreamFinalCountError;
  2698. if (pcbDecoded) {
  2699. *pcbDecoded = OutputInfo.cbData;
  2700. if (pbDecoded) {
  2701. if (cbDecoded < OutputInfo.cbData) {
  2702. SetLastError((DWORD) ERROR_MORE_DATA);
  2703. goto ErrorReturn; // no trace
  2704. }
  2705. if (OutputInfo.cbData > 0)
  2706. memcpy(pbDecoded, OutputInfo.pbData, OutputInfo.cbData);
  2707. }
  2708. }
  2709. fResult = TRUE;
  2710. CommonReturn:
  2711. SCAFree(OutputInfo.pbData);
  2712. if (hMsg)
  2713. CryptMsgClose(hMsg); // for success, preserves LastError
  2714. return fResult;
  2715. ErrorReturn:
  2716. if (ppXchgCert && *ppXchgCert) {
  2717. CertFreeCertificateContext(*ppXchgCert);
  2718. *ppXchgCert = NULL;
  2719. }
  2720. if (ppSignerCert && *ppSignerCert) {
  2721. CertFreeCertificateContext(*ppSignerCert);
  2722. *ppSignerCert = NULL;
  2723. }
  2724. fResult = FALSE;
  2725. goto CommonReturn;
  2726. SET_ERROR(InvalidArg, E_INVALIDARG)
  2727. TRACE_ERROR(OpenToDecodeError)
  2728. TRACE_ERROR(UpdateError)
  2729. TRACE_ERROR(GetTypeError)
  2730. TRACE_ERROR(GetInnerContentTypeError)
  2731. SET_ERROR(UnexpectedMsgTypeError, CRYPT_E_UNEXPECTED_MSG_TYPE)
  2732. TRACE_ERROR(GetXchgCertAndDecryptError)
  2733. TRACE_ERROR(GetSignerCertAndVerifyError)
  2734. SET_ERROR(BadStreamFinalCountError, E_UNEXPECTED)
  2735. }
  2736. #endif // ENABLE_SCA_STREAM_TEST
  2737. //+-------------------------------------------------------------------------
  2738. // Decodes the HASHED message type
  2739. //
  2740. // For detached hash (cToBeHashed != 0), then, pcbDecoded == NULL.
  2741. //--------------------------------------------------------------------------
  2742. static BOOL DecodeHashMsg(
  2743. IN PCRYPT_HASH_MESSAGE_PARA pHashPara,
  2744. IN const BYTE *pbEncodedBlob,
  2745. IN DWORD cbEncodedBlob,
  2746. IN DWORD cToBeHashed,
  2747. IN OPTIONAL const BYTE *rgpbToBeHashed[],
  2748. IN OPTIONAL DWORD rgcbToBeHashed[],
  2749. OUT OPTIONAL BYTE *pbDecoded,
  2750. IN OUT OPTIONAL DWORD *pcbDecoded,
  2751. OUT OPTIONAL BYTE *pbComputedHash,
  2752. IN OUT OPTIONAL DWORD *pcbComputedHash
  2753. )
  2754. {
  2755. BOOL fResult;
  2756. HCRYPTMSG hMsg = NULL;
  2757. DWORD cbData;
  2758. DWORD dwMsgType;
  2759. DWORD dwFlags;
  2760. HCRYPTPROV hCryptProv;
  2761. DWORD dwMsgEncodingType;
  2762. DWORD cbDecoded;
  2763. DWORD cbComputedHash;
  2764. // Get input lengths and default return lengths to 0
  2765. cbDecoded = 0;
  2766. if (pcbDecoded) {
  2767. if (pbDecoded)
  2768. cbDecoded = *pcbDecoded;
  2769. *pcbDecoded = 0;
  2770. }
  2771. cbComputedHash = 0;
  2772. if (pcbComputedHash) {
  2773. if (pbComputedHash)
  2774. cbComputedHash = *pcbComputedHash;
  2775. *pcbComputedHash = 0;
  2776. }
  2777. assert(pHashPara->cbSize == sizeof(CRYPT_HASH_MESSAGE_PARA));
  2778. if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
  2779. goto InvalidArg;
  2780. hCryptProv = pHashPara->hCryptProv;
  2781. dwMsgEncodingType = pHashPara->dwMsgEncodingType;
  2782. if (cToBeHashed)
  2783. dwFlags = CMSG_DETACHED_FLAG;
  2784. else if (0 == cbDecoded && NULL == pcbComputedHash)
  2785. dwFlags = CMSG_LENGTH_ONLY_FLAG;
  2786. else
  2787. dwFlags = 0;
  2788. if (NULL == (hMsg = CryptMsgOpenToDecode(
  2789. dwMsgEncodingType,
  2790. dwFlags,
  2791. 0, // dwMsgType
  2792. hCryptProv,
  2793. NULL, // pRecipientInfo
  2794. NULL // pStreamInfo
  2795. ))) goto OpenToDecodeError;
  2796. if (!CryptMsgUpdate(
  2797. hMsg,
  2798. pbEncodedBlob,
  2799. cbEncodedBlob,
  2800. TRUE // fFinal
  2801. )) goto UpdateError;
  2802. if (cToBeHashed) {
  2803. // Detached signature or hash
  2804. DWORD c = 0;
  2805. DWORD *pcb;
  2806. const BYTE **ppb;
  2807. for (c = cToBeHashed,
  2808. pcb = rgcbToBeHashed,
  2809. ppb = rgpbToBeHashed; c > 0; c--, pcb++, ppb++) {
  2810. if (!CryptMsgUpdate(
  2811. hMsg,
  2812. *ppb,
  2813. *pcb,
  2814. c == 1 // fFinal
  2815. )) goto UpdateError;
  2816. }
  2817. }
  2818. cbData = sizeof(dwMsgType);
  2819. dwMsgType = 0;
  2820. if (!CryptMsgGetParam(
  2821. hMsg,
  2822. CMSG_TYPE_PARAM,
  2823. 0, // dwIndex
  2824. &dwMsgType,
  2825. &cbData
  2826. )) goto GetTypeError;
  2827. if (dwMsgType != CMSG_HASHED)
  2828. goto UnexpectedMsgTypeError;
  2829. if (0 == (dwFlags & CMSG_LENGTH_ONLY_FLAG)) {
  2830. if (!CryptMsgControl(
  2831. hMsg,
  2832. 0, // dwFlags
  2833. CMSG_CTRL_VERIFY_HASH,
  2834. NULL // pvCtrlPara
  2835. )) goto ControlError;
  2836. }
  2837. fResult = TRUE;
  2838. if (pcbDecoded) {
  2839. fResult = CryptMsgGetParam(
  2840. hMsg,
  2841. CMSG_CONTENT_PARAM,
  2842. 0, // dwIndex
  2843. pbDecoded,
  2844. &cbDecoded
  2845. );
  2846. *pcbDecoded = cbDecoded;
  2847. }
  2848. if (pcbComputedHash) {
  2849. DWORD dwErr = 0;
  2850. BOOL fResult2;
  2851. if (!fResult)
  2852. dwErr = GetLastError();
  2853. fResult2 = CryptMsgGetParam(
  2854. hMsg,
  2855. CMSG_COMPUTED_HASH_PARAM,
  2856. 0, // dwIndex
  2857. pbComputedHash,
  2858. &cbComputedHash
  2859. );
  2860. *pcbComputedHash = cbComputedHash;
  2861. if (!fResult2)
  2862. fResult = FALSE;
  2863. else if (!fResult)
  2864. SetLastError(dwErr);
  2865. }
  2866. if (!fResult)
  2867. goto ErrorReturn; // NO_TRACE
  2868. CommonReturn:
  2869. if (hMsg)
  2870. CryptMsgClose(hMsg); // for success, preserves LastError
  2871. return fResult;
  2872. ErrorReturn:
  2873. fResult = FALSE;
  2874. goto CommonReturn;
  2875. SET_ERROR(InvalidArg, E_INVALIDARG)
  2876. TRACE_ERROR(OpenToDecodeError)
  2877. TRACE_ERROR(UpdateError)
  2878. TRACE_ERROR(GetTypeError)
  2879. SET_ERROR(UnexpectedMsgTypeError, CRYPT_E_UNEXPECTED_MSG_TYPE)
  2880. TRACE_ERROR(ControlError)
  2881. }
  2882. //+-------------------------------------------------------------------------
  2883. // Get certificate for and verify the message's signer.
  2884. //--------------------------------------------------------------------------
  2885. static BOOL GetSignerCertAndVerify(
  2886. IN PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  2887. IN DWORD dwSignerIndex,
  2888. IN HCRYPTMSG hMsg,
  2889. OUT OPTIONAL PCCERT_CONTEXT *ppSignerCert
  2890. )
  2891. {
  2892. BOOL fResult;
  2893. BOOL fNoSigner = FALSE;
  2894. PCERT_INFO pSignerId = NULL;
  2895. PCCERT_CONTEXT pSignerCert = NULL;
  2896. HCERTSTORE hMsgCertStore = NULL;
  2897. DWORD dwLastError = 0;
  2898. {
  2899. // First, get count of signers in the message and verify the
  2900. // dwSignerIndex
  2901. DWORD cSigner = 0;
  2902. DWORD cbData = sizeof(cSigner);
  2903. if (!CryptMsgGetParam(
  2904. hMsg,
  2905. CMSG_SIGNER_COUNT_PARAM,
  2906. 0, // dwIndex
  2907. &cSigner,
  2908. &cbData
  2909. )) goto ErrorReturn;
  2910. if (cSigner <= dwSignerIndex) fNoSigner = TRUE;
  2911. }
  2912. if (!fNoSigner) {
  2913. // Allocate and get the CERT_INFO containing the SignerId
  2914. // (Issuer and SerialNumber)
  2915. if (NULL == (pSignerId = (PCERT_INFO) AllocAndMsgGetParam(
  2916. hMsg,
  2917. CMSG_SIGNER_CERT_INFO_PARAM,
  2918. dwSignerIndex
  2919. ))) goto ErrorReturn;
  2920. }
  2921. // Open a cert store initialized with certs and CRLs from the message
  2922. hMsgCertStore = CertOpenStore(
  2923. CERT_STORE_PROV_MSG,
  2924. #ifdef ENABLE_SCA_STREAM_TEST
  2925. pVerifyPara->dwMsgAndCertEncodingType &= ~SCA_STREAM_ENABLE_FLAG,
  2926. #else
  2927. pVerifyPara->dwMsgAndCertEncodingType,
  2928. #endif
  2929. pVerifyPara->hCryptProv,
  2930. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  2931. hMsg // pvPara
  2932. );
  2933. if (hMsgCertStore == NULL) goto ErrorReturn;
  2934. if (pVerifyPara->pfnGetSignerCertificate)
  2935. pSignerCert = pVerifyPara->pfnGetSignerCertificate(
  2936. pVerifyPara->pvGetArg,
  2937. #ifdef ENABLE_SCA_STREAM_TEST
  2938. pVerifyPara->dwMsgAndCertEncodingType &= ~SCA_STREAM_ENABLE_FLAG,
  2939. #else
  2940. pVerifyPara->dwMsgAndCertEncodingType,
  2941. #endif
  2942. pSignerId,
  2943. hMsgCertStore
  2944. );
  2945. else
  2946. pSignerCert = NullGetSignerCertificate(
  2947. NULL,
  2948. #ifdef ENABLE_SCA_STREAM_TEST
  2949. pVerifyPara->dwMsgAndCertEncodingType &= ~SCA_STREAM_ENABLE_FLAG,
  2950. #else
  2951. pVerifyPara->dwMsgAndCertEncodingType,
  2952. #endif
  2953. pSignerId,
  2954. hMsgCertStore
  2955. );
  2956. if (fNoSigner) goto NoSigner;
  2957. if (pSignerCert == NULL) goto ErrorReturn;
  2958. #ifdef CMS_PKCS7
  2959. {
  2960. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA CtrlPara;
  2961. memset(&CtrlPara, 0, sizeof(CtrlPara));
  2962. CtrlPara.cbSize = sizeof(CtrlPara);
  2963. // CtrlPara.hCryptProv =
  2964. CtrlPara.dwSignerIndex = dwSignerIndex;
  2965. CtrlPara.dwSignerType = CMSG_VERIFY_SIGNER_CERT;
  2966. CtrlPara.pvSigner = (void *) pSignerCert;
  2967. if (!CryptMsgControl(
  2968. hMsg,
  2969. 0, // dwFlags
  2970. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  2971. &CtrlPara
  2972. )) {
  2973. if (CRYPT_E_MISSING_PUBKEY_PARA != GetLastError())
  2974. goto ErrorReturn;
  2975. else {
  2976. PCCERT_CHAIN_CONTEXT pChainContext;
  2977. CERT_CHAIN_PARA ChainPara;
  2978. // Build a chain. Hopefully, the signer inherit's its public key
  2979. // parameters from up the chain
  2980. memset(&ChainPara, 0, sizeof(ChainPara));
  2981. ChainPara.cbSize = sizeof(ChainPara);
  2982. if (CertGetCertificateChain(
  2983. NULL, // hChainEngine
  2984. pSignerCert,
  2985. NULL, // pTime
  2986. hMsgCertStore,
  2987. &ChainPara,
  2988. CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL,
  2989. NULL, // pvReserved
  2990. &pChainContext
  2991. ))
  2992. CertFreeCertificateChain(pChainContext);
  2993. // Try again. Hopefully the above chain building updated the
  2994. // signer's context property with the missing public key
  2995. // parameters
  2996. if (!CryptMsgControl(
  2997. hMsg,
  2998. 0, // dwFlags
  2999. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  3000. &CtrlPara)) goto ErrorReturn;
  3001. }
  3002. }
  3003. }
  3004. #else
  3005. if (!CryptMsgControl(
  3006. hMsg,
  3007. 0, // dwFlags
  3008. CMSG_CTRL_VERIFY_SIGNATURE,
  3009. pSignerCert->pCertInfo
  3010. )) goto ErrorReturn;
  3011. #endif // CMS_PKCS7
  3012. if (ppSignerCert)
  3013. *ppSignerCert = pSignerCert;
  3014. else
  3015. CertFreeCertificateContext(pSignerCert);
  3016. fResult = TRUE;
  3017. goto CommonReturn;
  3018. NoSigner:
  3019. SetLastError((DWORD) CRYPT_E_NO_SIGNER);
  3020. ErrorReturn:
  3021. if (pSignerCert)
  3022. CertFreeCertificateContext(pSignerCert);
  3023. if (ppSignerCert)
  3024. *ppSignerCert = NULL;
  3025. fResult = FALSE;
  3026. dwLastError = GetLastError();
  3027. CommonReturn:
  3028. if (pSignerId)
  3029. SCAFree(pSignerId);
  3030. if (hMsgCertStore)
  3031. CertCloseStore(hMsgCertStore, 0);
  3032. if (dwLastError)
  3033. SetLastError(dwLastError);
  3034. return fResult;
  3035. }
  3036. #ifdef CMS_PKCS7
  3037. static BOOL GetXchgCertAndDecrypt(
  3038. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  3039. IN HCRYPTMSG hMsg,
  3040. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert
  3041. )
  3042. {
  3043. BOOL fResult;
  3044. PCMSG_CMS_RECIPIENT_INFO pRecipientInfo = NULL;
  3045. PCCERT_CONTEXT pXchgCert = NULL;
  3046. DWORD cRecipient;
  3047. DWORD cbData;
  3048. DWORD dwRecipientIdx;
  3049. // Get # of CMS recipients in the message.
  3050. cbData = sizeof(cRecipient);
  3051. cRecipient = 0;
  3052. fResult = CryptMsgGetParam(
  3053. hMsg,
  3054. CMSG_CMS_RECIPIENT_COUNT_PARAM,
  3055. 0, // dwIndex
  3056. &cRecipient,
  3057. &cbData
  3058. );
  3059. if (!fResult) goto ErrorReturn;
  3060. if (cRecipient == 0) {
  3061. SetLastError((DWORD) CRYPT_E_RECIPIENT_NOT_FOUND);
  3062. goto ErrorReturn;
  3063. }
  3064. // Loop through the recipients in the message until we find a
  3065. // recipient cert in one of the stores with either the
  3066. // CERT_KEY_CONTEXT_PROP_ID or CERT_KEY_PROV_INFO_PROP_ID.
  3067. for (dwRecipientIdx = 0; dwRecipientIdx < cRecipient; dwRecipientIdx++) {
  3068. DWORD dwRecipientChoice;
  3069. PCMSG_KEY_TRANS_RECIPIENT_INFO pKeyTrans = NULL;
  3070. PCMSG_KEY_AGREE_RECIPIENT_INFO pKeyAgree = NULL;
  3071. DWORD cRecipientEncryptedKeys;
  3072. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *ppRecipientEncryptedKey = NULL;
  3073. DWORD dwRecipientEncryptedKeyIndex;
  3074. pRecipientInfo = (PCMSG_CMS_RECIPIENT_INFO) AllocAndMsgGetParam(
  3075. hMsg,
  3076. CMSG_CMS_RECIPIENT_INFO_PARAM,
  3077. dwRecipientIdx
  3078. );
  3079. if (pRecipientInfo == NULL) goto ErrorReturn;
  3080. dwRecipientChoice = pRecipientInfo->dwRecipientChoice;
  3081. switch (dwRecipientChoice) {
  3082. case CMSG_KEY_TRANS_RECIPIENT:
  3083. pKeyTrans = pRecipientInfo->pKeyTrans;
  3084. cRecipientEncryptedKeys = 1;
  3085. break;
  3086. case CMSG_KEY_AGREE_RECIPIENT:
  3087. pKeyAgree = pRecipientInfo->pKeyAgree;
  3088. if (CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY !=
  3089. pKeyAgree->dwOriginatorChoice) {
  3090. SCAFree(pRecipientInfo);
  3091. pRecipientInfo = NULL;
  3092. continue;
  3093. }
  3094. cRecipientEncryptedKeys = pKeyAgree->cRecipientEncryptedKeys;
  3095. ppRecipientEncryptedKey = pKeyAgree->rgpRecipientEncryptedKeys;
  3096. break;
  3097. default:
  3098. SCAFree(pRecipientInfo);
  3099. pRecipientInfo = NULL;
  3100. continue;
  3101. }
  3102. for (dwRecipientEncryptedKeyIndex = 0;
  3103. dwRecipientEncryptedKeyIndex < cRecipientEncryptedKeys;
  3104. dwRecipientEncryptedKeyIndex++) {
  3105. PCERT_ID pRecipientId;
  3106. DWORD dwStoreIdx;
  3107. if (CMSG_KEY_TRANS_RECIPIENT == dwRecipientChoice)
  3108. pRecipientId = &pKeyTrans->RecipientId;
  3109. else {
  3110. pRecipientId =
  3111. &ppRecipientEncryptedKey[
  3112. dwRecipientEncryptedKeyIndex]->RecipientId;
  3113. }
  3114. for (dwStoreIdx = 0;
  3115. dwStoreIdx < pDecryptPara->cCertStore; dwStoreIdx++) {
  3116. pXchgCert = CertFindCertificateInStore(
  3117. pDecryptPara->rghCertStore[dwStoreIdx],
  3118. pDecryptPara->dwMsgAndCertEncodingType,
  3119. 0, // dwFindFlags
  3120. CERT_FIND_CERT_ID,
  3121. pRecipientId,
  3122. NULL // pPrevCertContext
  3123. );
  3124. if (pXchgCert) {
  3125. HCRYPTPROV hCryptProv;
  3126. DWORD dwKeySpec;
  3127. BOOL fDidCryptAcquire;
  3128. DWORD dwAcquireFlags;
  3129. dwAcquireFlags = CRYPT_ACQUIRE_USE_PROV_INFO_FLAG;
  3130. if (pDecryptPara->cbSize >=
  3131. STRUCT_CBSIZE(CRYPT_DECRYPT_MESSAGE_PARA, dwFlags)
  3132. &&
  3133. (pDecryptPara->dwFlags &
  3134. CRYPT_MESSAGE_SILENT_KEYSET_FLAG))
  3135. dwAcquireFlags |= CRYPT_ACQUIRE_SILENT_FLAG;
  3136. fResult = CryptAcquireCertificatePrivateKey(
  3137. pXchgCert,
  3138. dwAcquireFlags,
  3139. NULL, // pvReserved
  3140. &hCryptProv,
  3141. &dwKeySpec,
  3142. &fDidCryptAcquire
  3143. );
  3144. if (fResult) {
  3145. if (CMSG_KEY_TRANS_RECIPIENT == dwRecipientChoice) {
  3146. CMSG_CTRL_KEY_TRANS_DECRYPT_PARA Para;
  3147. memset(&Para, 0, sizeof(Para));
  3148. Para.cbSize = sizeof(Para);
  3149. Para.hCryptProv = hCryptProv;
  3150. Para.dwKeySpec = dwKeySpec;
  3151. Para.pKeyTrans = pKeyTrans;
  3152. Para.dwRecipientIndex = dwRecipientIdx;
  3153. fResult = CryptMsgControl(
  3154. hMsg,
  3155. 0, // dwFlags
  3156. CMSG_CTRL_KEY_TRANS_DECRYPT,
  3157. &Para
  3158. );
  3159. } else {
  3160. CMSG_CTRL_KEY_AGREE_DECRYPT_PARA Para;
  3161. memset(&Para, 0, sizeof(Para));
  3162. Para.cbSize = sizeof(Para);
  3163. Para.hCryptProv = hCryptProv;
  3164. Para.dwKeySpec = dwKeySpec;
  3165. Para.pKeyAgree = pKeyAgree;
  3166. Para.dwRecipientIndex = dwRecipientIdx;
  3167. Para.dwRecipientEncryptedKeyIndex =
  3168. dwRecipientEncryptedKeyIndex;
  3169. Para.OriginatorPublicKey =
  3170. pKeyAgree->OriginatorPublicKeyInfo.PublicKey;
  3171. fResult = CryptMsgControl(
  3172. hMsg,
  3173. 0, // dwFlags
  3174. CMSG_CTRL_KEY_AGREE_DECRYPT,
  3175. &Para
  3176. );
  3177. }
  3178. if (fDidCryptAcquire) {
  3179. DWORD dwErr = GetLastError();
  3180. CryptReleaseContext(hCryptProv, 0);
  3181. SetLastError(dwErr);
  3182. }
  3183. if (fResult) {
  3184. if (ppXchgCert)
  3185. *ppXchgCert = pXchgCert;
  3186. else
  3187. CertFreeCertificateContext(pXchgCert);
  3188. goto CommonReturn;
  3189. } else
  3190. goto ErrorReturn;
  3191. }
  3192. CertFreeCertificateContext(pXchgCert);
  3193. pXchgCert = NULL;
  3194. }
  3195. }
  3196. }
  3197. SCAFree(pRecipientInfo);
  3198. pRecipientInfo = NULL;
  3199. }
  3200. SetLastError((DWORD) CRYPT_E_NO_DECRYPT_CERT);
  3201. ErrorReturn:
  3202. if (pXchgCert)
  3203. CertFreeCertificateContext(pXchgCert);
  3204. if (ppXchgCert)
  3205. *ppXchgCert = NULL;
  3206. fResult = FALSE;
  3207. CommonReturn:
  3208. if (pRecipientInfo)
  3209. SCAFree(pRecipientInfo);
  3210. return fResult;
  3211. }
  3212. #else
  3213. //+-------------------------------------------------------------------------
  3214. // Get a certificate with a key provider property for one of the message's
  3215. // recipients and use to decrypt the message.
  3216. //--------------------------------------------------------------------------
  3217. static BOOL GetXchgCertAndDecrypt(
  3218. IN PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
  3219. IN HCRYPTMSG hMsg,
  3220. OUT OPTIONAL PCCERT_CONTEXT *ppXchgCert
  3221. )
  3222. {
  3223. BOOL fResult;
  3224. PCERT_INFO pRecipientId = NULL;
  3225. PCCERT_CONTEXT pXchgCert = NULL;
  3226. DWORD cRecipient;
  3227. DWORD cbData;
  3228. DWORD dwRecipientIdx;
  3229. DWORD dwStoreIdx;
  3230. // Get # of recipients in the message.
  3231. cbData = sizeof(cRecipient);
  3232. cRecipient = 0;
  3233. fResult = CryptMsgGetParam(
  3234. hMsg,
  3235. CMSG_RECIPIENT_COUNT_PARAM,
  3236. 0, // dwIndex
  3237. &cRecipient,
  3238. &cbData
  3239. );
  3240. if (!fResult) goto ErrorReturn;
  3241. if (cRecipient == 0) {
  3242. SetLastError((DWORD) CRYPT_E_RECIPIENT_NOT_FOUND);
  3243. goto ErrorReturn;
  3244. }
  3245. // Loop through the recipients in the message until we find a
  3246. // recipient cert in one of the stores with either the
  3247. // CERT_KEY_CONTEXT_PROP_ID or CERT_KEY_PROV_INFO_PROP_ID.
  3248. for (dwRecipientIdx = 0; dwRecipientIdx < cRecipient; dwRecipientIdx++) {
  3249. // Allocate and get the CERT_INFO containing the RecipientId
  3250. // (Issuer and SerialNumber)
  3251. pRecipientId = (PCERT_INFO) AllocAndMsgGetParam(
  3252. hMsg,
  3253. CMSG_RECIPIENT_INFO_PARAM,
  3254. dwRecipientIdx
  3255. );
  3256. if (pRecipientId == NULL) goto ErrorReturn;
  3257. for (dwStoreIdx = 0;
  3258. dwStoreIdx < pDecryptPara->cCertStore; dwStoreIdx++) {
  3259. pXchgCert = CertGetSubjectCertificateFromStore(
  3260. pDecryptPara->rghCertStore[dwStoreIdx],
  3261. pDecryptPara->dwMsgAndCertEncodingType,
  3262. pRecipientId
  3263. );
  3264. if (pXchgCert) {
  3265. CMSG_CTRL_DECRYPT_PARA Para;
  3266. BOOL fDidCryptAcquire;
  3267. Para.cbSize = sizeof(CMSG_CTRL_DECRYPT_PARA);
  3268. fResult = CryptAcquireCertificatePrivateKey(
  3269. pXchgCert,
  3270. CRYPT_ACQUIRE_USE_PROV_INFO_FLAG,
  3271. NULL, // pvReserved
  3272. &Para.hCryptProv,
  3273. &Para.dwKeySpec,
  3274. &fDidCryptAcquire
  3275. );
  3276. if (fResult) {
  3277. Para.dwRecipientIndex = dwRecipientIdx;
  3278. fResult = CryptMsgControl(
  3279. hMsg,
  3280. 0, // dwFlags
  3281. CMSG_CTRL_DECRYPT,
  3282. &Para
  3283. );
  3284. if (fDidCryptAcquire) {
  3285. DWORD dwErr = GetLastError();
  3286. CryptReleaseContext(Para.hCryptProv, 0);
  3287. SetLastError(dwErr);
  3288. }
  3289. if (fResult) {
  3290. if (ppXchgCert)
  3291. *ppXchgCert = pXchgCert;
  3292. else
  3293. CertFreeCertificateContext(pXchgCert);
  3294. goto CommonReturn;
  3295. } else
  3296. goto ErrorReturn;
  3297. }
  3298. CertFreeCertificateContext(pXchgCert);
  3299. pXchgCert = NULL;
  3300. }
  3301. }
  3302. SCAFree(pRecipientId);
  3303. pRecipientId = NULL;
  3304. }
  3305. SetLastError((DWORD) CRYPT_E_NO_DECRYPT_CERT);
  3306. ErrorReturn:
  3307. if (pXchgCert)
  3308. CertFreeCertificateContext(pXchgCert);
  3309. if (ppXchgCert)
  3310. *ppXchgCert = NULL;
  3311. fResult = FALSE;
  3312. CommonReturn:
  3313. if (pRecipientId)
  3314. SCAFree(pRecipientId);
  3315. return fResult;
  3316. }
  3317. #endif // CMS_PKCS7
  3318. //+-------------------------------------------------------------------------
  3319. // Allocate and get the CMSG_SIGNER_CERT_INFO_PARAM or CMSG_RECIPIENT_INFO_PARAM
  3320. // from the message
  3321. //--------------------------------------------------------------------------
  3322. static void * AllocAndMsgGetParam(
  3323. IN HCRYPTMSG hMsg,
  3324. IN DWORD dwParamType,
  3325. IN DWORD dwIndex
  3326. )
  3327. {
  3328. BOOL fResult;
  3329. void *pvData;
  3330. DWORD cbData;
  3331. // First get the length of the CertId's CERT_INFO
  3332. cbData = 0;
  3333. CryptMsgGetParam(
  3334. hMsg,
  3335. dwParamType,
  3336. dwIndex,
  3337. NULL, // pvData
  3338. &cbData
  3339. );
  3340. if (cbData == 0) return NULL;
  3341. pvData = SCAAlloc(cbData);
  3342. if (pvData == NULL) return NULL;
  3343. fResult = CryptMsgGetParam(
  3344. hMsg,
  3345. dwParamType,
  3346. dwIndex,
  3347. pvData,
  3348. &cbData
  3349. );
  3350. if (fResult)
  3351. return pvData;
  3352. else {
  3353. SCAFree(pvData);
  3354. return NULL;
  3355. }
  3356. }