Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

19413 lines
597 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: wincrmsg.cpp
  8. //
  9. // Contents: Cryptographic Message APIs
  10. //
  11. // APIs:
  12. //
  13. // History: 14-Feb-96 kevinr created
  14. //
  15. //--------------------------------------------------------------------------
  16. #include "global.hxx"
  17. HCRYPTASN1MODULE ICM_hAsn1Module;
  18. COssDecodeInfoNode::~COssDecodeInfoNode()
  19. {
  20. PkiAsn1FreeInfo( ICM_GetDecoder(), m_data.iPDU, m_data.pvPDU);
  21. }
  22. CBlobNode::~CBlobNode()
  23. {
  24. ICM_Free( m_data.pbData);
  25. }
  26. CSignerNode::~CSignerNode()
  27. {
  28. ICM_Free( m_data.blob.pbData);
  29. delete m_data.pUnauthAttrList;
  30. }
  31. CHashNode::~CHashNode()
  32. {
  33. ICM_Free( m_data.HashBlob.pbData);
  34. if (m_data.hHash)
  35. CryptDestroyHash( m_data.hHash);
  36. }
  37. inline
  38. BOOL
  39. ICM_IsAddInnerContentOctetWrapper(
  40. IN PCRYPT_MSG_INFO pcmi
  41. )
  42. {
  43. #ifdef CMS_PKCS7
  44. return NULL == pcmi->pszInnerContentObjID ||
  45. (pcmi->dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG);
  46. #else
  47. return NULL == pcmi->pszInnerContentObjID;
  48. #endif // CMS_PKCS7
  49. }
  50. DWORD
  51. ICM_GetTaggedBlobCount(
  52. IN CBlobList *pBlobList,
  53. IN BYTE bTag
  54. )
  55. {
  56. DWORD dwCount = 0;
  57. CBlobNode *pBlobNode;
  58. for (pBlobNode=pBlobList->Head(); pBlobNode; pBlobNode=pBlobNode->Next()) {
  59. if (bTag == *(pBlobNode->Data()->pbData))
  60. dwCount++;
  61. }
  62. return dwCount;
  63. }
  64. // Advances index past other Tags
  65. CBlobNode *
  66. ICM_GetTaggedBlobAndAdvanceIndex(
  67. IN CBlobList *pBlobList,
  68. IN BYTE bTag, // 0 => any
  69. IN OUT DWORD *pdwIndex
  70. )
  71. {
  72. DWORD dwIndex = *pdwIndex;
  73. CBlobNode *pBlobNode;
  74. DWORD i;
  75. for (i=dwIndex, pBlobNode=pBlobList->Head();
  76. pBlobNode;
  77. pBlobNode=pBlobNode->Next()) {
  78. if (bTag && bTag != *(pBlobNode->Data()->pbData)) {
  79. // Advance index past other tags
  80. dwIndex++;
  81. } else {
  82. if (0 == i)
  83. break;
  84. else
  85. i--;
  86. }
  87. }
  88. *pdwIndex = dwIndex;
  89. return pBlobNode;
  90. }
  91. ObjectID aoidMessages[] = {
  92. { 7, {1,2,840,113549,1,7,1}}, // data
  93. { 7, {1,2,840,113549,1,7,2}}, // signed
  94. { 7, {1,2,840,113549,1,7,3}}, // enveloped
  95. { 7, {1,2,840,113549,1,7,4}}, // signed and enveloped
  96. { 7, {1,2,840,113549,1,7,5}}, // digested
  97. { 7, {1,2,840,113549,1,7,6}}, // encrypted
  98. { 7, {1,2,840,113549,1,7,7}} // dual-signed
  99. };
  100. #define COUNTOF_aoidMessages (sizeof(aoidMessages)/sizeof(aoidMessages[0]))
  101. ObjectID oidMessageDigest = { 7, {1,2,840,113549,1,9,4}};
  102. const LPSTR apszObjIdPKCS7[] = {
  103. szOID_RSA_data ,
  104. szOID_RSA_signedData ,
  105. szOID_RSA_envelopedData ,
  106. szOID_RSA_signEnvData ,
  107. szOID_RSA_digestedData ,
  108. szOID_RSA_encryptedData
  109. };
  110. const DWORD COUNTOF_apszObjIdPKCS7 = (sizeof(apszObjIdPKCS7)/sizeof(apszObjIdPKCS7[0]));
  111. //#if COUNTOF_apszObjIdPKCS7 - (sizeof(apszObjIdPKCS7)/sizeof(apszObjIdPKCS7[0]))
  112. //#error COUNTOF_apszObjIdPKCS7 wrong
  113. //#endif
  114. const LPSTR pszObjIdDataType = szOID_RSA_data;
  115. const LPSTR pszObjIdContentType = szOID_RSA_contentType;
  116. const LPSTR pszObjIdMessageDigest = szOID_RSA_messageDigest;
  117. int aiPduNum[] = {
  118. OctetStringType_PDU,
  119. SignedData_PDU,
  120. #ifdef CMS_PKCS7
  121. CmsEnvelopedData_PDU,
  122. #else
  123. EnvelopedData_PDU,
  124. #endif // CMS_PKCS7
  125. SignedAndEnvelopedData_PDU,
  126. DigestedData_PDU,
  127. EncryptedData_PDU
  128. };
  129. /*
  130. // Should be able to use aiPduNum, but first entry of aiPduNum
  131. // seems to need to be 0. ????
  132. int aiPduNum2[] = {
  133. OctetStringType_PDU,
  134. SignedData_PDU,
  135. #ifdef CMS_PKCS7
  136. CmsEnvelopedData_PDU,
  137. #else
  138. EnvelopedData_PDU,
  139. #endif // CMS_PKCS7
  140. SignedAndEnvelopedData_PDU,
  141. DigestedData_PDU,
  142. EncryptedData_PDU
  143. };
  144. */
  145. typedef struct _CRYPT_ABLOB {
  146. DWORD cBlob;
  147. PCRYPT_DATA_BLOB pBlob;
  148. } CRYPT_ABLOB, *PCRYPT_ABLOB;
  149. // Here is a table for keeping straight which phases are legal in which
  150. // situations:
  151. //
  152. // detached !detached
  153. // encode FO,FF FF
  154. // decode FF,SO,SF FF
  155. //
  156. enum Phases {
  157. PHASE_FIRST_ONGOING = 1,
  158. PHASE_FIRST_FINAL = 2,
  159. PHASE_SECOND_ONGOING = 3,
  160. PHASE_SECOND_FINAL = 4
  161. };
  162. BOOL
  163. WINAPI
  164. ICM_GetAnyData(
  165. IN Any *pAny,
  166. OUT void *pvData,
  167. IN OUT DWORD *pcbData);
  168. WINAPI
  169. ICM_GetOssContentInfoData(
  170. IN ContentInfo *poci,
  171. OUT void *pvData,
  172. IN OUT DWORD *pcbData);
  173. BOOL
  174. WINAPI
  175. ICM_GetSignerParamEncoding(
  176. IN PCRYPT_MSG_INFO pcmi,
  177. IN DWORD dwIndex,
  178. IN DWORD dwParamType,
  179. OUT PVOID pvData,
  180. IN OUT PDWORD pcbData);
  181. BOOL
  182. WINAPI
  183. ICM_GetALGORITHM_IDENTIFIER(
  184. IN AlgorithmIdentifier *paiOss,
  185. OUT void *pvData,
  186. IN OUT DWORD *pcbData);
  187. //+-------------------------------------------------------------------------
  188. // Lock and unlock HCRYPTMSG functions
  189. //--------------------------------------------------------------------------
  190. inline
  191. void
  192. ICM_Lock(
  193. IN PCRYPT_MSG_INFO pcmi
  194. )
  195. {
  196. EnterCriticalSection( &pcmi->CriticalSection);
  197. }
  198. inline
  199. void
  200. ICM_Unlock(
  201. IN PCRYPT_MSG_INFO pcmi
  202. )
  203. {
  204. LeaveCriticalSection( &pcmi->CriticalSection);
  205. }
  206. //+-------------------------------------------------------------------------
  207. // allocation and free routines
  208. //--------------------------------------------------------------------------
  209. void *
  210. WINAPI
  211. ICM_Alloc(
  212. IN size_t cb)
  213. {
  214. void *pv;
  215. if (NULL == (pv = malloc(cb)))
  216. goto mallocError;
  217. ErrorReturn:
  218. return pv;
  219. SET_ERROR(mallocError,E_OUTOFMEMORY)
  220. }
  221. void *
  222. WINAPI
  223. ICM_AllocZero(
  224. IN size_t cb)
  225. {
  226. void *pv;
  227. // Should map to LocalAlloc( ZERO_INIT).
  228. if (NULL != (pv = ICM_Alloc(cb)))
  229. memset( pv, 0, cb);
  230. return pv;
  231. }
  232. void *
  233. WINAPI
  234. ICM_ReAlloc(
  235. IN void *pvOrg,
  236. IN size_t cb)
  237. {
  238. void *pv;
  239. if (NULL == (pv = pvOrg ? realloc( pvOrg, cb) : malloc( cb)))
  240. goto allocError;
  241. ErrorReturn:
  242. return pv;
  243. SET_ERROR(allocError,E_OUTOFMEMORY)
  244. }
  245. void
  246. WINAPI
  247. ICM_Free(
  248. IN void *pv)
  249. {
  250. if (pv)
  251. free(pv);
  252. }
  253. // Stack allocations
  254. // NB: Use heap allocs on DBG so we can more easily catch buffer over-runs, etc.
  255. #if DBG
  256. #define ICM_AllocA ICM_Alloc
  257. #define ICM_FreeA ICM_Free
  258. #else
  259. #define ICM_AllocA ICM_Alloc
  260. #define ICM_FreeA ICM_Free
  261. // The following defines work fine on NT, but seem to have problems on Win95
  262. // REASON: unknown
  263. //#define ICM_AllocA(s) alloca(((s)+7))
  264. //#define ICM_FreeA(p)
  265. #endif
  266. void *
  267. WINAPI
  268. ICM_AllocZeroA(
  269. IN size_t cbBytes)
  270. {
  271. void *pv;
  272. if (NULL != (pv = ICM_AllocA(cbBytes)))
  273. memset( pv, 0, cbBytes);
  274. return pv;
  275. }
  276. void *ICM_DupMem(
  277. IN void *pvIn,
  278. IN size_t cb)
  279. {
  280. void *pv = NULL;
  281. if (pvIn) {
  282. if (NULL != (pv = ICM_Alloc(cb)))
  283. memcpy( pv, pvIn, cb);
  284. } else {
  285. SetLastError((DWORD) E_INVALIDARG);
  286. }
  287. return pv;
  288. }
  289. size_t ICM_StrLen(const char *pszIn)
  290. {
  291. return pszIn ? strlen(pszIn) : 0;
  292. }
  293. BOOL
  294. WINAPI
  295. ICM_AppendBlob(
  296. PCRYPT_DATA_BLOB pblob,
  297. const BYTE *pbIn,
  298. DWORD cbIn)
  299. {
  300. BOOL fRet;
  301. PBYTE pb = NULL;
  302. if (NULL == (pb = (PBYTE)ICM_ReAlloc(
  303. pblob->pbData,
  304. pblob->cbData + cbIn)))
  305. goto AllocError;
  306. memcpy( pb + pblob->cbData, pbIn, cbIn);
  307. pblob->pbData = pb;
  308. pblob->cbData += cbIn;
  309. fRet = TRUE;
  310. CommonReturn:
  311. return fRet;
  312. ErrorReturn:
  313. fRet = FALSE;
  314. goto CommonReturn;
  315. TRACE_ERROR(AllocError)
  316. }
  317. #ifdef CMS_PKCS7
  318. STATIC
  319. BOOL
  320. WINAPI
  321. ICM_InsertMsgAlloc(
  322. IN PCRYPT_MSG_INFO pcmi,
  323. IN void *pv
  324. )
  325. {
  326. BOOL fRet;
  327. CBlobNode *pnBlob = NULL;
  328. CRYPT_DATA_BLOB blob;
  329. if (NULL == pcmi->pFreeList) {
  330. if (NULL == (pcmi->pFreeList = new CBlobList))
  331. goto OutOfMemory;
  332. }
  333. if (NULL == (pnBlob = new CBlobNode))
  334. goto OutOfMemory;
  335. blob.cbData = 0;
  336. blob.pbData = (BYTE *) pv;
  337. pnBlob->SetData(&blob);
  338. pcmi->pFreeList->InsertTail(pnBlob);
  339. fRet = TRUE;
  340. CommonReturn:
  341. return fRet;
  342. ErrorReturn:
  343. fRet = FALSE;
  344. goto CommonReturn;
  345. SET_ERROR(OutOfMemory,E_OUTOFMEMORY)
  346. }
  347. #endif // CMS_PKCS7
  348. // Allocates algorithm parameters and inserts into the message's free
  349. // list before doing the ICM_Asn1ToAlgorithmIdentifier
  350. STATIC
  351. BOOL
  352. WINAPI
  353. ICM_MsgAsn1ToAlgorithmIdentifier(
  354. IN PCRYPT_MSG_INFO pcmi,
  355. IN PCRYPT_ALGORITHM_IDENTIFIER pai,
  356. IN OUT AlgorithmIdentifier *pOssAlgId
  357. )
  358. {
  359. #ifdef CMS_PKCS7
  360. CRYPT_ALGORITHM_IDENTIFIER ai;
  361. if (pcmi && 0 < pai->Parameters.cbData) {
  362. ai = *pai;
  363. if (NULL == (ai.Parameters.pbData = (BYTE *) ICM_DupMem(
  364. ai.Parameters.pbData, ai.Parameters.cbData)))
  365. return FALSE;
  366. if (!ICM_InsertMsgAlloc(pcmi, ai.Parameters.pbData)) {
  367. ICM_Free(ai.Parameters.pbData);
  368. return FALSE;
  369. }
  370. pai = &ai;
  371. }
  372. #endif // CMS_PKCS7
  373. return ICM_Asn1ToAlgorithmIdentifier(pai, pOssAlgId);
  374. }
  375. //+-------------------------------------------------------------------------
  376. //
  377. //--------------------------------------------------------------------------
  378. STATIC BOOL WINAPI
  379. ICM_PkcsSignerInfoEncode(
  380. IN DWORD dwCertEncodingType,
  381. IN LPCSTR lpszStructType,
  382. IN PCMSG_SIGNER_INFO pInfo,
  383. OUT PBYTE pbEncoded,
  384. IN OUT PDWORD pcbEncoded);
  385. STATIC BOOL WINAPI
  386. ICM_PkcsSignerInfoDecode(
  387. IN DWORD dwEncodingType,
  388. IN LPCSTR lpszStructType,
  389. IN const BYTE *pbEncoded,
  390. IN DWORD cbEncoded,
  391. IN DWORD dwFlags,
  392. OUT PCMSG_SIGNER_INFO pInfo,
  393. IN OUT DWORD *pcbInfo);
  394. STATIC BOOL WINAPI
  395. ICM_CmsSignerInfoEncode(
  396. IN DWORD dwCertEncodingType,
  397. IN LPCSTR lpszStructType,
  398. IN PCMSG_CMS_SIGNER_INFO pInfo,
  399. OUT PBYTE pbEncoded,
  400. IN OUT PDWORD pcbEncoded);
  401. STATIC BOOL WINAPI
  402. ICM_CmsSignerInfoDecode(
  403. IN DWORD dwEncodingType,
  404. IN LPCSTR lpszStructType,
  405. IN const BYTE *pbEncoded,
  406. IN DWORD cbEncoded,
  407. IN DWORD dwFlags,
  408. OUT PCMSG_CMS_SIGNER_INFO pInfo,
  409. IN OUT DWORD *pcbInfo);
  410. #ifdef OSS_CRYPT_ASN1
  411. #define ASN1_OID_OFFSET 10000 +
  412. #define ASN1_OID_PREFIX "OssCryptAsn1."
  413. #else
  414. #define ASN1_OID_OFFSET
  415. #define ASN1_OID_PREFIX
  416. #endif // OSS_CRYPT_ASN1
  417. STATIC
  418. const
  419. CRYPT_OID_FUNC_ENTRY
  420. ICM_EncodeFuncTable[] = {
  421. ASN1_OID_OFFSET PKCS7_SIGNER_INFO, ICM_PkcsSignerInfoEncode,
  422. ASN1_OID_OFFSET CMS_SIGNER_INFO, ICM_CmsSignerInfoEncode,
  423. };
  424. #define ICM_ENCODE_FUNC_COUNT \
  425. (sizeof(ICM_EncodeFuncTable) / sizeof(ICM_EncodeFuncTable[0]))
  426. STATIC
  427. const
  428. CRYPT_OID_FUNC_ENTRY
  429. ICM_DecodeFuncTable[] = {
  430. ASN1_OID_OFFSET PKCS7_SIGNER_INFO, ICM_PkcsSignerInfoDecode,
  431. ASN1_OID_OFFSET CMS_SIGNER_INFO, ICM_CmsSignerInfoDecode,
  432. };
  433. #define ICM_DECODE_FUNC_COUNT \
  434. (sizeof(ICM_DecodeFuncTable) / sizeof(ICM_DecodeFuncTable[0]))
  435. #ifdef CMS_PKCS7
  436. static HCRYPTOIDFUNCSET hOldStyleGenEncryptKeyFuncSet;
  437. static HCRYPTOIDFUNCSET hOldStyleExportEncryptKeyFuncSet;
  438. static HCRYPTOIDFUNCSET hOldStyleImportEncryptKeyFuncSet;
  439. static HCRYPTOIDFUNCSET hGenContentEncryptKeyFuncSet;
  440. static HCRYPTOIDFUNCSET hExportKeyTransFuncSet;
  441. static HCRYPTOIDFUNCSET hExportKeyAgreeFuncSet;
  442. static HCRYPTOIDFUNCSET hExportMailListFuncSet;
  443. static HCRYPTOIDFUNCSET hImportKeyTransFuncSet;
  444. static HCRYPTOIDFUNCSET hImportKeyAgreeFuncSet;
  445. static HCRYPTOIDFUNCSET hImportMailListFuncSet;
  446. //+-------------------------------------------------------------------------
  447. // GenContentEncryptKey OID Installable Functions
  448. //--------------------------------------------------------------------------
  449. BOOL
  450. WINAPI
  451. ICM_DefaultGenContentEncryptKey(
  452. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  453. IN DWORD dwFlags,
  454. IN OPTIONAL void *pvReserved
  455. );
  456. static const CRYPT_OID_FUNC_ENTRY GenContentEncryptKeyFuncTable[] = {
  457. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultGenContentEncryptKey
  458. };
  459. //+-------------------------------------------------------------------------
  460. // ExportKeyTrans OID Installable Functions
  461. //--------------------------------------------------------------------------
  462. BOOL
  463. WINAPI
  464. ICM_DefaultExportKeyTrans(
  465. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  466. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  467. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
  468. IN DWORD dwFlags,
  469. IN OPTIONAL void *pvReserved
  470. );
  471. static const CRYPT_OID_FUNC_ENTRY ExportKeyTransFuncTable[] = {
  472. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultExportKeyTrans
  473. };
  474. //+-------------------------------------------------------------------------
  475. // ExportKeyAgree OID Installable Functions
  476. //--------------------------------------------------------------------------
  477. BOOL
  478. WINAPI
  479. ICM_DefaultExportKeyAgree(
  480. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  481. IN PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgreeEncodeInfo,
  482. IN OUT PCMSG_KEY_AGREE_ENCRYPT_INFO pKeyAgreeEncryptInfo,
  483. IN DWORD dwFlags,
  484. IN OPTIONAL void *pvReserved
  485. );
  486. static const CRYPT_OID_FUNC_ENTRY ExportKeyAgreeFuncTable[] = {
  487. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultExportKeyAgree
  488. };
  489. //+-------------------------------------------------------------------------
  490. // ExportMailList OID Installable Functions
  491. //--------------------------------------------------------------------------
  492. BOOL
  493. WINAPI
  494. ICM_DefaultExportMailList(
  495. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  496. IN PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailListEncodeInfo,
  497. IN OUT PCMSG_MAIL_LIST_ENCRYPT_INFO pMailListEncryptInfo,
  498. IN DWORD dwFlags,
  499. IN OPTIONAL void *pvReserved
  500. );
  501. static const CRYPT_OID_FUNC_ENTRY ExportMailListFuncTable[] = {
  502. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultExportMailList
  503. };
  504. //+-------------------------------------------------------------------------
  505. // ImportKeyTrans OID Installable Functions
  506. //--------------------------------------------------------------------------
  507. BOOL
  508. WINAPI
  509. ICM_DefaultImportKeyTrans(
  510. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  511. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  512. IN DWORD dwFlags,
  513. IN OPTIONAL void *pvReserved,
  514. OUT HCRYPTKEY *phContentEncryptKey
  515. );
  516. static const CRYPT_OID_FUNC_ENTRY ImportKeyTransFuncTable[] = {
  517. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultImportKeyTrans
  518. };
  519. //+-------------------------------------------------------------------------
  520. // ImportKeyAgree OID Installable Functions
  521. //--------------------------------------------------------------------------
  522. BOOL
  523. WINAPI
  524. ICM_DefaultImportKeyAgree(
  525. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  526. IN PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA pKeyAgreeDecryptPara,
  527. IN DWORD dwFlags,
  528. IN OPTIONAL void *pvReserved,
  529. OUT HCRYPTKEY *phContentEncryptKey
  530. );
  531. static const CRYPT_OID_FUNC_ENTRY ImportKeyAgreeFuncTable[] = {
  532. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultImportKeyAgree
  533. };
  534. //+-------------------------------------------------------------------------
  535. // ImportMailList OID Installable Functions
  536. //--------------------------------------------------------------------------
  537. BOOL
  538. WINAPI
  539. ICM_DefaultImportMailList(
  540. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  541. IN PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA pMailListDecryptPara,
  542. IN DWORD dwFlags,
  543. IN OPTIONAL void *pvReserved,
  544. OUT HCRYPTKEY *phContentEncryptKey
  545. );
  546. static const CRYPT_OID_FUNC_ENTRY ImportMailListFuncTable[] = {
  547. CMSG_DEFAULT_INSTALLABLE_FUNC_OID, ICM_DefaultImportMailList
  548. };
  549. #else
  550. static HCRYPTOIDFUNCSET hGenEncryptKeyFuncSet;
  551. static HCRYPTOIDFUNCSET hExportEncryptKeyFuncSet;
  552. static HCRYPTOIDFUNCSET hImportEncryptKeyFuncSet;
  553. #endif // CMS_PKCS7
  554. //+-------------------------------------------------------------------------
  555. // GenEncryptKey OID Installable Functions (OldStyle)
  556. //--------------------------------------------------------------------------
  557. // rgcbEncryptParameters[1] contains the dwEncryptFlags passed to
  558. // ICM_DefaultExportEncryptKey
  559. BOOL
  560. WINAPI
  561. ICM_DefaultGenEncryptKey(
  562. IN OUT HCRYPTPROV *phCryptProv,
  563. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  564. IN PVOID pvEncryptAuxInfo,
  565. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  566. IN PFN_CMSG_ALLOC pfnAlloc,
  567. OUT HCRYPTKEY *phEncryptKey,
  568. OUT PBYTE *ppbEncryptParameters,
  569. OUT DWORD rgcbEncryptParameters[2]);
  570. static const CRYPT_OID_FUNC_ENTRY GenEncryptKeyFuncTable[] = {
  571. szOID_OIWSEC_desCBC, ICM_DefaultGenEncryptKey,
  572. szOID_RSA_DES_EDE3_CBC, ICM_DefaultGenEncryptKey,
  573. szOID_RSA_RC2CBC, ICM_DefaultGenEncryptKey,
  574. szOID_RSA_RC4, ICM_DefaultGenEncryptKey
  575. };
  576. #define GEN_ENCRYPT_KEY_FUNC_COUNT (sizeof(GenEncryptKeyFuncTable) / \
  577. sizeof(GenEncryptKeyFuncTable[0]))
  578. //+-------------------------------------------------------------------------
  579. // ExportEncryptKey OID Installable Functions (OldStyle)
  580. //--------------------------------------------------------------------------
  581. // rgcbData[1] is the dwEncryptFlags passed from ICM_DefaultGenEncryptKey
  582. BOOL
  583. WINAPI
  584. ICM_DefaultExportEncryptKey(
  585. IN HCRYPTPROV hCryptProv,
  586. IN HCRYPTKEY hEncryptKey,
  587. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  588. OUT PBYTE pbData,
  589. IN OUT DWORD rgcbData[2]);
  590. static const CRYPT_OID_FUNC_ENTRY ExportEncryptKeyFuncTable[] = {
  591. szOID_RSA_RSA, ICM_DefaultExportEncryptKey
  592. };
  593. #define EXPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ExportEncryptKeyFuncTable) / \
  594. sizeof(ExportEncryptKeyFuncTable[0]))
  595. //+-------------------------------------------------------------------------
  596. // ImportEncryptKey OID Installable Functions (OldStyle)
  597. //--------------------------------------------------------------------------
  598. BOOL
  599. WINAPI
  600. ICM_DefaultImportEncryptKey(
  601. IN HCRYPTPROV hCryptProv,
  602. IN DWORD dwKeySpec,
  603. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  604. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  605. IN PBYTE pbEncodedKey,
  606. IN DWORD cbEncodedKey,
  607. OUT HCRYPTKEY *phEncryptKey);
  608. static const CRYPT_OID_FUNC_ENTRY ImportEncryptKeyFuncTable[] = {
  609. szOID_OIWSEC_desCBC, ICM_DefaultImportEncryptKey,
  610. szOID_RSA_DES_EDE3_CBC, ICM_DefaultImportEncryptKey,
  611. szOID_RSA_RC2CBC, ICM_DefaultImportEncryptKey,
  612. szOID_RSA_RC4, ICM_DefaultImportEncryptKey
  613. };
  614. #define IMPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ImportEncryptKeyFuncTable) / \
  615. sizeof(ImportEncryptKeyFuncTable[0]))
  616. #ifdef DEBUG_CRYPT_ASN1_MASTER
  617. static HMODULE hOssCryptDll = NULL;
  618. #endif // DEBUG_CRYPT_ASN1_MASTER
  619. #ifdef DEBUG_CRYPT_ASN1
  620. #define DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG 0x010
  621. #define DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG 0x020
  622. #define DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG 0x100
  623. static BOOL fGotDebugCryptAsn1Flags = FALSE;
  624. static int iDebugCryptAsn1Flags = 0;
  625. int
  626. WINAPI
  627. ICMTest_GetDebugCryptAsn1Flags();
  628. #endif // DEBUG_CRYPT_ASN1
  629. //+-------------------------------------------------------------------------
  630. // Function: CryptMsgDllMain
  631. //
  632. // Synopsis: Initialize the CryptMsg module
  633. //
  634. // Returns: FALSE iff failed
  635. //--------------------------------------------------------------------------
  636. BOOL
  637. WINAPI
  638. CryptMsgDllMain(
  639. HMODULE hInst,
  640. ULONG ulReason,
  641. LPVOID lpReserved)
  642. {
  643. BOOL fRet;
  644. switch (ulReason) {
  645. case DLL_PROCESS_ATTACH:
  646. if (!CryptInstallOIDFunctionAddress(
  647. NULL, // hModule
  648. X509_ASN_ENCODING,
  649. CRYPT_OID_ENCODE_OBJECT_FUNC,
  650. ICM_ENCODE_FUNC_COUNT,
  651. ICM_EncodeFuncTable,
  652. 0)) // dwFlags
  653. goto CryptInstallOIDFunctionAddressError;
  654. if (!CryptInstallOIDFunctionAddress(
  655. NULL, // hModule
  656. X509_ASN_ENCODING,
  657. CRYPT_OID_DECODE_OBJECT_FUNC,
  658. ICM_DECODE_FUNC_COUNT,
  659. ICM_DecodeFuncTable,
  660. 0)) // dwFlags
  661. goto CryptInstallOIDFunctionAddressError;
  662. #ifdef CMS_PKCS7
  663. if (NULL == (hOldStyleGenEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  664. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  665. 0)))
  666. goto CryptInitOIDFunctionSetError;
  667. if (NULL == (hOldStyleExportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  668. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  669. 0)))
  670. goto CryptInitOIDFunctionSetError;
  671. if (NULL == (hOldStyleImportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  672. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  673. 0)))
  674. goto CryptInitOIDFunctionSetError;
  675. if (NULL == (hGenContentEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  676. CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
  677. 0)))
  678. goto CryptInitOIDFunctionSetError;
  679. if (NULL == (hExportKeyTransFuncSet = CryptInitOIDFunctionSet(
  680. CMSG_OID_EXPORT_KEY_TRANS_FUNC,
  681. 0)))
  682. goto CryptInitOIDFunctionSetError;
  683. if (NULL == (hExportKeyAgreeFuncSet = CryptInitOIDFunctionSet(
  684. CMSG_OID_EXPORT_KEY_AGREE_FUNC,
  685. 0)))
  686. goto CryptInitOIDFunctionSetError;
  687. if (NULL == (hExportMailListFuncSet = CryptInitOIDFunctionSet(
  688. CMSG_OID_EXPORT_MAIL_LIST_FUNC,
  689. 0)))
  690. goto CryptInitOIDFunctionSetError;
  691. if (NULL == (hImportKeyTransFuncSet = CryptInitOIDFunctionSet(
  692. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  693. 0)))
  694. goto CryptInitOIDFunctionSetError;
  695. if (NULL == (hImportKeyAgreeFuncSet = CryptInitOIDFunctionSet(
  696. CMSG_OID_IMPORT_KEY_AGREE_FUNC,
  697. 0)))
  698. goto CryptInitOIDFunctionSetError;
  699. if (NULL == (hImportMailListFuncSet = CryptInitOIDFunctionSet(
  700. CMSG_OID_IMPORT_MAIL_LIST_FUNC,
  701. 0)))
  702. goto CryptInitOIDFunctionSetError;
  703. if (!CryptInstallOIDFunctionAddress(
  704. NULL, // hModule
  705. X509_ASN_ENCODING,
  706. CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
  707. 1,
  708. GenContentEncryptKeyFuncTable,
  709. 0)) // dwFlags
  710. goto CryptInstallOIDFunctionAddressError;
  711. if (!CryptInstallOIDFunctionAddress(
  712. NULL, // hModule
  713. X509_ASN_ENCODING,
  714. CMSG_OID_EXPORT_KEY_TRANS_FUNC,
  715. 1,
  716. ExportKeyTransFuncTable,
  717. 0)) // dwFlags
  718. goto CryptInstallOIDFunctionAddressError;
  719. if (!CryptInstallOIDFunctionAddress(
  720. NULL, // hModule
  721. X509_ASN_ENCODING,
  722. CMSG_OID_EXPORT_KEY_AGREE_FUNC,
  723. 1,
  724. ExportKeyAgreeFuncTable,
  725. 0)) // dwFlags
  726. goto CryptInstallOIDFunctionAddressError;
  727. if (!CryptInstallOIDFunctionAddress(
  728. NULL, // hModule
  729. X509_ASN_ENCODING,
  730. CMSG_OID_EXPORT_MAIL_LIST_FUNC,
  731. 1,
  732. ExportMailListFuncTable,
  733. 0)) // dwFlags
  734. goto CryptInstallOIDFunctionAddressError;
  735. if (!CryptInstallOIDFunctionAddress(
  736. NULL, // hModule
  737. X509_ASN_ENCODING,
  738. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  739. 1,
  740. ImportKeyTransFuncTable,
  741. 0)) // dwFlags
  742. goto CryptInstallOIDFunctionAddressError;
  743. if (!CryptInstallOIDFunctionAddress(
  744. NULL, // hModule
  745. X509_ASN_ENCODING,
  746. CMSG_OID_IMPORT_KEY_AGREE_FUNC,
  747. 1,
  748. ImportKeyAgreeFuncTable,
  749. 0)) // dwFlags
  750. goto CryptInstallOIDFunctionAddressError;
  751. if (!CryptInstallOIDFunctionAddress(
  752. NULL, // hModule
  753. X509_ASN_ENCODING,
  754. CMSG_OID_IMPORT_MAIL_LIST_FUNC,
  755. 1,
  756. ImportMailListFuncTable,
  757. 0)) // dwFlags
  758. goto CryptInstallOIDFunctionAddressError;
  759. #else
  760. if (NULL == (hGenEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  761. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  762. 0)))
  763. goto CryptInitOIDFunctionSetError;
  764. if (NULL == (hExportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  765. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  766. 0)))
  767. goto CryptInitOIDFunctionSetError;
  768. if (NULL == (hImportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  769. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  770. 0)))
  771. goto CryptInitOIDFunctionSetError;
  772. #endif // CMS_PKCS7
  773. if (!CryptInstallOIDFunctionAddress(
  774. NULL, // hModule
  775. X509_ASN_ENCODING,
  776. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  777. GEN_ENCRYPT_KEY_FUNC_COUNT,
  778. GenEncryptKeyFuncTable,
  779. 0)) // dwFlags
  780. goto CryptInstallOIDFunctionAddressError;
  781. if (!CryptInstallOIDFunctionAddress(
  782. NULL, // hModule
  783. X509_ASN_ENCODING,
  784. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  785. EXPORT_ENCRYPT_KEY_FUNC_COUNT,
  786. ExportEncryptKeyFuncTable,
  787. 0)) // dwFlags
  788. goto CryptInstallOIDFunctionAddressError;
  789. if (!CryptInstallOIDFunctionAddress(
  790. NULL, // hModule
  791. X509_ASN_ENCODING,
  792. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  793. IMPORT_ENCRYPT_KEY_FUNC_COUNT,
  794. ImportEncryptKeyFuncTable,
  795. 0)) // dwFlags
  796. goto CryptInstallOIDFunctionAddressError;
  797. #ifdef OSS_CRYPT_ASN1
  798. if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(pkcs, 0, NULL)))
  799. goto CryptInstallAsn1ModuleError;
  800. #else
  801. PKCS_Module_Startup();
  802. if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(
  803. PKCS_Module, 0, NULL))) {
  804. PKCS_Module_Cleanup();
  805. goto CryptInstallAsn1ModuleError;
  806. }
  807. #endif // OSS_CRYPT_ASN1
  808. break;
  809. case DLL_PROCESS_DETACH:
  810. #ifdef DEBUG_CRYPT_ASN1_MASTER
  811. if (hOssCryptDll) {
  812. FreeLibrary(hOssCryptDll);
  813. hOssCryptDll = NULL;
  814. }
  815. #endif // DEBUG_CRYPT_ASN1_MASTER
  816. I_CryptUninstallAsn1Module(ICM_hAsn1Module);
  817. #ifndef OSS_CRYPT_ASN1
  818. PKCS_Module_Cleanup();
  819. #endif // OSS_CRYPT_ASN1
  820. case DLL_THREAD_DETACH:
  821. default:
  822. break;
  823. }
  824. fRet = TRUE;
  825. CommonReturn:
  826. return fRet;
  827. ErrorReturn:
  828. fRet = FALSE;
  829. goto CommonReturn;
  830. TRACE_ERROR(CryptInstallAsn1ModuleError)
  831. TRACE_ERROR(CryptInstallOIDFunctionAddressError)
  832. TRACE_ERROR(CryptInitOIDFunctionSetError)
  833. lpReserved;
  834. hInst;
  835. }
  836. //+-------------------------------------------------------------------------
  837. // Utility routines
  838. //--------------------------------------------------------------------------
  839. LONG
  840. WINAPI
  841. ICM_PszOidToIndex(
  842. IN LPSTR pszOID)
  843. {
  844. LONG i;
  845. for (i=COUNTOF_apszObjIdPKCS7; i>0; i--)
  846. if (0 == strcmp( apszObjIdPKCS7[i-1], pszOID))
  847. break;
  848. return i;
  849. }
  850. LONG
  851. WINAPI
  852. ICM_ObjIdToIndex(
  853. IN ObjectID *poi)
  854. {
  855. LONG i;
  856. LONG j;
  857. for (i=COUNTOF_aoidMessages; i>0; i--) {
  858. if (aoidMessages[i-1].count == poi->count) {
  859. for (j=poi->count; j>0; j--)
  860. if (poi->value[j-1] != aoidMessages[i-1].value[j-1])
  861. goto next;
  862. break;
  863. }
  864. next:
  865. ;
  866. }
  867. return i;
  868. }
  869. BOOL
  870. WINAPI
  871. ICM_CopyOssObjectIdentifier(
  872. OUT ObjectID *poiDst,
  873. IN ObjectID *poiSrc)
  874. {
  875. USHORT i;
  876. ULONG *pulDst;
  877. ULONG *pulSrc;
  878. poiDst->count = poiSrc->count;
  879. for (i=poiSrc->count, pulDst=poiDst->value, pulSrc=poiSrc->value;
  880. i>0;
  881. i--, pulDst++, pulSrc++)
  882. *pulDst = *pulSrc;
  883. return TRUE;
  884. }
  885. BOOL
  886. WINAPI
  887. ICM_IsData(
  888. IN LPSTR pszContentType)
  889. {
  890. return !pszContentType || (0 == strcmp( pszContentType, pszObjIdDataType));
  891. }
  892. BOOL
  893. WINAPI
  894. ICM_ReverseInPlace(
  895. IN OUT PBYTE pbIn,
  896. IN const ULONG cbIn)
  897. {
  898. PBYTE pbLo;
  899. PBYTE pbHi;
  900. BYTE bTmp;
  901. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  902. bTmp = *pbHi;
  903. *pbHi = *pbLo;
  904. *pbLo = bTmp;
  905. }
  906. return TRUE;
  907. }
  908. BOOL
  909. WINAPI
  910. ICM_ReverseCopy(
  911. OUT PBYTE pbOut,
  912. IN PBYTE pbInOrg,
  913. IN ULONG cbIn)
  914. {
  915. PBYTE pbIn = pbInOrg + cbIn - 1;
  916. while (cbIn-- > 0)
  917. *pbOut++ = *pbIn--;
  918. return TRUE;
  919. }
  920. //
  921. // return FALSE iff equal
  922. //
  923. BOOL
  924. WINAPI
  925. ICM_ReverseCompare(
  926. IN PBYTE pbInOrg1,
  927. IN PBYTE pbInOrg2,
  928. IN ULONG cb)
  929. {
  930. PBYTE pbIn1 = pbInOrg1;
  931. PBYTE pbIn2 = pbInOrg2 + cb - 1;
  932. while (cb-- > 0)
  933. if (*pbIn1++ != *pbIn2--)
  934. return TRUE;
  935. return FALSE;
  936. }
  937. BOOL
  938. WINAPI
  939. ICM_CopyOut(
  940. IN PBYTE pbData,
  941. IN DWORD cbData,
  942. OUT PBYTE pbOut,
  943. IN OUT PDWORD pcbOut)
  944. {
  945. BOOL fRet = TRUE;
  946. if (pbOut) {
  947. if (*pcbOut < cbData) {
  948. SetLastError((DWORD) ERROR_MORE_DATA);
  949. fRet = FALSE;
  950. } else {
  951. memcpy(pbOut, pbData, cbData);
  952. }
  953. }
  954. *pcbOut = cbData;
  955. return fRet;
  956. }
  957. //+-------------------------------------------------------------------------
  958. // Copy out the encoding of the length octets for a specified content length.
  959. //--------------------------------------------------------------------------
  960. BOOL
  961. WINAPI
  962. ICM_GetLengthOctets(
  963. IN DWORD cbContent,
  964. OUT OPTIONAL PBYTE pbOut,
  965. IN OUT PDWORD pcbOut)
  966. {
  967. BOOL fRet;
  968. BYTE rgbLength[5];
  969. DWORD cbLength;
  970. if (cbContent < 0x80) {
  971. rgbLength[0] = (BYTE)cbContent;
  972. cbLength = 0;
  973. } else {
  974. if (cbContent > 0xffffff)
  975. cbLength = 4;
  976. else if (cbContent > 0xffff)
  977. cbLength = 3;
  978. else if (cbContent > 0xff)
  979. cbLength = 2;
  980. else
  981. cbLength = 1;
  982. if (pbOut) {
  983. rgbLength[0] = (BYTE)cbLength | 0x80;
  984. ICM_ReverseCopy( (PBYTE)(rgbLength+1), (PBYTE)&cbContent, cbLength);
  985. }
  986. }
  987. if (pbOut) {
  988. fRet = ICM_CopyOut( (PBYTE)rgbLength, cbLength+1, pbOut, pcbOut);
  989. } else {
  990. fRet = TRUE;
  991. }
  992. *pcbOut = cbLength + 1;
  993. assert(fRet);
  994. return fRet;
  995. }
  996. //+-------------------------------------------------------------------------
  997. // Copy out a buffer, prepending the identifier and length octets for a
  998. // DER encoding.
  999. //--------------------------------------------------------------------------
  1000. BOOL
  1001. WINAPI
  1002. ICM_CopyOutAddDERPrefix(
  1003. IN PBYTE pbContent,
  1004. IN DWORD cbContent,
  1005. IN OPTIONAL BYTE bTag,
  1006. OUT PBYTE pbOut,
  1007. IN OUT PDWORD pcbOut)
  1008. {
  1009. BOOL fRet;
  1010. BYTE rgbLength[5];
  1011. DWORD cbLength;
  1012. DWORD cbData;
  1013. cbLength = sizeof(rgbLength);
  1014. if (!ICM_GetLengthOctets( cbContent, (PBYTE)rgbLength, &cbLength))
  1015. goto GetLengthOctetsError;
  1016. fRet = TRUE;
  1017. cbData = 1 + cbLength + cbContent;
  1018. if (pbOut) {
  1019. if (*pcbOut < cbData) {
  1020. SetLastError((DWORD) ERROR_MORE_DATA);
  1021. fRet = FALSE;
  1022. } else {
  1023. *pbOut++ = bTag;
  1024. memcpy(pbOut, rgbLength, cbLength);
  1025. pbOut += cbLength;
  1026. memcpy(pbOut, pbContent, cbContent);
  1027. }
  1028. }
  1029. CommonReturn:
  1030. *pcbOut = cbData;
  1031. return fRet;
  1032. ErrorReturn:
  1033. cbData = 0;
  1034. fRet = FALSE;
  1035. goto CommonReturn;
  1036. TRACE_ERROR(GetLengthOctetsError) // error already set
  1037. }
  1038. BOOL
  1039. WINAPI
  1040. ICM_GetSizeFromExtra(
  1041. IN LONG lRemainExtra,
  1042. OUT PVOID pOut,
  1043. IN OUT DWORD *pcbOut)
  1044. {
  1045. BOOL fRet = TRUE;
  1046. if ((lRemainExtra < 0) && pOut) {
  1047. SetLastError((DWORD) ERROR_MORE_DATA);
  1048. fRet = FALSE;
  1049. }
  1050. *pcbOut = (DWORD)((LONG)*pcbOut - lRemainExtra);
  1051. return fRet;
  1052. }
  1053. VOID
  1054. WINAPI
  1055. ICM_SetLastError(
  1056. IN DWORD dwError)
  1057. {
  1058. if (dwError != ERROR_SUCCESS)
  1059. SetLastError( dwError);
  1060. }
  1061. //+-------------------------------------------------------------------------
  1062. // Encode an OSS struct to a blob, internally allocated
  1063. //--------------------------------------------------------------------------
  1064. BOOL
  1065. WINAPI
  1066. ICM_Asn1Encode(
  1067. ASN1uint32_t pdunum,
  1068. IN PVOID pOssInfo,
  1069. OUT PCRYPT_DATA_BLOB pBlob)
  1070. {
  1071. BOOL fRet;
  1072. PBYTE pbEncoded = NULL;
  1073. DWORD cbEncoded;
  1074. ASN1encoding_t pEnc = ICM_GetEncoder();
  1075. DWORD dwError = ERROR_SUCCESS;
  1076. if (!PkiAsn1EncodeInfo(
  1077. pEnc,
  1078. pdunum,
  1079. pOssInfo,
  1080. NULL, // pbEncoded
  1081. &cbEncoded))
  1082. goto EncodeSizeError;
  1083. if (NULL == (pbEncoded = (PBYTE)ICM_Alloc( cbEncoded)))
  1084. goto AllocError;
  1085. if (!PkiAsn1EncodeInfo(
  1086. pEnc,
  1087. pdunum,
  1088. pOssInfo,
  1089. pbEncoded,
  1090. &cbEncoded))
  1091. goto EncodeError;
  1092. fRet = TRUE;
  1093. CommonReturn:
  1094. pBlob->pbData = pbEncoded;
  1095. pBlob->cbData = cbEncoded;
  1096. ICM_SetLastError(dwError);
  1097. return fRet;
  1098. ErrorReturn:
  1099. dwError = GetLastError();
  1100. ICM_Free(pbEncoded);
  1101. pbEncoded = NULL;
  1102. fRet = FALSE;
  1103. goto CommonReturn;
  1104. TRACE_ERROR(EncodeSizeError) // error already set
  1105. TRACE_ERROR(AllocError) // error already set
  1106. TRACE_ERROR(EncodeError) // error already set
  1107. }
  1108. //+-------------------------------------------------------------------------
  1109. // Given an OID, return the CAPI algorithm
  1110. //
  1111. // Caller sets error.
  1112. //--------------------------------------------------------------------------
  1113. BOOL
  1114. WINAPI
  1115. ICM_GetCAPIFromOID(
  1116. IN DWORD dwGroupId,
  1117. IN LPSTR pszObjId,
  1118. OUT PDWORD pdwAlgId)
  1119. {
  1120. BOOL fRet;
  1121. PCCRYPT_OID_INFO pOIDInfo;
  1122. if (NULL == (pOIDInfo = CryptFindOIDInfo(
  1123. CRYPT_OID_INFO_OID_KEY,
  1124. pszObjId,
  1125. dwGroupId))) goto NotFoundError;
  1126. *pdwAlgId = pOIDInfo->Algid;
  1127. fRet = TRUE;
  1128. CommonReturn:
  1129. return fRet;
  1130. ErrorReturn:
  1131. *pdwAlgId = 0;
  1132. fRet = FALSE;
  1133. goto CommonReturn;
  1134. TRACE_ERROR(NotFoundError)
  1135. }
  1136. //+-------------------------------------------------------------------------
  1137. // Given an CRYPT_ALGORITHM_IDENTIFIER, return the CAPI algorithm
  1138. //
  1139. // Caller sets error.
  1140. //--------------------------------------------------------------------------
  1141. BOOL
  1142. WINAPI
  1143. ICM_GetCAPI(
  1144. IN DWORD dwGroupId,
  1145. IN PCRYPT_ALGORITHM_IDENTIFIER pai,
  1146. OUT PDWORD pdwAlgId)
  1147. {
  1148. return ICM_GetCAPIFromOID(dwGroupId, pai->pszObjId, pdwAlgId);
  1149. }
  1150. //+-------------------------------------------------------------------------
  1151. // Given an OSS AlgorithmIdentifier, return the OID Info
  1152. //
  1153. // Caller sets error.
  1154. //--------------------------------------------------------------------------
  1155. PCCRYPT_OID_INFO
  1156. WINAPI
  1157. ICM_GetOssOIDInfo(
  1158. IN DWORD dwGroupId,
  1159. IN AlgorithmIdentifier *poai)
  1160. {
  1161. PCCRYPT_OID_INFO pInfo;
  1162. CRYPT_ALGORITHM_IDENTIFIER ai; ZEROSTRUCT( ai);
  1163. if (!ICM_Asn1FromAlgorithmIdentifier( poai, &ai))
  1164. goto Asn1FromAlgorithmIdentifierError;
  1165. pInfo = CryptFindOIDInfo(
  1166. CRYPT_OID_INFO_OID_KEY,
  1167. ai.pszObjId,
  1168. dwGroupId);
  1169. CommonReturn:
  1170. ICM_Free( ai.pszObjId);
  1171. return pInfo;
  1172. ErrorReturn:
  1173. pInfo = NULL;
  1174. goto CommonReturn;
  1175. TRACE_ERROR(Asn1FromAlgorithmIdentifierError)
  1176. }
  1177. //+-------------------------------------------------------------------------
  1178. // Given an OSS AlgorithmIdentifier, return the CAPI algorithm
  1179. //
  1180. // Caller sets error.
  1181. //--------------------------------------------------------------------------
  1182. BOOL
  1183. WINAPI
  1184. ICM_GetOssCAPI(
  1185. IN DWORD dwGroupId,
  1186. IN AlgorithmIdentifier *poai,
  1187. OUT PDWORD pdwAlgId)
  1188. {
  1189. BOOL fRet;
  1190. CRYPT_ALGORITHM_IDENTIFIER ai; ZEROSTRUCT( ai);
  1191. if (!ICM_Asn1FromAlgorithmIdentifier( poai, &ai))
  1192. goto Asn1FromAlgorithmIdentifierError;
  1193. fRet = ICM_GetCAPI( dwGroupId, &ai, pdwAlgId);
  1194. CommonReturn:
  1195. ICM_Free( ai.pszObjId);
  1196. return fRet;
  1197. ErrorReturn:
  1198. *pdwAlgId = 0;
  1199. fRet = FALSE;
  1200. goto CommonReturn;
  1201. TRACE_ERROR(Asn1FromAlgorithmIdentifierError)
  1202. }
  1203. //+-------------------------------------------------------------------------
  1204. // Allocate and NOCOPY decode
  1205. //--------------------------------------------------------------------------
  1206. PVOID
  1207. WINAPI
  1208. ICM_AllocAndDecodeObject(
  1209. IN LPCSTR lpszStructType,
  1210. IN const BYTE *pbEncoded,
  1211. IN DWORD cbEncoded
  1212. )
  1213. {
  1214. void *pvStructInfo = NULL;
  1215. DWORD cbStructInfo;
  1216. if (!CryptDecodeObject(
  1217. X509_ASN_ENCODING,
  1218. lpszStructType,
  1219. pbEncoded,
  1220. cbEncoded,
  1221. CRYPT_DECODE_NOCOPY_FLAG,
  1222. NULL, // pvStructInfo
  1223. &cbStructInfo
  1224. ) || 0 == cbStructInfo)
  1225. goto DecodeError;
  1226. if (NULL == (pvStructInfo = ICM_Alloc(cbStructInfo)))
  1227. goto OutOfMemory;
  1228. if (!CryptDecodeObject(
  1229. X509_ASN_ENCODING,
  1230. lpszStructType,
  1231. pbEncoded,
  1232. cbEncoded,
  1233. CRYPT_DECODE_NOCOPY_FLAG,
  1234. pvStructInfo,
  1235. &cbStructInfo
  1236. ))
  1237. goto DecodeError;
  1238. CommonReturn:
  1239. return pvStructInfo;
  1240. ErrorReturn:
  1241. ICM_Free(pvStructInfo);
  1242. pvStructInfo = NULL;
  1243. goto CommonReturn;
  1244. TRACE_ERROR(DecodeError)
  1245. TRACE_ERROR(OutOfMemory)
  1246. }
  1247. PCRYPT_ALGORITHM_IDENTIFIER
  1248. WINAPI
  1249. ICM_AllocAndGetALGORITHM_IDENTIFIER(
  1250. IN AlgorithmIdentifier *paiOss)
  1251. {
  1252. PCRYPT_ALGORITHM_IDENTIFIER pai = NULL;
  1253. DWORD cbData;
  1254. if (!ICM_GetALGORITHM_IDENTIFIER(
  1255. paiOss,
  1256. NULL, // pvData
  1257. &cbData) || 0 == cbData)
  1258. goto GetAlgorithmError;
  1259. if (NULL == (pai = (PCRYPT_ALGORITHM_IDENTIFIER)ICM_Alloc(cbData)))
  1260. goto OutOfMemory;;
  1261. if (!ICM_GetALGORITHM_IDENTIFIER(
  1262. paiOss,
  1263. pai,
  1264. &cbData))
  1265. goto GetAlgorithmError;
  1266. CommonReturn:
  1267. return pai;
  1268. ErrorReturn:
  1269. ICM_Free(pai);
  1270. pai = NULL;
  1271. goto CommonReturn;
  1272. TRACE_ERROR(GetAlgorithmError);
  1273. TRACE_ERROR(OutOfMemory)
  1274. }
  1275. #ifdef CMS_PKCS7
  1276. void *
  1277. WINAPI
  1278. ICM_AllocAndGetParam(
  1279. IN PCRYPT_MSG_INFO pcmi,
  1280. IN DWORD dwParamType,
  1281. IN DWORD dwIndex,
  1282. OUT OPTIONAL DWORD *pcbData = NULL
  1283. )
  1284. {
  1285. void *pvData = NULL;
  1286. DWORD cbData;
  1287. if (!CryptMsgGetParam(
  1288. (HCRYPTMSG) pcmi,
  1289. dwParamType,
  1290. dwIndex,
  1291. NULL, // pvData
  1292. &cbData))
  1293. goto CryptMsgGetParamError;
  1294. if (0 == cbData)
  1295. goto NoParamData;
  1296. if (NULL == (pvData = ICM_Alloc(cbData)))
  1297. goto OutOfMemory;
  1298. if (!CryptMsgGetParam(
  1299. (HCRYPTMSG) pcmi,
  1300. dwParamType,
  1301. dwIndex,
  1302. pvData,
  1303. &cbData))
  1304. goto CryptMsgGetParamError;
  1305. CommonReturn:
  1306. if (pcbData)
  1307. *pcbData = cbData;
  1308. return pvData;
  1309. ErrorReturn:
  1310. if (pvData) {
  1311. ICM_Free(pvData);
  1312. pvData = NULL;
  1313. }
  1314. cbData = 0;
  1315. goto CommonReturn;
  1316. TRACE_ERROR(CryptMsgGetParamError)
  1317. TRACE_ERROR(OutOfMemory)
  1318. SET_ERROR(NoParamData, CRYPT_E_INVALID_MSG_TYPE)
  1319. }
  1320. #endif // CMS_PKCS7
  1321. BOOL
  1322. WINAPI
  1323. ICM_RC2VersionToBitLength(
  1324. IN DWORD dwVersion,
  1325. OUT PDWORD pdwBitLen
  1326. )
  1327. {
  1328. BOOL fRet;
  1329. DWORD dwBitLen;
  1330. switch (dwVersion) {
  1331. case CRYPT_RC2_40BIT_VERSION:
  1332. dwBitLen = 40;
  1333. break;
  1334. case CRYPT_RC2_56BIT_VERSION:
  1335. dwBitLen = 56;
  1336. break;
  1337. case CRYPT_RC2_64BIT_VERSION:
  1338. dwBitLen = 64;
  1339. break;
  1340. case CRYPT_RC2_128BIT_VERSION:
  1341. dwBitLen = 128;
  1342. break;
  1343. default:
  1344. goto InvalidRC2VersionError;
  1345. }
  1346. fRet = TRUE;
  1347. CommonReturn:
  1348. *pdwBitLen = dwBitLen;
  1349. return fRet;
  1350. ErrorReturn:
  1351. dwBitLen = 0;
  1352. fRet = FALSE;
  1353. goto CommonReturn;
  1354. SET_ERROR(InvalidRC2VersionError, CRYPT_E_BAD_ENCODE)
  1355. }
  1356. BOOL
  1357. WINAPI
  1358. ICM_BitLengthToRC2Version(
  1359. IN DWORD dwBitLen,
  1360. OUT PDWORD pdwVersion
  1361. )
  1362. {
  1363. BOOL fRet;
  1364. DWORD dwVersion;
  1365. switch (dwBitLen) {
  1366. case 40:
  1367. dwVersion = CRYPT_RC2_40BIT_VERSION;
  1368. break;
  1369. case 56:
  1370. dwVersion = CRYPT_RC2_56BIT_VERSION;
  1371. break;
  1372. case 64:
  1373. dwVersion = CRYPT_RC2_64BIT_VERSION;
  1374. break;
  1375. case 128:
  1376. dwVersion = CRYPT_RC2_128BIT_VERSION;
  1377. break;
  1378. default:
  1379. goto InvalidArg;
  1380. }
  1381. fRet = TRUE;
  1382. CommonReturn:
  1383. *pdwVersion = dwVersion;
  1384. return fRet;
  1385. ErrorReturn:
  1386. dwVersion = 0xFFFFFFFF;
  1387. fRet = FALSE;
  1388. goto CommonReturn;
  1389. SET_ERROR(InvalidArg, E_INVALIDARG)
  1390. }
  1391. #define IV_LENGTH 8
  1392. // For RC4, the maximum salt length, (128 - 40)/8 = 11.
  1393. #define IV_MAX_LENGTH 11
  1394. #define AUX_INFO_BIT_LENGTH_MASK 0xFFFF
  1395. //+-------------------------------------------------------------------------
  1396. // Get the CAPI ALG_ID corresponding to the encryption OID. If the
  1397. // ASN.1 encryption algorithm has any parameters, decode to get IV and
  1398. // key bit length.
  1399. //
  1400. // Note, for RC4, the IV is its salt.
  1401. //--------------------------------------------------------------------------
  1402. BOOL
  1403. WINAPI
  1404. ICM_GetEncryptParameters(
  1405. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  1406. OUT PDWORD pdwAlgIdEncrypt,
  1407. OUT PDWORD pdwBitLen, // 0 => default length
  1408. OUT BYTE rgbIV[IV_MAX_LENGTH],
  1409. OUT PDWORD pcbIV
  1410. )
  1411. {
  1412. BOOL fRet;
  1413. PCRYPT_DATA_BLOB pIVBlob = NULL;
  1414. PCRYPT_RC2_CBC_PARAMETERS pRC2Para = NULL;
  1415. *pdwBitLen = 0;
  1416. *pcbIV = 0;
  1417. if (!ICM_GetCAPI(
  1418. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  1419. paiEncrypt,
  1420. pdwAlgIdEncrypt))
  1421. goto GetCAPIError;
  1422. // Check if more than just the NULL parameters
  1423. if (2 < paiEncrypt->Parameters.cbData) {
  1424. PBYTE pbIV = NULL;
  1425. DWORD cbIV = 0;
  1426. PBYTE pbEncoded = paiEncrypt->Parameters.pbData;
  1427. DWORD cbEncoded = paiEncrypt->Parameters.cbData;
  1428. if (CALG_RC2 == *pdwAlgIdEncrypt) {
  1429. // Try to decode as RC2_CBC parameters
  1430. if (pRC2Para =
  1431. (PCRYPT_RC2_CBC_PARAMETERS) ICM_AllocAndDecodeObject(
  1432. PKCS_RC2_CBC_PARAMETERS,
  1433. pbEncoded,
  1434. cbEncoded)) {
  1435. if (!ICM_RC2VersionToBitLength(pRC2Para->dwVersion, pdwBitLen))
  1436. goto RC2VersionToBitLengthError;
  1437. if (pRC2Para->fIV) {
  1438. pbIV = pRC2Para->rgbIV;
  1439. cbIV = sizeof(pRC2Para->rgbIV);
  1440. }
  1441. }
  1442. }
  1443. if (NULL == pRC2Para) {
  1444. // Try to decode as an OctetString containing the IV or the
  1445. // salt for RC4
  1446. if (pIVBlob = (PCRYPT_DATA_BLOB) ICM_AllocAndDecodeObject(
  1447. X509_OCTET_STRING,
  1448. pbEncoded,
  1449. cbEncoded)) {
  1450. pbIV = pIVBlob->pbData;
  1451. cbIV = pIVBlob->cbData;
  1452. } else
  1453. goto DecodeError;
  1454. }
  1455. if (0 != cbIV) {
  1456. if (IV_LENGTH != cbIV &&
  1457. (CALG_RC4 != *pdwAlgIdEncrypt ||
  1458. IV_MAX_LENGTH < cbIV))
  1459. goto InvalidIVLengthError;
  1460. memcpy(rgbIV, pbIV, cbIV);
  1461. *pcbIV = cbIV;
  1462. }
  1463. }
  1464. fRet = TRUE;
  1465. CommonReturn:
  1466. ICM_Free(pIVBlob);
  1467. ICM_Free(pRC2Para);
  1468. return fRet;
  1469. ErrorReturn:
  1470. fRet = FALSE;
  1471. goto CommonReturn;
  1472. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  1473. TRACE_ERROR(DecodeError)
  1474. TRACE_ERROR(RC2VersionToBitLengthError)
  1475. SET_ERROR(InvalidIVLengthError, CRYPT_E_BAD_ENCODE)
  1476. }
  1477. #ifdef CMS_PKCS7
  1478. //+-------------------------------------------------------------------------
  1479. // Get the CAPI ALG_ID corresponding to the encryption OID. Generate
  1480. // default parameters for and encode. For RC2, encode as RC2_CBC parameters.
  1481. // For all others encode as an IV octet string. The IV is initialized by
  1482. // calling CryptGenRandom. For RC4, the IV is really its salt.
  1483. //--------------------------------------------------------------------------
  1484. BOOL
  1485. WINAPI
  1486. ICM_CreateDefaultEncryptParameters(
  1487. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  1488. OUT PDWORD pdwAlgIdEncrypt,
  1489. OUT PDWORD pdwBitLen, // 0 => default length
  1490. OUT BYTE rgbIV[IV_MAX_LENGTH],
  1491. OUT PDWORD pcbIV
  1492. )
  1493. {
  1494. BOOL fRet;
  1495. HCRYPTPROV hCryptProv; // doesn't need to be released
  1496. CRYPT_RC2_CBC_PARAMETERS RC2Para;
  1497. CRYPT_DATA_BLOB IVPara;
  1498. void *pvPara;
  1499. LPCSTR pszStructType;
  1500. PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt =
  1501. &pContentEncryptInfo->ContentEncryptionAlgorithm;
  1502. DWORD dwBitLen = 0;
  1503. DWORD cbIV = IV_LENGTH;
  1504. CRYPT_ENCODE_PARA EncodePara;
  1505. // Get provider to use for generating the random IV or RC4 salt
  1506. hCryptProv = I_CryptGetDefaultCryptProv(0);
  1507. if (0 == hCryptProv)
  1508. goto GetDefaultCryptProvError;
  1509. if (!ICM_GetCAPI(
  1510. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  1511. paiEncrypt,
  1512. pdwAlgIdEncrypt))
  1513. goto GetCAPIError;
  1514. if (CALG_RC2 == *pdwAlgIdEncrypt) {
  1515. PCMSG_RC2_AUX_INFO pAuxInfo =
  1516. (PCMSG_RC2_AUX_INFO) pContentEncryptInfo->pvEncryptionAuxInfo;
  1517. if (pAuxInfo && pAuxInfo->cbSize >= sizeof(CMSG_RC2_AUX_INFO)) {
  1518. dwBitLen = pAuxInfo->dwBitLen & AUX_INFO_BIT_LENGTH_MASK;
  1519. if (!ICM_BitLengthToRC2Version(dwBitLen, &RC2Para.dwVersion))
  1520. goto BitLengthToRC2VersionError;
  1521. } else {
  1522. // Default to 40 bits;
  1523. dwBitLen = 40;
  1524. RC2Para.dwVersion = CRYPT_RC2_40BIT_VERSION;
  1525. }
  1526. // Generate the random IV.
  1527. if (!CryptGenRandom(hCryptProv, IV_LENGTH, rgbIV))
  1528. goto GenRandomError;
  1529. // Encode as RC2_CBC parameters
  1530. RC2Para.fIV = TRUE;
  1531. assert(sizeof(RC2Para.rgbIV) == IV_LENGTH);
  1532. memcpy(RC2Para.rgbIV, rgbIV, sizeof(RC2Para.rgbIV));
  1533. pvPara = &RC2Para;
  1534. pszStructType = PKCS_RC2_CBC_PARAMETERS;
  1535. } else {
  1536. if (CALG_RC4 == *pdwAlgIdEncrypt) {
  1537. // For RC4, the IV is really the RC4 salt. There are
  1538. // (128 - dwBitLen)/8 bytes of RC4 salt.
  1539. PCMSG_RC4_AUX_INFO pAuxInfo =
  1540. (PCMSG_RC4_AUX_INFO) pContentEncryptInfo->pvEncryptionAuxInfo;
  1541. // Default to no salt
  1542. cbIV = 0;
  1543. if (pAuxInfo && pAuxInfo->cbSize >= sizeof(CMSG_RC4_AUX_INFO)) {
  1544. dwBitLen = pAuxInfo->dwBitLen & AUX_INFO_BIT_LENGTH_MASK;
  1545. if (0 == (pAuxInfo->dwBitLen & CMSG_RC4_NO_SALT_FLAG) &&
  1546. 128 > dwBitLen) {
  1547. cbIV = (128 - dwBitLen)/ 8;
  1548. if (IV_MAX_LENGTH < cbIV)
  1549. cbIV = IV_MAX_LENGTH;
  1550. }
  1551. }
  1552. if (0 == cbIV)
  1553. // No salt
  1554. goto SuccessReturn;
  1555. }
  1556. // Generate the random IV or RC4 salt
  1557. assert(0 < cbIV && IV_MAX_LENGTH >= cbIV);
  1558. if (!CryptGenRandom(hCryptProv, cbIV, rgbIV))
  1559. goto GenRandomError;
  1560. IVPara.pbData = rgbIV;
  1561. IVPara.cbData = cbIV;
  1562. pvPara = &IVPara;
  1563. pszStructType = X509_OCTET_STRING;
  1564. }
  1565. ZEROSTRUCT(EncodePara);
  1566. EncodePara.cbSize = sizeof(EncodePara);
  1567. EncodePara.pfnAlloc = pContentEncryptInfo->pfnAlloc;
  1568. EncodePara.pfnFree = pContentEncryptInfo->pfnFree;
  1569. if (!CryptEncodeObjectEx(
  1570. X509_ASN_ENCODING,
  1571. pszStructType,
  1572. pvPara,
  1573. CRYPT_ENCODE_ALLOC_FLAG,
  1574. &EncodePara,
  1575. (void *) &paiEncrypt->Parameters.pbData,
  1576. &paiEncrypt->Parameters.cbData
  1577. )) goto EncodeError;
  1578. pContentEncryptInfo->dwFlags |= CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG;
  1579. SuccessReturn:
  1580. fRet = TRUE;
  1581. CommonReturn:
  1582. *pdwBitLen = dwBitLen;
  1583. *pcbIV = cbIV;
  1584. return fRet;
  1585. ErrorReturn:
  1586. fRet = FALSE;
  1587. goto CommonReturn;
  1588. TRACE_ERROR(GetDefaultCryptProvError)
  1589. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  1590. TRACE_ERROR(BitLengthToRC2VersionError)
  1591. TRACE_ERROR(GenRandomError)
  1592. TRACE_ERROR(EncodeError)
  1593. }
  1594. BOOL
  1595. WINAPI
  1596. ICM_IsSP3CompatibleEncrypt(
  1597. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
  1598. )
  1599. {
  1600. void *pvEncryptAuxInfo = pContentEncryptInfo->pvEncryptionAuxInfo;
  1601. BOOL fSP3CompatibleEncrypt = FALSE;
  1602. if (pvEncryptAuxInfo) {
  1603. PCMSG_SP3_COMPATIBLE_AUX_INFO pSP3AuxInfo =
  1604. (PCMSG_SP3_COMPATIBLE_AUX_INFO) pvEncryptAuxInfo;
  1605. if (sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO) <= pSP3AuxInfo->cbSize &&
  1606. (pSP3AuxInfo->dwFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)) {
  1607. fSP3CompatibleEncrypt = TRUE;
  1608. }
  1609. }
  1610. return fSP3CompatibleEncrypt;
  1611. }
  1612. //+-------------------------------------------------------------------------
  1613. // Default generation of the encryption key using the ASN.1 Encryption
  1614. // algorithm OID and optional parameters.
  1615. //--------------------------------------------------------------------------
  1616. BOOL
  1617. WINAPI
  1618. #ifdef DEBUG_CRYPT_ASN1
  1619. ICMTest_DefaultGenContentEncryptKey(
  1620. #else
  1621. ICM_DefaultGenContentEncryptKey(
  1622. #endif
  1623. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  1624. IN DWORD dwFlags,
  1625. IN OPTIONAL void *pvReserved
  1626. )
  1627. {
  1628. BOOL fRet;
  1629. PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt =
  1630. &pContentEncryptInfo->ContentEncryptionAlgorithm;
  1631. DWORD dwAlgIdEncrypt;
  1632. BYTE rgbIV[IV_MAX_LENGTH];
  1633. DWORD cbIV;
  1634. DWORD dwBitLen;
  1635. HCRYPTPROV hCryptProv;
  1636. DWORD dwGenFlags;
  1637. BOOL fSP3CompatibleEncrypt;
  1638. fSP3CompatibleEncrypt = ICM_IsSP3CompatibleEncrypt(pContentEncryptInfo);
  1639. if (fSP3CompatibleEncrypt) {
  1640. cbIV = 0;
  1641. dwBitLen = 0;
  1642. if (!ICM_GetCAPI(
  1643. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  1644. paiEncrypt,
  1645. &dwAlgIdEncrypt))
  1646. goto GetCAPIError;
  1647. } else if (0 == paiEncrypt->Parameters.cbData) {
  1648. if (!ICM_CreateDefaultEncryptParameters(
  1649. pContentEncryptInfo,
  1650. &dwAlgIdEncrypt,
  1651. &dwBitLen,
  1652. rgbIV,
  1653. &cbIV))
  1654. goto CreateDefaultEncryptParametersError;
  1655. } else {
  1656. if (!ICM_GetEncryptParameters(
  1657. paiEncrypt,
  1658. &dwAlgIdEncrypt,
  1659. &dwBitLen,
  1660. rgbIV,
  1661. &cbIV))
  1662. goto GetEncryptParametersError;
  1663. }
  1664. hCryptProv = pContentEncryptInfo->hCryptProv;
  1665. if (0 == hCryptProv) {
  1666. DWORD dwAlgIdPubKey = 0;
  1667. if (0 < pContentEncryptInfo->cRecipients) {
  1668. PCMSG_RECIPIENT_ENCODE_INFO prei;
  1669. PCRYPT_ALGORITHM_IDENTIFIER paiPubKey;
  1670. // Get pointer to public key algorithm associated with the first
  1671. // recipient
  1672. prei = &pContentEncryptInfo->rgCmsRecipients[0];
  1673. switch (prei->dwRecipientChoice) {
  1674. case CMSG_KEY_TRANS_RECIPIENT:
  1675. paiPubKey = &prei->pKeyTrans->KeyEncryptionAlgorithm;
  1676. break;
  1677. case CMSG_KEY_AGREE_RECIPIENT:
  1678. paiPubKey = &prei->pKeyAgree->KeyEncryptionAlgorithm;
  1679. break;
  1680. case CMSG_MAIL_LIST_RECIPIENT:
  1681. default:
  1682. paiPubKey = NULL;
  1683. }
  1684. if (paiPubKey)
  1685. ICM_GetCAPI(
  1686. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  1687. paiPubKey,
  1688. &dwAlgIdPubKey);
  1689. }
  1690. hCryptProv = I_CryptGetDefaultCryptProvForEncrypt(
  1691. dwAlgIdPubKey, dwAlgIdEncrypt, dwBitLen);
  1692. if (0 == hCryptProv)
  1693. goto GetDefaultCryptProvError;
  1694. else
  1695. pContentEncryptInfo->hCryptProv = hCryptProv;
  1696. }
  1697. if (fSP3CompatibleEncrypt)
  1698. dwGenFlags = CRYPT_EXPORTABLE;
  1699. else
  1700. dwGenFlags = CRYPT_EXPORTABLE | CRYPT_NO_SALT;
  1701. dwGenFlags |= dwBitLen << 16;
  1702. fRet = CryptGenKey(
  1703. hCryptProv,
  1704. dwAlgIdEncrypt,
  1705. dwGenFlags,
  1706. &pContentEncryptInfo->hContentEncryptKey);
  1707. if (!fRet) {
  1708. // Only need to provide backwards compatibility for
  1709. // key transport recipients
  1710. if (0 < pContentEncryptInfo->cRecipients) {
  1711. PCMSG_RECIPIENT_ENCODE_INFO prei;
  1712. prei = &pContentEncryptInfo->rgCmsRecipients[0];
  1713. if (CMSG_KEY_TRANS_RECIPIENT != prei->dwRecipientChoice)
  1714. goto GenKeyError;
  1715. }
  1716. if (dwBitLen) {
  1717. // Try without setting key length
  1718. dwGenFlags &= 0xFFFF;
  1719. fRet = CryptGenKey(
  1720. hCryptProv,
  1721. dwAlgIdEncrypt,
  1722. dwGenFlags,
  1723. &pContentEncryptInfo->hContentEncryptKey);
  1724. }
  1725. if (!fRet && NTE_BAD_FLAGS == GetLastError())
  1726. // Previous versions didn't support CRYPT_NO_SALT flag
  1727. fRet = CryptGenKey(
  1728. hCryptProv,
  1729. dwAlgIdEncrypt,
  1730. CRYPT_EXPORTABLE, // dwFlags
  1731. &pContentEncryptInfo->hContentEncryptKey);
  1732. if (!fRet) {
  1733. pContentEncryptInfo->hContentEncryptKey = 0;
  1734. goto GenKeyError;
  1735. }
  1736. }
  1737. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  1738. // Silently ignore any errors. Not supported in earlier versions
  1739. CryptSetKeyParam(
  1740. pContentEncryptInfo->hContentEncryptKey,
  1741. KP_EFFECTIVE_KEYLEN,
  1742. (PBYTE) &dwBitLen,
  1743. 0); // dwFlags
  1744. if (0 != cbIV) {
  1745. if (CALG_RC4 == dwAlgIdEncrypt) {
  1746. // For RC4, set the SALT, not the IV
  1747. CRYPT_DATA_BLOB SaltBlob;
  1748. SaltBlob.pbData = rgbIV;
  1749. SaltBlob.cbData = cbIV;
  1750. if (!CryptSetKeyParam(
  1751. pContentEncryptInfo->hContentEncryptKey,
  1752. KP_SALT_EX,
  1753. (PBYTE) &SaltBlob,
  1754. 0)) // dwFlags
  1755. goto SetSaltExError;
  1756. } else {
  1757. if (!CryptSetKeyParam(
  1758. pContentEncryptInfo->hContentEncryptKey,
  1759. KP_IV,
  1760. rgbIV,
  1761. 0)) // dwFlags
  1762. goto SetIVError;
  1763. }
  1764. }
  1765. fRet = TRUE;
  1766. CommonReturn:
  1767. return fRet;
  1768. ErrorReturn:
  1769. fRet = FALSE;
  1770. goto CommonReturn;
  1771. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  1772. TRACE_ERROR(CreateDefaultEncryptParametersError)
  1773. TRACE_ERROR(GetEncryptParametersError)
  1774. TRACE_ERROR(GetDefaultCryptProvError)
  1775. TRACE_ERROR(GenKeyError)
  1776. TRACE_ERROR(SetSaltExError)
  1777. TRACE_ERROR(SetIVError)
  1778. }
  1779. BOOL
  1780. WINAPI
  1781. ICM_GenContentEncryptKey(
  1782. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
  1783. )
  1784. {
  1785. BOOL fRet;
  1786. void *pvFuncAddr;
  1787. HCRYPTOIDFUNCADDR hFuncAddr = NULL;
  1788. LPCSTR pszContentEncryptOID =
  1789. pContentEncryptInfo->ContentEncryptionAlgorithm.pszObjId;
  1790. if (CryptGetOIDFunctionAddress(
  1791. hGenContentEncryptKeyFuncSet,
  1792. X509_ASN_ENCODING,
  1793. pszContentEncryptOID,
  1794. 0, // dwFlags
  1795. &pvFuncAddr,
  1796. &hFuncAddr)) {
  1797. fRet = ((PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY) pvFuncAddr)(
  1798. pContentEncryptInfo,
  1799. 0, // dwFlags
  1800. NULL // pvReserved
  1801. );
  1802. } else {
  1803. if (pContentEncryptInfo->cRecipients
  1804. &&
  1805. CMSG_KEY_TRANS_RECIPIENT ==
  1806. pContentEncryptInfo->rgCmsRecipients[0].dwRecipientChoice
  1807. &&
  1808. CryptGetOIDFunctionAddress(
  1809. hOldStyleGenEncryptKeyFuncSet,
  1810. X509_ASN_ENCODING,
  1811. pszContentEncryptOID,
  1812. 0, // dwFlags
  1813. &pvFuncAddr,
  1814. &hFuncAddr)
  1815. &&
  1816. #ifdef DEBUG_CRYPT_ASN1
  1817. 0 == (ICMTest_GetDebugCryptAsn1Flags() &
  1818. DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG)
  1819. &&
  1820. #endif // DEBUG_CRYPT_ASN1
  1821. (void *) ICM_DefaultGenEncryptKey != pvFuncAddr) {
  1822. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTrans =
  1823. pContentEncryptInfo->rgCmsRecipients[0].pKeyTrans;
  1824. CERT_PUBLIC_KEY_INFO PublicKeyInfo;
  1825. PBYTE pbEncryptParameters = NULL;
  1826. DWORD rgcbEncryptParameters[2] = {0, 0};
  1827. PublicKeyInfo.Algorithm = pKeyTrans->KeyEncryptionAlgorithm;
  1828. PublicKeyInfo.PublicKey = pKeyTrans->RecipientPublicKey;
  1829. fRet = ((PFN_CMSG_GEN_ENCRYPT_KEY) pvFuncAddr)(
  1830. &pContentEncryptInfo->hCryptProv,
  1831. &pContentEncryptInfo->ContentEncryptionAlgorithm,
  1832. pContentEncryptInfo->pvEncryptionAuxInfo,
  1833. &PublicKeyInfo,
  1834. pContentEncryptInfo->pfnAlloc,
  1835. &pContentEncryptInfo->hContentEncryptKey,
  1836. &pbEncryptParameters,
  1837. rgcbEncryptParameters);
  1838. if (pbEncryptParameters) {
  1839. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.pbData =
  1840. pbEncryptParameters;
  1841. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.cbData =
  1842. rgcbEncryptParameters[0];
  1843. pContentEncryptInfo->dwFlags |=
  1844. CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG;
  1845. }
  1846. } else {
  1847. fRet = ICM_DefaultGenContentEncryptKey(
  1848. pContentEncryptInfo,
  1849. 0, // dwFlags
  1850. NULL // pvReserved
  1851. );
  1852. }
  1853. }
  1854. if (hFuncAddr)
  1855. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  1856. return fRet;
  1857. }
  1858. //+-------------------------------------------------------------------------
  1859. // Default generation of the encryption key using the ASN.1 Encryption
  1860. // algorithm OID and optional parameters.
  1861. //
  1862. // rgcbEncryptParameters[1] is the dwEncryptFlags passed to
  1863. // ICM_DefaultExportEncryptKey
  1864. //
  1865. // OldStyle.
  1866. //--------------------------------------------------------------------------
  1867. BOOL
  1868. WINAPI
  1869. ICM_DefaultGenEncryptKey(
  1870. IN OUT HCRYPTPROV *phCryptProv,
  1871. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  1872. IN PVOID pvEncryptAuxInfo,
  1873. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  1874. IN PFN_CMSG_ALLOC pfnAlloc,
  1875. OUT HCRYPTKEY *phEncryptKey,
  1876. OUT PBYTE *ppbEncryptParameters,
  1877. OUT DWORD rgcbEncryptParameters[2])
  1878. {
  1879. BOOL fRet;
  1880. CMSG_CONTENT_ENCRYPT_INFO ContentEncryptInfo;
  1881. ZEROSTRUCT(ContentEncryptInfo);
  1882. CMSG_RECIPIENT_ENCODE_INFO CmsRecipientEncodeInfo;
  1883. ZEROSTRUCT(CmsRecipientEncodeInfo);
  1884. CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO KeyTransEncodeInfo;
  1885. ZEROSTRUCT(KeyTransEncodeInfo);
  1886. ContentEncryptInfo.cbSize = sizeof(ContentEncryptInfo);
  1887. ContentEncryptInfo.hCryptProv = *phCryptProv;
  1888. ContentEncryptInfo.ContentEncryptionAlgorithm = *paiEncrypt;
  1889. ContentEncryptInfo.pvEncryptionAuxInfo = pvEncryptAuxInfo;
  1890. ContentEncryptInfo.cRecipients = 1;
  1891. ContentEncryptInfo.rgCmsRecipients = &CmsRecipientEncodeInfo;
  1892. ContentEncryptInfo.pfnAlloc = pfnAlloc;
  1893. ContentEncryptInfo.pfnFree = ICM_Free;
  1894. // ContentEncryptInfo.hContentEncryptKey =
  1895. // ContentEncryptInfo.dwFlags =
  1896. CmsRecipientEncodeInfo.dwRecipientChoice = CMSG_KEY_TRANS_RECIPIENT;
  1897. CmsRecipientEncodeInfo.pKeyTrans = &KeyTransEncodeInfo;
  1898. KeyTransEncodeInfo.cbSize = sizeof(KeyTransEncodeInfo);
  1899. KeyTransEncodeInfo.KeyEncryptionAlgorithm = pPublicKeyInfo->Algorithm;
  1900. // KeyTransEncodeInfo.pvKeyEncryptionAuxInfo =
  1901. // KeyTransEncodeInfo.hCryptProv =
  1902. KeyTransEncodeInfo.RecipientPublicKey = pPublicKeyInfo->PublicKey;
  1903. // KeyTransEncodeInfo.RecipientId =
  1904. // dwEncryptFlags
  1905. if (ICM_IsSP3CompatibleEncrypt(&ContentEncryptInfo))
  1906. rgcbEncryptParameters[1] = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  1907. else
  1908. rgcbEncryptParameters[1] = 0;
  1909. fRet = ICM_DefaultGenContentEncryptKey(
  1910. &ContentEncryptInfo,
  1911. 0, // dwFlags
  1912. NULL // pvReserved
  1913. );
  1914. assert(0 == (ContentEncryptInfo.dwFlags &
  1915. CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG));
  1916. if (fRet) {
  1917. if (ContentEncryptInfo.dwFlags & CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG) {
  1918. *ppbEncryptParameters =
  1919. ContentEncryptInfo.ContentEncryptionAlgorithm.Parameters.pbData;
  1920. rgcbEncryptParameters[0] =
  1921. ContentEncryptInfo.ContentEncryptionAlgorithm.Parameters.cbData;
  1922. }
  1923. *phCryptProv = ContentEncryptInfo.hCryptProv;
  1924. *phEncryptKey = ContentEncryptInfo.hContentEncryptKey;
  1925. } else {
  1926. if (ContentEncryptInfo.dwFlags & CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG)
  1927. ICM_Free(ContentEncryptInfo.ContentEncryptionAlgorithm.Parameters.pbData);
  1928. if (ContentEncryptInfo.hContentEncryptKey) {
  1929. DWORD dwErr = GetLastError();
  1930. CryptDestroyKey(ContentEncryptInfo.hContentEncryptKey);
  1931. SetLastError(dwErr);
  1932. }
  1933. *phEncryptKey = 0;
  1934. }
  1935. return fRet;
  1936. }
  1937. #else
  1938. //+-------------------------------------------------------------------------
  1939. // Get the CAPI ALG_ID corresponding to the encryption OID. Generate
  1940. // default parameters for and encode. For RC2, encode as RC2_CBC parameters.
  1941. // For all others encode as an IV octet string. The IV is initialized by
  1942. // calling CryptGenRandom.
  1943. //--------------------------------------------------------------------------
  1944. BOOL
  1945. WINAPI
  1946. ICM_CreateDefaultEncryptParameters(
  1947. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  1948. IN PVOID pvEncryptAuxInfo,
  1949. IN PFN_CMSG_ALLOC pfnAlloc,
  1950. OUT PBYTE *ppbEncryptParameters,
  1951. OUT PDWORD pcbEncryptParameters,
  1952. OUT PDWORD pdwAlgIdEncrypt,
  1953. OUT PDWORD pdwBitLen, // 0 => default length
  1954. OUT BYTE rgbIV[IV_LENGTH],
  1955. OUT PDWORD pcbIV
  1956. )
  1957. {
  1958. BOOL fRet;
  1959. HCRYPTPROV hCryptProv; // doesn't need to be released
  1960. CRYPT_RC2_CBC_PARAMETERS RC2Para;
  1961. CRYPT_DATA_BLOB IVPara;
  1962. void *pvPara;
  1963. LPCSTR pszStructType;
  1964. *ppbEncryptParameters = NULL;
  1965. *pcbEncryptParameters = 0;
  1966. *pdwBitLen = 0;
  1967. *pcbIV = IV_LENGTH;
  1968. if (!ICM_GetCAPI(
  1969. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  1970. paiEncrypt,
  1971. pdwAlgIdEncrypt))
  1972. goto GetCAPIError;
  1973. // Generate the random IV.
  1974. hCryptProv = I_CryptGetDefaultCryptProv(0);
  1975. if (0 == hCryptProv)
  1976. goto GetDefaultCryptProvError;
  1977. if (!CryptGenRandom(hCryptProv, IV_LENGTH, rgbIV))
  1978. goto GenRandomError;
  1979. if (CALG_RC2 == *pdwAlgIdEncrypt) {
  1980. PCMSG_RC2_AUX_INFO pAuxInfo = (PCMSG_RC2_AUX_INFO) pvEncryptAuxInfo;
  1981. if (pAuxInfo && pAuxInfo->cbSize >= sizeof(CMSG_RC2_AUX_INFO)) {
  1982. *pdwBitLen = pAuxInfo->dwBitLen & ~CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  1983. if (!ICM_BitLengthToRC2Version(*pdwBitLen, &RC2Para.dwVersion))
  1984. goto BitLengthToRC2VersionError;
  1985. } else {
  1986. // Default to 40 bits;
  1987. *pdwBitLen = 40;
  1988. RC2Para.dwVersion = CRYPT_RC2_40BIT_VERSION;
  1989. }
  1990. // Encode as RC2_CBC parameters
  1991. RC2Para.fIV = TRUE;
  1992. assert(sizeof(RC2Para.rgbIV) == IV_LENGTH);
  1993. memcpy(RC2Para.rgbIV, rgbIV, sizeof(RC2Para.rgbIV));
  1994. pvPara = &RC2Para;
  1995. pszStructType = PKCS_RC2_CBC_PARAMETERS;
  1996. } else {
  1997. IVPara.pbData = rgbIV;
  1998. IVPara.cbData = IV_LENGTH;
  1999. pvPara = &IVPara;
  2000. pszStructType = X509_OCTET_STRING;
  2001. }
  2002. if (!CryptEncodeObject(
  2003. X509_ASN_ENCODING,
  2004. pszStructType,
  2005. pvPara,
  2006. NULL, // pbEncoded
  2007. pcbEncryptParameters
  2008. )) goto EncodeError;
  2009. if (NULL == (*ppbEncryptParameters = (PBYTE) pfnAlloc(
  2010. *pcbEncryptParameters)))
  2011. goto OutOfMemory;
  2012. if (!CryptEncodeObject(
  2013. X509_ASN_ENCODING,
  2014. pszStructType,
  2015. pvPara,
  2016. *ppbEncryptParameters,
  2017. pcbEncryptParameters
  2018. )) goto EncodeError;
  2019. fRet = TRUE;
  2020. CommonReturn:
  2021. return fRet;
  2022. ErrorReturn:
  2023. fRet = FALSE;
  2024. goto CommonReturn;
  2025. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  2026. TRACE_ERROR(BitLengthToRC2VersionError)
  2027. TRACE_ERROR(GetDefaultCryptProvError)
  2028. TRACE_ERROR(GenRandomError)
  2029. TRACE_ERROR(EncodeError)
  2030. TRACE_ERROR(OutOfMemory)
  2031. }
  2032. //+-------------------------------------------------------------------------
  2033. // Default generation of the encryption key using the ASN.1 Encryption
  2034. // algorithm OID and optional parameters.
  2035. //
  2036. // rgcbEncryptParameters[1] is the dwEncryptFlags passed to
  2037. // ICM_DefaultExportEncryptKey
  2038. //--------------------------------------------------------------------------
  2039. BOOL
  2040. WINAPI
  2041. ICM_DefaultGenEncryptKey(
  2042. IN OUT HCRYPTPROV *phCryptProv,
  2043. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  2044. IN PVOID pvEncryptAuxInfo,
  2045. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  2046. IN PFN_CMSG_ALLOC pfnAlloc,
  2047. OUT HCRYPTKEY *phEncryptKey,
  2048. OUT PBYTE *ppbEncryptParameters,
  2049. OUT DWORD rgcbEncryptParameters[2])
  2050. {
  2051. BOOL fRet;
  2052. DWORD dwAlgIdEncrypt;
  2053. HCRYPTPROV hCryptProv;
  2054. BYTE rgbIV[IV_LENGTH];
  2055. DWORD cbIV;
  2056. DWORD dwBitLen;
  2057. DWORD dwEncryptFlags;
  2058. *phEncryptKey = 0;
  2059. dwEncryptFlags = 0;
  2060. rgcbEncryptParameters[1] = 0; // dwEncryptFlags
  2061. if (pvEncryptAuxInfo) {
  2062. PCMSG_SP3_COMPATIBLE_AUX_INFO pSP3AuxInfo =
  2063. (PCMSG_SP3_COMPATIBLE_AUX_INFO) pvEncryptAuxInfo;
  2064. if (sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO) <= pSP3AuxInfo->cbSize &&
  2065. (pSP3AuxInfo->dwFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)) {
  2066. dwEncryptFlags = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  2067. rgcbEncryptParameters[1] = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  2068. }
  2069. }
  2070. if (dwEncryptFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG) {
  2071. cbIV = 0;
  2072. dwBitLen = 0;
  2073. if (!ICM_GetCAPI(
  2074. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  2075. paiEncrypt,
  2076. &dwAlgIdEncrypt))
  2077. goto GetCAPIError;
  2078. } else if (0 == paiEncrypt->Parameters.cbData) {
  2079. if (!ICM_CreateDefaultEncryptParameters(
  2080. paiEncrypt,
  2081. pvEncryptAuxInfo,
  2082. pfnAlloc,
  2083. ppbEncryptParameters,
  2084. rgcbEncryptParameters,
  2085. &dwAlgIdEncrypt,
  2086. &dwBitLen,
  2087. rgbIV,
  2088. &cbIV))
  2089. goto CreateDefaultEncryptParametersError;
  2090. } else {
  2091. if (!ICM_GetEncryptParameters(
  2092. paiEncrypt,
  2093. &dwAlgIdEncrypt,
  2094. &dwBitLen,
  2095. rgbIV,
  2096. &cbIV))
  2097. goto GetEncryptParametersError;
  2098. }
  2099. hCryptProv = *phCryptProv;
  2100. if (0 == hCryptProv) {
  2101. DWORD dwAlgIdPubKey = 0;
  2102. ICM_GetCAPI(
  2103. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  2104. &pPublicKeyInfo->Algorithm,
  2105. &dwAlgIdPubKey);
  2106. hCryptProv = I_CryptGetDefaultCryptProvForEncrypt(
  2107. dwAlgIdPubKey, dwAlgIdEncrypt, dwBitLen);
  2108. if (0 == hCryptProv)
  2109. goto GetDefaultCryptProvError;
  2110. else
  2111. *phCryptProv = hCryptProv;
  2112. }
  2113. fRet = CryptGenKey(
  2114. hCryptProv,
  2115. dwAlgIdEncrypt,
  2116. (dwEncryptFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG) ?
  2117. CRYPT_EXPORTABLE :
  2118. CRYPT_EXPORTABLE | CRYPT_NO_SALT, // dwFlags
  2119. phEncryptKey);
  2120. if (!fRet) {
  2121. if (NTE_BAD_FLAGS == GetLastError())
  2122. // Previous versions didn't support CRYPT_NO_SALT flag
  2123. fRet = CryptGenKey(
  2124. hCryptProv,
  2125. dwAlgIdEncrypt,
  2126. CRYPT_EXPORTABLE, // dwFlags
  2127. phEncryptKey);
  2128. if (!fRet) {
  2129. *phEncryptKey = 0;
  2130. goto GenKeyError;
  2131. }
  2132. }
  2133. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  2134. // Silently ignore any errors. Not supported in earlier versions
  2135. CryptSetKeyParam(
  2136. *phEncryptKey,
  2137. KP_EFFECTIVE_KEYLEN,
  2138. (PBYTE) &dwBitLen,
  2139. 0); // dwFlags
  2140. if (0 != cbIV) {
  2141. if (!CryptSetKeyParam(
  2142. *phEncryptKey,
  2143. KP_IV,
  2144. rgbIV,
  2145. 0)) // dwFlags
  2146. goto SetKeyParamError;
  2147. }
  2148. fRet = TRUE;
  2149. CommonReturn:
  2150. return fRet;
  2151. ErrorReturn:
  2152. if (*phEncryptKey) {
  2153. DWORD dwErr = GetLastError();
  2154. CryptDestroyKey(*phEncryptKey);
  2155. *phEncryptKey = 0;
  2156. SetLastError(dwErr);
  2157. }
  2158. fRet = FALSE;
  2159. goto CommonReturn;
  2160. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  2161. TRACE_ERROR(CreateDefaultEncryptParametersError)
  2162. TRACE_ERROR(GetEncryptParametersError)
  2163. TRACE_ERROR(GetDefaultCryptProvError)
  2164. TRACE_ERROR(GenKeyError)
  2165. TRACE_ERROR(SetKeyParamError)
  2166. }
  2167. //+-------------------------------------------------------------------------
  2168. // Get an hkey for content encryption for a particular algorithm
  2169. //
  2170. // rgcbEncryptParameters[1] is the dwEncryptFlags passed to
  2171. // ICM_ExportEncryptKey
  2172. //--------------------------------------------------------------------------
  2173. BOOL
  2174. WINAPI
  2175. ICM_GenEncryptKey(
  2176. IN OUT HCRYPTPROV *phCryptProv,
  2177. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  2178. IN PVOID pvEncryptAuxInfo,
  2179. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  2180. IN PFN_CMSG_ALLOC pfnAlloc,
  2181. OUT HCRYPTKEY *phEncryptKey,
  2182. OUT PBYTE *ppbEncryptParameters,
  2183. OUT DWORD rgcbEncryptParameters[2])
  2184. {
  2185. BOOL fResult;
  2186. void *pvFuncAddr;
  2187. HCRYPTOIDFUNCADDR hFuncAddr;
  2188. if (CryptGetOIDFunctionAddress(
  2189. hGenEncryptKeyFuncSet,
  2190. X509_ASN_ENCODING,
  2191. paiEncrypt->pszObjId,
  2192. 0, // dwFlags
  2193. &pvFuncAddr,
  2194. &hFuncAddr)) {
  2195. fResult = ((PFN_CMSG_GEN_ENCRYPT_KEY) pvFuncAddr)(
  2196. phCryptProv,
  2197. paiEncrypt,
  2198. pvEncryptAuxInfo,
  2199. pPublicKeyInfo,
  2200. pfnAlloc,
  2201. phEncryptKey,
  2202. ppbEncryptParameters,
  2203. rgcbEncryptParameters);
  2204. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  2205. } else
  2206. fResult = ICM_DefaultGenEncryptKey(
  2207. phCryptProv,
  2208. paiEncrypt,
  2209. pvEncryptAuxInfo,
  2210. pPublicKeyInfo,
  2211. pfnAlloc,
  2212. phEncryptKey,
  2213. ppbEncryptParameters,
  2214. rgcbEncryptParameters);
  2215. return fResult;
  2216. }
  2217. #endif // CMS_PKCS7
  2218. //+-------------------------------------------------------------------------
  2219. // Advance the phase of a message
  2220. //--------------------------------------------------------------------------
  2221. BOOL
  2222. WINAPI
  2223. ICM_AdvanceMsgPhase(
  2224. IN OUT PDWORD pdwPhase,
  2225. IN BOOL fFinal)
  2226. {
  2227. BOOL fRet;
  2228. DWORD dwPhase = *pdwPhase;
  2229. switch (dwPhase) {
  2230. case PHASE_FIRST_ONGOING:
  2231. dwPhase = fFinal ? PHASE_FIRST_FINAL : PHASE_FIRST_ONGOING;
  2232. break;
  2233. case PHASE_FIRST_FINAL:
  2234. dwPhase = fFinal ? PHASE_SECOND_FINAL : PHASE_SECOND_ONGOING;
  2235. break;
  2236. case PHASE_SECOND_ONGOING:
  2237. dwPhase = fFinal ? PHASE_SECOND_FINAL : PHASE_SECOND_ONGOING;
  2238. break;
  2239. case PHASE_SECOND_FINAL:
  2240. goto TransitionFromSecondFinalError;
  2241. default:
  2242. goto InvalidPhaseError;
  2243. }
  2244. *pdwPhase = dwPhase;
  2245. fRet = TRUE;
  2246. CommonReturn:
  2247. return fRet;
  2248. ErrorReturn:
  2249. fRet = FALSE;
  2250. goto CommonReturn;
  2251. SET_ERROR(TransitionFromSecondFinalError,CRYPT_E_MSG_ERROR)
  2252. SET_ERROR(InvalidPhaseError,CRYPT_E_MSG_ERROR)
  2253. }
  2254. //+-------------------------------------------------------------------------
  2255. // Return the (cached) value of the hash
  2256. //
  2257. // Returns FALSE iff conversion failed.
  2258. //--------------------------------------------------------------------------
  2259. BOOL
  2260. WINAPI
  2261. ICM_GetListHashValue(
  2262. IN CHashNode *pnHash,
  2263. OUT DWORD *pcbHash,
  2264. OUT PBYTE *ppbHash)
  2265. {
  2266. BOOL fRet;
  2267. PICM_HASH_INFO pHashInfo;
  2268. pHashInfo = pnHash->Data();
  2269. if (0 == pHashInfo->HashBlob.cbData) {
  2270. pHashInfo->HashBlob.pbData = NULL;
  2271. if (!CryptGetHashParam(
  2272. pHashInfo->hHash,
  2273. HP_HASHVAL,
  2274. NULL, // pbHash
  2275. &pHashInfo->HashBlob.cbData,
  2276. 0)) // dwFlags
  2277. goto GetHashParamSizeError;
  2278. pHashInfo->HashBlob.pbData = (PBYTE)ICM_Alloc(
  2279. pHashInfo->HashBlob.cbData);
  2280. if (NULL == pHashInfo->HashBlob.pbData)
  2281. goto HashAllocError;
  2282. if (!CryptGetHashParam(
  2283. pHashInfo->hHash,
  2284. HP_HASHVAL,
  2285. pHashInfo->HashBlob.pbData,
  2286. &pHashInfo->HashBlob.cbData,
  2287. 0)) // dwFlags
  2288. goto GetHashParamError;
  2289. }
  2290. *pcbHash = pHashInfo->HashBlob.cbData;
  2291. *ppbHash = pHashInfo->HashBlob.pbData;
  2292. fRet = TRUE;
  2293. CommonReturn:
  2294. return fRet;
  2295. ErrorReturn:
  2296. if(pHashInfo->HashBlob.pbData != NULL) {
  2297. ICM_Free(pHashInfo->HashBlob.pbData);
  2298. pHashInfo->HashBlob.pbData = NULL;
  2299. }
  2300. *pcbHash = 0;
  2301. #if DBG
  2302. *ppbHash = NULL;
  2303. #endif
  2304. fRet = FALSE;
  2305. goto CommonReturn;
  2306. TRACE_ERROR(GetHashParamSizeError) // error already set
  2307. TRACE_ERROR(HashAllocError) // error already set
  2308. TRACE_ERROR(GetHashParamError) // error already set
  2309. }
  2310. //+-------------------------------------------------------------------------
  2311. // Return a new hash handle equivalent to the original
  2312. //
  2313. // Returns FALSE iff creation failed.
  2314. //--------------------------------------------------------------------------
  2315. BOOL
  2316. WINAPI
  2317. ICM_DupListHash(
  2318. IN CHashNode *pnHash,
  2319. IN HCRYPTPROV hCryptProv,
  2320. OUT HCRYPTHASH *phHash)
  2321. {
  2322. DWORD dwError = ERROR_SUCCESS;
  2323. BOOL fRet;
  2324. PICM_HASH_INFO pHashInfo = pnHash->Data();
  2325. HCRYPTHASH hHash = NULL;
  2326. DWORD cbHash;
  2327. PBYTE pbHash;
  2328. if (!ICM_GetListHashValue(
  2329. pnHash,
  2330. &cbHash,
  2331. &pbHash))
  2332. goto GetListHashValueError;
  2333. if (!CryptCreateHash(
  2334. hCryptProv,
  2335. pHashInfo->dwAlgoCAPI,
  2336. NULL, // hKey - optional for MAC
  2337. 0, // dwFlags
  2338. &hHash))
  2339. goto CreateHashError;
  2340. if (!CryptSetHashParam(
  2341. hHash,
  2342. HP_HASHVAL,
  2343. pbHash,
  2344. 0)) // dwFlags
  2345. goto SetHashParamError;
  2346. fRet = TRUE;
  2347. CommonReturn:
  2348. *phHash = hHash;
  2349. ICM_SetLastError(dwError);
  2350. return fRet;
  2351. ErrorReturn:
  2352. dwError = GetLastError();
  2353. if (hHash)
  2354. CryptDestroyHash( hHash);
  2355. hHash = NULL;
  2356. fRet = FALSE;
  2357. goto CommonReturn;
  2358. TRACE_ERROR(GetListHashValueError) // error already set
  2359. TRACE_ERROR(CreateHashError) // error already set
  2360. TRACE_ERROR(SetHashParamError) // error already set
  2361. }
  2362. #ifndef CMS_PKCS7
  2363. //+-------------------------------------------------------------------------
  2364. // Set a DigestAlgorithmIdentifiers
  2365. //--------------------------------------------------------------------------
  2366. BOOL
  2367. WINAPI
  2368. ICM_SetAsnDigestAlgorithmIdentifiers(
  2369. OUT DigestAlgorithmIdentifiers *podais,
  2370. OUT PCRYPT_ALGORITHM_IDENTIFIER pai,
  2371. IN DWORD cSigners,
  2372. IN PCMSG_SIGNER_ENCODE_INFO rgSigners,
  2373. OUT HCRYPTPROV *phCryptProv,
  2374. OUT DWORD *pdwKeySpec)
  2375. {
  2376. DWORD dwError = ERROR_SUCCESS;
  2377. BOOL fRet;
  2378. DWORD i;
  2379. PCMSG_SIGNER_ENCODE_INFO psei;
  2380. DigestAlgorithmIdentifier *podai;
  2381. *phCryptProv = NULL;
  2382. // This code does not remove duplicates from the list of
  2383. // algorithms. It is not wrong, but the output message is
  2384. // unnecessarily bulky.
  2385. if (cSigners) {
  2386. podai = (DigestAlgorithmIdentifier *)ICM_AllocZero(
  2387. cSigners * sizeof( DigestAlgorithmIdentifier));
  2388. if (NULL == podai)
  2389. goto DigestAlgorithmIdentifierAllocError;
  2390. } else {
  2391. podai = NULL;
  2392. }
  2393. podais->count = cSigners;
  2394. podais->value = podai;
  2395. for (i=cSigners, psei=rgSigners; i>0; i--, psei++, podai++) {
  2396. assert( psei->cbSize >= STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO,
  2397. rgUnauthAttr));
  2398. assert( psei->pvHashAuxInfo == NULL);
  2399. if (psei->cbSize <
  2400. STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, rgUnauthAttr) ||
  2401. psei->pvHashAuxInfo != NULL)
  2402. goto InvalidArg;
  2403. *phCryptProv = psei->hCryptProv; // s/b array, one for each algo
  2404. *pdwKeySpec = psei->dwKeySpec; // s/b array, one for each algo
  2405. *pai = psei->HashAlgorithm; // s/b array, one for each algo
  2406. if (!ICM_Asn1ToAlgorithmIdentifier( &psei->HashAlgorithm, podai))
  2407. goto Asn1ToAlgorithmIdentifierError;
  2408. }
  2409. fRet = TRUE;
  2410. CommonReturn:
  2411. ICM_SetLastError(dwError);
  2412. return fRet;
  2413. ErrorReturn:
  2414. dwError = GetLastError();
  2415. ICM_Free( podai);
  2416. fRet = FALSE;
  2417. goto CommonReturn;
  2418. TRACE_ERROR(DigestAlgorithmIdentifierAllocError) // error already set
  2419. TRACE_ERROR(Asn1ToAlgorithmIdentifierError) // error already set
  2420. SET_ERROR(InvalidArg,E_INVALIDARG)
  2421. }
  2422. #endif // not defined CMS_PKCS7
  2423. //+-------------------------------------------------------------------------
  2424. // Fill digestEncryptionAlgorithm
  2425. //--------------------------------------------------------------------------
  2426. STATIC
  2427. BOOL
  2428. WINAPI
  2429. ICM_FillAsnDigestEncryptionAlgorithm(
  2430. IN PCRYPT_MSG_INFO pcmi,
  2431. IN PCRYPT_ALGORITHM_IDENTIFIER pDigestEncryptAlg,
  2432. IN OUT DigestEncryptionAlgId *pdea
  2433. )
  2434. {
  2435. BOOL fRet;
  2436. CRYPT_ALGORITHM_IDENTIFIER DigestEncryptAlg;
  2437. DWORD dwFlags;
  2438. PCCRYPT_OID_INFO pOIDInfo;
  2439. dwFlags = 0;
  2440. if (pOIDInfo = CryptFindOIDInfo(
  2441. CRYPT_OID_INFO_OID_KEY,
  2442. pDigestEncryptAlg->pszObjId,
  2443. CRYPT_PUBKEY_ALG_OID_GROUP_ID)) {
  2444. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  2445. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  2446. dwFlags = pdwExtra[0];
  2447. }
  2448. // Check if more than just the NULL parameters
  2449. if (2 < pDigestEncryptAlg->Parameters.cbData) {
  2450. // Check if we should use the public key parameters
  2451. if (0 == (dwFlags & CRYPT_OID_USE_PUBKEY_PARA_FOR_PKCS7_FLAG)) {
  2452. memset(&DigestEncryptAlg, 0, sizeof(DigestEncryptAlg));
  2453. DigestEncryptAlg.pszObjId = pDigestEncryptAlg->pszObjId;
  2454. pDigestEncryptAlg = &DigestEncryptAlg;
  2455. }
  2456. }
  2457. } else if (pOIDInfo = CryptFindOIDInfo(
  2458. CRYPT_OID_INFO_OID_KEY,
  2459. pDigestEncryptAlg->pszObjId,
  2460. CRYPT_SIGN_ALG_OID_GROUP_ID)) {
  2461. if (2 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  2462. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  2463. dwFlags = pdwExtra[1];
  2464. }
  2465. }
  2466. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  2467. pcmi,
  2468. pDigestEncryptAlg,
  2469. pdea))
  2470. goto DigestEncryptionAsn1ToAlgorithmIdentifierError;
  2471. if (0 == pDigestEncryptAlg->Parameters.cbData &&
  2472. 0 != (dwFlags & CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG)) {
  2473. // NO NULL parameters
  2474. pdea->bit_mask &= ~parameters_present;
  2475. pdea->parameters.length = 0;
  2476. pdea->parameters.value = NULL;
  2477. }
  2478. fRet = TRUE;
  2479. CommonReturn:
  2480. return fRet;
  2481. ErrorReturn:
  2482. fRet = FALSE;
  2483. goto CommonReturn;
  2484. TRACE_ERROR(DigestEncryptionAsn1ToAlgorithmIdentifierError) // error already set
  2485. }
  2486. void
  2487. WINAPI
  2488. ICM_GetCertIdFromCertInfo(
  2489. IN PCERT_INFO pCertInfo,
  2490. OUT PCERT_ID pCertId)
  2491. {
  2492. if (Asn1UtilExtractKeyIdFromCertInfo(pCertInfo, &pCertId->KeyId)) {
  2493. pCertId->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  2494. } else {
  2495. pCertId->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  2496. pCertId->IssuerSerialNumber.Issuer = pCertInfo->Issuer;
  2497. pCertId->IssuerSerialNumber.SerialNumber = pCertInfo->SerialNumber;
  2498. }
  2499. }
  2500. BOOL
  2501. WINAPI
  2502. ICM_GetSignerIdFromSignerEncodeInfo(
  2503. IN PCMSG_SIGNER_ENCODE_INFO psei,
  2504. OUT PCERT_ID pSignerId)
  2505. {
  2506. BOOL fRet;
  2507. if (STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, SignerId) <= psei->cbSize &&
  2508. psei->SignerId.dwIdChoice) {
  2509. *pSignerId = psei->SignerId;
  2510. if (!(CERT_ID_ISSUER_SERIAL_NUMBER == pSignerId->dwIdChoice ||
  2511. CERT_ID_KEY_IDENTIFIER == pSignerId->dwIdChoice))
  2512. goto InvalidSignerIdChoice;
  2513. } else
  2514. ICM_GetCertIdFromCertInfo(psei->pCertInfo, pSignerId);
  2515. fRet = TRUE;
  2516. CommonReturn:
  2517. return fRet;
  2518. ErrorReturn:
  2519. fRet = FALSE;
  2520. goto CommonReturn;
  2521. SET_ERROR(InvalidSignerIdChoice, E_INVALIDARG)
  2522. }
  2523. BOOL
  2524. WINAPI
  2525. ICM_SetOssCertIdentifier(
  2526. IN PCERT_ID pCertId,
  2527. IN OUT CertIdentifier *pOssCertId
  2528. );
  2529. void
  2530. WINAPI
  2531. ICM_FreeOssCertIdentifier(
  2532. IN OUT CertIdentifier *pOssCertId
  2533. );
  2534. //+-------------------------------------------------------------------------
  2535. // Fill a single SignerInfo
  2536. //--------------------------------------------------------------------------
  2537. BOOL
  2538. WINAPI
  2539. ICM_FillAsnSignerInfo(
  2540. IN PCMSG_SIGNER_ENCODE_INFO psei,
  2541. IN PCRYPT_MSG_INFO pcmi,
  2542. IN DWORD dwFlags,
  2543. IN OPTIONAL LPSTR pszInnerContentObjID,
  2544. IN OUT SignerInfo *psi,
  2545. IN OUT Attribute **ppAuthAttr,
  2546. IN OUT Attribute **ppUnauthAttr)
  2547. {
  2548. BOOL fRet;
  2549. Attribute *pAuthAttr;
  2550. Attribute *pUnauthAttr;
  2551. int i;
  2552. PCRYPT_ATTRIBUTE patr;
  2553. PCRYPT_ALGORITHM_IDENTIFIER pDigestEncryptAlg;
  2554. CERT_ID SignerId;
  2555. // psi->bit_mask = 0;
  2556. if (!ICM_GetSignerIdFromSignerEncodeInfo(psei, &SignerId))
  2557. goto GetSignerIdError;
  2558. // version
  2559. if (CERT_ID_ISSUER_SERIAL_NUMBER == SignerId.dwIdChoice)
  2560. psi->version = CMSG_SIGNER_INFO_PKCS_1_5_VERSION;
  2561. else
  2562. psi->version = CMSG_SIGNER_INFO_CMS_VERSION;
  2563. // sid
  2564. if (!ICM_SetOssCertIdentifier(
  2565. &SignerId,
  2566. &psi->sid
  2567. ))
  2568. goto SetOssCertIdentifierError;
  2569. // digestAlgorithm
  2570. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  2571. pcmi,
  2572. &psei->HashAlgorithm,
  2573. &psi->digestAlgorithm))
  2574. goto DigestAsn1ToAlgorithmIdentifierError;
  2575. // authenticatedAttributes
  2576. if (!ICM_IsData( pszInnerContentObjID) ||
  2577. psei->cAuthAttr ||
  2578. (dwFlags & CMSG_AUTHENTICATED_ATTRIBUTES_FLAG)) {
  2579. psi->bit_mask |= authenticatedAttributes_present;
  2580. // NB - The actual number of authenticated attributes will be
  2581. // 2 larger than requested, because of the 2 required
  2582. // attributes (if authenticated attributes are present).
  2583. // Leave room at the beginning of the attribute array.
  2584. pAuthAttr = *ppAuthAttr;
  2585. psi->authenticatedAttributes.count = psei->cAuthAttr + 2;
  2586. psi->authenticatedAttributes.value = pAuthAttr;
  2587. for (i=psei->cAuthAttr, patr=psei->rgAuthAttr, pAuthAttr+=2;
  2588. i>0;
  2589. i--, patr++, pAuthAttr++) {
  2590. if (!ICM_Asn1ToAttribute( patr, pAuthAttr))
  2591. goto Asn1AuthenticatedAttributeError;
  2592. }
  2593. *ppAuthAttr = pAuthAttr;
  2594. }
  2595. // digestEncryptionAlgorithm
  2596. #ifdef CMS_PKCS7
  2597. if (STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, HashEncryptionAlgorithm) <=
  2598. psei->cbSize && psei->HashEncryptionAlgorithm.pszObjId)
  2599. pDigestEncryptAlg = &psei->HashEncryptionAlgorithm;
  2600. else
  2601. #endif // CMS_PKCS7
  2602. pDigestEncryptAlg = &psei->pCertInfo->SubjectPublicKeyInfo.Algorithm;
  2603. if (!ICM_FillAsnDigestEncryptionAlgorithm(
  2604. pcmi, pDigestEncryptAlg, &psi->digestEncryptionAlgorithm))
  2605. goto FillAsnDigestEncryptionAlgorithmError;
  2606. // encryptedDigest is filled in later, when we see the content
  2607. // unauthenticatedAttributes
  2608. if (0 != psei->cUnauthAttr) {
  2609. psi->bit_mask |= unauthAttributes_present;
  2610. pUnauthAttr = *ppUnauthAttr;
  2611. psi->unauthAttributes.count = psei->cUnauthAttr;
  2612. psi->unauthAttributes.value = pUnauthAttr;
  2613. for (i=psei->cUnauthAttr, patr=psei->rgUnauthAttr;
  2614. i>0;
  2615. i--, patr++, pUnauthAttr++) {
  2616. if (!ICM_Asn1ToAttribute( patr, pUnauthAttr))
  2617. goto Asn1UnauthenticatedAttributeError;
  2618. }
  2619. *ppUnauthAttr = pUnauthAttr;
  2620. }
  2621. fRet = TRUE;
  2622. CommonReturn:
  2623. return fRet;
  2624. ErrorReturn:
  2625. fRet = FALSE;
  2626. goto CommonReturn;
  2627. TRACE_ERROR(GetSignerIdError)
  2628. TRACE_ERROR(SetOssCertIdentifierError)
  2629. TRACE_ERROR(DigestAsn1ToAlgorithmIdentifierError)
  2630. TRACE_ERROR(Asn1AuthenticatedAttributeError)
  2631. TRACE_ERROR(FillAsnDigestEncryptionAlgorithmError)
  2632. TRACE_ERROR(Asn1UnauthenticatedAttributeError)
  2633. }
  2634. //+-------------------------------------------------------------------------
  2635. // Free SignerInfo allocated memory
  2636. //--------------------------------------------------------------------------
  2637. void
  2638. WINAPI
  2639. ICM_FreeAsnSignerInfo(
  2640. IN OUT SignerInfo *psi)
  2641. {
  2642. Attribute *poatr;
  2643. DWORD i;
  2644. ICM_Free(psi->encryptedDigest.value);
  2645. ICM_FreeOssCertIdentifier(&psi->sid);
  2646. for (i=psi->authenticatedAttributes.count,
  2647. poatr = psi->authenticatedAttributes.value;
  2648. i>0;
  2649. i--, poatr++)
  2650. ICM_Free(poatr->attributeValue.value);
  2651. for (i=psi->unauthAttributes.count,
  2652. poatr=psi->unauthAttributes.value;
  2653. i>0;
  2654. i--, poatr++)
  2655. ICM_Free( poatr->attributeValue.value);
  2656. }
  2657. //+-------------------------------------------------------------------------
  2658. // Set a SignerInfos
  2659. //--------------------------------------------------------------------------
  2660. BOOL
  2661. WINAPI
  2662. ICM_SetAsnSignerInfos(
  2663. IN PCMSG_SIGNED_ENCODE_INFO psmei,
  2664. IN PCRYPT_MSG_INFO pcmi,
  2665. IN DWORD dwFlags,
  2666. IN OPTIONAL LPSTR pszInnerContentObjID,
  2667. OUT SignerInfos *psis,
  2668. OUT BOOL *pfHasCmsSignerId)
  2669. {
  2670. DWORD dwError = ERROR_SUCCESS;
  2671. BOOL fRet;
  2672. DWORD i;
  2673. DWORD cAuthAttr;
  2674. DWORD cUnauthAttr;
  2675. PCMSG_SIGNER_ENCODE_INFO psei;
  2676. SignerInfo *psi = NULL;
  2677. Attribute *pAuthAttr;
  2678. Attribute *pUnauthAttr;
  2679. DWORD cSigners = psmei->cSigners;
  2680. PCMSG_SIGNER_ENCODE_INFO rgSigners = psmei->rgSigners;
  2681. *pfHasCmsSignerId = FALSE;
  2682. psis->value = NULL;
  2683. psis->count = 0;
  2684. if (0 == cSigners)
  2685. goto SuccessReturn;
  2686. // NB - Each SignerInfo gets a non-empty authenticatedAttributes
  2687. // if the inner contentType is not data (passed in) or if
  2688. // there are authenticated attributes passed in. In this case,
  2689. // we reserve two Attribute slots at the beginning of the array
  2690. // for the content-type and message-digest Attribute values.
  2691. for (i=cSigners, psei=rgSigners, cAuthAttr=0, cUnauthAttr=0;
  2692. i>0;
  2693. i--,
  2694. #ifdef CMS_PKCS7
  2695. psei = (PCMSG_SIGNER_ENCODE_INFO) ((BYTE *) psei + psei->cbSize)) {
  2696. #else
  2697. psei++) {
  2698. #endif // CMS_PKCS7
  2699. if (!ICM_IsData( pszInnerContentObjID) ||
  2700. psei->cAuthAttr ||
  2701. (dwFlags & CMSG_AUTHENTICATED_ATTRIBUTES_FLAG))
  2702. cAuthAttr += psei->cAuthAttr + 2; // reserve 2
  2703. cUnauthAttr += psei->cUnauthAttr;
  2704. }
  2705. psi = (SignerInfo *)ICM_AllocZero( cSigners * sizeof( SignerInfo) +
  2706. cAuthAttr * sizeof( Attribute) +
  2707. cUnauthAttr * sizeof( Attribute)
  2708. );
  2709. if (NULL == psi)
  2710. goto SignerInfoAllocError;
  2711. psis->count = cSigners;
  2712. psis->value = psi;
  2713. pAuthAttr = (Attribute *)(psis->value + cSigners);
  2714. pUnauthAttr = pAuthAttr + cAuthAttr;
  2715. for (i=cSigners, psei=rgSigners, psi=psis->value; i>0; i--,
  2716. #ifdef CMS_PKCS7
  2717. psei = (PCMSG_SIGNER_ENCODE_INFO) ((BYTE *) psei + psei->cbSize),
  2718. #else
  2719. psei++,
  2720. #endif // CMS_PKCS7
  2721. psi++) {
  2722. if (!ICM_FillAsnSignerInfo(
  2723. psei,
  2724. pcmi,
  2725. dwFlags,
  2726. pszInnerContentObjID,
  2727. psi,
  2728. &pAuthAttr,
  2729. &pUnauthAttr))
  2730. goto FillAsnSignerInfoError;
  2731. if (CMSG_SIGNER_INFO_CMS_VERSION <= psi->version)
  2732. *pfHasCmsSignerId = TRUE;
  2733. }
  2734. SuccessReturn:
  2735. fRet = TRUE;
  2736. CommonReturn:
  2737. ICM_SetLastError(dwError);
  2738. return fRet;
  2739. ErrorReturn:
  2740. dwError = GetLastError();
  2741. fRet = FALSE;
  2742. goto CommonReturn;
  2743. TRACE_ERROR(SignerInfoAllocError) // error already set
  2744. TRACE_ERROR(FillAsnSignerInfoError) // error already set
  2745. }
  2746. #ifdef CMS_PKCS7
  2747. BOOL
  2748. WINAPI
  2749. ICM_IsDuplicateSignerEncodeHashAlgorithm(
  2750. IN PCMSG_SIGNER_ENCODE_INFO rgSigners,
  2751. IN PCMSG_SIGNER_ENCODE_INFO pNewSigner,
  2752. OUT OPTIONAL DWORD *pdwPrevIndex
  2753. )
  2754. {
  2755. PCRYPT_ALGORITHM_IDENTIFIER pNewHashAlg = &pNewSigner->HashAlgorithm;
  2756. PCMSG_SIGNER_ENCODE_INFO pPrevSigner;
  2757. DWORD dwPrevIndex;
  2758. pPrevSigner = rgSigners;
  2759. dwPrevIndex = 0;
  2760. while (pPrevSigner < pNewSigner) {
  2761. PCRYPT_ALGORITHM_IDENTIFIER pPrevHashAlg = &pPrevSigner->HashAlgorithm;
  2762. if (0 == strcmp(pNewHashAlg->pszObjId, pPrevHashAlg->pszObjId)
  2763. &&
  2764. pNewHashAlg->Parameters.cbData ==
  2765. pPrevHashAlg->Parameters.cbData
  2766. &&
  2767. (0 == pNewHashAlg->Parameters.cbData ||
  2768. 0 == memcmp(pNewHashAlg->Parameters.pbData,
  2769. pPrevHashAlg->Parameters.pbData,
  2770. pNewHashAlg->Parameters.cbData))) {
  2771. break;
  2772. }
  2773. assert(STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, rgUnauthAttr) <=
  2774. pPrevSigner->cbSize);
  2775. assert(pPrevSigner->cbSize == pNewSigner->cbSize);
  2776. pPrevSigner = (PCMSG_SIGNER_ENCODE_INFO) ((BYTE *) pPrevSigner +
  2777. pPrevSigner->cbSize);
  2778. dwPrevIndex++;
  2779. }
  2780. if (pdwPrevIndex)
  2781. *pdwPrevIndex = dwPrevIndex;
  2782. return pPrevSigner < pNewSigner;
  2783. }
  2784. //+-------------------------------------------------------------------------
  2785. // Set Signer DigestAlgorithmIdentifiers and create the SignerEncode and
  2786. // Hash lists
  2787. //--------------------------------------------------------------------------
  2788. BOOL
  2789. WINAPI
  2790. ICM_SetAsnSignerDigestInfo(
  2791. IN PCMSG_SIGNED_ENCODE_INFO psmei,
  2792. IN OUT PCRYPT_MSG_INFO pcmi,
  2793. IN OUT DigestAlgorithmIdentifiers *podais
  2794. )
  2795. {
  2796. BOOL fRet;
  2797. DigestAlgorithmIdentifier *podai = NULL;
  2798. DWORD cDigests = 0;
  2799. DWORD cSigners = psmei->cSigners;
  2800. if (cSigners) {
  2801. DWORD i;
  2802. PCMSG_SIGNER_ENCODE_INFO psei;
  2803. PSIGNER_ENCODE_DATA_INFO rgSignerEncodeDataInfo;
  2804. podai = (DigestAlgorithmIdentifier *) ICM_AllocZero(
  2805. cSigners * sizeof(DigestAlgorithmIdentifier));
  2806. if (NULL == podai)
  2807. goto OutOfMemory;
  2808. rgSignerEncodeDataInfo = (PSIGNER_ENCODE_DATA_INFO) ICM_AllocZero(
  2809. cSigners * sizeof(SIGNER_ENCODE_DATA_INFO));
  2810. if (NULL == rgSignerEncodeDataInfo)
  2811. goto OutOfMemory;
  2812. pcmi->cSignerEncodeDataInfo = cSigners;
  2813. pcmi->rgSignerEncodeDataInfo = rgSignerEncodeDataInfo;
  2814. if (NULL == (pcmi->pHashList = new CHashList))
  2815. goto OutOfMemory;
  2816. for (i = 0, psei = psmei->rgSigners; i < cSigners; i++,
  2817. psei = (PCMSG_SIGNER_ENCODE_INFO) ((BYTE *) psei + psei->cbSize)) {
  2818. DWORD dwPrevIndex;
  2819. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  2820. CHashNode *pHashNode;
  2821. assert(STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, rgUnauthAttr) <=
  2822. psei->cbSize);
  2823. assert(psei->hCryptProv);
  2824. if (STRUCT_CBSIZE(CMSG_SIGNER_ENCODE_INFO, rgUnauthAttr) >
  2825. psei->cbSize || 0 == psei->hCryptProv)
  2826. goto InvalidArg;
  2827. if (ICM_IsDuplicateSignerEncodeHashAlgorithm(
  2828. psmei->rgSigners,
  2829. psei,
  2830. &dwPrevIndex
  2831. )) {
  2832. assert(dwPrevIndex < i);
  2833. pHashNode = rgSignerEncodeDataInfo[dwPrevIndex].pHashNode;
  2834. } else {
  2835. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  2836. pcmi,
  2837. &psei->HashAlgorithm,
  2838. &podai[cDigests]))
  2839. goto MsgAsn1ToAlgorithmIdentifierError;
  2840. cDigests++;
  2841. if (!(ICM_GetCAPI(
  2842. CRYPT_HASH_ALG_OID_GROUP_ID,
  2843. &psei->HashAlgorithm,
  2844. &HashInfo.dwAlgoCAPI) ||
  2845. ICM_GetCAPI(
  2846. CRYPT_SIGN_ALG_OID_GROUP_ID,
  2847. &psei->HashAlgorithm,
  2848. &HashInfo.dwAlgoCAPI)))
  2849. goto GetCAPIError;
  2850. if (!CryptCreateHash(
  2851. psei->hCryptProv,
  2852. HashInfo.dwAlgoCAPI,
  2853. NULL, // hKey - optional for MAC
  2854. 0, // dwFlags
  2855. &HashInfo.hHash))
  2856. goto CreateHashError;
  2857. if (NULL == (pHashNode = new CHashNode)) {
  2858. DWORD dwErr = GetLastError();
  2859. CryptDestroyHash(HashInfo.hHash);
  2860. SetLastError(dwErr);
  2861. goto OutOfMemory;
  2862. }
  2863. pHashNode->SetData(&HashInfo);
  2864. pcmi->pHashList->InsertTail(pHashNode);
  2865. }
  2866. rgSignerEncodeDataInfo[i].hCryptProv = psei->hCryptProv;
  2867. rgSignerEncodeDataInfo[i].dwKeySpec = psei->dwKeySpec;
  2868. rgSignerEncodeDataInfo[i].pHashNode = pHashNode;
  2869. }
  2870. assert(cDigests);
  2871. }
  2872. podais->count = cDigests;
  2873. podais->value = podai;
  2874. fRet = TRUE;
  2875. CommonReturn:
  2876. return fRet;
  2877. ErrorReturn:
  2878. ICM_Free(podai);
  2879. fRet = FALSE;
  2880. goto CommonReturn;
  2881. TRACE_ERROR(OutOfMemory)
  2882. TRACE_ERROR(MsgAsn1ToAlgorithmIdentifierError)
  2883. SET_ERROR(InvalidArg, E_INVALIDARG)
  2884. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  2885. TRACE_ERROR(CreateHashError)
  2886. }
  2887. //+-------------------------------------------------------------------------
  2888. // Open a signed message for encoding
  2889. //--------------------------------------------------------------------------
  2890. HCRYPTMSG
  2891. WINAPI
  2892. ICM_OpenToEncodeSignedData(
  2893. IN DWORD dwEncodingType,
  2894. IN DWORD dwFlags,
  2895. IN void const *pvMsgEncodeInfo,
  2896. IN OPTIONAL LPSTR pszInnerContentObjID,
  2897. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  2898. {
  2899. DWORD dwError = ERROR_SUCCESS;
  2900. PCRYPT_MSG_INFO pcmi = NULL;
  2901. PCMSG_SIGNED_ENCODE_INFO psmei;
  2902. PCERT_BLOB pcert;
  2903. PCRL_BLOB pcrl;
  2904. SignedData *psd = NULL;
  2905. Certificate *pOssCert;
  2906. CertificateRevocationList *pOssCrl;
  2907. DWORD i;
  2908. DWORD cbCert;
  2909. PBYTE pbCert;
  2910. DWORD cbCrl;
  2911. PBYTE pbCrl;
  2912. DWORD cAttrCertEncoded;
  2913. BOOL fHasCmsSignerId;
  2914. psmei = (PCMSG_SIGNED_ENCODE_INFO)pvMsgEncodeInfo;
  2915. assert( psmei->cbSize >= STRUCT_CBSIZE(CMSG_SIGNED_ENCODE_INFO,
  2916. rgCrlEncoded));
  2917. if (psmei->cbSize < STRUCT_CBSIZE(CMSG_SIGNED_ENCODE_INFO, rgCrlEncoded))
  2918. goto InvalidArg;
  2919. for (i=psmei->cCertEncoded, pcert=psmei->rgCertEncoded, cbCert=0;
  2920. i>0;
  2921. i--, pcert++)
  2922. cbCert += pcert->cbData;
  2923. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, cbCrl=0;
  2924. i>0;
  2925. i--, pcrl++)
  2926. cbCrl += pcrl->cbData;
  2927. if (psmei->cbSize >= STRUCT_CBSIZE(CMSG_SIGNED_ENCODE_INFO,
  2928. rgAttrCertEncoded)) {
  2929. cAttrCertEncoded = psmei->cAttrCertEncoded;
  2930. for (i=cAttrCertEncoded, pcert=psmei->rgAttrCertEncoded;
  2931. i>0;
  2932. i--, pcert++)
  2933. cbCert += pcert->cbData;
  2934. } else
  2935. cAttrCertEncoded = 0;
  2936. psd = (SignedData *)ICM_AllocZero(
  2937. sizeof( SignedData) +
  2938. psmei->cCertEncoded * sizeof( Certificate) +
  2939. cAttrCertEncoded * sizeof( Certificate) +
  2940. psmei->cCrlEncoded * sizeof( CertificateRevocationList) +
  2941. cbCert +
  2942. cbCrl);
  2943. if (NULL == psd)
  2944. goto SignedDataAllocError;
  2945. // digest algorithms filled in as part of ICM_SetAsnSignerDigestInfo
  2946. // contentInfo filled in later, when we see the content
  2947. // certificates
  2948. if (0 != psmei->cCertEncoded || 0 != cAttrCertEncoded) {
  2949. psd->bit_mask |= certificates_present;
  2950. psd->certificates.count = psmei->cCertEncoded;
  2951. psd->certificates.count += cAttrCertEncoded;
  2952. #ifdef OSS_CRYPT_ASN1
  2953. psd->certificates.certificates = (Certificate *)(psd + 1);
  2954. #else
  2955. psd->certificates.value = (Certificate *)(psd + 1);
  2956. #endif // OSS_CRYPT_ASN1
  2957. pbCert = (PBYTE)psd +
  2958. sizeof( SignedData) +
  2959. psmei->cCertEncoded * sizeof( Certificate) +
  2960. cAttrCertEncoded * sizeof( Certificate) +
  2961. psmei->cCrlEncoded * sizeof( CertificateRevocationList);
  2962. for (i=psmei->cCertEncoded, pcert=psmei->rgCertEncoded,
  2963. #ifdef OSS_CRYPT_ASN1
  2964. pOssCert=psd->certificates.certificates;
  2965. #else
  2966. pOssCert=psd->certificates.value;
  2967. #endif // OSS_CRYPT_ASN1
  2968. i>0;
  2969. i--, pcert++, pOssCert++) {
  2970. pOssCert->length = pcert->cbData;
  2971. memcpy( pbCert, pcert->pbData, pcert->cbData);
  2972. pOssCert->value = pbCert;
  2973. pbCert += pcert->cbData;
  2974. }
  2975. for (i=cAttrCertEncoded, pcert=psmei->rgAttrCertEncoded;
  2976. i>0;
  2977. i--, pcert++, pOssCert++) {
  2978. pOssCert->length = pcert->cbData;
  2979. memcpy( pbCert, pcert->pbData, pcert->cbData);
  2980. if (pcert->cbData)
  2981. // Change tag from SEQUENCE to [1] IMPLICIT
  2982. *pbCert = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  2983. pOssCert->value = pbCert;
  2984. pbCert += pcert->cbData;
  2985. }
  2986. }
  2987. // crls
  2988. if (0 != psmei->cCrlEncoded) {
  2989. psd->bit_mask |= crls_present;
  2990. psd->crls.count = psmei->cCrlEncoded;
  2991. if (0 != psmei->cCertEncoded || 0 != cAttrCertEncoded)
  2992. #ifdef OSS_CRYPT_ASN1
  2993. psd->crls.crls = (CertificateRevocationList *)
  2994. (psd->certificates.certificates +
  2995. #else
  2996. psd->crls.value = (CertificateRevocationList *)
  2997. (psd->certificates.value +
  2998. #endif // OSS_CRYPT_ASN1
  2999. (psmei->cCertEncoded + cAttrCertEncoded));
  3000. else
  3001. #ifdef OSS_CRYPT_ASN1
  3002. psd->crls.crls = (CertificateRevocationList *) (psd + 1);
  3003. #else
  3004. psd->crls.value = (CertificateRevocationList *) (psd + 1);
  3005. #endif // OSS_CRYPT_ASN1
  3006. pbCrl = (PBYTE)psd +
  3007. sizeof( SignedData) +
  3008. psmei->cCertEncoded * sizeof( Certificate) +
  3009. cAttrCertEncoded * sizeof( Certificate) +
  3010. psmei->cCrlEncoded * sizeof( CertificateRevocationList) +
  3011. cbCert;
  3012. #ifdef OSS_CRYPT_ASN1
  3013. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, pOssCrl=psd->crls.crls;
  3014. #else
  3015. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, pOssCrl=psd->crls.value;
  3016. #endif // OSS_CRYPT_ASN1
  3017. i>0;
  3018. i--, pcrl++, pOssCrl++) {
  3019. pOssCrl->length = pcrl->cbData;
  3020. memcpy( pbCrl, pcrl->pbData, pcrl->cbData);
  3021. pOssCrl->value = pbCrl;
  3022. pbCrl += pcrl->cbData;
  3023. }
  3024. }
  3025. if (NULL == (pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero(
  3026. sizeof( CRYPT_MSG_INFO))))
  3027. goto OutOfMemory;
  3028. // signerInfos
  3029. if (!ICM_SetAsnSignerInfos(psmei, pcmi, dwFlags, pszInnerContentObjID,
  3030. &psd->signerInfos, &fHasCmsSignerId))
  3031. goto SetAsnSignerInfosError;
  3032. // version
  3033. if (0 < cAttrCertEncoded || fHasCmsSignerId) {
  3034. if (ICM_IsData(pszInnerContentObjID))
  3035. dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3036. else
  3037. dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3038. } else if (dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) {
  3039. if (ICM_IsData(pszInnerContentObjID))
  3040. dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3041. }
  3042. // If encapsulated other than id-data or has attribute certs or has
  3043. // CMS signers, then, CMS version
  3044. if ((dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) ||
  3045. 0 < cAttrCertEncoded || fHasCmsSignerId)
  3046. psd->version = CMSG_SIGNED_DATA_CMS_VERSION;
  3047. else
  3048. psd->version = CMSG_SIGNED_DATA_PKCS_1_5_VERSION;
  3049. pcmi->dwEncodingType = dwEncodingType;
  3050. pcmi->dwMsgType = CMSG_SIGNED;
  3051. pcmi->dwFlags = dwFlags;
  3052. pcmi->pvMsg = psd;
  3053. pcmi->fEncoding = TRUE;
  3054. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  3055. if (pszInnerContentObjID &&
  3056. (NULL == (pcmi->pszInnerContentObjID = (LPSTR)ICM_DupMem(
  3057. pszInnerContentObjID,
  3058. ICM_StrLen(pszInnerContentObjID) + 1))))
  3059. goto DupInnerContentObjIDError;
  3060. if (pStreamInfo &&
  3061. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  3062. pStreamInfo,
  3063. sizeof(*pStreamInfo)))))
  3064. goto DupStreamInfoError;
  3065. if (!ICM_SetAsnSignerDigestInfo(
  3066. psmei,
  3067. pcmi,
  3068. &psd->digestAlgorithms
  3069. ))
  3070. goto SetAsnSignerDigestInfoError;
  3071. if (pcmi->pStreamInfo && !ICMS_OpenToEncodeSignedData( pcmi, psmei))
  3072. goto StreamOpenToEncodeSignedDataError;
  3073. CommonReturn:
  3074. ICM_SetLastError(dwError);
  3075. return (HCRYPTMSG)pcmi;
  3076. ErrorReturn:
  3077. dwError = GetLastError();
  3078. if (psd) {
  3079. if (psd->signerInfos.value) {
  3080. SignerInfo *psi;
  3081. for (i=psd->signerInfos.count, psi=psd->signerInfos.value;
  3082. i>0;
  3083. i--, psi++)
  3084. ICM_FreeAsnSignerInfo(psi);
  3085. ICM_Free(psd->signerInfos.value);
  3086. }
  3087. ICM_Free(psd);
  3088. }
  3089. if (pcmi) {
  3090. if (pcmi->pFreeList)
  3091. delete pcmi->pFreeList;
  3092. if (pcmi->pHashList)
  3093. delete pcmi->pHashList;
  3094. ICM_Free(pcmi->rgSignerEncodeDataInfo);
  3095. ICM_Free(pcmi->pszInnerContentObjID);
  3096. ICM_Free(pcmi->pStreamInfo);
  3097. ICM_Free(pcmi);
  3098. pcmi = NULL;
  3099. }
  3100. goto CommonReturn;
  3101. SET_ERROR(InvalidArg,E_INVALIDARG)
  3102. TRACE_ERROR(DupInnerContentObjIDError) // error already set
  3103. TRACE_ERROR(DupStreamInfoError) // error already set
  3104. TRACE_ERROR(SetAsnSignerInfosError) // error already set
  3105. TRACE_ERROR(SetAsnSignerDigestInfoError) // error already set
  3106. TRACE_ERROR(SignedDataAllocError) // error already set
  3107. TRACE_ERROR(OutOfMemory) // error already set
  3108. TRACE_ERROR(StreamOpenToEncodeSignedDataError) // error already set
  3109. }
  3110. #else
  3111. //+-------------------------------------------------------------------------
  3112. // Open a signed message for encoding
  3113. //--------------------------------------------------------------------------
  3114. HCRYPTMSG
  3115. WINAPI
  3116. ICM_OpenToEncodeSignedData(
  3117. IN DWORD dwEncodingType,
  3118. IN DWORD dwFlags,
  3119. IN void const *pvMsgEncodeInfo,
  3120. IN OPTIONAL LPSTR pszInnerContentObjID,
  3121. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  3122. {
  3123. DWORD dwError = ERROR_SUCCESS;
  3124. PCRYPT_MSG_INFO pcmi = NULL;
  3125. PCMSG_SIGNED_ENCODE_INFO psmei;
  3126. PCERT_BLOB pcert;
  3127. PCRL_BLOB pcrl;
  3128. SignedData *psd = NULL;
  3129. Certificate *pOssCert;
  3130. CertificateRevocationList *pOssCrl;
  3131. DWORD i;
  3132. DWORD cDigestAlgorithms;
  3133. HCRYPTPROV hCryptProv;
  3134. DWORD dwKeySpec;
  3135. CRYPT_ALGORITHM_IDENTIFIER aiDigest;
  3136. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  3137. CHashNode *pHashNode;
  3138. DWORD cbCert;
  3139. PBYTE pbCert;
  3140. DWORD cbCrl;
  3141. PBYTE pbCrl;
  3142. BOOL fHasCmsSignerId;
  3143. #ifdef CMS_PKCS7
  3144. DWORD cAttrCertEncoded;
  3145. #endif // CMS_PKCS7
  3146. psmei = (PCMSG_SIGNED_ENCODE_INFO)pvMsgEncodeInfo;
  3147. assert( 2 > psmei->cSigners);
  3148. if (!( 2 > psmei->cSigners))
  3149. goto TooManySignersError;
  3150. #ifdef CMS_PKCS7
  3151. assert( psmei->cbSize >= offsetof(CMSG_SIGNED_ENCODE_INFO,
  3152. cAttrCertEncoded));
  3153. if (psmei->cbSize < offsetof(CMSG_SIGNED_ENCODE_INFO, cAttrCertEncoded))
  3154. #else
  3155. assert( psmei->cbSize >= sizeof(CMSG_SIGNED_ENCODE_INFO));
  3156. if (psmei->cbSize < sizeof(CMSG_SIGNED_ENCODE_INFO))
  3157. #endif
  3158. goto InvalidArg;
  3159. for (i=psmei->cCertEncoded, pcert=psmei->rgCertEncoded, cbCert=0;
  3160. i>0;
  3161. i--, pcert++)
  3162. cbCert += pcert->cbData;
  3163. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, cbCrl=0;
  3164. i>0;
  3165. i--, pcrl++)
  3166. cbCrl += pcrl->cbData;
  3167. #ifdef CMS_PKCS7
  3168. if (psmei->cbSize > offsetof(CMSG_SIGNED_ENCODE_INFO, rgAttrCertEncoded)) {
  3169. cAttrCertEncoded = psmei->cAttrCertEncoded;
  3170. for (i=cAttrCertEncoded, pcert=psmei->rgAttrCertEncoded;
  3171. i>0;
  3172. i--, pcert++)
  3173. cbCert += pcert->cbData;
  3174. } else
  3175. cAttrCertEncoded = 0;
  3176. #endif // CMS_PKCS7
  3177. psd = (SignedData *)ICM_AllocZero(
  3178. sizeof( SignedData) +
  3179. psmei->cCertEncoded * sizeof( Certificate) +
  3180. #ifdef CMS_PKCS7
  3181. cAttrCertEncoded * sizeof( Certificate) +
  3182. #endif // CMS_PKCS7
  3183. psmei->cCrlEncoded * sizeof( CertificateRevocationList) +
  3184. cbCert +
  3185. cbCrl);
  3186. if (NULL == psd)
  3187. goto SignedDataAllocError;
  3188. psd->bit_mask = 0;
  3189. psd->signerInfos.value = NULL;
  3190. psd->contentInfo.content.value = NULL;
  3191. // version
  3192. #ifdef CMS_PKCS7
  3193. if (0 < cAttrCertEncoded) {
  3194. if (ICM_IsData(pszInnerContentObjID))
  3195. dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3196. else
  3197. dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3198. } else if (dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) {
  3199. if (ICM_IsData(pszInnerContentObjID))
  3200. dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3201. }
  3202. // If encapsulated other than id-data or has attribute certs, then,
  3203. // version = 3
  3204. if ((dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) ||
  3205. 0 < cAttrCertEncoded)
  3206. psd->version = CMSG_SIGNED_DATA_CMS_VERSION;
  3207. else
  3208. psd->version = CMSG_SIGNED_DATA_PKCS_1_5_VERSION;
  3209. #else
  3210. psd->version = 1;
  3211. #endif // CMS_PKCS7
  3212. // digest algorithms
  3213. if (!ICM_SetAsnDigestAlgorithmIdentifiers(
  3214. &psd->digestAlgorithms,
  3215. &aiDigest,
  3216. psmei->cSigners,
  3217. psmei->rgSigners,
  3218. &hCryptProv,
  3219. &dwKeySpec))
  3220. goto SetAsnDigestAlgorithmIdentifiersError;
  3221. // contentInfo filled in later, when we see the content
  3222. // certificates
  3223. if (0 != psmei->cCertEncoded
  3224. #ifdef CMS_PKCS7
  3225. || 0 != cAttrCertEncoded
  3226. #endif // CMS_PKCS7
  3227. ) {
  3228. psd->bit_mask |= certificates_present;
  3229. psd->certificates.count = psmei->cCertEncoded;
  3230. #ifdef CMS_PKCS7
  3231. psd->certificates.count += cAttrCertEncoded;
  3232. #endif // CMS_PKCS7
  3233. #ifdef OSS_CRYPT_ASN1
  3234. psd->certificates.certificates = (Certificate *)(psd + 1);
  3235. #else
  3236. psd->certificates.value = (Certificate *)(psd + 1);
  3237. #endif // OSS_CRYPT_ASN1
  3238. pbCert = (PBYTE)psd +
  3239. sizeof( SignedData) +
  3240. psmei->cCertEncoded * sizeof( Certificate) +
  3241. #ifdef CMS_PKCS7
  3242. cAttrCertEncoded * sizeof( Certificate) +
  3243. #endif // CMS_PKCS7
  3244. psmei->cCrlEncoded * sizeof( CertificateRevocationList);
  3245. for (i=psmei->cCertEncoded, pcert=psmei->rgCertEncoded,
  3246. #ifdef OSS_CRYPT_ASN1
  3247. pOssCert=psd->certificates.certificates;
  3248. #else
  3249. pOssCert=psd->certificates.value;
  3250. #endif // OSS_CRYPT_ASN1
  3251. i>0;
  3252. i--, pcert++, pOssCert++) {
  3253. pOssCert->length = pcert->cbData;
  3254. memcpy( pbCert, pcert->pbData, pcert->cbData);
  3255. pOssCert->value = pbCert;
  3256. pbCert += pcert->cbData;
  3257. }
  3258. #ifdef CMS_PKCS7
  3259. for (i=cAttrCertEncoded, pcert=psmei->rgAttrCertEncoded;
  3260. i>0;
  3261. i--, pcert++, pOssCert++) {
  3262. pOssCert->length = pcert->cbData;
  3263. memcpy( pbCert, pcert->pbData, pcert->cbData);
  3264. if (pcert->cbData)
  3265. // Change tag from SEQUENCE to [1] IMPLICIT
  3266. *pbCert = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  3267. pOssCert->value = pbCert;
  3268. pbCert += pcert->cbData;
  3269. }
  3270. #endif // CMS_PKCS7
  3271. }
  3272. // crls
  3273. if (0 != psmei->cCrlEncoded) {
  3274. psd->bit_mask |= crls_present;
  3275. psd->crls.count = psmei->cCrlEncoded;
  3276. if (0 != psmei->cCertEncoded
  3277. #ifdef CMS_PKCS7
  3278. || 0 != cAttrCertEncoded
  3279. #endif // CMS_PKCS7
  3280. )
  3281. #ifdef OSS_CRYPT_ASN1
  3282. psd->crls.crls = (CertificateRevocationList *)
  3283. (psd->certificates.certificates +
  3284. #else
  3285. psd->crls.value = (CertificateRevocationList *)
  3286. (psd->certificates.value +
  3287. #endif // OSS_CRYPT_ASN1
  3288. (psmei->cCertEncoded
  3289. #ifdef CMS_PKCS7
  3290. + cAttrCertEncoded
  3291. #endif // CMS_PKCS7
  3292. ));
  3293. else
  3294. #ifdef OSS_CRYPT_ASN1
  3295. psd->crls.crls = (CertificateRevocationList *) (psd + 1);
  3296. #else
  3297. psd->crls.value = (CertificateRevocationList *) (psd + 1);
  3298. #endif // OSS_CRYPT_ASN1
  3299. pbCrl = (PBYTE)psd +
  3300. sizeof( SignedData) +
  3301. psmei->cCertEncoded * sizeof( Certificate) +
  3302. #ifdef CMS_PKCS7
  3303. cAttrCertEncoded * sizeof( Certificate) +
  3304. #endif // CMS_PKCS7
  3305. psmei->cCrlEncoded * sizeof( CertificateRevocationList) +
  3306. cbCert;
  3307. #ifdef OSS_CRYPT_ASN1
  3308. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, pOssCrl=psd->crls.crls;
  3309. #else
  3310. for (i=psmei->cCrlEncoded, pcrl=psmei->rgCrlEncoded, pOssCrl=psd->crls.value;
  3311. #endif // OSS_CRYPT_ASN1
  3312. i>0;
  3313. i--, pcrl++, pOssCrl++) {
  3314. pOssCrl->length = pcrl->cbData;
  3315. memcpy( pbCrl, pcrl->pbData, pcrl->cbData);
  3316. pOssCrl->value = pbCrl;
  3317. pbCrl += pcrl->cbData;
  3318. }
  3319. }
  3320. // signerInfos
  3321. // psd->signerInfos.count = psmei->cSigners;
  3322. // psd->signerInfos.value = (SignerInfo *)
  3323. // (psd->crls.crls + psmei->cCrlEncoded);
  3324. if (!ICM_SetAsnSignerInfos( psmei, pcmi, dwFlags, pszInnerContentObjID,
  3325. &psd->signerInfos, &fHasCmsSignerId))
  3326. goto SetAsnSignerInfosError;
  3327. cDigestAlgorithms = psmei->cSigners;
  3328. if (NULL == (pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO))))
  3329. goto OutOfMemory;
  3330. pcmi->hCryptProv = hCryptProv;
  3331. if (0 == hCryptProv)
  3332. pcmi->fDefaultCryptProv = TRUE;
  3333. pcmi->dwKeySpec = dwKeySpec;
  3334. pcmi->dwEncodingType = dwEncodingType;
  3335. pcmi->dwMsgType = CMSG_SIGNED;
  3336. pcmi->dwFlags = dwFlags;
  3337. pcmi->pvMsg = psd;
  3338. pcmi->fEncoding = TRUE;
  3339. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  3340. if (pszInnerContentObjID &&
  3341. (NULL == (pcmi->pszInnerContentObjID = (LPSTR)ICM_DupMem(
  3342. pszInnerContentObjID,
  3343. ICM_StrLen(pszInnerContentObjID) + 1))))
  3344. goto DupInnerContentObjIDError;
  3345. if (pStreamInfo &&
  3346. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  3347. pStreamInfo,
  3348. sizeof(*pStreamInfo)))))
  3349. goto DupStreamInfoError;
  3350. if (psmei->cSigners) {
  3351. if (!(ICM_GetCAPI(
  3352. CRYPT_HASH_ALG_OID_GROUP_ID,
  3353. &aiDigest,
  3354. &HashInfo.dwAlgoCAPI) ||
  3355. ICM_GetCAPI(
  3356. CRYPT_SIGN_ALG_OID_GROUP_ID,
  3357. &aiDigest,
  3358. &HashInfo.dwAlgoCAPI)))
  3359. goto GetCAPIError;
  3360. HashInfo.hCryptProv = hCryptProv;
  3361. if (!CryptCreateHash(
  3362. HashInfo.hCryptProv,
  3363. HashInfo.dwAlgoCAPI,
  3364. NULL, // hKey - optional for MAC
  3365. 0, // dwFlags
  3366. &HashInfo.hHash))
  3367. goto CreateHashError;
  3368. if (NULL == (pcmi->pHashList = new CHashList))
  3369. goto NewHashListError;
  3370. if (NULL == (pHashNode = new CHashNode))
  3371. goto NewHashNodeError;
  3372. pHashNode->SetData( &HashInfo);
  3373. pcmi->pHashList->InsertTail( pHashNode);
  3374. }
  3375. if (pcmi->pStreamInfo && !ICMS_OpenToEncodeSignedData( pcmi, psmei))
  3376. goto StreamOpenToEncodeSignedDataError;
  3377. CommonReturn:
  3378. ICM_SetLastError(dwError);
  3379. return (HCRYPTMSG)pcmi;
  3380. ErrorReturn:
  3381. dwError = GetLastError();
  3382. ICM_Free( psd);
  3383. ICM_Free( pcmi);
  3384. pcmi = NULL;
  3385. goto CommonReturn;
  3386. SET_ERROR(TooManySignersError,E_INVALIDARG)
  3387. SET_ERROR(NewHashListError,E_OUTOFMEMORY)
  3388. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  3389. SET_ERROR(InvalidArg,E_INVALIDARG)
  3390. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  3391. TRACE_ERROR(DupInnerContentObjIDError) // error already set
  3392. TRACE_ERROR(DupStreamInfoError) // error already set
  3393. TRACE_ERROR(SetAsnSignerInfosError) // error already set
  3394. TRACE_ERROR(SetAsnDigestAlgorithmIdentifiersError) // error already set
  3395. TRACE_ERROR(SignedDataAllocError) // error already set
  3396. TRACE_ERROR(OutOfMemory) // error already set
  3397. TRACE_ERROR(CreateHashError) // error already set
  3398. TRACE_ERROR(StreamOpenToEncodeSignedDataError) // error already set
  3399. }
  3400. #endif // CMS_PKCS7
  3401. //+-------------------------------------------------------------------------
  3402. // Open a data message for encoding
  3403. //--------------------------------------------------------------------------
  3404. HCRYPTMSG
  3405. WINAPI
  3406. ICM_OpenToEncodeData(
  3407. IN DWORD dwEncodingType,
  3408. IN DWORD dwFlags,
  3409. IN void const *pvMsgEncodeInfo,
  3410. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  3411. {
  3412. DWORD dwError = ERROR_SUCCESS;
  3413. PCRYPT_MSG_INFO pcmi = NULL;
  3414. OctetStringType *poos = NULL;
  3415. if (pvMsgEncodeInfo)
  3416. goto EncodeInfoPresentError;
  3417. if (NULL == (poos = (OctetStringType *)ICM_AllocZero( sizeof( OctetStringType))))
  3418. goto AllocOctetStringTypeError;
  3419. if (NULL == (pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO))))
  3420. goto AllocMsgInfoError;
  3421. pcmi->dwEncodingType = dwEncodingType;
  3422. pcmi->dwMsgType = CMSG_DATA;
  3423. // pcmi->hCryptProv = 0;
  3424. pcmi->fDefaultCryptProv = TRUE;
  3425. pcmi->dwFlags = dwFlags;
  3426. pcmi->pvMsg = poos;
  3427. pcmi->fEncoding = TRUE;
  3428. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  3429. pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  3430. pStreamInfo,
  3431. sizeof(*pStreamInfo));
  3432. if (pcmi->pStreamInfo && !ICMS_OpenToEncodeData( pcmi))
  3433. goto StreamOpenToEncodeDataError;
  3434. CommonReturn:
  3435. ICM_SetLastError(dwError);
  3436. return (HCRYPTMSG)pcmi;
  3437. ErrorReturn:
  3438. dwError = GetLastError();
  3439. ICM_Free( poos);
  3440. if (pcmi) {
  3441. ICM_Free(pcmi->pStreamInfo);
  3442. ICM_Free( pcmi);
  3443. }
  3444. pcmi = NULL;
  3445. goto CommonReturn;
  3446. SET_ERROR(EncodeInfoPresentError,E_INVALIDARG)
  3447. TRACE_ERROR(AllocMsgInfoError) // error already set
  3448. TRACE_ERROR(AllocOctetStringTypeError) // error already set
  3449. TRACE_ERROR(StreamOpenToEncodeDataError) // error already set
  3450. }
  3451. //+-------------------------------------------------------------------------
  3452. // Open a digested message for encoding
  3453. //--------------------------------------------------------------------------
  3454. HCRYPTMSG
  3455. WINAPI
  3456. ICM_OpenToEncodeDigestedData(
  3457. IN DWORD dwEncodingType,
  3458. IN DWORD dwFlags,
  3459. IN void const *pvMsgEncodeInfo,
  3460. IN OPTIONAL LPSTR pszInnerContentObjID,
  3461. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  3462. {
  3463. DWORD dwError = ERROR_SUCCESS;
  3464. PCRYPT_MSG_INFO pcmi = NULL;
  3465. PCMSG_HASHED_ENCODE_INFO pdmei;
  3466. DigestedData *pdd = NULL;
  3467. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  3468. CHashNode *pHashNode;
  3469. pdmei = (PCMSG_HASHED_ENCODE_INFO)pvMsgEncodeInfo;
  3470. assert( pdmei->cbSize >= sizeof(CMSG_HASHED_ENCODE_INFO));
  3471. assert( pdmei->pvHashAuxInfo == NULL);
  3472. if (pdmei->cbSize < sizeof(CMSG_HASHED_ENCODE_INFO) ||
  3473. pdmei->pvHashAuxInfo != NULL)
  3474. goto InvalidArg;
  3475. pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO));
  3476. if (NULL == pcmi)
  3477. goto OutOfMemory;
  3478. pdd = (DigestedData *)ICM_AllocZero( sizeof( DigestedData));
  3479. if (NULL == pdd)
  3480. goto DigestedDataAllocError;
  3481. // version
  3482. #ifdef CMS_PKCS7
  3483. if (dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) {
  3484. if (ICM_IsData(pszInnerContentObjID))
  3485. dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3486. }
  3487. // If encapsulated other than id-data, then, version = 2
  3488. if (dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG)
  3489. pdd->version = CMSG_HASHED_DATA_V2;
  3490. else
  3491. pdd->version = CMSG_HASHED_DATA_V0;
  3492. #else
  3493. pdd->version = 0;
  3494. #endif // CMS_PKCS7
  3495. // digest algorithm
  3496. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  3497. pcmi,
  3498. &pdmei->HashAlgorithm,
  3499. &pdd->digestAlgorithm))
  3500. goto MsgAsn1ToAlgorithmIdentifierError;
  3501. // contentInfo filled in later, when we see the content
  3502. if (pdmei->hCryptProv)
  3503. pcmi->hCryptProv = pdmei->hCryptProv;
  3504. else {
  3505. pcmi->fDefaultCryptProv = TRUE;
  3506. pcmi->hCryptProv = I_CryptGetDefaultCryptProv(0);
  3507. if (0 == pcmi->hCryptProv)
  3508. goto GetDefaultCryptProvError;
  3509. }
  3510. pcmi->dwEncodingType = dwEncodingType;
  3511. pcmi->dwMsgType = CMSG_HASHED;
  3512. pcmi->dwFlags = dwFlags;
  3513. pcmi->pvMsg = pdd;
  3514. pcmi->fEncoding = TRUE;
  3515. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  3516. pcmi->pszInnerContentObjID = (LPSTR)ICM_DupMem(
  3517. pszInnerContentObjID,
  3518. ICM_StrLen(pszInnerContentObjID) + 1);
  3519. pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  3520. pStreamInfo,
  3521. sizeof(*pStreamInfo));
  3522. if (!ICM_GetCAPI(
  3523. CRYPT_HASH_ALG_OID_GROUP_ID,
  3524. &pdmei->HashAlgorithm,
  3525. &HashInfo.dwAlgoCAPI))
  3526. goto GetCAPIError;
  3527. #ifndef CMS_PKCS7
  3528. HashInfo.hCryptProv = pcmi->hCryptProv;
  3529. #endif // CMS_PKCS7
  3530. if (!CryptCreateHash(
  3531. pcmi->hCryptProv,
  3532. HashInfo.dwAlgoCAPI,
  3533. NULL, // hKey - optional for MAC
  3534. 0, // dwFlags
  3535. &HashInfo.hHash))
  3536. goto CreateHashError;
  3537. if (NULL == (pcmi->pHashList = new CHashList) ||
  3538. NULL == (pHashNode = new CHashNode)) {
  3539. DWORD dwErr = GetLastError();
  3540. CryptDestroyHash(HashInfo.hHash);
  3541. SetLastError(dwErr);
  3542. goto NewHashListOrNodeError;
  3543. }
  3544. pHashNode->SetData( &HashInfo);
  3545. pcmi->pHashList->InsertTail( pHashNode);
  3546. CommonReturn:
  3547. ICM_SetLastError(dwError);
  3548. return (HCRYPTMSG)pcmi;
  3549. ErrorReturn:
  3550. dwError = GetLastError();
  3551. ICM_Free( pdd);
  3552. if (pcmi) {
  3553. #ifdef CMS_PKCS7
  3554. if (pcmi->pFreeList)
  3555. delete pcmi->pFreeList;
  3556. #endif // CMS_PKCS7
  3557. if (pcmi->pHashList)
  3558. delete pcmi->pHashList;
  3559. ICM_Free(pcmi->pszInnerContentObjID);
  3560. ICM_Free(pcmi->pStreamInfo);
  3561. ICM_Free( pcmi);
  3562. pcmi = NULL;
  3563. }
  3564. goto CommonReturn;
  3565. SET_ERROR(InvalidArg,E_INVALIDARG)
  3566. TRACE_ERROR(GetDefaultCryptProvError)
  3567. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  3568. SET_ERROR(NewHashListOrNodeError,E_OUTOFMEMORY)
  3569. TRACE_ERROR(MsgAsn1ToAlgorithmIdentifierError) // error already set
  3570. TRACE_ERROR(DigestedDataAllocError) // error already set
  3571. TRACE_ERROR(CreateHashError) // error already set
  3572. TRACE_ERROR(OutOfMemory) // error already set
  3573. }
  3574. #ifdef CMS_PKCS7
  3575. //+-------------------------------------------------------------------------
  3576. // Export the hContentEncryptKey from the ContentEncrypt
  3577. // provider and import into the specified provider
  3578. //--------------------------------------------------------------------------
  3579. HCRYPTKEY
  3580. WINAPI
  3581. ICM_ExportContentEncryptKeyAndImport(
  3582. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  3583. IN HCRYPTPROV hImportProv
  3584. )
  3585. {
  3586. DWORD dwError = ERROR_SUCCESS;
  3587. HCRYPTPROV hExportProv = pContentEncryptInfo->hCryptProv;
  3588. HCRYPTHASH hHash = 0;
  3589. HCRYPTKEY hDeriveKey = 0;
  3590. HCRYPTKEY hImportContentEncryptKey = 0;
  3591. #define BASE_DATA_LENGTH 8
  3592. BYTE rgbBaseData[BASE_DATA_LENGTH];
  3593. PBYTE pbContentKey = NULL;
  3594. DWORD cbContentKey = 0;
  3595. DWORD dwImportFlags;
  3596. DWORD dwAlgIdEncrypt;
  3597. DWORD dwBitLen;
  3598. BYTE rgbIV[IV_MAX_LENGTH];
  3599. DWORD cbIV;
  3600. const DWORD dw40BitLen = 40;
  3601. // Generate derive key to use to encrypt and export the content encrypt key
  3602. if (!CryptGenRandom(hExportProv, BASE_DATA_LENGTH, rgbBaseData))
  3603. goto GenRandomError;
  3604. if (!CryptCreateHash(hExportProv, CALG_SHA1, 0, 0, &hHash))
  3605. goto ExportCreateHashError;
  3606. if (!CryptHashData(hHash, rgbBaseData, BASE_DATA_LENGTH, 0))
  3607. goto ExportHashDataError;
  3608. if (!CryptDeriveKey(
  3609. hExportProv,
  3610. CALG_RC2,
  3611. hHash,
  3612. 40 << 16, // dwFlags, dwBitLen in upper WORD
  3613. &hDeriveKey))
  3614. goto ExportDeriveKeyError;
  3615. CryptSetKeyParam(
  3616. hDeriveKey,
  3617. KP_EFFECTIVE_KEYLEN,
  3618. (PBYTE) &dw40BitLen,
  3619. 0); // dwFlags
  3620. // Export the content encrypt key
  3621. if (!CryptExportKey(
  3622. pContentEncryptInfo->hContentEncryptKey,
  3623. hDeriveKey,
  3624. SYMMETRICWRAPKEYBLOB,
  3625. 0, // dwFlags
  3626. NULL,
  3627. &cbContentKey))
  3628. goto ExportKeyError;
  3629. if (NULL == (pbContentKey = (PBYTE) ICM_Alloc(cbContentKey)))
  3630. goto AllocError;
  3631. if (!CryptExportKey(
  3632. pContentEncryptInfo->hContentEncryptKey,
  3633. hDeriveKey,
  3634. SYMMETRICWRAPKEYBLOB,
  3635. 0, // dwFlags
  3636. pbContentKey,
  3637. &cbContentKey))
  3638. goto ExportKeyError;
  3639. // Generate derive key to use to decrypt and import the content encrypt key
  3640. CryptDestroyKey(hDeriveKey);
  3641. hDeriveKey = 0;
  3642. CryptDestroyHash(hHash);
  3643. hHash = 0;
  3644. if (!CryptCreateHash(hImportProv, CALG_SHA1, 0, 0, &hHash))
  3645. goto ImportCreateHashError;
  3646. if (!CryptHashData(hHash, rgbBaseData, BASE_DATA_LENGTH, 0))
  3647. goto ImportHashDataError;
  3648. if (!CryptDeriveKey(
  3649. hImportProv,
  3650. CALG_RC2,
  3651. hHash,
  3652. 40 << 16, // dwFlags, dwBitLen in upper WORD
  3653. &hDeriveKey))
  3654. goto ImportDeriveKeyError;
  3655. CryptSetKeyParam(
  3656. hDeriveKey,
  3657. KP_EFFECTIVE_KEYLEN,
  3658. (PBYTE) &dw40BitLen,
  3659. 0); // dwFlags
  3660. // Decrypt and import the content encrypt key
  3661. dwImportFlags = CRYPT_EXPORTABLE;
  3662. if (!ICM_IsSP3CompatibleEncrypt(pContentEncryptInfo))
  3663. dwImportFlags |= CRYPT_NO_SALT;
  3664. if (!CryptImportKey(
  3665. hImportProv,
  3666. pbContentKey,
  3667. cbContentKey,
  3668. hDeriveKey,
  3669. dwImportFlags,
  3670. &hImportContentEncryptKey))
  3671. goto ImportKeyError;
  3672. // Need to re-set effective key length and IV
  3673. if (!ICM_GetEncryptParameters(
  3674. &pContentEncryptInfo->ContentEncryptionAlgorithm,
  3675. &dwAlgIdEncrypt,
  3676. &dwBitLen,
  3677. rgbIV,
  3678. &cbIV))
  3679. goto GetEncryptParametersError;
  3680. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  3681. // Silently ignore any errors. Not supported in earlier versions
  3682. CryptSetKeyParam(
  3683. hImportContentEncryptKey,
  3684. KP_EFFECTIVE_KEYLEN,
  3685. (PBYTE) &dwBitLen,
  3686. 0); // dwFlags
  3687. if (0 != cbIV) {
  3688. if (CALG_RC4 == dwAlgIdEncrypt) {
  3689. // For RC4, set the SALT, not the IV
  3690. CRYPT_DATA_BLOB SaltBlob;
  3691. SaltBlob.pbData = rgbIV;
  3692. SaltBlob.cbData = cbIV;
  3693. if (!CryptSetKeyParam(
  3694. hImportContentEncryptKey,
  3695. KP_SALT_EX,
  3696. (PBYTE) &SaltBlob,
  3697. 0)) // dwFlags
  3698. goto SetSaltExError;
  3699. } else {
  3700. if (!CryptSetKeyParam(
  3701. hImportContentEncryptKey,
  3702. KP_IV,
  3703. rgbIV,
  3704. 0)) // dwFlags
  3705. goto SetIVError;
  3706. }
  3707. }
  3708. CommonReturn:
  3709. if (hDeriveKey)
  3710. CryptDestroyKey(hDeriveKey);
  3711. if (hHash)
  3712. CryptDestroyHash(hHash);
  3713. ICM_Free(pbContentKey);
  3714. ICM_SetLastError(dwError);
  3715. return hImportContentEncryptKey;
  3716. ErrorReturn:
  3717. dwError = GetLastError();
  3718. if (hImportContentEncryptKey) {
  3719. CryptDestroyKey(hImportContentEncryptKey);
  3720. hImportContentEncryptKey = 0;
  3721. }
  3722. goto CommonReturn;
  3723. TRACE_ERROR(GenRandomError)
  3724. TRACE_ERROR(ExportCreateHashError)
  3725. TRACE_ERROR(ExportHashDataError)
  3726. TRACE_ERROR(ExportDeriveKeyError)
  3727. TRACE_ERROR(ExportKeyError)
  3728. TRACE_ERROR(AllocError)
  3729. TRACE_ERROR(ImportCreateHashError)
  3730. TRACE_ERROR(ImportHashDataError)
  3731. TRACE_ERROR(ImportDeriveKeyError)
  3732. TRACE_ERROR(ImportKeyError)
  3733. TRACE_ERROR(GetEncryptParametersError)
  3734. TRACE_ERROR(SetSaltExError)
  3735. TRACE_ERROR(SetIVError)
  3736. }
  3737. //+-------------------------------------------------------------------------
  3738. // Export the encrypted content encrypt key using the KeyTrans or KeyAgree
  3739. // key.
  3740. //--------------------------------------------------------------------------
  3741. BOOL
  3742. WINAPI
  3743. ICM_ExportEncryptedKey(
  3744. IN HCRYPTKEY hContentEncryptKey,
  3745. IN HCRYPTKEY hPubKey,
  3746. IN DWORD dwBlobType,
  3747. IN BOOL fSP3CompatibleEncrypt,
  3748. OUT PCRYPT_DATA_BLOB pEncryptedKey
  3749. )
  3750. {
  3751. BOOL fRet;
  3752. PBYTE pbCspEncryptedKey = NULL;
  3753. DWORD cbCspEncryptedKey;
  3754. if (!CryptExportKey(
  3755. hContentEncryptKey,
  3756. hPubKey,
  3757. dwBlobType,
  3758. 0, // dwFlags
  3759. NULL,
  3760. &cbCspEncryptedKey))
  3761. goto ExportEncryptedKeyError;
  3762. if (NULL == (pbCspEncryptedKey = (PBYTE) ICM_AllocA(cbCspEncryptedKey)))
  3763. goto AllocError;
  3764. if (!CryptExportKey(
  3765. hContentEncryptKey,
  3766. hPubKey,
  3767. dwBlobType,
  3768. 0, // dwFlags
  3769. pbCspEncryptedKey,
  3770. &cbCspEncryptedKey))
  3771. goto ExportEncryptedKeyError;
  3772. assert(cbCspEncryptedKey >
  3773. (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)));
  3774. cbCspEncryptedKey -= sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  3775. if (NULL == (pEncryptedKey->pbData = (PBYTE) ICM_Alloc(cbCspEncryptedKey)))
  3776. goto AllocError;
  3777. pEncryptedKey->cbData = cbCspEncryptedKey;
  3778. if (SYMMETRICWRAPKEYBLOB == dwBlobType || fSP3CompatibleEncrypt)
  3779. // Don't byte reverse
  3780. memcpy(pEncryptedKey->pbData,
  3781. pbCspEncryptedKey +
  3782. (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)),
  3783. cbCspEncryptedKey);
  3784. else
  3785. ICM_ReverseCopy(pEncryptedKey->pbData,
  3786. pbCspEncryptedKey +
  3787. (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)),
  3788. cbCspEncryptedKey);
  3789. fRet = TRUE;
  3790. CommonReturn:
  3791. ICM_FreeA(pbCspEncryptedKey);
  3792. return fRet;
  3793. ErrorReturn:
  3794. fRet = FALSE;
  3795. goto CommonReturn;
  3796. TRACE_ERROR(AllocError)
  3797. TRACE_ERROR(ExportEncryptedKeyError)
  3798. }
  3799. BOOL
  3800. WINAPI
  3801. ICM_IsSameRecipientPublicKeyAlgorithm(
  3802. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey1,
  3803. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey2
  3804. )
  3805. {
  3806. DWORD dwAlgIdPubKey1;
  3807. DWORD dwAlgIdPubKey2;
  3808. if (0 == strcmp(paiPubKey1->pszObjId, paiPubKey2->pszObjId))
  3809. return TRUE;
  3810. ICM_GetCAPI(
  3811. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  3812. paiPubKey1,
  3813. &dwAlgIdPubKey1);
  3814. ICM_GetCAPI(
  3815. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  3816. paiPubKey2,
  3817. &dwAlgIdPubKey2);
  3818. if (dwAlgIdPubKey1 == dwAlgIdPubKey2)
  3819. return TRUE;
  3820. // If we don't know about either public key, default to being the same.
  3821. if (0 == dwAlgIdPubKey1 || 0 == dwAlgIdPubKey2)
  3822. return TRUE;
  3823. return FALSE;
  3824. }
  3825. //+-------------------------------------------------------------------------
  3826. // Default export of the encryption key for key transport recipient
  3827. //--------------------------------------------------------------------------
  3828. BOOL
  3829. WINAPI
  3830. #ifdef DEBUG_CRYPT_ASN1
  3831. ICMTest_DefaultExportKeyTrans(
  3832. #else
  3833. ICM_DefaultExportKeyTrans(
  3834. #endif
  3835. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  3836. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  3837. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
  3838. IN DWORD dwFlags,
  3839. IN OPTIONAL void *pvReserved
  3840. )
  3841. {
  3842. BOOL fRet;
  3843. DWORD dwError = ERROR_SUCCESS;
  3844. HCRYPTPROV hKeyTransProv = 0;
  3845. HCRYPTKEY hContentEncryptKey = 0;
  3846. CERT_PUBLIC_KEY_INFO PublicKeyInfo;
  3847. HCRYPTKEY hPubKey = 0;
  3848. hKeyTransProv = pKeyTransEncodeInfo->hCryptProv;
  3849. if (0 == hKeyTransProv) {
  3850. if (0 == pKeyTransEncryptInfo->dwRecipientIndex)
  3851. hKeyTransProv = pContentEncryptInfo->hCryptProv;
  3852. else {
  3853. // Check if the type of and public key algorithm for this
  3854. // recipient is the same as the first recipient's.
  3855. PCMSG_RECIPIENT_ENCODE_INFO prei;
  3856. prei = &pContentEncryptInfo->rgCmsRecipients[0];
  3857. if (CMSG_KEY_TRANS_RECIPIENT == prei->dwRecipientChoice &&
  3858. ICM_IsSameRecipientPublicKeyAlgorithm(
  3859. &prei->pKeyTrans->KeyEncryptionAlgorithm,
  3860. &pKeyTransEncryptInfo->KeyEncryptionAlgorithm))
  3861. hKeyTransProv = pContentEncryptInfo->hCryptProv;
  3862. else {
  3863. // Get default provider associated with the encryption
  3864. // and public key algorithms
  3865. DWORD dwAlgIdPubKey;
  3866. DWORD dwAlgIdEncrypt;
  3867. BYTE rgbIV[IV_MAX_LENGTH];
  3868. DWORD cbIV;
  3869. DWORD dwBitLen;
  3870. if (!ICM_GetEncryptParameters(
  3871. &pContentEncryptInfo->ContentEncryptionAlgorithm,
  3872. &dwAlgIdEncrypt,
  3873. &dwBitLen,
  3874. rgbIV,
  3875. &cbIV))
  3876. goto GetEncryptParametersError;
  3877. ICM_GetCAPI(
  3878. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  3879. &pKeyTransEncryptInfo->KeyEncryptionAlgorithm,
  3880. &dwAlgIdPubKey);
  3881. hKeyTransProv = I_CryptGetDefaultCryptProvForEncrypt(
  3882. dwAlgIdPubKey, dwAlgIdEncrypt, dwBitLen);
  3883. if (0 == hKeyTransProv)
  3884. goto GetDefaultCryptProvError;
  3885. }
  3886. }
  3887. }
  3888. if (hKeyTransProv != pContentEncryptInfo->hCryptProv) {
  3889. // Need to export the hContentEncryptKey from the ContentEncrypt
  3890. // provider and import into the KeyTrans provider
  3891. hContentEncryptKey = ICM_ExportContentEncryptKeyAndImport(
  3892. pContentEncryptInfo,
  3893. hKeyTransProv);
  3894. if (0 == hContentEncryptKey)
  3895. goto ImportContentKeyError;
  3896. } else
  3897. hContentEncryptKey = pContentEncryptInfo->hContentEncryptKey;
  3898. PublicKeyInfo.Algorithm = pKeyTransEncryptInfo->KeyEncryptionAlgorithm;
  3899. PublicKeyInfo.PublicKey = pKeyTransEncodeInfo->RecipientPublicKey;
  3900. if (!CryptImportPublicKeyInfo(
  3901. hKeyTransProv,
  3902. X509_ASN_ENCODING,
  3903. &PublicKeyInfo,
  3904. &hPubKey))
  3905. goto ImportPubKeyError;
  3906. if (!ICM_ExportEncryptedKey(
  3907. hContentEncryptKey,
  3908. hPubKey,
  3909. SIMPLEBLOB,
  3910. ICM_IsSP3CompatibleEncrypt(pContentEncryptInfo),
  3911. &pKeyTransEncryptInfo->EncryptedKey))
  3912. goto ExportEncryptedKeyError;
  3913. fRet = TRUE;
  3914. CommonReturn:
  3915. if (hKeyTransProv != pContentEncryptInfo->hCryptProv &&
  3916. hContentEncryptKey)
  3917. CryptDestroyKey(hContentEncryptKey);
  3918. if (hPubKey)
  3919. CryptDestroyKey(hPubKey);
  3920. ICM_SetLastError(dwError);
  3921. return fRet;
  3922. ErrorReturn:
  3923. dwError = GetLastError();
  3924. fRet = FALSE;
  3925. goto CommonReturn;
  3926. TRACE_ERROR(GetEncryptParametersError)
  3927. TRACE_ERROR(GetDefaultCryptProvError)
  3928. TRACE_ERROR(ImportContentKeyError)
  3929. TRACE_ERROR(ImportPubKeyError)
  3930. TRACE_ERROR(ExportEncryptedKeyError)
  3931. }
  3932. BOOL
  3933. WINAPI
  3934. ICM_ExportKeyTrans(
  3935. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  3936. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  3937. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo
  3938. )
  3939. {
  3940. BOOL fRet;
  3941. void *pvFuncAddr;
  3942. HCRYPTOIDFUNCADDR hFuncAddr = NULL;
  3943. LPCSTR pszKeyEncryptOID =
  3944. pKeyTransEncryptInfo->KeyEncryptionAlgorithm.pszObjId;
  3945. if (CryptGetOIDFunctionAddress(
  3946. hExportKeyTransFuncSet,
  3947. X509_ASN_ENCODING,
  3948. pszKeyEncryptOID,
  3949. 0, // dwFlags
  3950. &pvFuncAddr,
  3951. &hFuncAddr)) {
  3952. fRet = ((PFN_CMSG_EXPORT_KEY_TRANS) pvFuncAddr)(
  3953. pContentEncryptInfo,
  3954. pKeyTransEncodeInfo,
  3955. pKeyTransEncryptInfo,
  3956. 0, // dwFlags
  3957. NULL // pvReserved
  3958. );
  3959. } else if ((NULL == pKeyTransEncodeInfo->hCryptProv ||
  3960. pKeyTransEncodeInfo->hCryptProv ==
  3961. pContentEncryptInfo->hCryptProv)
  3962. &&
  3963. CryptGetOIDFunctionAddress(
  3964. hOldStyleExportEncryptKeyFuncSet,
  3965. X509_ASN_ENCODING,
  3966. pszKeyEncryptOID,
  3967. 0, // dwFlags
  3968. &pvFuncAddr,
  3969. &hFuncAddr)
  3970. &&
  3971. #ifdef DEBUG_CRYPT_ASN1
  3972. 0 == (ICMTest_GetDebugCryptAsn1Flags() &
  3973. DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG)
  3974. &&
  3975. #endif // DEBUG_CRYPT_ASN1
  3976. (void *) ICM_DefaultExportEncryptKey != pvFuncAddr) {
  3977. CERT_PUBLIC_KEY_INFO PublicKeyInfo;
  3978. PBYTE pbData;
  3979. DWORD rgcbData[2] = {0, 0};
  3980. if (ICM_IsSP3CompatibleEncrypt(pContentEncryptInfo))
  3981. rgcbData[1] = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  3982. PublicKeyInfo.Algorithm = pKeyTransEncryptInfo->KeyEncryptionAlgorithm;
  3983. PublicKeyInfo.PublicKey = pKeyTransEncodeInfo->RecipientPublicKey;
  3984. fRet = ((PFN_CMSG_EXPORT_ENCRYPT_KEY) pvFuncAddr)(
  3985. pContentEncryptInfo->hCryptProv,
  3986. pContentEncryptInfo->hContentEncryptKey,
  3987. &PublicKeyInfo,
  3988. NULL, // pbData
  3989. rgcbData);
  3990. if (fRet) {
  3991. if (NULL == (pbData = (PBYTE) ICM_Alloc(rgcbData[0])))
  3992. fRet = FALSE;
  3993. else {
  3994. fRet = ((PFN_CMSG_EXPORT_ENCRYPT_KEY) pvFuncAddr)(
  3995. pContentEncryptInfo->hCryptProv,
  3996. pContentEncryptInfo->hContentEncryptKey,
  3997. &PublicKeyInfo,
  3998. pbData,
  3999. rgcbData);
  4000. if (fRet) {
  4001. pKeyTransEncryptInfo->EncryptedKey.pbData = pbData;
  4002. pKeyTransEncryptInfo->EncryptedKey.cbData = rgcbData[0];
  4003. } else
  4004. ICM_Free(pbData);
  4005. }
  4006. }
  4007. } else
  4008. fRet = ICM_DefaultExportKeyTrans(
  4009. pContentEncryptInfo,
  4010. pKeyTransEncodeInfo,
  4011. pKeyTransEncryptInfo,
  4012. 0, // dwFlags
  4013. NULL // pvReserved
  4014. );
  4015. if (hFuncAddr)
  4016. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  4017. return fRet;
  4018. }
  4019. //+-------------------------------------------------------------------------
  4020. // Get the CAPI ALG_ID corresponding to the wrap encryption OID.
  4021. //
  4022. // For RC2, if the ASN.1 encryption algorithm has any parameters, decode to
  4023. // get the key bit length.
  4024. //--------------------------------------------------------------------------
  4025. BOOL
  4026. WINAPI
  4027. ICM_GetWrapEncryptParameters(
  4028. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  4029. OUT PDWORD pdwAlgIdEncrypt,
  4030. OUT PDWORD pdwBitLen // 0 => default length
  4031. )
  4032. {
  4033. BOOL fRet;
  4034. *pdwBitLen = 0;
  4035. if (!ICM_GetCAPI(
  4036. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  4037. paiEncrypt,
  4038. pdwAlgIdEncrypt))
  4039. goto GetCAPIError;
  4040. if (CALG_RC2 == *pdwAlgIdEncrypt) {
  4041. // Check if more than just the NULL parameters
  4042. if (2 < paiEncrypt->Parameters.cbData) {
  4043. PBYTE pbEncoded = paiEncrypt->Parameters.pbData;
  4044. DWORD cbEncoded = paiEncrypt->Parameters.cbData;
  4045. // Try to decode as an integer containing the RC2 version
  4046. int iVersion = 0;
  4047. DWORD cbStructInfo = sizeof(iVersion);
  4048. if (!CryptDecodeObject(
  4049. X509_ASN_ENCODING,
  4050. X509_INTEGER,
  4051. pbEncoded,
  4052. cbEncoded,
  4053. 0, // dwFlags
  4054. &iVersion,
  4055. &cbStructInfo))
  4056. goto RC2VersionDecodeError;
  4057. if (!ICM_RC2VersionToBitLength(iVersion, pdwBitLen))
  4058. goto RC2VersionToBitLengthError;
  4059. } else
  4060. *pdwBitLen = 40;
  4061. }
  4062. fRet = TRUE;
  4063. CommonReturn:
  4064. return fRet;
  4065. ErrorReturn:
  4066. fRet = FALSE;
  4067. goto CommonReturn;
  4068. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  4069. TRACE_ERROR(RC2VersionDecodeError)
  4070. TRACE_ERROR(RC2VersionToBitLengthError)
  4071. }
  4072. //+-------------------------------------------------------------------------
  4073. // Get the CAPI ALG_ID and bit length by decoding the DH Encryption Parameters
  4074. //--------------------------------------------------------------------------
  4075. BOOL
  4076. WINAPI
  4077. ICM_GetDhWrapEncryptParameters(
  4078. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  4079. OUT LPSTR *ppszAllocWrapOID,
  4080. OUT PDWORD pdwAlgIdWrap,
  4081. OUT PDWORD pdwBitLen // 0 => default length
  4082. )
  4083. {
  4084. DWORD dwError = ERROR_SUCCESS;
  4085. BOOL fRet;
  4086. ASN1error_e Asn1Err;
  4087. ASN1decoding_t pDec = ICM_GetDecoder();
  4088. AlgorithmIdentifier *poai = NULL;
  4089. CRYPT_ALGORITHM_IDENTIFIER ai; ZEROSTRUCT(ai);
  4090. // Decode the DH KeyEncryption Parameters to get the Wrap Encryption
  4091. // Algorithm
  4092. if (0 == paiEncrypt->Parameters.cbData)
  4093. goto NoDhWrapParametersError;
  4094. if (0 != (Asn1Err = PkiAsn1Decode(
  4095. pDec,
  4096. (void **)&poai,
  4097. AlgorithmIdentifier_PDU,
  4098. paiEncrypt->Parameters.pbData,
  4099. paiEncrypt->Parameters.cbData)))
  4100. goto Asn1DecodeAlgorithmIdentifierError;
  4101. if (!ICM_Asn1FromAlgorithmIdentifier(poai, &ai))
  4102. goto Asn1FromAlgorithmIdentifierError;
  4103. if (!ICM_GetWrapEncryptParameters(&ai, pdwAlgIdWrap, pdwBitLen))
  4104. goto GetWrapEncryptParametersError;
  4105. *ppszAllocWrapOID = ai.pszObjId;
  4106. fRet = TRUE;
  4107. CommonReturn:
  4108. PkiAsn1FreeInfo(pDec, AlgorithmIdentifier_PDU, poai);
  4109. ICM_SetLastError(dwError);
  4110. return fRet;
  4111. ErrorReturn:
  4112. dwError = GetLastError();
  4113. ICM_Free(ai.pszObjId);
  4114. *ppszAllocWrapOID = NULL;
  4115. *pdwBitLen = 0;
  4116. *pdwAlgIdWrap = 0;
  4117. fRet = FALSE;
  4118. goto CommonReturn;
  4119. SET_ERROR(NoDhWrapParametersError, CRYPT_E_UNKNOWN_ALGO)
  4120. SET_ERROR_VAR(Asn1DecodeAlgorithmIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  4121. TRACE_ERROR(Asn1FromAlgorithmIdentifierError)
  4122. TRACE_ERROR(GetWrapEncryptParametersError)
  4123. }
  4124. //+-------------------------------------------------------------------------
  4125. // Get the CAPI ALG_ID corresponding to the wrap encryption OID. Generate
  4126. // default parameters for and encode. For RC2, encode as RC2ParameterVersion
  4127. // integer.
  4128. //--------------------------------------------------------------------------
  4129. BOOL
  4130. WINAPI
  4131. ICM_CreateDefaultWrapEncryptParameters(
  4132. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4133. IN OUT PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  4134. IN PVOID pvEncryptAuxInfo,
  4135. OUT PDWORD pdwAlgIdEncrypt,
  4136. OUT PDWORD pdwBitLen // 0 => default length
  4137. )
  4138. {
  4139. BOOL fRet;
  4140. assert(0 == paiEncrypt->Parameters.cbData);
  4141. *pdwBitLen = 0;
  4142. if (!ICM_GetCAPI(
  4143. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  4144. paiEncrypt,
  4145. pdwAlgIdEncrypt))
  4146. goto GetCAPIError;
  4147. if (CALG_RC2 == *pdwAlgIdEncrypt) {
  4148. PCMSG_RC2_AUX_INFO pAuxInfo =
  4149. (PCMSG_RC2_AUX_INFO) pvEncryptAuxInfo;
  4150. CRYPT_ENCODE_PARA EncodePara;
  4151. int iVersion;
  4152. if (pAuxInfo && pAuxInfo->cbSize >= sizeof(CMSG_RC2_AUX_INFO)) {
  4153. DWORD dwVersion;
  4154. *pdwBitLen = pAuxInfo->dwBitLen & AUX_INFO_BIT_LENGTH_MASK;
  4155. if (!ICM_BitLengthToRC2Version(*pdwBitLen, &dwVersion))
  4156. goto BitLengthToRC2VersionError;
  4157. iVersion = dwVersion;
  4158. } else {
  4159. iVersion = CRYPT_RC2_40BIT_VERSION;
  4160. *pdwBitLen = 40;
  4161. }
  4162. ZEROSTRUCT(EncodePara);
  4163. EncodePara.cbSize = sizeof(EncodePara);
  4164. EncodePara.pfnAlloc = pContentEncryptInfo->pfnAlloc;
  4165. EncodePara.pfnFree = pContentEncryptInfo->pfnFree;
  4166. if (!CryptEncodeObjectEx(
  4167. X509_ASN_ENCODING,
  4168. X509_INTEGER,
  4169. &iVersion,
  4170. CRYPT_ENCODE_ALLOC_FLAG,
  4171. &EncodePara,
  4172. (void *) &paiEncrypt->Parameters.pbData,
  4173. &paiEncrypt->Parameters.cbData
  4174. )) goto EncodeError;
  4175. }
  4176. fRet = TRUE;
  4177. CommonReturn:
  4178. return fRet;
  4179. ErrorReturn:
  4180. fRet = FALSE;
  4181. goto CommonReturn;
  4182. SET_ERROR(GetCAPIError, CRYPT_E_UNKNOWN_ALGO)
  4183. TRACE_ERROR(BitLengthToRC2VersionError)
  4184. TRACE_ERROR(EncodeError)
  4185. }
  4186. //+-------------------------------------------------------------------------
  4187. // Get the CAPI ALG_ID corresponding to the wrap encryption OID.
  4188. // Encode the DH EncryptionAlgorithmIdentifier parameters which is the encoded
  4189. // WrapAlgorithmIdentifier.
  4190. //--------------------------------------------------------------------------
  4191. BOOL
  4192. WINAPI
  4193. ICM_CreateDefaultDhWrapEncryptParameters(
  4194. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4195. IN OUT PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  4196. IN PCRYPT_ALGORITHM_IDENTIFIER paiWrap,
  4197. IN PVOID pvWrapAuxInfo,
  4198. OUT PDWORD pdwAlgIdWrap,
  4199. OUT PDWORD pdwBitLen // 0 => default length
  4200. )
  4201. {
  4202. BOOL fRet;
  4203. CRYPT_ALGORITHM_IDENTIFIER aiWrap; ZEROSTRUCT(aiWrap);
  4204. AlgorithmIdentifier oaiWrap;
  4205. assert(0 == paiEncrypt->Parameters.cbData);
  4206. if (0 == paiWrap->Parameters.cbData) {
  4207. aiWrap = *paiWrap;
  4208. if (!ICM_CreateDefaultWrapEncryptParameters(
  4209. pContentEncryptInfo,
  4210. &aiWrap,
  4211. pvWrapAuxInfo,
  4212. pdwAlgIdWrap,
  4213. pdwBitLen))
  4214. goto CreateDefaultWrapEncryptParametersError;
  4215. paiWrap = &aiWrap;
  4216. } else {
  4217. if (!ICM_GetWrapEncryptParameters(
  4218. paiWrap,
  4219. pdwAlgIdWrap,
  4220. pdwBitLen))
  4221. goto GetWrapEncryptParametersError;
  4222. }
  4223. // Encode the Wrap Algorithm Identifier
  4224. if (!ICM_Asn1ToAlgorithmIdentifier(
  4225. paiWrap,
  4226. &oaiWrap))
  4227. goto Asn1ToAlgorithmIdentifierError;
  4228. if (!ICM_Asn1Encode(
  4229. AlgorithmIdentifier_PDU,
  4230. &oaiWrap,
  4231. &paiEncrypt->Parameters))
  4232. goto EncodeAlgorithmIdentifierError;
  4233. fRet = TRUE;
  4234. CommonReturn:
  4235. ICM_Free(aiWrap.Parameters.pbData);
  4236. return fRet;
  4237. ErrorReturn:
  4238. fRet = FALSE;
  4239. goto CommonReturn;
  4240. TRACE_ERROR(CreateDefaultWrapEncryptParametersError)
  4241. TRACE_ERROR(GetWrapEncryptParametersError)
  4242. TRACE_ERROR(Asn1ToAlgorithmIdentifierError)
  4243. TRACE_ERROR(EncodeAlgorithmIdentifierError)
  4244. }
  4245. BOOL
  4246. WINAPI
  4247. ICM_PadEncodedOctets(
  4248. IN DWORD cbMaxContents,
  4249. IN OUT BYTE **ppbEncoded,
  4250. IN OUT DWORD *pcbEncoded
  4251. )
  4252. {
  4253. BOOL fRet;
  4254. DWORD cbEncoded = *pcbEncoded;
  4255. DWORD cbMaxEncoded;
  4256. DWORD cbLength;
  4257. ICM_GetLengthOctets(cbMaxContents, NULL, &cbLength);
  4258. cbMaxEncoded = 1 + cbLength + cbMaxContents;
  4259. if (cbMaxEncoded > cbEncoded) {
  4260. BYTE *pbMaxEncoded;
  4261. BYTE *pbEncoded;
  4262. if (NULL == (pbMaxEncoded = (BYTE *) ICM_Alloc(cbMaxEncoded)))
  4263. goto OutOfMemory;
  4264. pbEncoded = *ppbEncoded;
  4265. memcpy(pbMaxEncoded, pbEncoded, cbEncoded);
  4266. memset(pbMaxEncoded + cbEncoded, 0, cbMaxEncoded - cbEncoded);
  4267. ICM_Free(pbEncoded);
  4268. *ppbEncoded = pbMaxEncoded;
  4269. *pcbEncoded = cbMaxEncoded;
  4270. } else if (cbMaxEncoded < cbEncoded)
  4271. goto InvalidMaxEncodedLength;
  4272. fRet = TRUE;
  4273. CommonReturn:
  4274. return fRet;
  4275. ErrorReturn:
  4276. fRet = FALSE;
  4277. goto CommonReturn;
  4278. TRACE_ERROR(OutOfMemory)
  4279. SET_ERROR(InvalidMaxEncodedLength, ERROR_INVALID_DATA)
  4280. }
  4281. #ifndef DH1
  4282. #define DH1 (((DWORD)'D'<<8)+((DWORD)'H'<<16)+((DWORD)'1'<<24))
  4283. #endif
  4284. HCRYPTKEY
  4285. WINAPI
  4286. ICM_GenerateEphemeralDh(
  4287. IN HCRYPTPROV hProv,
  4288. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4289. IN PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgreeEncodeInfo,
  4290. IN OUT PCMSG_KEY_AGREE_ENCRYPT_INFO pKeyAgreeEncryptInfo,
  4291. OUT DWORD *pcbP
  4292. )
  4293. {
  4294. DWORD dwError = ERROR_SUCCESS;
  4295. HCRYPTKEY hEphemeralKey = 0;
  4296. PCRYPT_ALGORITHM_IDENTIFIER paiEphemeral =
  4297. pKeyAgreeEncodeInfo->pEphemeralAlgorithm;
  4298. PCERT_PUBLIC_KEY_INFO pPubKeyInfo =
  4299. &pKeyAgreeEncryptInfo->OriginatorPublicKeyInfo;
  4300. PCERT_X942_DH_PARAMETERS pDhParameters = NULL;
  4301. PUBLICKEYSTRUC *pPubKeyStruc = NULL;
  4302. DWORD cbPubKeyStruc;
  4303. BYTE *pbKeyBlob;
  4304. DHPUBKEY *pCspPubKey;
  4305. DWORD cbP;
  4306. PCRYPT_UINT_BLOB pGBlob;
  4307. BYTE *pbY;
  4308. DWORD cbY;
  4309. CRYPT_UINT_BLOB YBlob;
  4310. CRYPT_ENCODE_PARA EncodePara;
  4311. assert(CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE ==
  4312. pKeyAgreeEncodeInfo->dwKeyChoice);
  4313. if (NULL == (pDhParameters =
  4314. (PCERT_X942_DH_PARAMETERS) ICM_AllocAndDecodeObject(
  4315. X942_DH_PARAMETERS,
  4316. paiEphemeral->Parameters.pbData,
  4317. paiEphemeral->Parameters.cbData)))
  4318. goto DhParametersDecodeError;
  4319. cbP = pDhParameters->p.cbData;
  4320. *pcbP = cbP;
  4321. if (!CryptGenKey(
  4322. hProv,
  4323. CALG_DH_EPHEM,
  4324. ((cbP * 8) << 16) | CRYPT_EXPORTABLE | CRYPT_PREGEN,
  4325. &hEphemeralKey))
  4326. goto GenEphemeralKeyError;
  4327. if (!CryptSetKeyParam(
  4328. hEphemeralKey,
  4329. KP_P,
  4330. (PBYTE) &pDhParameters->p,
  4331. 0)) // dwFlags
  4332. goto SetPError;
  4333. // Note, the length of G can be less than length P. Pad with leading
  4334. // zeroes in little endian form.
  4335. if (pDhParameters->g.cbData >= cbP)
  4336. pGBlob = &pDhParameters->g;
  4337. else {
  4338. DWORD cbG = pDhParameters->g.cbData;
  4339. // We are done using P parameter. Overwrite with the G parameter and
  4340. // pad with leading zeroes in little endian form.
  4341. pGBlob = &pDhParameters->p;
  4342. memcpy(pGBlob->pbData, pDhParameters->g.pbData, cbG);
  4343. memset(pGBlob->pbData + cbG, 0, cbP - cbG);
  4344. }
  4345. if (!CryptSetKeyParam(
  4346. hEphemeralKey,
  4347. KP_G,
  4348. (PBYTE) pGBlob,
  4349. 0)) // dwFlags
  4350. goto SetGError;
  4351. if (0 < pDhParameters->q.cbData) {
  4352. if (!CryptSetKeyParam(
  4353. hEphemeralKey,
  4354. KP_Q,
  4355. (PBYTE) &pDhParameters->q,
  4356. 0)) // dwFlags
  4357. goto SetQError;
  4358. }
  4359. if (!CryptSetKeyParam(
  4360. hEphemeralKey,
  4361. KP_X,
  4362. NULL, // pbData
  4363. 0)) // dwFlags
  4364. goto SetXError;
  4365. // Export the public key to get Y
  4366. cbPubKeyStruc = 0;
  4367. if (!CryptExportKey(
  4368. hEphemeralKey,
  4369. 0, // hPubKey
  4370. PUBLICKEYBLOB,
  4371. 0, // dwFlags
  4372. NULL, // pbData
  4373. &cbPubKeyStruc
  4374. ) || (cbPubKeyStruc == 0))
  4375. goto ExportPublicKeyBlobError;
  4376. if (NULL == (pPubKeyStruc = (PUBLICKEYSTRUC *) ICM_Alloc(cbPubKeyStruc)))
  4377. goto OutOfMemory;
  4378. if (!CryptExportKey(
  4379. hEphemeralKey,
  4380. 0, // hPubKey
  4381. PUBLICKEYBLOB,
  4382. 0, // dwFlags
  4383. (BYTE *) pPubKeyStruc,
  4384. &cbPubKeyStruc
  4385. ))
  4386. goto ExportPublicKeyBlobError;
  4387. // The CAPI public key representation consists of the following sequence:
  4388. // - PUBLICKEYSTRUC
  4389. // - DHPUBKEY
  4390. // - rgbY[cbKey]
  4391. pbKeyBlob = (BYTE *) pPubKeyStruc;
  4392. pCspPubKey = (DHPUBKEY *) (pbKeyBlob + sizeof(PUBLICKEYSTRUC));
  4393. pbY = pbKeyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY);
  4394. cbY = pCspPubKey->bitlen / 8;
  4395. if (cbPubKeyStruc < sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY) + cbY)
  4396. goto InvalidEphemeralKey;
  4397. if (pPubKeyStruc->bType != PUBLICKEYBLOB)
  4398. goto InvalidEphemeralKey;
  4399. if (pCspPubKey->magic != DH1)
  4400. goto InvalidEphemeralKey;
  4401. if (cbY != cbP)
  4402. goto InvalidEphemeralKey;
  4403. ZEROSTRUCT(EncodePara);
  4404. EncodePara.cbSize = sizeof(EncodePara);
  4405. EncodePara.pfnAlloc = pContentEncryptInfo->pfnAlloc;
  4406. EncodePara.pfnFree = pContentEncryptInfo->pfnFree;
  4407. YBlob.pbData = pbY;
  4408. YBlob.cbData = cbY;
  4409. if (!CryptEncodeObjectEx(
  4410. X509_ASN_ENCODING,
  4411. X509_DH_PUBLICKEY,
  4412. &YBlob,
  4413. CRYPT_ENCODE_ALLOC_FLAG,
  4414. &EncodePara,
  4415. (void *) &pPubKeyInfo->PublicKey.pbData,
  4416. &pPubKeyInfo->PublicKey.cbData
  4417. ))
  4418. goto EncodeDHPublicKeyError;
  4419. pKeyAgreeEncryptInfo->dwOriginatorChoice =
  4420. CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY;
  4421. pPubKeyInfo->Algorithm.pszObjId = paiEphemeral->pszObjId;
  4422. pKeyAgreeEncryptInfo->dwFlags |=
  4423. CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_BITS_FLAG;
  4424. if (pContentEncryptInfo->dwEncryptFlags &
  4425. CMSG_CONTENT_ENCRYPT_PAD_ENCODED_LEN_FLAG) {
  4426. if (!ICM_PadEncodedOctets(
  4427. cbY + 1,
  4428. &pPubKeyInfo->PublicKey.pbData,
  4429. &pPubKeyInfo->PublicKey.cbData
  4430. ))
  4431. goto PadEncodedOctetsError;
  4432. }
  4433. CommonReturn:
  4434. ICM_Free(pDhParameters);
  4435. ICM_Free(pPubKeyStruc);
  4436. ICM_SetLastError(dwError);
  4437. return hEphemeralKey;
  4438. ErrorReturn:
  4439. dwError = GetLastError();
  4440. if (hEphemeralKey) {
  4441. CryptDestroyKey(hEphemeralKey);
  4442. hEphemeralKey = 0;
  4443. }
  4444. goto CommonReturn;
  4445. TRACE_ERROR(DhParametersDecodeError)
  4446. TRACE_ERROR(GenEphemeralKeyError)
  4447. TRACE_ERROR(SetPError)
  4448. TRACE_ERROR(SetGError)
  4449. TRACE_ERROR(SetQError)
  4450. TRACE_ERROR(SetXError)
  4451. TRACE_ERROR(ExportPublicKeyBlobError)
  4452. SET_ERROR(InvalidEphemeralKey, NTE_BAD_PUBLIC_KEY)
  4453. TRACE_ERROR(OutOfMemory)
  4454. TRACE_ERROR(EncodeDHPublicKeyError)
  4455. TRACE_ERROR(PadEncodedOctetsError)
  4456. }
  4457. HCRYPTKEY
  4458. WINAPI
  4459. ICM_ImportDhAgreeKey(
  4460. IN HCRYPTPROV hKeyAgreeProv,
  4461. IN HCRYPTKEY hMyKey,
  4462. IN DWORD cbP,
  4463. IN PCRYPT_BIT_BLOB pPublicKey,
  4464. IN LPSTR pszWrapOID,
  4465. IN ALG_ID AlgidWrap,
  4466. IN DWORD dwBitLen,
  4467. IN PCRYPT_DATA_BLOB pUserKeyingMaterial
  4468. )
  4469. {
  4470. DWORD dwError = ERROR_SUCCESS;
  4471. HCRYPTKEY hAgreeKey = 0;
  4472. PCRYPT_UINT_BLOB pDhPubKey = NULL;
  4473. PBYTE pbKeyBlob = NULL;
  4474. DWORD cbKeyBlob;
  4475. PUBLICKEYSTRUC *pPubKeyStruc;
  4476. DHPUBKEY *pCspPubKey;
  4477. DWORD cbY;
  4478. PBYTE pbKey;
  4479. CMS_DH_KEY_INFO CmsDhKeyInfo; ZEROSTRUCT(CmsDhKeyInfo);
  4480. if (NULL == (pDhPubKey = (PCRYPT_UINT_BLOB) ICM_AllocAndDecodeObject(
  4481. X509_DH_PUBLICKEY,
  4482. pPublicKey->pbData,
  4483. pPublicKey->cbData)))
  4484. goto DecodePubKeyError;
  4485. // The CAPI public key representation consists of the following sequence:
  4486. // - PUBLICKEYSTRUC
  4487. // - DHPUBKEY
  4488. // - rgbY[cbP]
  4489. cbY = pDhPubKey->cbData;
  4490. if (0 == cbY || cbY > cbP)
  4491. goto InvalidDhPubKeyError;
  4492. cbKeyBlob = sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY) + cbP;
  4493. if (NULL == (pbKeyBlob = (PBYTE) ICM_Alloc(cbKeyBlob)))
  4494. goto OutOfMemory;
  4495. pPubKeyStruc = (PUBLICKEYSTRUC *) pbKeyBlob;
  4496. pCspPubKey = (DHPUBKEY *) (pbKeyBlob + sizeof(PUBLICKEYSTRUC));
  4497. pbKey = pbKeyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY);
  4498. // PUBLICKEYSTRUC
  4499. pPubKeyStruc->bType = PUBLICKEYBLOB;
  4500. pPubKeyStruc->bVersion = CUR_BLOB_VERSION;
  4501. pPubKeyStruc->reserved = 0;
  4502. pPubKeyStruc->aiKeyAlg = CALG_DH_SF;
  4503. // DHPUBKEY
  4504. pCspPubKey->magic = DH1;
  4505. pCspPubKey->bitlen = cbP * 8;
  4506. // rgbY[cbP]
  4507. memcpy(pbKey, pDhPubKey->pbData, cbY);
  4508. if (cbP > cbY)
  4509. memset(pbKey + cbY, 0, cbP - cbY);
  4510. if (!CryptImportKey(
  4511. hKeyAgreeProv,
  4512. pbKeyBlob,
  4513. cbKeyBlob,
  4514. hMyKey,
  4515. 0, // dwFlags
  4516. &hAgreeKey)) {
  4517. hAgreeKey = 0;
  4518. goto ImportKeyError;
  4519. }
  4520. CmsDhKeyInfo.dwVersion = sizeof(CmsDhKeyInfo);
  4521. CmsDhKeyInfo.Algid = AlgidWrap;
  4522. CmsDhKeyInfo.pszContentEncObjId = pszWrapOID;
  4523. CmsDhKeyInfo.PubInfo = *pUserKeyingMaterial;
  4524. // CmsDhKeyInfo.pReserved
  4525. if (!CryptSetKeyParam(
  4526. hAgreeKey,
  4527. KP_CMS_DH_KEY_INFO,
  4528. (PBYTE) &CmsDhKeyInfo,
  4529. (CALG_RC2 == AlgidWrap) ? (dwBitLen << 16) : 0)) // dwFlags
  4530. goto SetCmsDhKeyInfoError;
  4531. if (CALG_RC2 == AlgidWrap && 0 != dwBitLen) {
  4532. if (!CryptSetKeyParam(
  4533. hAgreeKey,
  4534. KP_EFFECTIVE_KEYLEN,
  4535. (PBYTE) &dwBitLen,
  4536. 0)) // dwFlags
  4537. goto SetEffectiveKeyLenError;
  4538. }
  4539. CommonReturn:
  4540. ICM_Free(pDhPubKey);
  4541. ICM_Free(pbKeyBlob);
  4542. ICM_SetLastError(dwError);
  4543. return hAgreeKey;
  4544. ErrorReturn:
  4545. dwError = GetLastError();
  4546. if (hAgreeKey) {
  4547. CryptDestroyKey(hAgreeKey);
  4548. hAgreeKey = 0;
  4549. }
  4550. goto CommonReturn;
  4551. TRACE_ERROR(DecodePubKeyError)
  4552. SET_ERROR(InvalidDhPubKeyError, E_INVALIDARG)
  4553. TRACE_ERROR(OutOfMemory)
  4554. TRACE_ERROR(ImportKeyError)
  4555. TRACE_ERROR(SetCmsDhKeyInfoError)
  4556. TRACE_ERROR(SetEffectiveKeyLenError)
  4557. }
  4558. BOOL
  4559. WINAPI
  4560. ICM_DefaultExportKeyAgree(
  4561. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4562. IN PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgreeEncodeInfo,
  4563. IN OUT PCMSG_KEY_AGREE_ENCRYPT_INFO pKeyAgreeEncryptInfo,
  4564. IN DWORD dwFlags,
  4565. IN OPTIONAL void *pvReserved
  4566. )
  4567. {
  4568. BOOL fRet;
  4569. DWORD dwError = ERROR_SUCCESS;
  4570. HCRYPTPROV hKeyAgreeProv = 0; // Doesn't need to be released
  4571. HCRYPTKEY hContentEncryptKey = 0;
  4572. HCRYPTKEY hEphemeralKey = 0;
  4573. HCRYPTKEY hAgreeKey = 0;
  4574. DWORD cbP;
  4575. PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt =
  4576. &pKeyAgreeEncryptInfo->KeyEncryptionAlgorithm;
  4577. LPSTR pszAllocWrapOID = NULL;
  4578. LPSTR pszWrapOID;
  4579. DWORD dwAlgIdWrap;
  4580. DWORD dwBitLen;
  4581. DWORD cRecipient;
  4582. PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO *ppRecipientEncryptInfo;
  4583. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *ppRecipientEncodeInfo;
  4584. assert(CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE ==
  4585. pKeyAgreeEncodeInfo->dwKeyChoice);
  4586. if (CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE != pKeyAgreeEncodeInfo->dwKeyChoice)
  4587. goto InvalidKeyAgreeKeyChoice;
  4588. if (0 == paiEncrypt->Parameters.cbData) {
  4589. PCRYPT_ALGORITHM_IDENTIFIER paiWrap =
  4590. &pKeyAgreeEncodeInfo->KeyWrapAlgorithm;
  4591. if (!ICM_CreateDefaultDhWrapEncryptParameters(
  4592. pContentEncryptInfo,
  4593. paiEncrypt,
  4594. paiWrap,
  4595. pKeyAgreeEncodeInfo->pvKeyWrapAuxInfo,
  4596. &dwAlgIdWrap,
  4597. &dwBitLen))
  4598. goto CreateDefaultDhWrapEncryptParametersError;
  4599. assert(paiEncrypt->Parameters.cbData);
  4600. pKeyAgreeEncryptInfo->dwFlags |= CMSG_KEY_AGREE_ENCRYPT_FREE_PARA_FLAG;
  4601. pszWrapOID = paiWrap->pszObjId;
  4602. } else {
  4603. if (!ICM_GetDhWrapEncryptParameters(
  4604. paiEncrypt,
  4605. &pszAllocWrapOID,
  4606. &dwAlgIdWrap,
  4607. &dwBitLen))
  4608. goto GetDhWrapEncryptParametersError;
  4609. pszWrapOID = pszAllocWrapOID;
  4610. }
  4611. hKeyAgreeProv = pKeyAgreeEncodeInfo->hCryptProv;
  4612. if (0 == hKeyAgreeProv) {
  4613. if (0 == pKeyAgreeEncryptInfo->dwRecipientIndex)
  4614. hKeyAgreeProv = pContentEncryptInfo->hCryptProv;
  4615. else {
  4616. // Check if the type of and public key algorithm for this
  4617. // recipient is the same as the first recipient's.
  4618. PCMSG_RECIPIENT_ENCODE_INFO prei;
  4619. prei = &pContentEncryptInfo->rgCmsRecipients[0];
  4620. if (CMSG_KEY_AGREE_RECIPIENT == prei->dwRecipientChoice &&
  4621. ICM_IsSameRecipientPublicKeyAlgorithm(
  4622. &prei->pKeyAgree->KeyEncryptionAlgorithm,
  4623. paiEncrypt))
  4624. hKeyAgreeProv = pContentEncryptInfo->hCryptProv;
  4625. else {
  4626. // Get default provider associated with the
  4627. // key encryption algorithm
  4628. DWORD dwAlgIdPubKey;
  4629. if (!ICM_GetCAPI(
  4630. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  4631. paiEncrypt,
  4632. &dwAlgIdPubKey))
  4633. goto GetPublicKeyAlgIdError;
  4634. hKeyAgreeProv = I_CryptGetDefaultCryptProvForEncrypt(
  4635. dwAlgIdPubKey, dwAlgIdWrap, dwBitLen);
  4636. if (0 == hKeyAgreeProv)
  4637. goto GetDefaultCryptProvError;
  4638. }
  4639. }
  4640. }
  4641. if (hKeyAgreeProv != pContentEncryptInfo->hCryptProv) {
  4642. // Need to export the hContentEncryptKey from the ContentEncrypt
  4643. // provider and import into the KeyAgree provider
  4644. hContentEncryptKey = ICM_ExportContentEncryptKeyAndImport(
  4645. pContentEncryptInfo,
  4646. hKeyAgreeProv);
  4647. if (0 == hContentEncryptKey)
  4648. goto ImportContentKeyError;
  4649. } else
  4650. hContentEncryptKey = pContentEncryptInfo->hContentEncryptKey;
  4651. if (0 == (hEphemeralKey = ICM_GenerateEphemeralDh(
  4652. hKeyAgreeProv,
  4653. pContentEncryptInfo,
  4654. pKeyAgreeEncodeInfo,
  4655. pKeyAgreeEncryptInfo,
  4656. &cbP)))
  4657. goto GenerateEphemeralDhError;
  4658. cRecipient = pKeyAgreeEncryptInfo->cKeyAgreeKeyEncryptInfo;
  4659. ppRecipientEncryptInfo = pKeyAgreeEncryptInfo->rgpKeyAgreeKeyEncryptInfo;
  4660. ppRecipientEncodeInfo = pKeyAgreeEncodeInfo->rgpRecipientEncryptedKeys;
  4661. for ( ; 0 < cRecipient;
  4662. cRecipient--,
  4663. ppRecipientEncryptInfo++,
  4664. ppRecipientEncodeInfo++) {
  4665. if (0 == (hAgreeKey = ICM_ImportDhAgreeKey(
  4666. hKeyAgreeProv,
  4667. hEphemeralKey,
  4668. cbP,
  4669. &(*ppRecipientEncodeInfo)->RecipientPublicKey,
  4670. pszWrapOID,
  4671. dwAlgIdWrap,
  4672. dwBitLen,
  4673. &pKeyAgreeEncodeInfo->UserKeyingMaterial
  4674. )))
  4675. goto ImportDhAgreeKeyError;
  4676. if (!ICM_ExportEncryptedKey(
  4677. hContentEncryptKey,
  4678. hAgreeKey,
  4679. SYMMETRICWRAPKEYBLOB,
  4680. FALSE, // fAllowSP3CompatibleEncrypt
  4681. &(*ppRecipientEncryptInfo)->EncryptedKey))
  4682. goto ExportEncryptedKeyError;
  4683. CryptDestroyKey(hAgreeKey);
  4684. hAgreeKey = 0;
  4685. }
  4686. fRet = TRUE;
  4687. CommonReturn:
  4688. ICM_Free(pszAllocWrapOID);
  4689. if (hKeyAgreeProv != pContentEncryptInfo->hCryptProv &&
  4690. hContentEncryptKey)
  4691. CryptDestroyKey(hContentEncryptKey);
  4692. if (hAgreeKey)
  4693. CryptDestroyKey(hAgreeKey);
  4694. if (hEphemeralKey)
  4695. CryptDestroyKey(hEphemeralKey);
  4696. ICM_SetLastError(dwError);
  4697. return fRet;
  4698. ErrorReturn:
  4699. dwError = GetLastError();
  4700. fRet = FALSE;
  4701. goto CommonReturn;
  4702. SET_ERROR(InvalidKeyAgreeKeyChoice, E_INVALIDARG)
  4703. TRACE_ERROR(CreateDefaultDhWrapEncryptParametersError)
  4704. TRACE_ERROR(GetDhWrapEncryptParametersError)
  4705. TRACE_ERROR(GetPublicKeyAlgIdError)
  4706. TRACE_ERROR(GetDefaultCryptProvError)
  4707. TRACE_ERROR(ImportContentKeyError)
  4708. TRACE_ERROR(GenerateEphemeralDhError)
  4709. TRACE_ERROR(ImportDhAgreeKeyError)
  4710. TRACE_ERROR(ExportEncryptedKeyError)
  4711. }
  4712. BOOL
  4713. WINAPI
  4714. ICM_ExportKeyAgree(
  4715. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4716. IN PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgreeEncodeInfo,
  4717. IN OUT PCMSG_KEY_AGREE_ENCRYPT_INFO pKeyAgreeEncryptInfo
  4718. )
  4719. {
  4720. BOOL fRet;
  4721. void *pvFuncAddr;
  4722. HCRYPTOIDFUNCADDR hFuncAddr;
  4723. if (CryptGetOIDFunctionAddress(
  4724. hExportKeyAgreeFuncSet,
  4725. X509_ASN_ENCODING,
  4726. pKeyAgreeEncryptInfo->KeyEncryptionAlgorithm.pszObjId,
  4727. 0, // dwFlags
  4728. &pvFuncAddr,
  4729. &hFuncAddr)) {
  4730. fRet = ((PFN_CMSG_EXPORT_KEY_AGREE) pvFuncAddr)(
  4731. pContentEncryptInfo,
  4732. pKeyAgreeEncodeInfo,
  4733. pKeyAgreeEncryptInfo,
  4734. 0, // dwFlags
  4735. NULL // pvReserved
  4736. );
  4737. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  4738. } else
  4739. fRet = ICM_DefaultExportKeyAgree(
  4740. pContentEncryptInfo,
  4741. pKeyAgreeEncodeInfo,
  4742. pKeyAgreeEncryptInfo,
  4743. 0, // dwFlags
  4744. NULL // pvReserved
  4745. );
  4746. return fRet;
  4747. }
  4748. BOOL
  4749. WINAPI
  4750. ICM_DefaultExportMailList(
  4751. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4752. IN PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailListEncodeInfo,
  4753. IN OUT PCMSG_MAIL_LIST_ENCRYPT_INFO pMailListEncryptInfo,
  4754. IN DWORD dwFlags,
  4755. IN OPTIONAL void *pvReserved
  4756. )
  4757. {
  4758. BOOL fRet;
  4759. DWORD dwError = ERROR_SUCCESS;
  4760. HCRYPTPROV hMailListProv = 0; // not released
  4761. HCRYPTKEY hContentEncryptKey = 0; // destroy if exported/imported
  4762. HCRYPTKEY hKeyEncryptionKey = 0; // not destroyed
  4763. PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt =
  4764. &pMailListEncryptInfo->KeyEncryptionAlgorithm;
  4765. DWORD dwAlgIdEncrypt;
  4766. DWORD dwBitLen;
  4767. hMailListProv = pMailListEncodeInfo->hCryptProv;
  4768. switch (pMailListEncodeInfo->dwKeyChoice) {
  4769. case CMSG_MAIL_LIST_HANDLE_KEY_CHOICE:
  4770. hKeyEncryptionKey = pMailListEncodeInfo->hKeyEncryptionKey;
  4771. assert(hMailListProv && hKeyEncryptionKey);
  4772. if (0 == hMailListProv || 0 == hKeyEncryptionKey)
  4773. goto InvalidMailListHandleKeyPara;
  4774. break;
  4775. default:
  4776. goto InvalidMailListKeyChoice;
  4777. }
  4778. if (0 == paiEncrypt->Parameters.cbData) {
  4779. if (!ICM_CreateDefaultWrapEncryptParameters(
  4780. pContentEncryptInfo,
  4781. paiEncrypt,
  4782. pMailListEncodeInfo->pvKeyEncryptionAuxInfo,
  4783. &dwAlgIdEncrypt,
  4784. &dwBitLen))
  4785. goto CreateDefaultWrapEncryptParametersError;
  4786. if (paiEncrypt->Parameters.cbData)
  4787. pMailListEncryptInfo->dwFlags |=
  4788. CMSG_MAIL_LIST_ENCRYPT_FREE_PARA_FLAG;
  4789. } else {
  4790. if (!ICM_GetWrapEncryptParameters(
  4791. paiEncrypt,
  4792. &dwAlgIdEncrypt,
  4793. &dwBitLen))
  4794. goto GetWrapEncryptParametersError;
  4795. }
  4796. if (hMailListProv != pContentEncryptInfo->hCryptProv) {
  4797. // Need to export the hContentEncryptKey from the ContentEncrypt
  4798. // provider and import into the MailList provider
  4799. hContentEncryptKey = ICM_ExportContentEncryptKeyAndImport(
  4800. pContentEncryptInfo,
  4801. hMailListProv);
  4802. if (0 == hContentEncryptKey)
  4803. goto ImportContentKeyError;
  4804. } else
  4805. hContentEncryptKey = pContentEncryptInfo->hContentEncryptKey;
  4806. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  4807. // Silently ignore any errors. Not supported in earlier versions
  4808. CryptSetKeyParam(
  4809. hKeyEncryptionKey,
  4810. KP_EFFECTIVE_KEYLEN,
  4811. (PBYTE) &dwBitLen,
  4812. 0); // dwFlags
  4813. if (!ICM_ExportEncryptedKey(
  4814. hContentEncryptKey,
  4815. hKeyEncryptionKey,
  4816. SYMMETRICWRAPKEYBLOB,
  4817. FALSE, // fAllowSP3CompatibleEncrypt
  4818. &pMailListEncryptInfo->EncryptedKey))
  4819. goto ExportEncryptedKeyError;
  4820. fRet = TRUE;
  4821. CommonReturn:
  4822. if (hMailListProv != pContentEncryptInfo->hCryptProv &&
  4823. hContentEncryptKey)
  4824. CryptDestroyKey(hContentEncryptKey);
  4825. ICM_SetLastError(dwError);
  4826. return fRet;
  4827. ErrorReturn:
  4828. dwError = GetLastError();
  4829. fRet = FALSE;
  4830. goto CommonReturn;
  4831. SET_ERROR(InvalidMailListHandleKeyPara, E_INVALIDARG)
  4832. SET_ERROR(InvalidMailListKeyChoice, E_INVALIDARG)
  4833. TRACE_ERROR(CreateDefaultWrapEncryptParametersError)
  4834. TRACE_ERROR(GetWrapEncryptParametersError)
  4835. TRACE_ERROR(ImportContentKeyError)
  4836. TRACE_ERROR(ExportEncryptedKeyError)
  4837. }
  4838. BOOL
  4839. WINAPI
  4840. ICM_ExportMailList(
  4841. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  4842. IN PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailListEncodeInfo,
  4843. IN OUT PCMSG_MAIL_LIST_ENCRYPT_INFO pMailListEncryptInfo
  4844. )
  4845. {
  4846. BOOL fRet;
  4847. void *pvFuncAddr;
  4848. HCRYPTOIDFUNCADDR hFuncAddr;
  4849. if (CryptGetOIDFunctionAddress(
  4850. hExportMailListFuncSet,
  4851. X509_ASN_ENCODING,
  4852. pMailListEncryptInfo->KeyEncryptionAlgorithm.pszObjId,
  4853. 0, // dwFlags
  4854. &pvFuncAddr,
  4855. &hFuncAddr)) {
  4856. fRet = ((PFN_CMSG_EXPORT_MAIL_LIST) pvFuncAddr)(
  4857. pContentEncryptInfo,
  4858. pMailListEncodeInfo,
  4859. pMailListEncryptInfo,
  4860. 0, // dwFlags
  4861. NULL // pvReserved
  4862. );
  4863. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  4864. } else
  4865. fRet = ICM_DefaultExportMailList(
  4866. pContentEncryptInfo,
  4867. pMailListEncodeInfo,
  4868. pMailListEncryptInfo,
  4869. 0, // dwFlags
  4870. NULL // pvReserved
  4871. );
  4872. return fRet;
  4873. }
  4874. //+-------------------------------------------------------------------------
  4875. // Default export of the encryption key
  4876. //
  4877. // Note, pcbData[1] contains dwEncryptFlags, where,
  4878. // CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG may be set to disable the reversing
  4879. // of the encoded, encrypted symmetric key.
  4880. //
  4881. // rgcbData[1] is the dwEncryptFlags passed from ICM_DefaultGenEncryptKey
  4882. //
  4883. // OldStyle
  4884. //--------------------------------------------------------------------------
  4885. BOOL
  4886. WINAPI
  4887. ICM_DefaultExportEncryptKey(
  4888. IN HCRYPTPROV hCryptProv,
  4889. IN HCRYPTKEY hEncryptKey,
  4890. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  4891. OUT PBYTE pbData,
  4892. IN OUT DWORD rgcbData[2])
  4893. {
  4894. BOOL fRet;
  4895. DWORD dwError = ERROR_SUCCESS;
  4896. HCRYPTKEY hPubKey = NULL;
  4897. CRYPT_DATA_BLOB EncryptedKey; ZEROSTRUCT(EncryptedKey);
  4898. DWORD cb;
  4899. if (!CryptImportPublicKeyInfo(
  4900. hCryptProv,
  4901. X509_ASN_ENCODING,
  4902. pPublicKeyInfo,
  4903. &hPubKey))
  4904. goto ImportKeyError;
  4905. if (!ICM_ExportEncryptedKey(
  4906. hEncryptKey,
  4907. hPubKey,
  4908. SIMPLEBLOB,
  4909. 0 != (rgcbData[1] & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG),
  4910. &EncryptedKey))
  4911. goto ExportEncryptedKeyError;
  4912. fRet = TRUE;
  4913. cb = EncryptedKey.cbData;
  4914. if (pbData) {
  4915. if (rgcbData[0] < cb) {
  4916. SetLastError((DWORD) ERROR_MORE_DATA);
  4917. fRet = FALSE;
  4918. } else
  4919. memcpy(pbData, EncryptedKey.pbData, cb);
  4920. }
  4921. CommonReturn:
  4922. rgcbData[0] = cb;
  4923. ICM_Free(EncryptedKey.pbData);
  4924. if (hPubKey)
  4925. CryptDestroyKey(hPubKey);
  4926. ICM_SetLastError(dwError);
  4927. return fRet;
  4928. ErrorReturn:
  4929. dwError = GetLastError();
  4930. cb = 0;
  4931. fRet = FALSE;
  4932. goto CommonReturn;
  4933. TRACE_ERROR(ImportKeyError)
  4934. TRACE_ERROR(ExportEncryptedKeyError)
  4935. }
  4936. //+-------------------------------------------------------------------------
  4937. //--------------------------------------------------------------------------
  4938. PCMSG_RECIPIENT_ENCODE_INFO
  4939. WINAPI
  4940. ICM_CreateCmsRecipientEncodeInfos(
  4941. IN DWORD cRecipients,
  4942. IN PCERT_INFO *rgpCertInfoRecipients
  4943. )
  4944. {
  4945. PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients = NULL;
  4946. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO rgKeyTrans;
  4947. DWORD cbCmsRecipients;
  4948. DWORD i;
  4949. assert(cRecipients && rgpCertInfoRecipients);
  4950. cbCmsRecipients = sizeof(CMSG_RECIPIENT_ENCODE_INFO) * cRecipients +
  4951. sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO) * cRecipients;
  4952. if (NULL == (rgCmsRecipients = (PCMSG_RECIPIENT_ENCODE_INFO) ICM_AllocZero(
  4953. cbCmsRecipients)))
  4954. return NULL;
  4955. rgKeyTrans = (PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)
  4956. (((PBYTE) rgCmsRecipients) +
  4957. sizeof(CMSG_RECIPIENT_ENCODE_INFO) * cRecipients);
  4958. for (i = 0; i < cRecipients; i++) {
  4959. rgCmsRecipients[i].dwRecipientChoice = CMSG_KEY_TRANS_RECIPIENT;
  4960. rgCmsRecipients[i].pKeyTrans = &rgKeyTrans[i];
  4961. rgKeyTrans[i].cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO);
  4962. rgKeyTrans[i].KeyEncryptionAlgorithm =
  4963. rgpCertInfoRecipients[i]->SubjectPublicKeyInfo.Algorithm;
  4964. // rgKeyTrans[i].pvKeyEncryptionAuxInfo =
  4965. // rgKeyTrans[i].hCryptProv =
  4966. rgKeyTrans[i].RecipientPublicKey =
  4967. rgpCertInfoRecipients[i]->SubjectPublicKeyInfo.PublicKey;
  4968. ICM_GetCertIdFromCertInfo(rgpCertInfoRecipients[i],
  4969. &rgKeyTrans[i].RecipientId);
  4970. }
  4971. return rgCmsRecipients;
  4972. }
  4973. void
  4974. WINAPI
  4975. ICM_FreeContentEncryptInfo(
  4976. IN PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedEncodeInfo,
  4977. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
  4978. )
  4979. {
  4980. DWORD dwErr = GetLastError();
  4981. if (pEnvelopedEncodeInfo->rgpRecipients) {
  4982. ICM_Free(pContentEncryptInfo->rgCmsRecipients);
  4983. pContentEncryptInfo->rgCmsRecipients = NULL;
  4984. }
  4985. if (pContentEncryptInfo->hContentEncryptKey) {
  4986. CryptDestroyKey(pContentEncryptInfo->hContentEncryptKey);
  4987. pContentEncryptInfo->hContentEncryptKey = 0;
  4988. }
  4989. if (pContentEncryptInfo->dwFlags &
  4990. CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG) {
  4991. pContentEncryptInfo->dwFlags &=
  4992. ~CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG;
  4993. assert(pContentEncryptInfo->hCryptProv);
  4994. CryptReleaseContext(pContentEncryptInfo->hCryptProv, 0);
  4995. pContentEncryptInfo->hCryptProv = 0;
  4996. }
  4997. if (pContentEncryptInfo->dwFlags &
  4998. CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG) {
  4999. pContentEncryptInfo->dwFlags &=
  5000. ~CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG;
  5001. assert(
  5002. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.cbData
  5003. &&
  5004. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.pbData);
  5005. ICM_Free(
  5006. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.pbData);
  5007. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.cbData = 0;
  5008. pContentEncryptInfo->ContentEncryptionAlgorithm.Parameters.pbData = NULL;
  5009. }
  5010. SetLastError(dwErr);
  5011. }
  5012. BOOL
  5013. WINAPI
  5014. ICM_InitializeContentEncryptInfo(
  5015. IN PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedEncodeInfo,
  5016. OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo
  5017. )
  5018. {
  5019. BOOL fRet;
  5020. DWORD cRecipients;
  5021. memset(pContentEncryptInfo, 0, sizeof(*pContentEncryptInfo));
  5022. pContentEncryptInfo->cbSize = sizeof(*pContentEncryptInfo);
  5023. pContentEncryptInfo->hCryptProv =
  5024. pEnvelopedEncodeInfo->hCryptProv;
  5025. pContentEncryptInfo->ContentEncryptionAlgorithm =
  5026. pEnvelopedEncodeInfo->ContentEncryptionAlgorithm;
  5027. pContentEncryptInfo->pvEncryptionAuxInfo =
  5028. pEnvelopedEncodeInfo->pvEncryptionAuxInfo;
  5029. pContentEncryptInfo->pfnAlloc = ICM_Alloc;
  5030. pContentEncryptInfo->pfnFree = ICM_Free;
  5031. // pContentEncryptInfo->dwEncryptFlags =
  5032. // pContentEncryptInfo->hContentEncryptKey =
  5033. // pContentEncryptInfo->dwFlags =
  5034. cRecipients = pEnvelopedEncodeInfo->cRecipients;
  5035. pContentEncryptInfo->cRecipients = cRecipients;
  5036. if (0 == cRecipients)
  5037. ;
  5038. else if (pEnvelopedEncodeInfo->rgpRecipients) {
  5039. if (NULL == (pContentEncryptInfo->rgCmsRecipients =
  5040. ICM_CreateCmsRecipientEncodeInfos(
  5041. cRecipients, pEnvelopedEncodeInfo->rgpRecipients)))
  5042. goto CreateCmsRecipientEncodeInfosError;
  5043. } else {
  5044. if (sizeof(CMSG_ENVELOPED_ENCODE_INFO) > pEnvelopedEncodeInfo->cbSize)
  5045. goto MissingCmsRecipients;
  5046. pContentEncryptInfo->rgCmsRecipients =
  5047. pEnvelopedEncodeInfo->rgCmsRecipients;
  5048. if (NULL == pContentEncryptInfo->rgCmsRecipients)
  5049. goto MissingCmsRecipients;
  5050. }
  5051. if (!ICM_GenContentEncryptKey(pContentEncryptInfo))
  5052. goto GenContentEncryptKeyError;
  5053. fRet = TRUE;
  5054. CommonReturn:
  5055. return fRet;
  5056. ErrorReturn:
  5057. ICM_FreeContentEncryptInfo(pEnvelopedEncodeInfo, pContentEncryptInfo);
  5058. fRet = FALSE;
  5059. goto CommonReturn;
  5060. SET_ERROR(MissingCmsRecipients, E_INVALIDARG)
  5061. TRACE_ERROR(CreateCmsRecipientEncodeInfosError)
  5062. TRACE_ERROR(GenContentEncryptKeyError)
  5063. }
  5064. //+-------------------------------------------------------------------------
  5065. // Oss set/free functions
  5066. //
  5067. // Assumption: upon entry to the set functions, the Oss data structure has
  5068. // already been zeroed.
  5069. //--------------------------------------------------------------------------
  5070. BOOL
  5071. WINAPI
  5072. ICM_SetOssAny(
  5073. IN PCRYPT_DATA_BLOB pAny,
  5074. IN OUT Any *pOssAny
  5075. )
  5076. {
  5077. if (NULL == (pOssAny->value =
  5078. (unsigned char *) ICM_DupMem(pAny->pbData, pAny->cbData)))
  5079. return FALSE;
  5080. pOssAny->length = pAny->cbData;
  5081. return TRUE;
  5082. }
  5083. void
  5084. WINAPI
  5085. ICM_FreeOssAny(
  5086. IN OUT Any *pOssAny
  5087. )
  5088. {
  5089. if (pOssAny->value) {
  5090. ICM_Free(pOssAny->value);
  5091. pOssAny->value = NULL;
  5092. }
  5093. }
  5094. BOOL
  5095. WINAPI
  5096. ICM_SetOssHugeInteger(
  5097. IN PCRYPT_INTEGER_BLOB pHugeInteger,
  5098. IN OUT HugeIntegerType *pOssHugeInteger
  5099. )
  5100. {
  5101. return PkiAsn1SetHugeInteger(
  5102. pHugeInteger,
  5103. &pOssHugeInteger->length,
  5104. &pOssHugeInteger->value
  5105. );
  5106. }
  5107. void
  5108. WINAPI
  5109. ICM_FreeOssHugeInteger(
  5110. IN OUT HugeIntegerType *pOssHugeInteger
  5111. )
  5112. {
  5113. if (pOssHugeInteger->value) {
  5114. PkiAsn1FreeHugeInteger(pOssHugeInteger->value);
  5115. pOssHugeInteger->value = NULL;
  5116. }
  5117. }
  5118. BOOL
  5119. WINAPI
  5120. ICM_SetOssOctetString(
  5121. IN PCRYPT_DATA_BLOB pOctetString,
  5122. IN OUT OctetStringType *pOssOctetString
  5123. )
  5124. {
  5125. if (NULL == (pOssOctetString->value =
  5126. (unsigned char *) ICM_DupMem(
  5127. pOctetString->pbData, pOctetString->cbData)))
  5128. return FALSE;
  5129. pOssOctetString->length = pOctetString->cbData;
  5130. return TRUE;
  5131. }
  5132. void
  5133. WINAPI
  5134. ICM_FreeOssOctetString(
  5135. IN OUT OctetStringType *pOssOctetString
  5136. )
  5137. {
  5138. if (pOssOctetString->value) {
  5139. ICM_Free(pOssOctetString->value);
  5140. pOssOctetString->value = NULL;
  5141. }
  5142. }
  5143. BOOL
  5144. WINAPI
  5145. ICM_SetOssBitString(
  5146. IN PCRYPT_BIT_BLOB pBitString,
  5147. IN OUT BitStringType *pOssBitString
  5148. )
  5149. {
  5150. CRYPT_BIT_BLOB BitString = *pBitString;
  5151. if (NULL == (BitString.pbData = (PBYTE) ICM_DupMem(
  5152. BitString.pbData, BitString.cbData)))
  5153. return FALSE;
  5154. PkiAsn1SetBitString(&BitString, &pOssBitString->length,
  5155. &pOssBitString->value);
  5156. return TRUE;
  5157. }
  5158. void
  5159. WINAPI
  5160. ICM_FreeOssBitString(
  5161. IN OUT BitStringType *pOssBitString
  5162. )
  5163. {
  5164. if (pOssBitString->value) {
  5165. ICM_Free(pOssBitString->value);
  5166. pOssBitString->value = NULL;
  5167. }
  5168. }
  5169. static BYTE abDerNULL[] = {5, 0};
  5170. BOOL
  5171. WINAPI
  5172. ICM_SetOssAlgorithmIdentifier(
  5173. IN PCRYPT_ALGORITHM_IDENTIFIER pai,
  5174. IN OUT AlgorithmIdentifier *pOssAlgId
  5175. )
  5176. {
  5177. BOOL fRet;
  5178. PBYTE pbData;
  5179. DWORD cbData;
  5180. pOssAlgId->algorithm.count = SIZE_OSS_OID;
  5181. if (!PkiAsn1ToObjectIdentifier(
  5182. pai->pszObjId,
  5183. &pOssAlgId->algorithm.count,
  5184. pOssAlgId->algorithm.value))
  5185. goto PkiAsn1ToObjectIdentifierError;
  5186. pOssAlgId->bit_mask = parameters_present;
  5187. pbData = pai->Parameters.pbData;
  5188. cbData = pai->Parameters.cbData;
  5189. if (0 == cbData) {
  5190. pOssAlgId->parameters.length = sizeof(abDerNULL);
  5191. pOssAlgId->parameters.value = abDerNULL;
  5192. } else {
  5193. if (NULL == (pOssAlgId->parameters.value =
  5194. (unsigned char *) ICM_DupMem(pbData, cbData)))
  5195. goto OutOfMemory;
  5196. pOssAlgId->parameters.length = cbData;
  5197. }
  5198. fRet = TRUE;
  5199. CommonReturn:
  5200. return fRet;
  5201. ErrorReturn:
  5202. fRet = FALSE;
  5203. goto CommonReturn;
  5204. SET_ERROR(PkiAsn1ToObjectIdentifierError, CRYPT_E_OID_FORMAT)
  5205. TRACE_ERROR(OutOfMemory)
  5206. }
  5207. void
  5208. WINAPI
  5209. ICM_FreeOssAlgorithmIdentifier(
  5210. IN OUT AlgorithmIdentifier *pOssAlgId
  5211. )
  5212. {
  5213. unsigned char *value;
  5214. #ifdef OSS_CRYPT_ASN1
  5215. value = pOssAlgId->parameters.value;
  5216. #else
  5217. value = (unsigned char *) pOssAlgId->parameters.value;
  5218. #endif // OSS_CRYPT_ASN1
  5219. if (value && value != abDerNULL) {
  5220. ICM_Free(value);
  5221. pOssAlgId->parameters.value = NULL;
  5222. }
  5223. }
  5224. BOOL
  5225. WINAPI
  5226. ICM_SetOssOtherKeyAttribute(
  5227. IN PCRYPT_ATTRIBUTE_TYPE_VALUE pOtherAttr,
  5228. IN OUT OtherKeyAttribute *pOssOtherAttr
  5229. )
  5230. {
  5231. BOOL fRet;
  5232. pOssOtherAttr->keyAttrId.count = SIZE_OSS_OID;
  5233. if (!PkiAsn1ToObjectIdentifier(
  5234. pOtherAttr->pszObjId,
  5235. &pOssOtherAttr->keyAttrId.count,
  5236. pOssOtherAttr->keyAttrId.value))
  5237. goto PkiAsn1ToObjectIdentifierError;
  5238. if (pOtherAttr->Value.cbData) {
  5239. if (!ICM_SetOssAny(&pOtherAttr->Value, &pOssOtherAttr->keyAttr))
  5240. goto SetOssAnyError;
  5241. pOssOtherAttr->bit_mask |= keyAttr_present;
  5242. }
  5243. fRet = TRUE;
  5244. CommonReturn:
  5245. return fRet;
  5246. ErrorReturn:
  5247. fRet = FALSE;
  5248. goto CommonReturn;
  5249. SET_ERROR(PkiAsn1ToObjectIdentifierError, CRYPT_E_OID_FORMAT)
  5250. TRACE_ERROR(SetOssAnyError)
  5251. }
  5252. void
  5253. WINAPI
  5254. ICM_FreeOssOtherKeyAttribute(
  5255. OUT OtherKeyAttribute *pOssOtherAttr
  5256. )
  5257. {
  5258. ICM_FreeOssAny(&pOssOtherAttr->keyAttr);
  5259. }
  5260. void
  5261. WINAPI
  5262. ICM_FreeOssIssuerAndSerialNumber(
  5263. IN OUT IssuerAndSerialNumber *pOssIssuerAndSerialNumber
  5264. )
  5265. {
  5266. ICM_FreeOssAny(&pOssIssuerAndSerialNumber->issuer);
  5267. ICM_FreeOssHugeInteger(&pOssIssuerAndSerialNumber->serialNumber);
  5268. }
  5269. BOOL
  5270. WINAPI
  5271. ICM_SetOssIssuerAndSerialNumber(
  5272. IN PCERT_ISSUER_SERIAL_NUMBER pIssuerAndSerialNumber,
  5273. IN OUT IssuerAndSerialNumber *pOssIssuerAndSerialNumber
  5274. )
  5275. {
  5276. BOOL fRet;
  5277. if (!ICM_SetOssAny(&pIssuerAndSerialNumber->Issuer,
  5278. &pOssIssuerAndSerialNumber->issuer))
  5279. goto SetOssAnyError;
  5280. if (!ICM_SetOssHugeInteger(&pIssuerAndSerialNumber->SerialNumber,
  5281. &pOssIssuerAndSerialNumber->serialNumber))
  5282. goto SetOssHugeIntegerError;
  5283. fRet = TRUE;
  5284. CommonReturn:
  5285. return fRet;
  5286. ErrorReturn:
  5287. ICM_FreeOssIssuerAndSerialNumber(pOssIssuerAndSerialNumber);
  5288. fRet = FALSE;
  5289. goto CommonReturn;
  5290. TRACE_ERROR(SetOssAnyError)
  5291. TRACE_ERROR(SetOssHugeIntegerError)
  5292. }
  5293. BOOL
  5294. WINAPI
  5295. ICM_SetOssCertIdentifier(
  5296. IN PCERT_ID pCertId,
  5297. IN OUT CertIdentifier *pOssCertId
  5298. )
  5299. {
  5300. BOOL fRet;
  5301. switch (pCertId->dwIdChoice) {
  5302. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5303. if (!ICM_SetOssIssuerAndSerialNumber(
  5304. &pCertId->IssuerSerialNumber,
  5305. &pOssCertId->u.issuerAndSerialNumber
  5306. ))
  5307. goto SetOssIssuerAndSerialNumberError;
  5308. break;
  5309. case CERT_ID_KEY_IDENTIFIER:
  5310. if (!ICM_SetOssOctetString(
  5311. &pCertId->KeyId,
  5312. &pOssCertId->u.subjectKeyIdentifier
  5313. ))
  5314. goto SetOssOctetStringError;
  5315. break;
  5316. default:
  5317. goto InvalidIdChoice;
  5318. }
  5319. assert(CERT_ID_ISSUER_SERIAL_NUMBER == issuerAndSerialNumber_chosen);
  5320. assert(CERT_ID_KEY_IDENTIFIER == subjectKeyIdentifier_chosen);
  5321. pOssCertId->choice = (unsigned short) pCertId->dwIdChoice;
  5322. fRet = TRUE;
  5323. CommonReturn:
  5324. return fRet;
  5325. ErrorReturn:
  5326. fRet = FALSE;
  5327. goto CommonReturn;
  5328. TRACE_ERROR(SetOssIssuerAndSerialNumberError)
  5329. TRACE_ERROR(SetOssOctetStringError)
  5330. SET_ERROR(InvalidIdChoice, E_INVALIDARG)
  5331. }
  5332. void
  5333. WINAPI
  5334. ICM_FreeOssCertIdentifier(
  5335. IN OUT CertIdentifier *pOssCertId
  5336. )
  5337. {
  5338. switch (pOssCertId->choice) {
  5339. case issuerAndSerialNumber_chosen:
  5340. ICM_FreeOssIssuerAndSerialNumber(
  5341. &pOssCertId->u.issuerAndSerialNumber);
  5342. break;
  5343. case subjectKeyIdentifier_chosen:
  5344. ICM_FreeOssOctetString(&pOssCertId->u.subjectKeyIdentifier);
  5345. break;
  5346. default:
  5347. break;
  5348. }
  5349. pOssCertId->choice = 0;
  5350. }
  5351. void
  5352. WINAPI
  5353. ICM_FreeOssOriginatorCertIdentifierOrKey(
  5354. IN OUT OriginatorIdentifierOrKey *pOssOriginator
  5355. )
  5356. {
  5357. switch (pOssOriginator->choice) {
  5358. case issuerAndSerialNumber_chosen:
  5359. ICM_FreeOssIssuerAndSerialNumber(
  5360. &pOssOriginator->u.issuerAndSerialNumber);
  5361. break;
  5362. case subjectKeyIdentifier_chosen:
  5363. ICM_FreeOssOctetString(
  5364. &pOssOriginator->u.subjectKeyIdentifier);
  5365. break;
  5366. case originatorKey_chosen:
  5367. ICM_FreeOssAlgorithmIdentifier(
  5368. &pOssOriginator->u.originatorKey.algorithm);
  5369. ICM_FreeOssBitString(
  5370. &pOssOriginator->u.originatorKey.publicKey);
  5371. break;
  5372. default:
  5373. break;
  5374. }
  5375. pOssOriginator->choice = 0;
  5376. }
  5377. BOOL
  5378. WINAPI
  5379. ICM_SetOssOriginatorCertIdentifier(
  5380. IN PCERT_ID pCertId,
  5381. IN OUT OriginatorIdentifierOrKey *pOssOriginator
  5382. )
  5383. {
  5384. BOOL fRet;
  5385. switch (pCertId->dwIdChoice) {
  5386. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5387. if (!ICM_SetOssIssuerAndSerialNumber(
  5388. &pCertId->IssuerSerialNumber,
  5389. &pOssOriginator->u.issuerAndSerialNumber
  5390. ))
  5391. goto SetOssIssuerAndSerialNumberError;
  5392. pOssOriginator->choice = issuerAndSerialNumber_chosen;
  5393. break;
  5394. case CERT_ID_KEY_IDENTIFIER:
  5395. if (!ICM_SetOssOctetString(
  5396. &pCertId->KeyId,
  5397. &pOssOriginator->u.subjectKeyIdentifier
  5398. ))
  5399. goto SetOssOctetStringError;
  5400. pOssOriginator->choice = subjectKeyIdentifier_chosen;
  5401. break;
  5402. default:
  5403. goto InvalidIdChoice;
  5404. }
  5405. fRet = TRUE;
  5406. CommonReturn:
  5407. return fRet;
  5408. ErrorReturn:
  5409. fRet = FALSE;
  5410. goto CommonReturn;
  5411. TRACE_ERROR(SetOssIssuerAndSerialNumberError)
  5412. TRACE_ERROR(SetOssOctetStringError)
  5413. SET_ERROR(InvalidIdChoice, E_INVALIDARG)
  5414. }
  5415. BOOL
  5416. WINAPI
  5417. ICM_SetOssOriginatorPublicKey(
  5418. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  5419. IN OUT OriginatorIdentifierOrKey *pOssOriginator
  5420. )
  5421. {
  5422. BOOL fRet;
  5423. PCRYPT_ALGORITHM_IDENTIFIER pai = &pPublicKeyInfo->Algorithm;
  5424. AlgorithmIdentifier *pOssAlgId = &pOssOriginator->u.originatorKey.algorithm;
  5425. pOssOriginator->choice = originatorKey_chosen;
  5426. if (!ICM_SetOssAlgorithmIdentifier(
  5427. pai,
  5428. pOssAlgId
  5429. ))
  5430. goto SetOssAlgorithmIdentifierError;
  5431. if (0 == pai->Parameters.cbData) {
  5432. DWORD dwFlags;
  5433. PCCRYPT_OID_INFO pOIDInfo;
  5434. dwFlags = 0;
  5435. if (pOIDInfo = CryptFindOIDInfo(
  5436. CRYPT_OID_INFO_OID_KEY,
  5437. pai->pszObjId,
  5438. CRYPT_PUBKEY_ALG_OID_GROUP_ID)) {
  5439. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  5440. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  5441. dwFlags = pdwExtra[0];
  5442. }
  5443. }
  5444. if (dwFlags & CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG) {
  5445. // NO NULL parameters
  5446. pOssAlgId->bit_mask &= ~parameters_present;
  5447. pOssAlgId->parameters.length = 0;
  5448. pOssAlgId->parameters.value = NULL;
  5449. }
  5450. }
  5451. if (!ICM_SetOssBitString(
  5452. &pPublicKeyInfo->PublicKey,
  5453. &pOssOriginator->u.originatorKey.publicKey
  5454. ))
  5455. goto SetOssBitStringError;
  5456. fRet = TRUE;
  5457. CommonReturn:
  5458. return fRet;
  5459. ErrorReturn:
  5460. ICM_FreeOssOriginatorCertIdentifierOrKey(pOssOriginator);
  5461. fRet = FALSE;
  5462. goto CommonReturn;
  5463. TRACE_ERROR(SetOssAlgorithmIdentifierError)
  5464. TRACE_ERROR(SetOssBitStringError)
  5465. }
  5466. //+-------------------------------------------------------------------------
  5467. // Free the Oss KeyTransRecipientInfo
  5468. //--------------------------------------------------------------------------
  5469. void
  5470. WINAPI
  5471. ICM_FreeOssKeyTransRecipientInfo(
  5472. IN OUT KeyTransRecipientInfo *pori
  5473. )
  5474. {
  5475. ICM_FreeOssCertIdentifier(&pori->rid);
  5476. ICM_FreeOssAlgorithmIdentifier(&pori->keyEncryptionAlgorithm);
  5477. ICM_Free(pori->encryptedKey.value);
  5478. pori->encryptedKey.value = NULL;
  5479. }
  5480. //+-------------------------------------------------------------------------
  5481. // Fill the Oss KeyTransRecipientInfo
  5482. //--------------------------------------------------------------------------
  5483. BOOL
  5484. WINAPI
  5485. ICM_FillOssKeyTransRecipientInfo(
  5486. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  5487. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  5488. IN DWORD dwRecipientIndex,
  5489. IN OUT KeyTransRecipientInfo *pori,
  5490. #ifdef OSS_CRYPT_ASN1
  5491. IN OUT int *pEnvelopedDataVersion
  5492. #else
  5493. IN OUT ASN1int32_t *pEnvelopedDataVersion
  5494. #endif // OSS_CRYPT_ASN1
  5495. )
  5496. {
  5497. BOOL fRet;
  5498. CMSG_KEY_TRANS_ENCRYPT_INFO KeyTransEncryptInfo;
  5499. memset(&KeyTransEncryptInfo, 0, sizeof(KeyTransEncryptInfo));
  5500. KeyTransEncryptInfo.cbSize = sizeof(KeyTransEncryptInfo);
  5501. KeyTransEncryptInfo.dwRecipientIndex = dwRecipientIndex;
  5502. KeyTransEncryptInfo.KeyEncryptionAlgorithm =
  5503. pKeyTransEncodeInfo->KeyEncryptionAlgorithm;
  5504. // KeyTransEncryptInfo.EncryptedKey =
  5505. // KeyTransEncryptInfo.dwFlags =
  5506. if (!ICM_ExportKeyTrans(
  5507. pContentEncryptInfo,
  5508. pKeyTransEncodeInfo,
  5509. &KeyTransEncryptInfo
  5510. ))
  5511. goto ExportKeyTransError;
  5512. pori->encryptedKey.length = KeyTransEncryptInfo.EncryptedKey.cbData;
  5513. pori->encryptedKey.value = KeyTransEncryptInfo.EncryptedKey.pbData;
  5514. if (CERT_ID_ISSUER_SERIAL_NUMBER ==
  5515. pKeyTransEncodeInfo->RecipientId.dwIdChoice)
  5516. pori->version = CMSG_KEY_TRANS_PKCS_1_5_VERSION;
  5517. else {
  5518. pori->version = CMSG_KEY_TRANS_CMS_VERSION;
  5519. *pEnvelopedDataVersion = CMSG_ENVELOPED_DATA_CMS_VERSION;
  5520. }
  5521. if (!ICM_SetOssCertIdentifier(
  5522. &pKeyTransEncodeInfo->RecipientId,
  5523. &pori->rid
  5524. ))
  5525. goto SetOssCertIdentifierError;
  5526. if (!ICM_SetOssAlgorithmIdentifier(
  5527. &KeyTransEncryptInfo.KeyEncryptionAlgorithm,
  5528. &pori->keyEncryptionAlgorithm
  5529. ))
  5530. goto SetOssAlgorithmIdentifierError;
  5531. fRet = TRUE;
  5532. CommonReturn:
  5533. if (KeyTransEncryptInfo.dwFlags & CMSG_KEY_TRANS_ENCRYPT_FREE_PARA_FLAG)
  5534. ICM_Free(KeyTransEncryptInfo.KeyEncryptionAlgorithm.Parameters.pbData);
  5535. return fRet;
  5536. ErrorReturn:
  5537. ICM_FreeOssKeyTransRecipientInfo(pori);
  5538. fRet = FALSE;
  5539. goto CommonReturn;
  5540. TRACE_ERROR(ExportKeyTransError)
  5541. TRACE_ERROR(SetOssCertIdentifierError)
  5542. TRACE_ERROR(SetOssAlgorithmIdentifierError)
  5543. }
  5544. //+-------------------------------------------------------------------------
  5545. // Free the Oss KeyAgreeRecipientInfo
  5546. //--------------------------------------------------------------------------
  5547. void
  5548. WINAPI
  5549. ICM_FreeOssKeyAgreeRecipientInfo(
  5550. IN OUT KeyAgreeRecipientInfo *pori
  5551. )
  5552. {
  5553. RecipientEncryptedKey *porek;
  5554. unsigned int count;
  5555. ICM_FreeOssOriginatorCertIdentifierOrKey(&pori->originator);
  5556. ICM_FreeOssOctetString(&pori->ukm);
  5557. ICM_FreeOssAlgorithmIdentifier(&pori->keyEncryptionAlgorithm);
  5558. porek = pori->recipientEncryptedKeys.value;
  5559. if (NULL == porek)
  5560. return;
  5561. for (count = pori->recipientEncryptedKeys.count;
  5562. 0 < count; count--, porek++) {
  5563. switch (porek->rid.choice) {
  5564. case issuerAndSerialNumber_chosen:
  5565. ICM_FreeOssIssuerAndSerialNumber(
  5566. &porek->rid.u.issuerAndSerialNumber);
  5567. break;
  5568. case rKeyId_chosen:
  5569. ICM_FreeOssOctetString(
  5570. &porek->rid.u.rKeyId.subjectKeyIdentifier);
  5571. ICM_FreeOssOtherKeyAttribute(&porek->rid.u.rKeyId.other);
  5572. break;
  5573. }
  5574. ICM_Free(porek->encryptedKey.value);
  5575. porek->encryptedKey.value = NULL;
  5576. }
  5577. ICM_Free(pori->recipientEncryptedKeys.value);
  5578. }
  5579. //+-------------------------------------------------------------------------
  5580. // Fill the Oss KeyAgreeRecipientInfo
  5581. //--------------------------------------------------------------------------
  5582. BOOL
  5583. WINAPI
  5584. ICM_FillOssKeyAgreeRecipientInfo(
  5585. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  5586. IN PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgreeEncodeInfo,
  5587. IN DWORD dwRecipientIndex,
  5588. IN OUT KeyAgreeRecipientInfo *pori
  5589. )
  5590. {
  5591. BOOL fRet;
  5592. DWORD i;
  5593. CMSG_KEY_AGREE_ENCRYPT_INFO KeyAgreeEncryptInfo;
  5594. DWORD cKeyAgreeKeyEncryptInfo;
  5595. PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO *rgpKeyAgreeKeyEncryptInfo = NULL;
  5596. PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO pKeyAgreeKeyEncryptInfo;
  5597. RecipientEncryptedKey *porek;
  5598. memset(&KeyAgreeEncryptInfo, 0, sizeof(KeyAgreeEncryptInfo));
  5599. KeyAgreeEncryptInfo.cbSize = sizeof(KeyAgreeEncryptInfo);
  5600. KeyAgreeEncryptInfo.dwRecipientIndex = dwRecipientIndex;
  5601. KeyAgreeEncryptInfo.KeyEncryptionAlgorithm =
  5602. pKeyAgreeEncodeInfo->KeyEncryptionAlgorithm;
  5603. KeyAgreeEncryptInfo.UserKeyingMaterial =
  5604. pKeyAgreeEncodeInfo->UserKeyingMaterial;
  5605. // KeyAgreeEncryptInfo.dwOriginatorChoice =
  5606. // union
  5607. // KeyAgreeEncryptInfo.OriginatorCertId =
  5608. // KeyAgreeEncryptInfo.OriginatorPublicKeyInfo =
  5609. // KeyAgreeEncryptInfo.cKeyAgreeKeyEncryptInfo =
  5610. // KeyAgreeEncryptInfo.rgpKeyAgreeKeyEncryptInfo =
  5611. // KeyAgreeEncryptInfo.dwFlags =
  5612. cKeyAgreeKeyEncryptInfo = pKeyAgreeEncodeInfo->cRecipientEncryptedKeys;
  5613. if (0 == cKeyAgreeKeyEncryptInfo)
  5614. goto NoKeyAgreeKeys;
  5615. if (NULL == (pori->recipientEncryptedKeys.value =
  5616. (RecipientEncryptedKey *) ICM_AllocZero(
  5617. cKeyAgreeKeyEncryptInfo * sizeof(RecipientEncryptedKey))))
  5618. goto OutOfMemory;
  5619. pori->recipientEncryptedKeys.count = cKeyAgreeKeyEncryptInfo;
  5620. if (NULL == (rgpKeyAgreeKeyEncryptInfo =
  5621. (PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO *) ICM_AllocZero(
  5622. cKeyAgreeKeyEncryptInfo *
  5623. sizeof(PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO) +
  5624. cKeyAgreeKeyEncryptInfo *
  5625. sizeof(CMSG_KEY_AGREE_KEY_ENCRYPT_INFO))))
  5626. goto OutOfMemory;
  5627. pKeyAgreeKeyEncryptInfo =
  5628. PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO (((PBYTE) rgpKeyAgreeKeyEncryptInfo) +
  5629. cKeyAgreeKeyEncryptInfo * sizeof(PCMSG_KEY_AGREE_KEY_ENCRYPT_INFO));
  5630. for (i = 0; i < cKeyAgreeKeyEncryptInfo; i++, pKeyAgreeKeyEncryptInfo++) {
  5631. rgpKeyAgreeKeyEncryptInfo[i] = pKeyAgreeKeyEncryptInfo;
  5632. pKeyAgreeKeyEncryptInfo->cbSize =
  5633. sizeof(CMSG_KEY_AGREE_KEY_ENCRYPT_INFO);
  5634. }
  5635. KeyAgreeEncryptInfo.cKeyAgreeKeyEncryptInfo = cKeyAgreeKeyEncryptInfo;
  5636. KeyAgreeEncryptInfo.rgpKeyAgreeKeyEncryptInfo = rgpKeyAgreeKeyEncryptInfo;
  5637. if (!ICM_ExportKeyAgree(
  5638. pContentEncryptInfo,
  5639. pKeyAgreeEncodeInfo,
  5640. &KeyAgreeEncryptInfo
  5641. ))
  5642. goto ExportKeyAgreeError;
  5643. for (i = 0, porek = pori->recipientEncryptedKeys.value;
  5644. i < cKeyAgreeKeyEncryptInfo; i++, porek++) {
  5645. porek->encryptedKey.length =
  5646. rgpKeyAgreeKeyEncryptInfo[i]->EncryptedKey.cbData;
  5647. porek->encryptedKey.value =
  5648. rgpKeyAgreeKeyEncryptInfo[i]->EncryptedKey.pbData;
  5649. }
  5650. pori->version = CMSG_KEY_AGREE_VERSION;
  5651. switch (KeyAgreeEncryptInfo.dwOriginatorChoice) {
  5652. case CMSG_KEY_AGREE_ORIGINATOR_CERT:
  5653. if (!ICM_SetOssOriginatorCertIdentifier(
  5654. &KeyAgreeEncryptInfo.OriginatorCertId,
  5655. &pori->originator
  5656. ))
  5657. goto SetOssOriginatorCertIdentifierError;
  5658. break;
  5659. case CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY:
  5660. if (!ICM_SetOssOriginatorPublicKey(
  5661. &KeyAgreeEncryptInfo.OriginatorPublicKeyInfo,
  5662. &pori->originator
  5663. ))
  5664. goto SetOssOriginatorPublicKeyError;
  5665. break;
  5666. default:
  5667. goto InvalidOriginatorChoice;
  5668. }
  5669. if (KeyAgreeEncryptInfo.UserKeyingMaterial.cbData) {
  5670. if (!ICM_SetOssOctetString(
  5671. &KeyAgreeEncryptInfo.UserKeyingMaterial,
  5672. &pori->ukm
  5673. ))
  5674. goto SetOssUserKeyingMaterialError;
  5675. pori->bit_mask |= ukm_present;
  5676. }
  5677. if (!ICM_SetOssAlgorithmIdentifier(
  5678. &KeyAgreeEncryptInfo.KeyEncryptionAlgorithm,
  5679. &pori->keyEncryptionAlgorithm
  5680. ))
  5681. goto SetOssAlgorithmIdentifierError;
  5682. for (i = 0, porek = pori->recipientEncryptedKeys.value;
  5683. i < cKeyAgreeKeyEncryptInfo; i++, porek++) {
  5684. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO pEncryptedKeyEncodeInfo =
  5685. pKeyAgreeEncodeInfo->rgpRecipientEncryptedKeys[i];
  5686. switch (pEncryptedKeyEncodeInfo->RecipientId.dwIdChoice) {
  5687. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5688. if (!ICM_SetOssIssuerAndSerialNumber(
  5689. &pEncryptedKeyEncodeInfo->RecipientId.IssuerSerialNumber,
  5690. &porek->rid.u.issuerAndSerialNumber
  5691. ))
  5692. goto SetOssIssuerAndSerialNumberError;
  5693. porek->rid.choice = issuerAndSerialNumber_chosen;
  5694. break;
  5695. case CERT_ID_KEY_IDENTIFIER:
  5696. if (!ICM_SetOssOctetString(
  5697. &pEncryptedKeyEncodeInfo->RecipientId.KeyId,
  5698. &porek->rid.u.rKeyId.subjectKeyIdentifier
  5699. ))
  5700. goto SetOssOctetStringError;
  5701. porek->rid.choice = rKeyId_chosen;
  5702. if (pEncryptedKeyEncodeInfo->Date.dwLowDateTime ||
  5703. pEncryptedKeyEncodeInfo->Date.dwHighDateTime) {
  5704. if (!PkiAsn1ToGeneralizedTime(
  5705. &pEncryptedKeyEncodeInfo->Date,
  5706. &porek->rid.u.rKeyId.date
  5707. ))
  5708. goto ConvToGeneralizedTimeError;
  5709. porek->rid.u.rKeyId.bit_mask |= date_present;
  5710. }
  5711. if (pEncryptedKeyEncodeInfo->pOtherAttr) {
  5712. if (!ICM_SetOssOtherKeyAttribute(
  5713. pEncryptedKeyEncodeInfo->pOtherAttr,
  5714. &porek->rid.u.rKeyId.other
  5715. ))
  5716. goto SetOssOtherKeyAttributeError;
  5717. porek->rid.u.rKeyId.bit_mask |= other_present;
  5718. }
  5719. break;
  5720. default:
  5721. goto InvalidRecipientIdChoice;
  5722. }
  5723. }
  5724. fRet = TRUE;
  5725. CommonReturn:
  5726. ICM_Free(rgpKeyAgreeKeyEncryptInfo);
  5727. if (KeyAgreeEncryptInfo.dwFlags & CMSG_KEY_AGREE_ENCRYPT_FREE_PARA_FLAG)
  5728. ICM_Free(KeyAgreeEncryptInfo.KeyEncryptionAlgorithm.Parameters.pbData);
  5729. if (KeyAgreeEncryptInfo.dwFlags &
  5730. CMSG_KEY_AGREE_ENCRYPT_FREE_MATERIAL_FLAG)
  5731. ICM_Free(KeyAgreeEncryptInfo.UserKeyingMaterial.pbData);
  5732. if (KeyAgreeEncryptInfo.dwFlags &
  5733. CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_ALG_FLAG)
  5734. ICM_Free(
  5735. KeyAgreeEncryptInfo.OriginatorPublicKeyInfo.Algorithm.pszObjId);
  5736. if (KeyAgreeEncryptInfo.dwFlags &
  5737. CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_PARA_FLAG)
  5738. ICM_Free(
  5739. KeyAgreeEncryptInfo.OriginatorPublicKeyInfo.Algorithm.Parameters.pbData);
  5740. if (KeyAgreeEncryptInfo.dwFlags &
  5741. CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_BITS_FLAG)
  5742. ICM_Free(KeyAgreeEncryptInfo.OriginatorPublicKeyInfo.PublicKey.pbData);
  5743. return fRet;
  5744. ErrorReturn:
  5745. ICM_FreeOssKeyAgreeRecipientInfo(pori);
  5746. fRet = FALSE;
  5747. goto CommonReturn;
  5748. SET_ERROR(InvalidOriginatorChoice, E_INVALIDARG)
  5749. SET_ERROR(NoKeyAgreeKeys, E_INVALIDARG)
  5750. TRACE_ERROR(OutOfMemory)
  5751. TRACE_ERROR(ExportKeyAgreeError)
  5752. TRACE_ERROR(SetOssOriginatorCertIdentifierError)
  5753. TRACE_ERROR(SetOssOriginatorPublicKeyError)
  5754. TRACE_ERROR(SetOssUserKeyingMaterialError)
  5755. TRACE_ERROR(SetOssAlgorithmIdentifierError)
  5756. TRACE_ERROR(SetOssIssuerAndSerialNumberError)
  5757. TRACE_ERROR(SetOssOctetStringError)
  5758. TRACE_ERROR(ConvToGeneralizedTimeError)
  5759. TRACE_ERROR(SetOssOtherKeyAttributeError)
  5760. SET_ERROR(InvalidRecipientIdChoice, E_INVALIDARG)
  5761. }
  5762. //+-------------------------------------------------------------------------
  5763. // Free the Oss MailListRecipientInfo
  5764. //--------------------------------------------------------------------------
  5765. void
  5766. WINAPI
  5767. ICM_FreeOssMailListRecipientInfo(
  5768. IN OUT MailListRecipientInfo *pori
  5769. )
  5770. {
  5771. ICM_FreeOssOctetString(&pori->mlid.kekIdentifier);
  5772. ICM_FreeOssOtherKeyAttribute(&pori->mlid.other);
  5773. ICM_FreeOssAlgorithmIdentifier(&pori->keyEncryptionAlgorithm);
  5774. ICM_Free(pori->encryptedKey.value);
  5775. pori->encryptedKey.value = NULL;
  5776. }
  5777. //+-------------------------------------------------------------------------
  5778. // Fill the Oss MailListRecipientInfo
  5779. //--------------------------------------------------------------------------
  5780. BOOL
  5781. WINAPI
  5782. ICM_FillOssMailListRecipientInfo(
  5783. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  5784. IN PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailListEncodeInfo,
  5785. IN DWORD dwRecipientIndex,
  5786. IN OUT MailListRecipientInfo *pori
  5787. )
  5788. {
  5789. BOOL fRet;
  5790. CMSG_MAIL_LIST_ENCRYPT_INFO MailListEncryptInfo;
  5791. memset(&MailListEncryptInfo, 0, sizeof(MailListEncryptInfo));
  5792. MailListEncryptInfo.cbSize = sizeof(MailListEncryptInfo);
  5793. MailListEncryptInfo.dwRecipientIndex = dwRecipientIndex;
  5794. MailListEncryptInfo.KeyEncryptionAlgorithm =
  5795. pMailListEncodeInfo->KeyEncryptionAlgorithm;
  5796. // MailListEncryptInfo.EncryptedKey =
  5797. // MailListEncryptInfo.dwFlags =
  5798. if (!ICM_ExportMailList(
  5799. pContentEncryptInfo,
  5800. pMailListEncodeInfo,
  5801. &MailListEncryptInfo
  5802. ))
  5803. goto ExportMailListError;
  5804. pori->encryptedKey.length = MailListEncryptInfo.EncryptedKey.cbData;
  5805. pori->encryptedKey.value = MailListEncryptInfo.EncryptedKey.pbData;
  5806. pori->version = CMSG_MAIL_LIST_VERSION;
  5807. if (!ICM_SetOssOctetString(
  5808. &pMailListEncodeInfo->KeyId,
  5809. &pori->mlid.kekIdentifier
  5810. ))
  5811. goto SetOssOctetStringError;
  5812. if (pMailListEncodeInfo->Date.dwLowDateTime ||
  5813. pMailListEncodeInfo->Date.dwHighDateTime) {
  5814. if (!PkiAsn1ToGeneralizedTime(
  5815. &pMailListEncodeInfo->Date,
  5816. &pori->mlid.date
  5817. ))
  5818. goto ConvToGeneralizedTimeError;
  5819. pori->mlid.bit_mask |= date_present;
  5820. }
  5821. if (pMailListEncodeInfo->pOtherAttr) {
  5822. if (!ICM_SetOssOtherKeyAttribute(
  5823. pMailListEncodeInfo->pOtherAttr,
  5824. &pori->mlid.other
  5825. ))
  5826. goto SetOssOtherKeyAttributeError;
  5827. pori->mlid.bit_mask |= other_present;
  5828. }
  5829. if (!ICM_SetOssAlgorithmIdentifier(
  5830. &MailListEncryptInfo.KeyEncryptionAlgorithm,
  5831. &pori->keyEncryptionAlgorithm
  5832. ))
  5833. goto SetOssAlgorithmIdentifierError;
  5834. fRet = TRUE;
  5835. CommonReturn:
  5836. if (MailListEncryptInfo.dwFlags & CMSG_MAIL_LIST_ENCRYPT_FREE_PARA_FLAG)
  5837. ICM_Free(MailListEncryptInfo.KeyEncryptionAlgorithm.Parameters.pbData);
  5838. return fRet;
  5839. ErrorReturn:
  5840. ICM_FreeOssMailListRecipientInfo(pori);
  5841. fRet = FALSE;
  5842. goto CommonReturn;
  5843. TRACE_ERROR(ExportMailListError)
  5844. TRACE_ERROR(SetOssOctetStringError)
  5845. TRACE_ERROR(ConvToGeneralizedTimeError)
  5846. TRACE_ERROR(SetOssOtherKeyAttributeError)
  5847. TRACE_ERROR(SetOssAlgorithmIdentifierError)
  5848. }
  5849. //+-------------------------------------------------------------------------
  5850. // Free the Oss CmsRecipientInfos
  5851. //--------------------------------------------------------------------------
  5852. void
  5853. WINAPI
  5854. ICM_FreeOssCmsRecipientInfos(
  5855. IN OUT CmsRecipientInfos *poris
  5856. )
  5857. {
  5858. DWORD i;
  5859. CmsRecipientInfo *pori;
  5860. if (NULL == poris->value)
  5861. return;
  5862. for (i = 0, pori = poris->value; i < poris->count; i++, pori++) {
  5863. switch (pori->choice) {
  5864. case keyTransRecipientInfo_chosen:
  5865. ICM_FreeOssKeyTransRecipientInfo(
  5866. &pori->u.keyTransRecipientInfo);
  5867. break;
  5868. case keyAgreeRecipientInfo_chosen:
  5869. ICM_FreeOssKeyAgreeRecipientInfo(
  5870. &pori->u.keyAgreeRecipientInfo);
  5871. break;
  5872. case mailListRecipientInfo_chosen:
  5873. ICM_FreeOssMailListRecipientInfo(
  5874. &pori->u.mailListRecipientInfo);
  5875. break;
  5876. case 0:
  5877. default:
  5878. break;
  5879. }
  5880. }
  5881. ICM_Free(poris->value);
  5882. poris->value = NULL;
  5883. }
  5884. //+-------------------------------------------------------------------------
  5885. // Fill the Oss CmsRecipientInfos
  5886. //--------------------------------------------------------------------------
  5887. BOOL
  5888. WINAPI
  5889. ICM_FillOssCmsRecipientInfos(
  5890. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  5891. IN OUT CmsRecipientInfos *poris,
  5892. #ifdef OSS_CRYPT_ASN1
  5893. IN OUT int *pEnvelopedDataVersion
  5894. #else
  5895. IN OUT ASN1int32_t *pEnvelopedDataVersion
  5896. #endif // OSS_CRYPT_ASN1
  5897. )
  5898. {
  5899. BOOL fRet;
  5900. DWORD cRecipients;
  5901. PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients;
  5902. CmsRecipientInfo *pori = NULL;
  5903. DWORD i;
  5904. cRecipients = pContentEncryptInfo->cRecipients;
  5905. if (0 == cRecipients)
  5906. goto SuccessReturn;
  5907. rgCmsRecipients = pContentEncryptInfo->rgCmsRecipients;
  5908. assert(cRecipients && rgCmsRecipients);
  5909. if (NULL == (poris->value = (CmsRecipientInfo *) ICM_AllocZero(
  5910. cRecipients * sizeof(CmsRecipientInfo))))
  5911. goto OutOfMemory;
  5912. poris->count = cRecipients;
  5913. for (i = 0, pori = poris->value; i < cRecipients; i++, pori++) {
  5914. switch (rgCmsRecipients[i].dwRecipientChoice) {
  5915. case CMSG_KEY_TRANS_RECIPIENT:
  5916. if (!ICM_FillOssKeyTransRecipientInfo(
  5917. pContentEncryptInfo,
  5918. rgCmsRecipients[i].pKeyTrans,
  5919. i,
  5920. &pori->u.keyTransRecipientInfo,
  5921. pEnvelopedDataVersion
  5922. ))
  5923. goto FillOssKeyTransRecipientInfoError;
  5924. pori->choice = keyTransRecipientInfo_chosen;
  5925. break;
  5926. case CMSG_KEY_AGREE_RECIPIENT:
  5927. if (!ICM_FillOssKeyAgreeRecipientInfo(
  5928. pContentEncryptInfo,
  5929. rgCmsRecipients[i].pKeyAgree,
  5930. i,
  5931. &pori->u.keyAgreeRecipientInfo
  5932. ))
  5933. goto FillOssKeyAgreeRecipientInfoError;
  5934. pori->choice = keyAgreeRecipientInfo_chosen;
  5935. *pEnvelopedDataVersion = CMSG_ENVELOPED_DATA_CMS_VERSION;
  5936. break;
  5937. case CMSG_MAIL_LIST_RECIPIENT:
  5938. if (!ICM_FillOssMailListRecipientInfo(
  5939. pContentEncryptInfo,
  5940. rgCmsRecipients[i].pMailList,
  5941. i,
  5942. &pori->u.mailListRecipientInfo
  5943. ))
  5944. goto FillOssMailLIstRecipientInfoError;
  5945. pori->choice = mailListRecipientInfo_chosen;
  5946. *pEnvelopedDataVersion = CMSG_ENVELOPED_DATA_CMS_VERSION;
  5947. break;
  5948. default:
  5949. goto InvalidRecipientChoice;
  5950. }
  5951. }
  5952. SuccessReturn:
  5953. fRet = TRUE;
  5954. CommonReturn:
  5955. return fRet;
  5956. ErrorReturn:
  5957. ICM_FreeOssCmsRecipientInfos(poris);
  5958. fRet = FALSE;
  5959. goto CommonReturn;
  5960. TRACE_ERROR(OutOfMemory)
  5961. TRACE_ERROR(FillOssKeyTransRecipientInfoError)
  5962. TRACE_ERROR(FillOssKeyAgreeRecipientInfoError)
  5963. TRACE_ERROR(FillOssMailLIstRecipientInfoError)
  5964. SET_ERROR(InvalidRecipientChoice, E_INVALIDARG)
  5965. }
  5966. //+-------------------------------------------------------------------------
  5967. // Open an enveloped message for encoding
  5968. //--------------------------------------------------------------------------
  5969. HCRYPTMSG
  5970. WINAPI
  5971. ICM_OpenToEncodeEnvelopedData(
  5972. IN DWORD dwEncodingType,
  5973. IN DWORD dwFlags,
  5974. IN void const *pvMsgEncodeInfo,
  5975. IN OPTIONAL LPSTR pszInnerContentObjID,
  5976. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  5977. {
  5978. DWORD dwError = ERROR_SUCCESS;
  5979. PCRYPT_MSG_INFO pcmi = NULL;
  5980. PCMSG_ENVELOPED_ENCODE_INFO pemei =
  5981. (PCMSG_ENVELOPED_ENCODE_INFO) pvMsgEncodeInfo;
  5982. CmsEnvelopedData *ped = NULL;
  5983. EncryptedContentInfo *peci;
  5984. CMSG_CONTENT_ENCRYPT_INFO ContentEncryptInfo;
  5985. ZEROSTRUCT(ContentEncryptInfo);
  5986. DWORD i;
  5987. PCERT_BLOB pcert;
  5988. PCRL_BLOB pcrl;
  5989. Certificate *pOssCert;
  5990. CertificateRevocationList *pOssCrl;
  5991. DWORD cbCert = 0;
  5992. PBYTE pbCert;
  5993. DWORD cbCrl;
  5994. PBYTE pbCrl;
  5995. DWORD cbOriginatorInfo;
  5996. DWORD cUnprotectedAttr;
  5997. assert(pemei->cbSize >= STRUCT_CBSIZE(CMSG_ENVELOPED_ENCODE_INFO,
  5998. rgpRecipients));
  5999. if (pemei->cbSize <
  6000. STRUCT_CBSIZE(CMSG_ENVELOPED_ENCODE_INFO, rgpRecipients))
  6001. goto InvalidArg;
  6002. if (pemei->cbSize >= sizeof(CMSG_ENVELOPED_ENCODE_INFO)) {
  6003. for (i=pemei->cCertEncoded, pcert=pemei->rgCertEncoded, cbCert=0;
  6004. i>0;
  6005. i--, pcert++)
  6006. cbCert += pcert->cbData;
  6007. for (i=pemei->cAttrCertEncoded, pcert=pemei->rgAttrCertEncoded;
  6008. i>0;
  6009. i--, pcert++)
  6010. cbCert += pcert->cbData;
  6011. for (i=pemei->cCrlEncoded, pcrl=pemei->rgCrlEncoded, cbCrl=0;
  6012. i>0;
  6013. i--, pcrl++)
  6014. cbCrl += pcrl->cbData;
  6015. cbOriginatorInfo =
  6016. pemei->cCertEncoded * sizeof(Certificate) +
  6017. pemei->cAttrCertEncoded * sizeof(Certificate) +
  6018. pemei->cCrlEncoded * sizeof(CertificateRevocationList) +
  6019. cbCert + cbCrl;
  6020. cUnprotectedAttr = pemei->cUnprotectedAttr;
  6021. } else {
  6022. cbOriginatorInfo = 0;
  6023. cUnprotectedAttr = 0;
  6024. }
  6025. ped = (CmsEnvelopedData *)ICM_AllocZero(
  6026. sizeof(CmsEnvelopedData) + cbOriginatorInfo);
  6027. if (NULL == ped)
  6028. goto CmsEnvelopedDataAllocError;
  6029. // pcmi
  6030. pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero(sizeof(CRYPT_MSG_INFO));
  6031. if (NULL == pcmi)
  6032. goto PcmiAllocError;
  6033. // pcmi->hCryptProv
  6034. // pcmi->fDefaultCryptProv
  6035. pcmi->dwEncodingType = dwEncodingType;
  6036. pcmi->dwMsgType = CMSG_ENVELOPED;
  6037. pcmi->dwFlags = dwFlags;
  6038. pcmi->pvMsg = ped;
  6039. pcmi->fEncoding = TRUE;
  6040. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  6041. if (pszInnerContentObjID &&
  6042. (NULL == (pcmi->pszInnerContentObjID = (LPSTR)ICM_DupMem(
  6043. pszInnerContentObjID,
  6044. ICM_StrLen(pszInnerContentObjID) + 1))))
  6045. goto DupInnerContentObjIDError;
  6046. if (pStreamInfo &&
  6047. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  6048. pStreamInfo,
  6049. sizeof(*pStreamInfo)))))
  6050. goto DupStreamInfoError;
  6051. // version
  6052. if (0 < cbOriginatorInfo || 0 < cUnprotectedAttr)
  6053. ped->version = CMSG_ENVELOPED_DATA_CMS_VERSION;
  6054. else
  6055. ped->version = CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION;
  6056. if (0 < cbOriginatorInfo) {
  6057. OriginatorInfo *poi = &ped->originatorInfo;
  6058. // originatorInfo
  6059. ped->bit_mask |= originatorInfo_present;
  6060. // certificates
  6061. if (0 != pemei->cCertEncoded || 0 != pemei->cAttrCertEncoded) {
  6062. poi->bit_mask |= certificates_present;
  6063. poi->certificates.count = pemei->cCertEncoded +
  6064. pemei->cAttrCertEncoded;
  6065. #ifdef OSS_CRYPT_ASN1
  6066. poi->certificates.certificates = (Certificate *)(ped + 1);
  6067. #else
  6068. poi->certificates.value = (Certificate *)(ped + 1);
  6069. #endif // OSS_CRYPT_ASN1
  6070. pbCert = (PBYTE)ped +
  6071. sizeof( CmsEnvelopedData) +
  6072. pemei->cCertEncoded * sizeof( Certificate) +
  6073. pemei->cAttrCertEncoded * sizeof( Certificate) +
  6074. pemei->cCrlEncoded * sizeof( CertificateRevocationList);
  6075. for (i=pemei->cCertEncoded, pcert=pemei->rgCertEncoded,
  6076. #ifdef OSS_CRYPT_ASN1
  6077. pOssCert=poi->certificates.certificates;
  6078. #else
  6079. pOssCert=poi->certificates.value;
  6080. #endif // OSS_CRYPT_ASN1
  6081. i>0;
  6082. i--, pcert++, pOssCert++) {
  6083. pOssCert->length = pcert->cbData;
  6084. memcpy( pbCert, pcert->pbData, pcert->cbData);
  6085. pOssCert->value = pbCert;
  6086. pbCert += pcert->cbData;
  6087. }
  6088. for (i=pemei->cAttrCertEncoded, pcert=pemei->rgAttrCertEncoded;
  6089. i>0;
  6090. i--, pcert++, pOssCert++) {
  6091. pOssCert->length = pcert->cbData;
  6092. memcpy( pbCert, pcert->pbData, pcert->cbData);
  6093. if (pcert->cbData)
  6094. // Change tag from SEQUENCE to [1] IMPLICIT
  6095. *pbCert = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  6096. pOssCert->value = pbCert;
  6097. pbCert += pcert->cbData;
  6098. }
  6099. }
  6100. // crls
  6101. if (0 != pemei->cCrlEncoded) {
  6102. poi->bit_mask |= crls_present;
  6103. poi->crls.count = pemei->cCrlEncoded;
  6104. if (0 != pemei->cCertEncoded || 0 != pemei->cAttrCertEncoded)
  6105. #ifdef OSS_CRYPT_ASN1
  6106. poi->crls.crls = (CertificateRevocationList *)
  6107. (poi->certificates.certificates +
  6108. #else
  6109. poi->crls.value = (CertificateRevocationList *)
  6110. (poi->certificates.value +
  6111. #endif // OSS_CRYPT_ASN1
  6112. (pemei->cCertEncoded + pemei->cAttrCertEncoded));
  6113. else
  6114. #ifdef OSS_CRYPT_ASN1
  6115. poi->crls.crls = (CertificateRevocationList *) (ped + 1);
  6116. #else
  6117. poi->crls.value = (CertificateRevocationList *) (ped + 1);
  6118. #endif // OSS_CRYPT_ASN1
  6119. pbCrl = (PBYTE)ped +
  6120. sizeof( CmsEnvelopedData) +
  6121. pemei->cCertEncoded * sizeof( Certificate) +
  6122. pemei->cAttrCertEncoded * sizeof( Certificate) +
  6123. pemei->cCrlEncoded * sizeof( CertificateRevocationList) +
  6124. cbCert;
  6125. #ifdef OSS_CRYPT_ASN1
  6126. for (i=pemei->cCrlEncoded, pcrl=pemei->rgCrlEncoded, pOssCrl=poi->crls.crls;
  6127. #else
  6128. for (i=pemei->cCrlEncoded, pcrl=pemei->rgCrlEncoded, pOssCrl=poi->crls.value;
  6129. #endif // OSS_CRYPT_ASN1
  6130. i>0;
  6131. i--, pcrl++, pOssCrl++) {
  6132. pOssCrl->length = pcrl->cbData;
  6133. memcpy( pbCrl, pcrl->pbData, pcrl->cbData);
  6134. pOssCrl->value = pbCrl;
  6135. pbCrl += pcrl->cbData;
  6136. }
  6137. }
  6138. }
  6139. if (0 < cUnprotectedAttr) {
  6140. Attribute *poatr;
  6141. PCRYPT_ATTRIBUTE patr;
  6142. if (NULL == (poatr = (Attribute *) ICM_AllocZero(
  6143. cUnprotectedAttr * sizeof(Attribute))))
  6144. goto UnprotectedAttrsAllocError;
  6145. ped->unprotectedAttrs.value = poatr;
  6146. ped->unprotectedAttrs.count = cUnprotectedAttr;
  6147. ped->bit_mask |= unprotectedAttrs_present;
  6148. for (i=cUnprotectedAttr, patr=pemei->rgUnprotectedAttr;
  6149. i>0;
  6150. i--, patr++, poatr++) {
  6151. if (!ICM_Asn1ToAttribute(patr, poatr))
  6152. goto Asn1ToAttributeError;
  6153. }
  6154. }
  6155. if (!ICM_InitializeContentEncryptInfo(pemei, &ContentEncryptInfo))
  6156. goto InitializeContentEncryptInfoError;
  6157. // assert(ContentEncryptInfo.hCryptProv);
  6158. pcmi->hCryptProv = ContentEncryptInfo.hCryptProv;
  6159. assert(ContentEncryptInfo.hContentEncryptKey);
  6160. pcmi->hkeyContentCrypt = ContentEncryptInfo.hContentEncryptKey;
  6161. if (pStreamInfo && CMSG_INDEFINITE_LENGTH != pStreamInfo->cbContent)
  6162. ContentEncryptInfo.dwEncryptFlags |=
  6163. CMSG_CONTENT_ENCRYPT_PAD_ENCODED_LEN_FLAG;
  6164. if (!ICM_FillOssCmsRecipientInfos(
  6165. &ContentEncryptInfo,
  6166. &ped->recipientInfos,
  6167. &ped->version
  6168. ))
  6169. goto FillOssCmsRecipientInfosError;
  6170. // Is encryptedContent encapsulated ???
  6171. if (ped->version > CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION) {
  6172. if (ICM_IsData(pszInnerContentObjID))
  6173. pcmi->dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  6174. else
  6175. pcmi->dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  6176. } else if (pcmi->dwFlags & CMSG_CMS_ENCAPSULATED_CONTENT_FLAG) {
  6177. if (ICM_IsData(pszInnerContentObjID))
  6178. pcmi->dwFlags &= ~CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  6179. else
  6180. ped->version = CMSG_ENVELOPED_DATA_CMS_VERSION;
  6181. }
  6182. // encryptedContentInfo
  6183. // (.encryptedContent filled in during update)
  6184. peci = &ped->encryptedContentInfo;
  6185. peci->bit_mask = encryptedContent_present;
  6186. peci->contentType.count =
  6187. sizeof(peci->contentType.value)/sizeof(peci->contentType.value[0]);
  6188. if (!PkiAsn1ToObjectIdentifier(
  6189. pszInnerContentObjID ? pszInnerContentObjID : pszObjIdDataType,
  6190. &peci->contentType.count,
  6191. peci->contentType.value))
  6192. goto PkiAsn1ToObjectIdentifierError;
  6193. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  6194. pcmi,
  6195. &ContentEncryptInfo.ContentEncryptionAlgorithm,
  6196. &peci->contentEncryptionAlgorithm))
  6197. goto MsgAsn1ToAlgorithmIdentifierError;
  6198. if (pStreamInfo && !ICMS_OpenToEncodeEnvelopedData( pcmi, pemei))
  6199. goto StreamOpenToEncodeEnvelopedDataError;
  6200. // From here to CommonReturn, NO Errors
  6201. if (ContentEncryptInfo.hCryptProv == pemei->hCryptProv) {
  6202. // assert(ContentEncryptInfo.hCryptProv);
  6203. assert(0 == (ContentEncryptInfo.dwFlags &
  6204. CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG));
  6205. } else {
  6206. if (pcmi->dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) {
  6207. pcmi->dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
  6208. CryptReleaseContext(pemei->hCryptProv, 0);
  6209. }
  6210. }
  6211. if (ContentEncryptInfo.dwFlags &
  6212. CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG) {
  6213. pcmi->dwFlags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
  6214. ContentEncryptInfo.dwFlags &=
  6215. ~CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG;
  6216. }
  6217. ContentEncryptInfo.hContentEncryptKey = 0;
  6218. CommonReturn:
  6219. ICM_FreeContentEncryptInfo(pemei, &ContentEncryptInfo);
  6220. ICM_SetLastError(dwError);
  6221. return (HCRYPTMSG) pcmi;
  6222. ErrorReturn:
  6223. dwError = GetLastError();
  6224. if (ped) {
  6225. ICM_FreeOssCmsRecipientInfos(&ped->recipientInfos);
  6226. if (ped->unprotectedAttrs.value) {
  6227. Attribute *poatr;
  6228. for (i=ped->unprotectedAttrs.count,
  6229. poatr=ped->unprotectedAttrs.value;
  6230. i>0;
  6231. i--, poatr++) {
  6232. ICM_Free(poatr->attributeValue.value);
  6233. }
  6234. ICM_Free(ped->unprotectedAttrs.value);
  6235. }
  6236. ICM_Free(ped);
  6237. }
  6238. if (pcmi) {
  6239. if (pcmi->pFreeList)
  6240. delete pcmi->pFreeList;
  6241. ICM_Free(pcmi->pszInnerContentObjID);
  6242. ICM_Free(pcmi->pStreamInfo);
  6243. ICM_Free(pcmi);
  6244. pcmi = NULL;
  6245. }
  6246. goto CommonReturn;
  6247. SET_ERROR(InvalidArg,E_INVALIDARG)
  6248. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  6249. TRACE_ERROR(DupInnerContentObjIDError)
  6250. TRACE_ERROR(DupStreamInfoError)
  6251. TRACE_ERROR(CmsEnvelopedDataAllocError)
  6252. TRACE_ERROR(PcmiAllocError)
  6253. TRACE_ERROR(UnprotectedAttrsAllocError)
  6254. TRACE_ERROR(Asn1ToAttributeError)
  6255. TRACE_ERROR(InitializeContentEncryptInfoError)
  6256. TRACE_ERROR(FillOssCmsRecipientInfosError)
  6257. TRACE_ERROR(MsgAsn1ToAlgorithmIdentifierError)
  6258. TRACE_ERROR(StreamOpenToEncodeEnvelopedDataError)
  6259. }
  6260. #else
  6261. //+-------------------------------------------------------------------------
  6262. // Default export of the encryption key
  6263. //
  6264. // Note, pcbData[1] contains dwEncryptFlags, where,
  6265. // CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG may be set to disable the reversing
  6266. // of the encoded, encrypted symmetric key.
  6267. //
  6268. // rgcbData[1] is the dwEncryptFlags passed from ICM_DefaultGenEncryptKey
  6269. //--------------------------------------------------------------------------
  6270. BOOL
  6271. WINAPI
  6272. ICM_DefaultExportEncryptKey(
  6273. IN HCRYPTPROV hCryptProv,
  6274. IN HCRYPTKEY hEncryptKey,
  6275. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  6276. OUT PBYTE pbData,
  6277. IN OUT DWORD rgcbData[2])
  6278. {
  6279. BOOL fRet;
  6280. DWORD dwError = ERROR_SUCCESS;
  6281. HCRYPTKEY hPubKey = NULL;
  6282. PBYTE pb = NULL;
  6283. DWORD cb;
  6284. if (!CryptImportPublicKeyInfo(
  6285. hCryptProv,
  6286. X509_ASN_ENCODING,
  6287. pPublicKeyInfo,
  6288. &hPubKey))
  6289. goto ImportKeyError;
  6290. if (!CryptExportKey(
  6291. hEncryptKey,
  6292. hPubKey,
  6293. SIMPLEBLOB,
  6294. 0, // dwFlags
  6295. NULL,
  6296. &cb))
  6297. goto ExportKeySizeError;
  6298. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  6299. goto ExportKeyAllocError;
  6300. if (!CryptExportKey(
  6301. hEncryptKey,
  6302. hPubKey,
  6303. SIMPLEBLOB,
  6304. 0, // dwFlags
  6305. pb,
  6306. &cb))
  6307. goto ExportKeyError;
  6308. assert( cb > (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)));
  6309. cb -= sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  6310. fRet = TRUE;
  6311. if (pbData) {
  6312. if (rgcbData[0] < cb) {
  6313. SetLastError((DWORD) ERROR_MORE_DATA);
  6314. fRet = FALSE;
  6315. } else if (0 < cb) {
  6316. if (rgcbData[1] & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)
  6317. // Don't byte reverse
  6318. memcpy(pbData,
  6319. pb + (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)),
  6320. cb);
  6321. else
  6322. ICM_ReverseCopy(pbData,
  6323. pb + (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)),
  6324. cb);
  6325. }
  6326. }
  6327. CommonReturn:
  6328. rgcbData[0] = cb;
  6329. ICM_FreeA(pb);
  6330. if (hPubKey)
  6331. CryptDestroyKey(hPubKey);
  6332. ICM_SetLastError(dwError);
  6333. return fRet;
  6334. ErrorReturn:
  6335. dwError = GetLastError();
  6336. cb = 0;
  6337. fRet = FALSE;
  6338. goto CommonReturn;
  6339. TRACE_ERROR(ImportKeyError)
  6340. TRACE_ERROR(ExportKeySizeError)
  6341. TRACE_ERROR(ExportKeyAllocError)
  6342. TRACE_ERROR(ExportKeyError)
  6343. }
  6344. //+-------------------------------------------------------------------------
  6345. // Export of the encryption key
  6346. //
  6347. // rgcbData[1] is the dwEncryptFlags passed from ICM_GenEncryptKey
  6348. //--------------------------------------------------------------------------
  6349. BOOL
  6350. WINAPI
  6351. ICM_ExportEncryptKey(
  6352. IN HCRYPTPROV hCryptProv,
  6353. IN HCRYPTKEY hEncryptKey,
  6354. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  6355. OUT PBYTE pbData,
  6356. IN OUT DWORD rgcbData[2])
  6357. {
  6358. BOOL fResult;
  6359. void *pvFuncAddr;
  6360. HCRYPTOIDFUNCADDR hFuncAddr;
  6361. if (CryptGetOIDFunctionAddress(
  6362. hExportEncryptKeyFuncSet,
  6363. X509_ASN_ENCODING,
  6364. pPublicKeyInfo->Algorithm.pszObjId,
  6365. 0, // dwFlags
  6366. &pvFuncAddr,
  6367. &hFuncAddr)) {
  6368. fResult = ((PFN_CMSG_EXPORT_ENCRYPT_KEY) pvFuncAddr)(
  6369. hCryptProv,
  6370. hEncryptKey,
  6371. pPublicKeyInfo,
  6372. pbData,
  6373. rgcbData);
  6374. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  6375. } else
  6376. fResult = ICM_DefaultExportEncryptKey(
  6377. hCryptProv,
  6378. hEncryptKey,
  6379. pPublicKeyInfo,
  6380. pbData,
  6381. rgcbData);
  6382. return fResult;
  6383. }
  6384. // This size is good up through a 2048 bit exchange key
  6385. #define EXPORT_ENCRYPT_KEY_LENGTH 256
  6386. //+-------------------------------------------------------------------------
  6387. // Fill the RecipientInfos
  6388. //--------------------------------------------------------------------------
  6389. BOOL
  6390. WINAPI
  6391. ICM_FillRecipientInfos(
  6392. IN HCRYPTPROV hCryptProv,
  6393. IN HCRYPTKEY hKeyContent,
  6394. IN DWORD cRecipients,
  6395. IN PCERT_INFO *rgpRecipients,
  6396. IN OUT RecipientInfos *pris,
  6397. IN DWORD dwEncryptFlags)
  6398. {
  6399. BOOL fRet;
  6400. PCERT_INFO *ppci;
  6401. RecipientInfo *pri;
  6402. PBYTE pb = NULL;
  6403. DWORD rgcb[2]; // rgcb[1] is updated with dwEncryptFlags
  6404. DWORD cTryAgain;
  6405. DWORD i;
  6406. PBYTE pbSerialNumber;
  6407. DWORD cbSerialNumber = 0;
  6408. for (i=cRecipients, ppci=rgpRecipients; i>0; i--, ppci++)
  6409. cbSerialNumber += (*ppci)->SerialNumber.cbData;
  6410. pris->value = (RecipientInfo *)ICM_AllocZero(
  6411. cRecipients * sizeof( RecipientInfo) +
  6412. cbSerialNumber);
  6413. if (NULL == pris->value)
  6414. goto RecipientInfoAllocError;
  6415. pris->count = cRecipients;
  6416. pbSerialNumber = (PBYTE)(pris->value + cRecipients);
  6417. for (i=cRecipients, ppci=rgpRecipients, pri=pris->value;
  6418. i>0;
  6419. i--, ppci++, pri++) {
  6420. // version
  6421. pri->version = 0;
  6422. // issuerAndSerialNumber
  6423. pri->issuerAndSerialNumber.issuer.length = (*ppci)->Issuer.cbData;
  6424. pri->issuerAndSerialNumber.issuer.value = (*ppci)->Issuer.pbData;
  6425. pri->issuerAndSerialNumber.serialNumber.length = (*ppci)->SerialNumber.cbData;
  6426. pb = pbSerialNumber;
  6427. pbSerialNumber += (*ppci)->SerialNumber.cbData;
  6428. ICM_ReverseCopy(
  6429. pb,
  6430. (*ppci)->SerialNumber.pbData,
  6431. (*ppci)->SerialNumber.cbData);
  6432. pri->issuerAndSerialNumber.serialNumber.value = pb;
  6433. // keyEncryptionAlgorithm
  6434. if (!ICM_Asn1ToAlgorithmIdentifier(
  6435. &(*ppci)->SubjectPublicKeyInfo.Algorithm,
  6436. &pri->keyEncryptionAlgorithm))
  6437. goto Asn1ToAlgorithmIdentifierError;
  6438. rgcb[0] = EXPORT_ENCRYPT_KEY_LENGTH;
  6439. rgcb[1] = dwEncryptFlags;
  6440. cTryAgain = 1;
  6441. while (TRUE) {
  6442. if (NULL == (pb = (PBYTE)ICM_Alloc(rgcb[0])))
  6443. goto ExportKeyAllocError;
  6444. if (ICM_ExportEncryptKey(
  6445. hCryptProv,
  6446. hKeyContent,
  6447. &(*ppci)->SubjectPublicKeyInfo,
  6448. pb,
  6449. rgcb))
  6450. break;
  6451. ICM_Free(pb);
  6452. if (rgcb[0] && cTryAgain--)
  6453. continue;
  6454. else
  6455. goto ExportKeyError;
  6456. }
  6457. pri->encryptedKey.length = rgcb[0];
  6458. pri->encryptedKey.value = pb;
  6459. pb = NULL;
  6460. }
  6461. fRet = TRUE;
  6462. CommonReturn:
  6463. return fRet;
  6464. ErrorReturn:
  6465. // Need to free EncrytedKey for each recipient
  6466. ICM_Free( pris->value);
  6467. fRet = FALSE;
  6468. goto CommonReturn;
  6469. TRACE_ERROR(RecipientInfoAllocError)
  6470. TRACE_ERROR(Asn1ToAlgorithmIdentifierError)
  6471. TRACE_ERROR(ExportKeyAllocError)
  6472. TRACE_ERROR(ExportKeyError)
  6473. }
  6474. //+-------------------------------------------------------------------------
  6475. // Open an enveloped message for encoding
  6476. //--------------------------------------------------------------------------
  6477. HCRYPTMSG
  6478. WINAPI
  6479. ICM_OpenToEncodeEnvelopedData(
  6480. IN DWORD dwEncodingType,
  6481. IN DWORD dwFlags,
  6482. IN void const *pvMsgEncodeInfo,
  6483. IN OPTIONAL LPSTR pszInnerContentObjID,
  6484. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  6485. {
  6486. DWORD dwError = ERROR_SUCCESS;
  6487. PCRYPT_MSG_INFO pcmi = NULL;
  6488. PCMSG_ENVELOPED_ENCODE_INFO pemei = (PCMSG_ENVELOPED_ENCODE_INFO)pvMsgEncodeInfo;
  6489. EnvelopedData *ped = NULL;
  6490. EncryptedContentInfo *peci;
  6491. DWORD dwAlgoCAPI;
  6492. CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm;
  6493. PBYTE pbEncryptParameters = NULL;
  6494. // rgcbEncryptParameters[1] contains dwEncryptFlags
  6495. DWORD rgcbEncryptParameters[2];
  6496. assert( pemei->cbSize >= sizeof(CMSG_ENVELOPED_ENCODE_INFO));
  6497. assert( 0 != pemei->cRecipients);
  6498. if (pemei->cbSize < sizeof(CMSG_ENVELOPED_ENCODE_INFO) ||
  6499. 0 == pemei->cRecipients)
  6500. goto InvalidArg;
  6501. ped = (EnvelopedData *)ICM_AllocZero( sizeof( EnvelopedData));
  6502. if (NULL == ped)
  6503. goto EnvelopedDataAllocError;
  6504. // pcmi
  6505. pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO));
  6506. if (NULL == pcmi)
  6507. goto PcmiAllocError;
  6508. pcmi->hCryptProv = pemei->hCryptProv;
  6509. if (0 == pcmi->hCryptProv)
  6510. pcmi->fDefaultCryptProv = TRUE;
  6511. pcmi->dwEncodingType = dwEncodingType;
  6512. pcmi->dwMsgType = CMSG_ENVELOPED;
  6513. pcmi->dwFlags = dwFlags;
  6514. pcmi->pvMsg = ped;
  6515. pcmi->fEncoding = TRUE;
  6516. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  6517. if (pszInnerContentObjID &&
  6518. (NULL == (pcmi->pszInnerContentObjID = (LPSTR)ICM_DupMem(
  6519. pszInnerContentObjID,
  6520. ICM_StrLen(pszInnerContentObjID) + 1))))
  6521. goto DupInnerContentObjIDError;
  6522. if (pStreamInfo &&
  6523. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  6524. pStreamInfo,
  6525. sizeof(*pStreamInfo)))))
  6526. goto DupStreamInfoError;
  6527. // version
  6528. ped->version = 0;
  6529. // recipientInfos
  6530. // Use first recipients public key info
  6531. ContentEncryptionAlgorithm = pemei->ContentEncryptionAlgorithm;
  6532. rgcbEncryptParameters[0] = 0;
  6533. rgcbEncryptParameters[1] = 0;
  6534. if (!ICM_GenEncryptKey(
  6535. &pcmi->hCryptProv,
  6536. &ContentEncryptionAlgorithm,
  6537. pemei->pvEncryptionAuxInfo,
  6538. &pemei->rgpRecipients[0]->SubjectPublicKeyInfo,
  6539. ICM_Alloc,
  6540. &pcmi->hkeyContentCrypt, // not freed for an error
  6541. &pbEncryptParameters,
  6542. rgcbEncryptParameters))
  6543. goto GenKeyError;
  6544. if (rgcbEncryptParameters[0] && pbEncryptParameters) {
  6545. pcmi->pbEncryptParameters = pbEncryptParameters;
  6546. ContentEncryptionAlgorithm.Parameters.pbData = pbEncryptParameters;
  6547. ContentEncryptionAlgorithm.Parameters.cbData = rgcbEncryptParameters[0];
  6548. } else if (pbEncryptParameters) {
  6549. ICM_Free(pbEncryptParameters);
  6550. pbEncryptParameters = NULL;
  6551. }
  6552. if (!ICM_FillRecipientInfos(
  6553. pcmi->hCryptProv,
  6554. pcmi->hkeyContentCrypt,
  6555. pemei->cRecipients,
  6556. pemei->rgpRecipients,
  6557. &ped->recipientInfos,
  6558. rgcbEncryptParameters[1])) // dwEncryptFlags
  6559. goto FillRecipientInfosError;
  6560. // encryptedContentInfo
  6561. // (.encryptedContent filled in during update)
  6562. peci = &ped->encryptedContentInfo;
  6563. peci->bit_mask = encryptedContent_present;
  6564. peci->contentType.count = sizeof(peci->contentType.value)/sizeof(peci->contentType.value[0]);
  6565. if (!PkiAsn1ToObjectIdentifier(
  6566. pszInnerContentObjID ? pszInnerContentObjID : pszObjIdDataType,
  6567. &peci->contentType.count,
  6568. peci->contentType.value))
  6569. goto PkiAsn1ToObjectIdentifierError;
  6570. if (!ICM_Asn1ToAlgorithmIdentifier(
  6571. &ContentEncryptionAlgorithm,
  6572. &peci->contentEncryptionAlgorithm))
  6573. goto Asn1ToAlgorithmIdentifierError;
  6574. if (pStreamInfo && !ICMS_OpenToEncodeEnvelopedData( pcmi, pemei))
  6575. goto StreamOpenToEncodeEnvelopedDataError;
  6576. CommonReturn:
  6577. ICM_SetLastError(dwError);
  6578. return (HCRYPTMSG)pcmi;
  6579. ErrorReturn:
  6580. dwError = GetLastError();
  6581. ICM_Free( pbEncryptParameters);
  6582. ICM_Free( ped);
  6583. ICM_Free( pcmi);
  6584. pcmi = NULL;
  6585. goto CommonReturn;
  6586. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  6587. SET_ERROR(InvalidArg,E_INVALIDARG)
  6588. TRACE_ERROR(DupInnerContentObjIDError) // error already set
  6589. TRACE_ERROR(DupStreamInfoError) // error already set
  6590. TRACE_ERROR(EnvelopedDataAllocError) // error already set
  6591. TRACE_ERROR(PcmiAllocError) // error already set
  6592. TRACE_ERROR(GenKeyError) // error already set
  6593. TRACE_ERROR(FillRecipientInfosError) // error already set
  6594. TRACE_ERROR(Asn1ToAlgorithmIdentifierError) // error already set
  6595. TRACE_ERROR(StreamOpenToEncodeEnvelopedDataError) // error already set
  6596. }
  6597. #endif // CMS_PKCS7
  6598. //+-------------------------------------------------------------------------
  6599. // Open a signed and enveloped message for encoding
  6600. //--------------------------------------------------------------------------
  6601. #if 0
  6602. HCRYPTMSG
  6603. WINAPI
  6604. ICM_OpenToEncodeSignedAndEnvelopedData(
  6605. IN DWORD dwEncodingType,
  6606. IN DWORD dwFlags,
  6607. IN void *pvMsgEncodeInfo,
  6608. IN OPTIONAL LPSTR pszInnerContentObjID,
  6609. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  6610. {
  6611. DWORD dwError = ERROR_SUCCESS;
  6612. HCRYPTPROV hCryptProv;
  6613. DWORD dwKeySpec;
  6614. PCRYPT_MSG_INFO pcmi = NULL;
  6615. PCMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO psemei;
  6616. SignedAndEnvelopedData *psed = NULL;
  6617. ContentEncryptionAlgorithmIdentifier *pceai;
  6618. DWORD dwVersion = 1;
  6619. HCRYPTKEY hkeyContentEncryption;
  6620. PCERT_BLOB pcert;
  6621. PCRL_BLOB pcrl;
  6622. DWORD i;
  6623. CRYPT_ALGORITHM_IDENTIFIER aiDigest;
  6624. DWORD dwAlgoCAPISign;
  6625. DWORD dwAlgoCAPIEncrypt;
  6626. psemei = (PCMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO)pvMsgEncodeInfo;
  6627. psed = new SignedAndEnvelopedData;
  6628. assert( 1 == psemei->SignedInfo.cSigners); // just for now
  6629. assert( psemei->cbSize >= sizeof(CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO));
  6630. if (psemei->cbSize < sizeof(CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO))
  6631. goto InvalidArg;
  6632. // version
  6633. psed->version.Write( &dwVersion);
  6634. // recipientInfos
  6635. if (!ICM_GetCAPI(
  6636. CRYPT_ENCRYPT_ALG_OID_GROUP_ID,
  6637. &psemei->ContentEncryptionAlgorithm,
  6638. &dwAlgoCAPIEncrypt))
  6639. goto GetCAPIEncryptError;
  6640. if (!CryptGenKey(
  6641. psemei->EnvelopedInfo.hCryptProv,
  6642. dwAlgoCAPIEncrypt,
  6643. CRYPT_EXPORTABLE, // dwFlags
  6644. &hkeyContentEncryption))
  6645. goto GenKeyError;
  6646. if (!ICM_FillRecipientInfos(
  6647. psemei->EnvelopedInfo.hCryptProv,
  6648. hkeyContentEncryption,
  6649. psemei->EnvelopedInfo.cRecipients,
  6650. psemei->EnvelopedInfo.rgpRecipients,
  6651. psed->recipientInfos,
  6652. dwEncryptFlags))
  6653. goto FillRecipientInfosError;
  6654. // digestAlgorithms
  6655. if (!ICM_SetAsnDigestAlgorithmIdentifiers(
  6656. psed->digestAlgorithms,
  6657. &aiDigest,
  6658. psemei->SignedInfo.cSigners,
  6659. psemei->SignedInfo.rgSigners,
  6660. &hCryptProv,
  6661. &dwKeySpec))
  6662. goto SetAsnDigestAlgorithmIdentifiersError;
  6663. // encryptedContentInfo.contentEncryptionAlgorithm
  6664. // (.encryptedContent and .encryptedContent filled in during update)
  6665. pceai = &psed->encryptedContentInfo.contentEncryptionAlgorithm;
  6666. pceai->algorithm = psemei->EnvelopedInfo.ContentEncryptionAlgorithm.pszObjId;
  6667. if (0 != psemei->EnvelopedInfo.ContentEncryptionAlgorithm.Parameters.cbData) {
  6668. if (0 > pceai->parameters.Decode(
  6669. psemei->EnvelopedInfo.ContentEncryptionAlgorithm.Parameters.pbData))
  6670. goto ContentEncryptionAlgorithmParametersDecodeError;
  6671. }
  6672. // certificates
  6673. for (i=psemei->SignedInfo.cCertEncoded, pcert=psemei->SignedInfo.rgCertEncoded;
  6674. i>0;
  6675. i--, pcert++) {
  6676. if (0 > psed->certificates[ psed->certificates.Add()].Decode( pcert->pbData))
  6677. goto BadParameter;
  6678. }
  6679. // crls
  6680. for (i=psemei->SignedInfo.cCrlEncoded, pcrl=psemei->SignedInfo.rgCrlEncoded;
  6681. i>0;
  6682. i--, pcrl++) {
  6683. if (0 > psed->crls[ psed->crls.Add()].Decode( pcrl->pbData))
  6684. goto BadParameter;
  6685. }
  6686. // signerInfos
  6687. if (!ICM_SetAsnSignerInfos(
  6688. psed->signerInfos,
  6689. dwFlags,
  6690. psemei->SignedInfo.cSigners,
  6691. psemei->SignedInfo.rgSigners))
  6692. goto SetAsnSignerInfosError;
  6693. // pcmi
  6694. pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO));
  6695. if (NULL == pcmi)
  6696. goto OutOfMemory;
  6697. pcmi->hCryptProv = hCryptProv;
  6698. if (0 == hCryptProv)
  6699. pcmi->fDefaultCryptProv = TRUE;
  6700. pcmi->dwKeySpec = dwKeySpec;
  6701. pcmi->dwEncodingType = dwEncodingType;
  6702. pcmi->dwMsgType = CMSG_SIGNED_AND_ENVELOPED;
  6703. pcmi->dwFlags = dwFlags;
  6704. pcmi->pvMsg = psed;
  6705. pcmi->fEncoding = TRUE;
  6706. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  6707. pcmi->pszInnerContentObjID = ICM_DupMem(
  6708. pszInnerContentObjID,
  6709. ICM_StrLen(pszInnerContentObjID) + 1);
  6710. pcmi->pStreamInfo = ICM_DupMem( pStreamInfo, sizeof(*pStreamInfo));
  6711. // pcmi->cDigestAlgorithms = 1; // temp
  6712. if (!(ICM_GetCAPI(
  6713. CRYPT_HASH_ALG_OID_GROUP_ID,
  6714. &aiDigest,
  6715. &dwAlgoCAPISign) ||
  6716. ICM_GetCAPI(
  6717. CRYPT_SIGN_ALG_OID_GROUP_ID,
  6718. &aiDigest,
  6719. &dwAlgoCAPISign)))
  6720. goto GetCAPISignError;
  6721. pcmi->adwDigestAlgorithms[0] = dwAlgoCAPISign;
  6722. pcmi->hkeyContentCrypt = hkeyContentEncryption;
  6723. if (!CryptCreateHash(
  6724. hCryptProv, // s/b various per array
  6725. dwAlgoCAPISign, // s/b various per array
  6726. NULL, // hKey - optional for MAC
  6727. 0, // dwFlags
  6728. &pcmi->ahHash[0]))
  6729. goto CreateHashError;
  6730. CommonReturn:
  6731. ICM_SetLastError(dwError);
  6732. return (HCRYPTMSG)pcmi;
  6733. ErrorReturn:
  6734. dwError = GetLastError();
  6735. if (psed)
  6736. delete psed;
  6737. ICM_Free( pcmi);
  6738. pcmi = NULL;
  6739. goto CommonReturn;
  6740. SET_ERROR(InvalidArg,E_INVALIDARG)
  6741. TRACE_ERROR(FillRecipientInfosError) // error already set
  6742. TRACE_ERROR(SetAsnDigestAlgorithmIdentifiersError) // error already set
  6743. TRACE_ERROR(OutOfMemory) // error already set
  6744. SET_ERROR(GetCAPIEncryptError,CRYPT_E_UNKNOWN_ALGO)
  6745. TRACE_ERROR(GenKeyError) // error already set
  6746. TRACE_ERROR(BadParameter)
  6747. TRACE_ERROR(ContentEncryptionAlgorithmParametersDecodeError)
  6748. TRACE_ERROR(SetAsnSignerInfosError)
  6749. TRACE_ERROR(GetCAPISignError)
  6750. TRACE_ERROR(CreateHashError)
  6751. }
  6752. #endif
  6753. //+-------------------------------------------------------------------------
  6754. // Open a cryptographic message for encoding
  6755. //
  6756. // If CMSG_BARE_CONTENT_FLAG is specified for a streamed message,
  6757. // the streamed output will not have an outer ContentInfo wrapper. This
  6758. // makes it suitable to be streamed into an enclosing message.
  6759. //
  6760. // The pStreamInfo parameter needs to be set to stream the encoded message
  6761. // output.
  6762. //--------------------------------------------------------------------------
  6763. HCRYPTMSG
  6764. WINAPI
  6765. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6766. ICMTest_NewCryptMsgOpenToEncode(
  6767. #else
  6768. CryptMsgOpenToEncode(
  6769. #endif
  6770. IN DWORD dwEncodingType,
  6771. IN DWORD dwFlags,
  6772. IN DWORD dwMsgType,
  6773. IN void const *pvMsgEncodeInfo,
  6774. IN OPTIONAL LPSTR pszInnerContentObjID,
  6775. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  6776. {
  6777. HCRYPTMSG hcrmsg = NULL;
  6778. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  6779. goto InvalidEncoding;
  6780. switch (dwMsgType) {
  6781. case CMSG_DATA:
  6782. hcrmsg = ICM_OpenToEncodeData(
  6783. dwEncodingType,
  6784. dwFlags,
  6785. pvMsgEncodeInfo,
  6786. pStreamInfo);
  6787. break;
  6788. case CMSG_SIGNED:
  6789. hcrmsg = ICM_OpenToEncodeSignedData(
  6790. dwEncodingType,
  6791. dwFlags,
  6792. pvMsgEncodeInfo,
  6793. pszInnerContentObjID,
  6794. pStreamInfo);
  6795. break;
  6796. case CMSG_ENVELOPED:
  6797. hcrmsg = ICM_OpenToEncodeEnvelopedData(
  6798. dwEncodingType,
  6799. dwFlags,
  6800. pvMsgEncodeInfo,
  6801. pszInnerContentObjID,
  6802. pStreamInfo);
  6803. break;
  6804. case CMSG_SIGNED_AND_ENVELOPED:
  6805. #if 0
  6806. hcrmsg = ICM_OpenToEncodeSignedAndEnvelopedData(
  6807. dwEncodingType,
  6808. dwFlags,
  6809. pvMsgEncodeInfo,
  6810. pszInnerContentObjID,
  6811. pStreamInfo);
  6812. break;
  6813. #endif
  6814. goto MessageTypeNotSupportedYet;
  6815. case CMSG_HASHED:
  6816. hcrmsg = ICM_OpenToEncodeDigestedData(
  6817. dwEncodingType,
  6818. dwFlags,
  6819. pvMsgEncodeInfo,
  6820. pszInnerContentObjID,
  6821. pStreamInfo);
  6822. break;
  6823. case CMSG_ENCRYPTED:
  6824. goto MessageTypeNotSupportedYet;
  6825. default:
  6826. goto InvalidMsgType;
  6827. }
  6828. CommonReturn:
  6829. if (hcrmsg) {
  6830. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO) hcrmsg;
  6831. pcmi->lRefCnt = 1;
  6832. if (!Pki_InitializeCriticalSection( &pcmi->CriticalSection)) {
  6833. CryptMsgClose(hcrmsg);
  6834. hcrmsg = NULL;
  6835. }
  6836. }
  6837. return hcrmsg;
  6838. ErrorReturn:
  6839. hcrmsg = NULL;
  6840. goto CommonReturn;
  6841. SET_ERROR(InvalidEncoding,E_INVALIDARG)
  6842. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  6843. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  6844. }
  6845. //+-------------------------------------------------------------------------
  6846. // Open a cryptographic message for decoding
  6847. //
  6848. // hCryptProv specifies the crypto provider to use for hashing and/or
  6849. // decrypting the message. If hCryptProv is NULL, a default crypt provider
  6850. // is used.
  6851. //
  6852. // Currently pRecipientInfo isn't used and should be set to NULL.
  6853. //
  6854. // The pStreamInfo parameter needs to be set to stream the decoded content
  6855. // output.
  6856. //--------------------------------------------------------------------------
  6857. HCRYPTMSG
  6858. WINAPI
  6859. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6860. ICMTest_NewCryptMsgOpenToDecode(
  6861. #else
  6862. CryptMsgOpenToDecode(
  6863. #endif
  6864. IN DWORD dwEncodingType,
  6865. IN DWORD dwFlags,
  6866. IN DWORD dwMsgType,
  6867. IN HCRYPTPROV hCryptProv,
  6868. IN PCERT_INFO pRecipientInfo,
  6869. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  6870. {
  6871. DWORD dwError = ERROR_SUCCESS;
  6872. HCRYPTMSG hcrmsg;
  6873. PCRYPT_MSG_INFO pcmi = NULL;
  6874. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  6875. goto InvalidEncodingTypeError;
  6876. if (NULL != pRecipientInfo)
  6877. goto RecipientInfoNotSupportedYet;
  6878. if (NULL == (pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO))))
  6879. goto AllocCmsgError;
  6880. if (0 == hCryptProv) {
  6881. pcmi->fDefaultCryptProv = TRUE;
  6882. pcmi->hCryptProv = I_CryptGetDefaultCryptProv(0);
  6883. if (0 == pcmi->hCryptProv)
  6884. goto GetDefaultCryptProvError;
  6885. } else
  6886. pcmi->hCryptProv = hCryptProv;
  6887. pcmi->dwEncodingType = dwEncodingType;
  6888. pcmi->dwMsgType = dwMsgType;
  6889. pcmi->dwFlags = dwFlags;
  6890. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  6891. if (pStreamInfo &&
  6892. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  6893. pStreamInfo,
  6894. sizeof(*pStreamInfo)))))
  6895. goto DupStreamInfoError;
  6896. if (!Pki_InitializeCriticalSection( &pcmi->CriticalSection))
  6897. goto InitializeCriticalSectionError;
  6898. pcmi->lRefCnt = 1;
  6899. hcrmsg = (HCRYPTMSG)pcmi;
  6900. CommonReturn:
  6901. ICM_SetLastError(dwError);
  6902. return hcrmsg;
  6903. ErrorReturn:
  6904. dwError = GetLastError();
  6905. ICM_Free( pcmi);
  6906. hcrmsg = NULL;
  6907. goto CommonReturn;
  6908. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  6909. SET_ERROR(RecipientInfoNotSupportedYet,E_INVALIDARG)
  6910. TRACE_ERROR(AllocCmsgError) // error already set
  6911. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  6912. TRACE_ERROR(DupStreamInfoError) // error already set
  6913. TRACE_ERROR(InitializeCriticalSectionError) // error already set
  6914. }
  6915. //+-------------------------------------------------------------------------
  6916. // Duplicate a cryptographic message handle
  6917. //--------------------------------------------------------------------------
  6918. HCRYPTMSG
  6919. WINAPI
  6920. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6921. ICMTest_NewCryptMsgDuplicate(
  6922. #else
  6923. CryptMsgDuplicate(
  6924. #endif
  6925. IN HCRYPTMSG hCryptMsg
  6926. )
  6927. {
  6928. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  6929. if (pcmi)
  6930. InterlockedIncrement(&pcmi->lRefCnt);
  6931. return hCryptMsg;
  6932. }
  6933. //+-------------------------------------------------------------------------
  6934. // Close a cryptographic message handle
  6935. //
  6936. // NB- Must preserve LastError.
  6937. //--------------------------------------------------------------------------
  6938. BOOL
  6939. WINAPI
  6940. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6941. ICMTest_NewCryptMsgClose(
  6942. #else
  6943. CryptMsgClose(
  6944. #endif
  6945. IN HCRYPTMSG hCryptMsg)
  6946. {
  6947. DWORD dwError;
  6948. BOOL fRet;
  6949. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  6950. PCMSG_STREAM_INFO pcsi;
  6951. if (NULL == hCryptMsg)
  6952. return TRUE;
  6953. if (0 != InterlockedDecrement(&pcmi->lRefCnt))
  6954. return TRUE;
  6955. // Preserve LastError
  6956. dwError = GetLastError();
  6957. pcsi = pcmi->pStreamInfo;
  6958. switch (pcmi->dwMsgType) {
  6959. case CMSG_DATA:
  6960. {
  6961. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  6962. if (!poos)
  6963. break;
  6964. if (pcmi->fEncoding) {
  6965. ICM_Free( poos->value);
  6966. ICM_Free( poos);
  6967. } else {
  6968. PkiAsn1FreeInfo( ICM_GetDecoder(), OctetStringType_PDU, poos);
  6969. }
  6970. break;
  6971. }
  6972. case CMSG_SIGNED:
  6973. {
  6974. SignedData *psd = (SignedData *)pcmi->pvMsg;
  6975. if (!(psd || pcmi->psdi))
  6976. break;
  6977. if (pcmi->fEncoding) {
  6978. if (psd->signerInfos.value) {
  6979. SignerInfo *psi;
  6980. DWORD i;
  6981. for (i=psd->signerInfos.count, psi=psd->signerInfos.value;
  6982. i>0;
  6983. i--, psi++)
  6984. ICM_FreeAsnSignerInfo(psi);
  6985. ICM_Free( psd->signerInfos.value);
  6986. }
  6987. if (ICM_IsAddInnerContentOctetWrapper(pcmi) &&
  6988. psd->contentInfo.content.length &&
  6989. psd->contentInfo.content.value)
  6990. PkiAsn1FreeEncoded( ICM_GetEncoder(),
  6991. psd->contentInfo.content.value);
  6992. if (psd->digestAlgorithms.count && psd->digestAlgorithms.value)
  6993. ICM_Free( psd->digestAlgorithms.value);
  6994. ICM_Free( psd);
  6995. ICM_Free( pcmi->pszInnerContentObjID);
  6996. } else {
  6997. // decoding
  6998. delete pcmi->psdi->pAlgidList;
  6999. delete pcmi->psdi->pCertificateList;
  7000. delete pcmi->psdi->pCrlList;
  7001. delete pcmi->psdi->pSignerList;
  7002. ICM_Free( pcmi->psdi->pci);
  7003. ICM_Free( pcmi->psdi);
  7004. }
  7005. if (pcmi->pHashList)
  7006. delete pcmi->pHashList;
  7007. #ifdef CMS_PKCS7
  7008. if (pcmi->rgSignerEncodeDataInfo) {
  7009. assert(pcmi->cSignerEncodeDataInfo);
  7010. if (pcmi->dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) {
  7011. DWORD i;
  7012. for (i = 0; i < pcmi->cSignerEncodeDataInfo; i++) {
  7013. if (pcmi->rgSignerEncodeDataInfo[i].hCryptProv)
  7014. CryptReleaseContext(
  7015. pcmi->rgSignerEncodeDataInfo[i].hCryptProv, 0);
  7016. }
  7017. }
  7018. ICM_Free(pcmi->rgSignerEncodeDataInfo);
  7019. }
  7020. #endif // CMS_PKCS7
  7021. break;
  7022. }
  7023. case CMSG_ENVELOPED:
  7024. {
  7025. #ifdef CMS_PKCS7
  7026. CmsEnvelopedData *ped = (CmsEnvelopedData *)pcmi->pvMsg;
  7027. #else
  7028. EnvelopedData *ped = (EnvelopedData *)pcmi->pvMsg;
  7029. RecipientInfo *pri;
  7030. #endif // CMS_PKCS7
  7031. DWORD i;
  7032. if (pcmi->hkeyContentCrypt)
  7033. CryptDestroyKey( pcmi->hkeyContentCrypt);
  7034. ICM_Free( pcmi->Plaintext.pbData);
  7035. #ifndef CMS_PKCS7
  7036. ICM_Free( pcmi->pbEncryptParameters);
  7037. #endif // CMS_PKCS7
  7038. if (pcmi->fEncoding) {
  7039. #ifdef CMS_PKCS7
  7040. ICM_FreeOssCmsRecipientInfos(&ped->recipientInfos);
  7041. if (ped->unprotectedAttrs.value) {
  7042. Attribute *poatr;
  7043. for (i=ped->unprotectedAttrs.count,
  7044. poatr=ped->unprotectedAttrs.value;
  7045. i>0;
  7046. i--, poatr++) {
  7047. ICM_Free(poatr->attributeValue.value);
  7048. }
  7049. ICM_Free(ped->unprotectedAttrs.value);
  7050. }
  7051. #else
  7052. for (i=ped->recipientInfos.count, pri=ped->recipientInfos.value;
  7053. i>0;
  7054. i--, pri++)
  7055. ICM_Free( pri->encryptedKey.value);
  7056. ICM_Free( ped->recipientInfos.value);
  7057. #endif // CMS_PKCS7
  7058. ICM_Free( ped->encryptedContentInfo.encryptedContent.value);
  7059. ICM_Free( ped);
  7060. ICM_Free( pcmi->pszInnerContentObjID);
  7061. } else {
  7062. // decoding
  7063. #ifdef CMS_PKCS7
  7064. if (NULL != pcmi->pCertificateList)
  7065. delete pcmi->pCertificateList;
  7066. if (NULL != pcmi->pCrlList)
  7067. delete pcmi->pCrlList;
  7068. #endif // CMS_PKCS7
  7069. if (pcsi) {
  7070. ICM_Free( ped);
  7071. } else {
  7072. #ifdef CMS_PKCS7
  7073. PkiAsn1FreeInfo( ICM_GetDecoder(), CmsEnvelopedData_PDU, ped);
  7074. #else
  7075. PkiAsn1FreeInfo( ICM_GetDecoder(), EnvelopedData_PDU, ped);
  7076. #endif // CMS_PKCS7
  7077. }
  7078. }
  7079. break;
  7080. }
  7081. case CMSG_HASHED:
  7082. {
  7083. DigestedData *pdd = (DigestedData *)pcmi->pvMsg;
  7084. if (pcmi->fEncoding) {
  7085. if (ICM_IsAddInnerContentOctetWrapper(pcmi) &&
  7086. pdd->contentInfo.content.length &&
  7087. pdd->contentInfo.content.value)
  7088. PkiAsn1FreeEncoded( ICM_GetEncoder(),
  7089. pdd->contentInfo.content.value);
  7090. ICM_Free ((DigestedData *)pcmi->pvMsg);
  7091. ICM_Free( pcmi->pszInnerContentObjID);
  7092. } else {
  7093. // decoding
  7094. PkiAsn1FreeInfo( ICM_GetDecoder(), DigestedData_PDU,
  7095. (DigestedData *)pcmi->pvMsg);
  7096. }
  7097. if (pcmi->pHashList)
  7098. delete pcmi->pHashList;
  7099. break;
  7100. }
  7101. case CMSG_SIGNED_AND_ENVELOPED:
  7102. case CMSG_ENCRYPTED:
  7103. goto MessageTypeNotSupportedYet;
  7104. default:
  7105. goto InvalidMsgType;
  7106. }
  7107. fRet = TRUE;
  7108. CommonReturn:
  7109. #ifdef CMS_PKCS7
  7110. if (pcmi->pFreeList)
  7111. delete pcmi->pFreeList;
  7112. #endif // CMS_PKCS7
  7113. if (pcmi->plDecodeInfo)
  7114. delete pcmi->plDecodeInfo;
  7115. ICM_Free( pcmi->pStreamInfo);
  7116. ICM_Free( pcmi->bufOutput.pbData);
  7117. ICM_Free( pcmi->bufCrypt.pbData);
  7118. ICM_Free( pcmi->bufPendingCrypt.pbData);
  7119. ICM_Free( pcmi->bufDecode.pbData);
  7120. ICM_Free( pcmi->bufEncode.pbData);
  7121. if (pcmi->pooid)
  7122. PkiAsn1FreeDecoded(ICM_GetDecoder(), pcmi->pooid,
  7123. ObjectIdentifierType_PDU);
  7124. if ((pcmi->dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) &&
  7125. !pcmi->fDefaultCryptProv && pcmi->hCryptProv)
  7126. CryptReleaseContext(pcmi->hCryptProv, 0);
  7127. if (pcmi->hCryptProvContentCrypt)
  7128. CryptReleaseContext(pcmi->hCryptProvContentCrypt, 0);
  7129. DeleteCriticalSection( &pcmi->CriticalSection);
  7130. ICM_Free( hCryptMsg);
  7131. SetLastError(dwError); // Preserve LastError
  7132. return fRet;
  7133. ErrorReturn:
  7134. fRet = TRUE;
  7135. goto CommonReturn;
  7136. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  7137. TRACE_ERROR(InvalidMsgType)
  7138. }
  7139. //+-------------------------------------------------------------------------
  7140. // Since the encoding might be indefinite-length encoded,
  7141. // decode and re-encode as DER.
  7142. //
  7143. // Returns: FALSE iff fails
  7144. //
  7145. // NB: The caller of this routine needs to call
  7146. // PkiAsn1FreeEncoded( ICM_GetEncoder(), pbOut);
  7147. //--------------------------------------------------------------------------
  7148. BOOL
  7149. WINAPI
  7150. ICM_ReEncodeAsOctetDER(
  7151. IN PBYTE pbIn,
  7152. IN DWORD cbIn,
  7153. OUT PBYTE *ppbOut,
  7154. OUT DWORD *pcbOut)
  7155. {
  7156. DWORD dwError = ERROR_SUCCESS;
  7157. BOOL fRet;
  7158. ASN1error_e Asn1Err;
  7159. ASN1decoding_t pDec = ICM_GetDecoder();
  7160. PVOID pvMsg = NULL;
  7161. DWORD dwExceptionCode;
  7162. // Handle MappedFile Exceptions
  7163. __try {
  7164. if (0 != (Asn1Err = PkiAsn1Decode(pDec, (void **)&pvMsg,
  7165. OctetStringType_PDU, pbIn, cbIn)))
  7166. goto DecodeInnerContentError;
  7167. if (0 != (Asn1Err = PkiAsn1Encode(ICM_GetEncoder(), pvMsg,
  7168. OctetStringType_PDU, ppbOut, pcbOut)))
  7169. goto EncodeInnerContentError;
  7170. fRet = TRUE;
  7171. } __except(EXCEPTION_EXECUTE_HANDLER) {
  7172. dwExceptionCode = GetExceptionCode();
  7173. goto ExceptionError;
  7174. }
  7175. CommonReturn:
  7176. PkiAsn1FreeInfo(pDec, OctetStringType_PDU, pvMsg);
  7177. ICM_SetLastError(dwError);
  7178. return fRet;
  7179. ErrorReturn:
  7180. *ppbOut = NULL;
  7181. *pcbOut = 0;
  7182. dwError = GetLastError();
  7183. fRet = FALSE;
  7184. goto CommonReturn;
  7185. SET_ERROR_VAR(DecodeInnerContentError, PkiAsn1ErrToHr(Asn1Err))
  7186. SET_ERROR_VAR(EncodeInnerContentError, PkiAsn1ErrToHr(Asn1Err))
  7187. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  7188. }
  7189. //+-------------------------------------------------------------------------
  7190. // Update the digest
  7191. //
  7192. // Returns:
  7193. // FALSE iff error
  7194. //--------------------------------------------------------------------------
  7195. BOOL
  7196. WINAPI
  7197. ICM_UpdateDigest(
  7198. IN HCRYPTHASH hHash,
  7199. IN const BYTE *pbData,
  7200. IN DWORD cbData)
  7201. {
  7202. BOOL fRet;
  7203. if (0 != cbData)
  7204. fRet = CryptHashData(
  7205. hHash,
  7206. pbData,
  7207. cbData,
  7208. 0); // dwFlags
  7209. else
  7210. fRet = TRUE;
  7211. if (!fRet)
  7212. goto HashDataError;
  7213. CommonReturn:
  7214. return fRet;
  7215. ErrorReturn:
  7216. goto CommonReturn;
  7217. TRACE_ERROR(HashDataError) // error already set
  7218. }
  7219. //+-------------------------------------------------------------------------
  7220. // Update the digests in a list
  7221. //
  7222. // Returns:
  7223. // FALSE iff error
  7224. //--------------------------------------------------------------------------
  7225. BOOL
  7226. WINAPI
  7227. ICM_UpdateListDigest(
  7228. IN CHashList *pHashList,
  7229. IN const BYTE *pbData,
  7230. IN DWORD cbData)
  7231. {
  7232. BOOL fRet;
  7233. CHashNode *pnHash;
  7234. if (pHashList) {
  7235. for (pnHash=pHashList->Head(); pnHash; pnHash=pnHash->Next()) {
  7236. if (!ICM_UpdateDigest( pnHash->Data()->hHash, pbData, cbData))
  7237. goto UpdateDigestError;
  7238. }
  7239. }
  7240. fRet = TRUE;
  7241. CommonReturn:
  7242. return fRet;
  7243. ErrorReturn:
  7244. fRet = FALSE;
  7245. goto CommonReturn;
  7246. TRACE_ERROR(UpdateDigestError) // error already set
  7247. }
  7248. //+-------------------------------------------------------------------------
  7249. // Alloc and sign a hash.
  7250. //
  7251. // Returns: FALSE iff failed
  7252. //--------------------------------------------------------------------------
  7253. BOOL
  7254. WINAPI
  7255. ICM_AllocAndSignHash(
  7256. IN HCRYPTHASH hHash,
  7257. IN DWORD dwKeySpec,
  7258. IN DWORD dwAlgIdPubKey,
  7259. IN DWORD dwPubKeyFlags,
  7260. IN BOOL fMaxLength,
  7261. OUT PBYTE *ppbSignature,
  7262. OUT DWORD *pcbSignature)
  7263. {
  7264. DWORD dwError = ERROR_SUCCESS;
  7265. BOOL fRet;
  7266. PBYTE pbSignature = NULL;
  7267. DWORD cbSignature = 0;
  7268. if (dwKeySpec == 0)
  7269. dwKeySpec = AT_SIGNATURE;
  7270. if (CALG_NO_SIGN == dwAlgIdPubKey) {
  7271. if (!CryptGetHashParam(
  7272. hHash,
  7273. HP_HASHVAL,
  7274. NULL,
  7275. &cbSignature,
  7276. 0)) // dwFlags
  7277. goto GetHashParamSizeError;
  7278. if (NULL == (pbSignature = (PBYTE)ICM_Alloc( cbSignature)))
  7279. goto AllocHashParamError;
  7280. if (!CryptGetHashParam(
  7281. hHash,
  7282. HP_HASHVAL,
  7283. pbSignature,
  7284. &cbSignature,
  7285. 0)) // dwFlags
  7286. goto GetHashParamError;
  7287. } else if (CALG_DSS_SIGN == dwAlgIdPubKey &&
  7288. 0 == (dwPubKeyFlags & CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG)) {
  7289. DWORD cbData;
  7290. BYTE rgbDssSignature[CERT_DSS_SIGNATURE_LEN];
  7291. cbData = sizeof(rgbDssSignature);
  7292. if (!CryptSignHash(
  7293. hHash,
  7294. dwKeySpec,
  7295. NULL, // sDescription
  7296. 0, // dwFlags
  7297. rgbDssSignature,
  7298. &cbData
  7299. )) goto SignHashError;
  7300. assert(cbData == sizeof(rgbDssSignature));
  7301. if (NULL == (pbSignature = (PBYTE)ICM_Alloc(
  7302. CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN)))
  7303. goto AllocSignatureError;
  7304. // Convert from the CSP signature format to an ASN.1 sequence of
  7305. // two integers
  7306. cbSignature = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN;
  7307. if (!CryptEncodeObject(
  7308. X509_ASN_ENCODING,
  7309. X509_DSS_SIGNATURE,
  7310. rgbDssSignature,
  7311. pbSignature,
  7312. &cbSignature
  7313. )) goto EncodeDssSignatureError;
  7314. if (fMaxLength) {
  7315. int cbRemain;
  7316. assert(CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN >= cbSignature);
  7317. cbRemain = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN - cbSignature;
  7318. if (cbRemain > 0) {
  7319. memset(pbSignature + cbSignature, 0, cbRemain);
  7320. cbSignature = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN;
  7321. }
  7322. }
  7323. } else {
  7324. if (!CryptSignHash(
  7325. hHash,
  7326. dwKeySpec,
  7327. NULL, // description ?
  7328. 0, // dwFlags
  7329. NULL, // pbSignature
  7330. &cbSignature))
  7331. goto SignHashSizeError;
  7332. if (NULL == (pbSignature = (PBYTE)ICM_Alloc( cbSignature)))
  7333. goto AllocSignatureError;
  7334. if (!CryptSignHash(
  7335. hHash,
  7336. dwKeySpec,
  7337. NULL, // description ?
  7338. 0, // dwFlags
  7339. pbSignature,
  7340. &cbSignature))
  7341. goto SignHashError;
  7342. ICM_ReverseInPlace( pbSignature, cbSignature);
  7343. }
  7344. fRet = TRUE;
  7345. CommonReturn:
  7346. *ppbSignature = pbSignature;
  7347. *pcbSignature = cbSignature;
  7348. ICM_SetLastError(dwError);
  7349. return fRet;
  7350. ErrorReturn:
  7351. dwError = GetLastError();
  7352. ICM_Free( pbSignature);
  7353. pbSignature = NULL;
  7354. cbSignature = 0;
  7355. fRet = FALSE;
  7356. goto CommonReturn;
  7357. TRACE_ERROR(GetHashParamSizeError) // error already set
  7358. TRACE_ERROR(AllocHashParamError) // error already set
  7359. TRACE_ERROR(GetHashParamError) // error already set
  7360. TRACE_ERROR(SignHashSizeError) // error already set
  7361. TRACE_ERROR(AllocSignatureError) // error already set
  7362. TRACE_ERROR(SignHashError) // error already set
  7363. TRACE_ERROR(EncodeDssSignatureError) // error already set
  7364. }
  7365. //+-------------------------------------------------------------------------
  7366. // Get the hash of a blob.
  7367. //
  7368. // Returns: FALSE iff failed
  7369. //--------------------------------------------------------------------------
  7370. BOOL
  7371. WINAPI
  7372. ICM_GetBlobHash(
  7373. IN HCRYPTPROV hCryptProv,
  7374. IN DWORD dwDigestAlgorithm,
  7375. IN PBYTE pb,
  7376. IN DWORD cb,
  7377. OUT HCRYPTHASH *phHash)
  7378. {
  7379. BOOL fRet;
  7380. HCRYPTHASH hHash;
  7381. if (!CryptCreateHash(
  7382. hCryptProv,
  7383. dwDigestAlgorithm,
  7384. NULL, // hKey - optional for MAC
  7385. 0, // dwFlags
  7386. &hHash))
  7387. goto CreateHashError;
  7388. if (!ICM_UpdateDigest( hHash, pb, cb))
  7389. goto UpdateDigestError;
  7390. fRet = TRUE;
  7391. CommonReturn:
  7392. *phHash = hHash;
  7393. return fRet;
  7394. ErrorReturn:
  7395. hHash = NULL;
  7396. fRet = FALSE;
  7397. goto CommonReturn;
  7398. TRACE_ERROR(CreateHashError) // error already set
  7399. TRACE_ERROR(UpdateDigestError) // error already set
  7400. }
  7401. //+-------------------------------------------------------------------------
  7402. // Get the hash of an OSS Attributes. This is used to hash the authenticated
  7403. // attributes for a Signed or SignedAndEnveloped message.
  7404. //
  7405. // Returns: FALSE iff failed
  7406. //--------------------------------------------------------------------------
  7407. BOOL
  7408. WINAPI
  7409. ICM_GetAttrsHash(
  7410. IN DWORD dwDigestAlgorithm,
  7411. IN HCRYPTPROV hCryptProv,
  7412. IN Attributes *possAttrs,
  7413. OUT HCRYPTHASH *phHash)
  7414. {
  7415. DWORD dwError = ERROR_SUCCESS;
  7416. BOOL fRet;
  7417. ASN1error_e Asn1Err;
  7418. ASN1encoding_t pEnc = ICM_GetEncoder();
  7419. PBYTE pbEncoded = NULL;
  7420. DWORD cbEncoded;
  7421. HCRYPTHASH hHash;
  7422. if (!CryptCreateHash(
  7423. hCryptProv,
  7424. dwDigestAlgorithm,
  7425. NULL, // hKey - optional for MAC
  7426. 0, // dwFlags
  7427. &hHash))
  7428. goto CreateHashError;
  7429. if (0 != (Asn1Err = PkiAsn1Encode(
  7430. pEnc,
  7431. possAttrs,
  7432. Attributes_PDU,
  7433. &pbEncoded,
  7434. &cbEncoded)))
  7435. goto EncodeAttributesError;
  7436. if (!ICM_UpdateDigest(
  7437. hHash,
  7438. pbEncoded,
  7439. cbEncoded))
  7440. goto UpdateDigestAttributesError;
  7441. fRet = TRUE;
  7442. CommonReturn:
  7443. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7444. *phHash = hHash;
  7445. ICM_SetLastError(dwError);
  7446. return fRet;
  7447. ErrorReturn:
  7448. dwError = GetLastError();
  7449. hHash = NULL;
  7450. fRet = FALSE;
  7451. goto CommonReturn;
  7452. SET_ERROR_VAR(EncodeAttributesError, PkiAsn1ErrToHr(Asn1Err))
  7453. TRACE_ERROR(CreateHashError) // error already set
  7454. TRACE_ERROR(UpdateDigestAttributesError) // error already set
  7455. }
  7456. //+-------------------------------------------------------------------------
  7457. // Compare 2 OSS object id's.
  7458. //
  7459. // Returns: FALSE iff !equal
  7460. //--------------------------------------------------------------------------
  7461. BOOL
  7462. WINAPI
  7463. ICM_EqualObjectIDs(
  7464. IN ObjectID *poid1,
  7465. IN ObjectID *poid2)
  7466. {
  7467. BOOL fRet;
  7468. DWORD i;
  7469. PDWORD pdw1;
  7470. PDWORD pdw2;
  7471. if (poid1->count != poid2->count)
  7472. goto Unequal;
  7473. for (i=poid1->count, pdw1=poid1->value, pdw2=poid2->value;
  7474. (i>0) && (*pdw1==*pdw2);
  7475. i--, pdw1++, pdw2++)
  7476. ;
  7477. if (i>0)
  7478. goto Unequal;
  7479. fRet = TRUE; // equal
  7480. CommonReturn:
  7481. return fRet;
  7482. Unequal:
  7483. fRet = FALSE; // !equal
  7484. goto CommonReturn;
  7485. }
  7486. //+-------------------------------------------------------------------------
  7487. // Get the value of an Attribute of a given type.
  7488. //
  7489. // Returns: FALSE iff fails
  7490. //
  7491. // NB- Does not set error
  7492. //--------------------------------------------------------------------------
  7493. BOOL
  7494. WINAPI
  7495. ICM_GetAttrValue(
  7496. IN Attributes *poatrs,
  7497. IN ObjectID *poid,
  7498. OUT Any *panyValue)
  7499. {
  7500. BOOL fRet;
  7501. DWORD i;
  7502. Attribute *poatr;
  7503. for (i=poatrs->count, poatr=poatrs->value; i>0; i--, poatr++) {
  7504. if (ICM_EqualObjectIDs( &poatr->attributeType, poid))
  7505. break;
  7506. }
  7507. if (0 == i)
  7508. goto AttributeNotFoundError;
  7509. *panyValue = *poatr->attributeValue.value;
  7510. fRet = TRUE;
  7511. CommonReturn:
  7512. return fRet;
  7513. ErrorReturn:
  7514. panyValue->length = 0;
  7515. fRet = FALSE;
  7516. goto CommonReturn;
  7517. TRACE_ERROR(AttributeNotFoundError)
  7518. }
  7519. //+-------------------------------------------------------------------------
  7520. // Fill in the content-type and message-digest authenticated attributes,
  7521. // which are required in a SignedData or SignedAndEnvelopedData message.
  7522. //
  7523. // Returns: FALSE iff failed
  7524. //--------------------------------------------------------------------------
  7525. BOOL
  7526. WINAPI
  7527. ICM_FillReqAuthAttrs(
  7528. IN OPTIONAL LPSTR pszInnerContentObjID,
  7529. IN CHashNode *pnHash,
  7530. IN OUT Attribute *possAttr)
  7531. {
  7532. BOOL fRet;
  7533. CRYPT_ATTRIBUTE atr;
  7534. CRYPT_ATTR_BLOB atrblob;
  7535. ASN1error_e Asn1Err;
  7536. ASN1encoding_t pEnc = ICM_GetEncoder();
  7537. PBYTE pbEncoded;
  7538. DWORD cbEncoded;
  7539. ObjectID ossObjID;
  7540. OctetStringType ost;
  7541. // NB - When psi->authenticatedAttributes was created,
  7542. // the first 2 slots were reserved for the
  7543. // content-type and message-digest attributes.
  7544. // content-type attribute
  7545. ossObjID.count = sizeof(ossObjID.value)/sizeof(ossObjID.value[0]);
  7546. if (!PkiAsn1ToObjectIdentifier(
  7547. pszInnerContentObjID ? pszInnerContentObjID : pszObjIdDataType,
  7548. &ossObjID.count,
  7549. ossObjID.value))
  7550. goto ConvToObjectIdentifierError;
  7551. if (0 != (Asn1Err = PkiAsn1Encode(
  7552. pEnc,
  7553. &ossObjID,
  7554. ObjectIdentifierType_PDU,
  7555. &pbEncoded,
  7556. &cbEncoded)))
  7557. goto EncodeObjectIdentifierError;
  7558. atr.pszObjId = pszObjIdContentType;
  7559. atr.cValue = 1;
  7560. atr.rgValue = &atrblob;
  7561. atrblob.cbData = cbEncoded;
  7562. atrblob.pbData = pbEncoded;
  7563. fRet = ICM_Asn1ToAttribute( &atr, possAttr);
  7564. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7565. if (!fRet)
  7566. goto ContentTypeAsn1ToAttributeError;
  7567. // message-digest attribute
  7568. if (!ICM_GetListHashValue( pnHash, (DWORD*)&ost.length, &ost.value))
  7569. goto GetHashValueError;
  7570. if (0 != (Asn1Err = PkiAsn1Encode(
  7571. pEnc,
  7572. &ost,
  7573. OctetStringType_PDU,
  7574. &pbEncoded,
  7575. &cbEncoded)))
  7576. goto EncodeOctetStringError;
  7577. atr.pszObjId = pszObjIdMessageDigest;
  7578. atr.cValue = 1;
  7579. atr.rgValue = &atrblob;
  7580. atrblob.cbData = cbEncoded;
  7581. atrblob.pbData = pbEncoded;
  7582. fRet = ICM_Asn1ToAttribute( &atr, possAttr + 1);
  7583. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7584. if (!fRet)
  7585. goto MsgDigestAsn1ToAttributeError;
  7586. fRet = TRUE;
  7587. CommonReturn:
  7588. return fRet;
  7589. ErrorReturn:
  7590. fRet = FALSE;
  7591. goto CommonReturn;
  7592. SET_ERROR_VAR(EncodeObjectIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  7593. SET_ERROR_VAR(EncodeOctetStringError, PkiAsn1ErrToHr(Asn1Err))
  7594. SET_ERROR(ConvToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  7595. TRACE_ERROR(ContentTypeAsn1ToAttributeError) // error already set
  7596. TRACE_ERROR(GetHashValueError) // error already set
  7597. TRACE_ERROR(MsgDigestAsn1ToAttributeError) // error already set
  7598. }
  7599. //+-------------------------------------------------------------------------
  7600. // Fill the inner ContentInfo.
  7601. //--------------------------------------------------------------------------
  7602. BOOL
  7603. WINAPI
  7604. ICM_FillInnerContentInfo(
  7605. OUT ContentInfo *pci,
  7606. IN OPTIONAL LPSTR pszInnerID,
  7607. IN DWORD cbData,
  7608. IN const BYTE *pbData,
  7609. IN BOOL fAddInnerContentOctetWrapper // CMS_PKCS7
  7610. )
  7611. {
  7612. BOOL fRet;
  7613. ASN1error_e Asn1Err;
  7614. PBYTE pbEncoded;
  7615. DWORD cbEncoded;
  7616. OctetStringType ost;
  7617. pci->contentType.count = sizeof(pci->contentType.value)/sizeof(pci->contentType.value[0]);
  7618. if (!PkiAsn1ToObjectIdentifier(
  7619. pszInnerID ? pszInnerID : pszObjIdDataType,
  7620. &pci->contentType.count,
  7621. pci->contentType.value))
  7622. goto PkiAsn1ToObjectIdentifierError;
  7623. if (0 != cbData) {
  7624. pci->bit_mask |= content_present;
  7625. if (!fAddInnerContentOctetWrapper) {
  7626. pci->content.length = cbData;
  7627. pci->content.value = (PBYTE)pbData;
  7628. } else {
  7629. ost.length = cbData;
  7630. ost.value = (PBYTE)pbData;
  7631. if (0 != (Asn1Err = PkiAsn1Encode(
  7632. ICM_GetEncoder(),
  7633. &ost,
  7634. OctetStringType_PDU,
  7635. &pbEncoded,
  7636. &cbEncoded)))
  7637. goto EncodeOctetStringError;
  7638. pci->content.length = cbEncoded;
  7639. pci->content.value = pbEncoded;
  7640. }
  7641. }
  7642. fRet = TRUE;
  7643. CommonReturn:
  7644. return fRet;
  7645. ErrorReturn:
  7646. fRet = FALSE;
  7647. goto CommonReturn;
  7648. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  7649. SET_ERROR_VAR(EncodeOctetStringError, PkiAsn1ErrToHr(Asn1Err))
  7650. }
  7651. #ifdef CMS_PKCS7
  7652. //+-------------------------------------------------------------------------
  7653. // Fill in the encrypted digest in a signer info.
  7654. //--------------------------------------------------------------------------
  7655. BOOL
  7656. WINAPI
  7657. ICM_FillSignerEncryptedDigest(
  7658. IN SignerInfo *psi,
  7659. IN OPTIONAL LPSTR pszInnerContentObjID,
  7660. IN PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo,
  7661. IN BOOL fMaxLength)
  7662. {
  7663. DWORD dwError = ERROR_SUCCESS;
  7664. BOOL fRet;
  7665. HCRYPTHASH hHash;
  7666. HCRYPTHASH hHashAttr = NULL;
  7667. HCRYPTHASH hHashDup = NULL;
  7668. PBYTE pbSignature = NULL;
  7669. DWORD cbSignature;
  7670. CHashNode *pnHash = pSignerEncodeDataInfo->pHashNode;
  7671. PICM_HASH_INFO pHashInfo = pnHash->Data();
  7672. PCCRYPT_OID_INFO pOIDInfo;
  7673. DWORD dwAlgIdPubKey;
  7674. DWORD dwPubKeyFlags;
  7675. if (psi->bit_mask & authenticatedAttributes_present) {
  7676. if (!ICM_FillReqAuthAttrs(
  7677. pszInnerContentObjID,
  7678. pSignerEncodeDataInfo->pHashNode,
  7679. psi->authenticatedAttributes.value))
  7680. goto FillReqAuthAttrsError;
  7681. if (!ICM_GetAttrsHash(
  7682. pHashInfo->dwAlgoCAPI,
  7683. pSignerEncodeDataInfo->hCryptProv,
  7684. &psi->authenticatedAttributes,
  7685. &hHashAttr))
  7686. goto GetAuthAttrsHashError;
  7687. hHash = hHashAttr;
  7688. } else {
  7689. if (!ICM_DupListHash( pnHash, pSignerEncodeDataInfo->hCryptProv,
  7690. &hHashDup))
  7691. goto DupListHashError;
  7692. hHash = hHashDup;
  7693. }
  7694. dwAlgIdPubKey = 0;
  7695. dwPubKeyFlags = 0;
  7696. if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  7697. &psi->digestEncryptionAlgorithm)) {
  7698. dwAlgIdPubKey = pOIDInfo->Algid;
  7699. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  7700. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7701. dwPubKeyFlags = pdwExtra[0];
  7702. }
  7703. } else if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_SIGN_ALG_OID_GROUP_ID,
  7704. &psi->digestEncryptionAlgorithm)) {
  7705. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  7706. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7707. if (1 <= cExtra) {
  7708. dwAlgIdPubKey = pdwExtra[0];
  7709. if (2 <= cExtra)
  7710. dwPubKeyFlags = pdwExtra[1];
  7711. }
  7712. }
  7713. if (!ICM_AllocAndSignHash( hHash, pSignerEncodeDataInfo->dwKeySpec,
  7714. dwAlgIdPubKey, dwPubKeyFlags, fMaxLength,
  7715. &pbSignature, &cbSignature))
  7716. goto AllocAndSignHashError;
  7717. psi->encryptedDigest.length = cbSignature;
  7718. psi->encryptedDigest.value = pbSignature;
  7719. pbSignature = NULL;
  7720. fRet = TRUE;
  7721. CommonReturn:
  7722. if (hHashAttr)
  7723. CryptDestroyHash( hHashAttr);
  7724. if (hHashDup)
  7725. CryptDestroyHash( hHashDup);
  7726. ICM_Free(pbSignature);
  7727. ICM_SetLastError(dwError);
  7728. return fRet;
  7729. ErrorReturn:
  7730. dwError = GetLastError();
  7731. fRet = FALSE;
  7732. goto CommonReturn;
  7733. TRACE_ERROR(FillReqAuthAttrsError) // error already set
  7734. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  7735. TRACE_ERROR(DupListHashError) // error already set
  7736. TRACE_ERROR(AllocAndSignHashError) // error already set
  7737. }
  7738. BOOL
  7739. WINAPI
  7740. ICM_FillSignerEncodeEncryptedDigests(
  7741. IN PCRYPT_MSG_INFO pcmi,
  7742. IN BOOL fMaxLength)
  7743. {
  7744. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  7745. DWORD cSignerEncodeDataInfo = pcmi->cSignerEncodeDataInfo;
  7746. PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo =
  7747. pcmi->rgSignerEncodeDataInfo;
  7748. SignedData *psd = (SignedData *)pcmi->pvMsg;
  7749. SignerInfo *psi = psd->signerInfos.value;
  7750. assert(psd->signerInfos.count == cSignerEncodeDataInfo);
  7751. for ( ; 0 < cSignerEncodeDataInfo;
  7752. cSignerEncodeDataInfo--,
  7753. pSignerEncodeDataInfo++,
  7754. psi++) {
  7755. if (!ICM_FillSignerEncryptedDigest(
  7756. psi,
  7757. pszInnerContentObjID,
  7758. pSignerEncodeDataInfo,
  7759. fMaxLength))
  7760. return FALSE;
  7761. }
  7762. return TRUE;
  7763. }
  7764. #else
  7765. //+-------------------------------------------------------------------------
  7766. // Fill in the encrypted digest in a signer info.
  7767. //--------------------------------------------------------------------------
  7768. BOOL
  7769. WINAPI
  7770. ICM_FillSignerEncryptedDigest(
  7771. IN SignerInfo *psi,
  7772. IN OPTIONAL LPSTR pszInnerContentObjID,
  7773. IN CHashNode *pnHash,
  7774. IN DWORD dwKeySpec,
  7775. IN BOOL fMaxLength)
  7776. {
  7777. DWORD dwError = ERROR_SUCCESS;
  7778. BOOL fRet;
  7779. HCRYPTHASH hHash;
  7780. HCRYPTHASH hHashAttr = NULL;
  7781. HCRYPTHASH hHashDup = NULL;
  7782. PBYTE pbSignature = NULL;
  7783. DWORD cbSignature;
  7784. PICM_HASH_INFO pHashInfo = pnHash->Data();
  7785. PCCRYPT_OID_INFO pOIDInfo;
  7786. DWORD dwAlgIdPubKey;
  7787. DWORD dwPubKeyFlags;
  7788. if (psi->bit_mask & authenticatedAttributes_present) {
  7789. if (!ICM_FillReqAuthAttrs(
  7790. pszInnerContentObjID,
  7791. pnHash,
  7792. psi->authenticatedAttributes.value))
  7793. goto FillReqAuthAttrsError;
  7794. if (!ICM_GetAttrsHash(
  7795. pHashInfo->dwAlgoCAPI,
  7796. pHashInfo->hCryptProv,
  7797. &psi->authenticatedAttributes,
  7798. &hHashAttr))
  7799. goto GetAuthAttrsHashError;
  7800. hHash = hHashAttr;
  7801. } else {
  7802. if (!ICM_DupListHash( pnHash, pHashInfo->hCryptProv, &hHashDup))
  7803. goto DupListHashError;
  7804. hHash = hHashDup;
  7805. }
  7806. dwAlgIdPubKey = 0;
  7807. dwPubKeyFlags = 0;
  7808. if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  7809. &psi->digestEncryptionAlgorithm)) {
  7810. dwAlgIdPubKey = pOIDInfo->Algid;
  7811. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  7812. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7813. dwPubKeyFlags = pdwExtra[0];
  7814. }
  7815. }
  7816. if (!ICM_AllocAndSignHash( hHash, dwKeySpec,
  7817. dwAlgIdPubKey, dwPubKeyFlags, fMaxLength,
  7818. &pbSignature, &cbSignature))
  7819. goto AllocAndSignHashError;
  7820. psi->encryptedDigest.length = cbSignature;
  7821. psi->encryptedDigest.value = pbSignature;
  7822. pbSignature = NULL;
  7823. fRet = TRUE;
  7824. CommonReturn:
  7825. if (hHashAttr)
  7826. CryptDestroyHash( hHashAttr);
  7827. if (hHashDup)
  7828. CryptDestroyHash( hHashDup);
  7829. ICM_Free(pbSignature);
  7830. ICM_SetLastError(dwError);
  7831. return fRet;
  7832. ErrorReturn:
  7833. dwError = GetLastError();
  7834. fRet = FALSE;
  7835. goto CommonReturn;
  7836. TRACE_ERROR(FillReqAuthAttrsError) // error already set
  7837. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  7838. TRACE_ERROR(DupListHashError) // error already set
  7839. TRACE_ERROR(AllocAndSignHashError) // error already set
  7840. }
  7841. #endif // CMS_PKCS7
  7842. //+-------------------------------------------------------------------------
  7843. // Update the content of a signed message.
  7844. //
  7845. // Assume all more-deeply-nested messages are DER-encoded.
  7846. //--------------------------------------------------------------------------
  7847. BOOL
  7848. WINAPI
  7849. ICM_UpdateEncodingSignedData(
  7850. IN PCRYPT_MSG_INFO pcmi,
  7851. IN const BYTE *pbData,
  7852. IN DWORD cbData,
  7853. IN BOOL fFinal)
  7854. {
  7855. BOOL fRet;
  7856. SignedData *psd = (SignedData *)pcmi->pvMsg;
  7857. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  7858. PBYTE pb;
  7859. DWORD cb;
  7860. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  7861. BOOL fAddInnerContentOctetWrapper; // CMS_PKCS7
  7862. if (pcsi) {
  7863. if (!ICMS_UpdateEncodingSignedData( pcmi, (PBYTE)pbData, cbData, fFinal))
  7864. goto StreamUpdateEncodingSignedDataError;
  7865. } else {
  7866. psd->contentInfo.bit_mask = 0;
  7867. fAddInnerContentOctetWrapper = ICM_IsAddInnerContentOctetWrapper(pcmi);
  7868. if (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG) &&
  7869. !fAddInnerContentOctetWrapper && pbData) {
  7870. // must be encoded, hash only the contents octets
  7871. if (0 > Asn1UtilExtractContent(
  7872. (PBYTE)pbData,
  7873. cbData,
  7874. &cb,
  7875. (const BYTE **)&pb))
  7876. goto ExtractContentError;
  7877. } else {
  7878. cb = cbData;
  7879. pb = (PBYTE)pbData;
  7880. }
  7881. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  7882. goto UpdateDigestError;
  7883. if (fFinal) {
  7884. if (pcmi->dwFlags & CMSG_DETACHED_FLAG) {
  7885. if (!ICM_FillInnerContentInfo(
  7886. &psd->contentInfo,
  7887. pszInnerContentObjID,
  7888. 0, // cbData
  7889. NULL, // pbData
  7890. FALSE)) // fAddInnerContentOctetWrapper
  7891. goto DetachedFillInnerContentInfoError;
  7892. } else {
  7893. if (!ICM_FillInnerContentInfo(
  7894. &psd->contentInfo,
  7895. pszInnerContentObjID,
  7896. cbData,
  7897. (PBYTE)pbData,
  7898. fAddInnerContentOctetWrapper
  7899. ))
  7900. goto FillInnerContentInfoError;
  7901. }
  7902. #ifdef CMS_PKCS7
  7903. if (pcmi->rgSignerEncodeDataInfo) {
  7904. BOOL fMaxLength =
  7905. (0 != (pcmi->dwFlags & CMSG_MAX_LENGTH_FLAG));
  7906. if (!ICM_FillSignerEncodeEncryptedDigests(
  7907. pcmi,
  7908. fMaxLength))
  7909. goto FillSignerEncodeEncryptedDigestsError;
  7910. }
  7911. #else
  7912. if (pcmi->pHashList) {
  7913. BOOL fMaxLength =
  7914. (0 != (pcmi->dwFlags & CMSG_MAX_LENGTH_FLAG));
  7915. if (!ICM_FillSignerEncryptedDigest(
  7916. psd->signerInfos.value,
  7917. pszInnerContentObjID,
  7918. pcmi->pHashList->Head(),
  7919. pcmi->dwKeySpec,
  7920. fMaxLength))
  7921. goto FillSignerEncryptedDigestError;
  7922. }
  7923. #endif // CMS_PKCS7
  7924. }
  7925. }
  7926. fRet = TRUE;
  7927. CommonReturn:
  7928. return fRet;
  7929. ErrorReturn:
  7930. fRet = FALSE;
  7931. goto CommonReturn;
  7932. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  7933. TRACE_ERROR(UpdateDigestError) // error already set
  7934. TRACE_ERROR(DetachedFillInnerContentInfoError) // error already set
  7935. TRACE_ERROR(FillInnerContentInfoError) // error already set
  7936. TRACE_ERROR(StreamUpdateEncodingSignedDataError) // error already set
  7937. #ifdef CMS_PKCS7
  7938. TRACE_ERROR(FillSignerEncodeEncryptedDigestsError) // error already set
  7939. #else
  7940. TRACE_ERROR(FillSignerEncryptedDigestError) // error already set
  7941. #endif // CMS_PKCS7
  7942. }
  7943. //+-------------------------------------------------------------------------
  7944. // Update the content of a data message.
  7945. //--------------------------------------------------------------------------
  7946. BOOL
  7947. WINAPI
  7948. ICM_UpdateEncodingData(
  7949. IN PCRYPT_MSG_INFO pcmi,
  7950. IN const BYTE *pbData,
  7951. IN DWORD cbData,
  7952. IN BOOL fFinal)
  7953. {
  7954. DWORD dwError = ERROR_SUCCESS;
  7955. BOOL fRet;
  7956. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  7957. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  7958. if (!pcsi) {
  7959. if (!fFinal)
  7960. goto NotFinalNotSupportedError;
  7961. poos->length = cbData;
  7962. if (NULL == (poos->value = (PBYTE)ICM_DupMem( (PBYTE)pbData, cbData)))
  7963. goto AllocOctetStringError;
  7964. }
  7965. if (pcsi && !ICMS_UpdateEncodingData( pcmi, (PBYTE)pbData, cbData, fFinal))
  7966. goto StreamUpdateEncodingDataError;
  7967. fRet = TRUE;
  7968. CommonReturn:
  7969. ICM_SetLastError(dwError);
  7970. return fRet;
  7971. ErrorReturn:
  7972. dwError = GetLastError();
  7973. ICM_Free( poos->value);
  7974. fRet = FALSE;
  7975. goto CommonReturn;
  7976. SET_ERROR(NotFinalNotSupportedError,E_INVALIDARG)
  7977. TRACE_ERROR(AllocOctetStringError) // error already set
  7978. TRACE_ERROR(StreamUpdateEncodingDataError) // error already set
  7979. }
  7980. //+-------------------------------------------------------------------------
  7981. // Update the content of a digested message.
  7982. //
  7983. // Assume all more-deeply-nested messages are DER-encoded.
  7984. //--------------------------------------------------------------------------
  7985. BOOL
  7986. WINAPI
  7987. ICM_UpdateEncodingDigestedData(
  7988. IN PCRYPT_MSG_INFO pcmi,
  7989. IN const BYTE *pbData,
  7990. IN DWORD cbData,
  7991. IN BOOL fFinal)
  7992. {
  7993. BOOL fRet;
  7994. DigestedData *pdd = (DigestedData *)pcmi->pvMsg;
  7995. PBYTE pb;
  7996. DWORD cb;
  7997. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  7998. BOOL fAddInnerContentOctetWrapper; // CMS_PKCS7
  7999. pdd->contentInfo.bit_mask = 0;
  8000. if (pcmi->dwFlags & CMSG_DETACHED_FLAG) {
  8001. // must be non-encoded
  8002. if (!ICM_UpdateListDigest( pcmi->pHashList, pbData, cbData))
  8003. goto DetachedUpdateDigestError;
  8004. if (!ICM_FillInnerContentInfo(
  8005. &pdd->contentInfo,
  8006. pszInnerContentObjID,
  8007. 0, // cbData
  8008. NULL, // pbData
  8009. FALSE // fAddInnerContentOctetWrapper
  8010. ))
  8011. goto DetachedFillInnerContentInfoError;
  8012. } else {
  8013. fAddInnerContentOctetWrapper = ICM_IsAddInnerContentOctetWrapper(pcmi);
  8014. if (!fAddInnerContentOctetWrapper && pbData) {
  8015. // must be encoded, hash only the contents octets
  8016. if (0 > Asn1UtilExtractContent( (PBYTE)pbData, cbData, &cb,
  8017. (const BYTE **)&pb))
  8018. goto ExtractContentError;
  8019. } else {
  8020. cb = cbData;
  8021. pb = (PBYTE)pbData;
  8022. }
  8023. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  8024. goto UpdateDigestError;
  8025. if (!ICM_FillInnerContentInfo(
  8026. &pdd->contentInfo,
  8027. pszInnerContentObjID,
  8028. cbData,
  8029. (PBYTE)pbData,
  8030. fAddInnerContentOctetWrapper
  8031. ))
  8032. goto FillInnerContentInfoError;
  8033. }
  8034. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8035. if (!ICM_GetListHashValue(
  8036. pcmi->pHashList->Head(),
  8037. (DWORD*)&pdd->digest.length,
  8038. &pdd->digest.value))
  8039. goto GetHashValueError;
  8040. }
  8041. fRet = TRUE;
  8042. CommonReturn:
  8043. return fRet;
  8044. ErrorReturn:
  8045. fRet = FALSE;
  8046. goto CommonReturn;
  8047. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8048. TRACE_ERROR(DetachedUpdateDigestError) // error already set
  8049. TRACE_ERROR(UpdateDigestError) // error already set
  8050. TRACE_ERROR(DetachedFillInnerContentInfoError) // error already set
  8051. TRACE_ERROR(FillInnerContentInfoError) // error already set
  8052. TRACE_ERROR(GetHashValueError) // error already set
  8053. fFinal;
  8054. }
  8055. //+-------------------------------------------------------------------------
  8056. // Get the block size for an encryption algorithm
  8057. //--------------------------------------------------------------------------
  8058. BOOL
  8059. WINAPI
  8060. ICM_GetKeyBlockSize(
  8061. IN HCRYPTKEY hkeyEncrypt,
  8062. OUT PDWORD pcbBlockSize,
  8063. OUT OPTIONAL PBOOL pfBlockCipher)
  8064. {
  8065. BOOL fRet;
  8066. BOOL fBlockCipher;
  8067. DWORD cbBlockSize;
  8068. DWORD cbKeyParamLen;
  8069. // Get key's blocksize.
  8070. // Encryption will pad the output data to be blocksize aligned,
  8071. // in the case of a block cipher.
  8072. cbBlockSize = 0;
  8073. cbKeyParamLen = sizeof( cbBlockSize);
  8074. if (!CryptGetKeyParam(
  8075. hkeyEncrypt,
  8076. KP_BLOCKLEN,
  8077. (PBYTE)&cbBlockSize,
  8078. &cbKeyParamLen,
  8079. 0)) // dwFlags
  8080. goto GetKeyParamError;
  8081. if (0 == cbBlockSize) {
  8082. // stream cipher
  8083. fBlockCipher = FALSE;
  8084. cbBlockSize = 8; // convenient size
  8085. } else {
  8086. // block cipher
  8087. fBlockCipher = TRUE;
  8088. cbBlockSize /= 8; // convert from bits to bytes
  8089. }
  8090. fRet = TRUE;
  8091. CommonReturn:
  8092. *pcbBlockSize = cbBlockSize;
  8093. if (pfBlockCipher)
  8094. *pfBlockCipher = fBlockCipher;
  8095. return fRet;
  8096. ErrorReturn:
  8097. cbBlockSize = 0;
  8098. fBlockCipher = FALSE;
  8099. fRet = FALSE;
  8100. goto CommonReturn;
  8101. TRACE_ERROR(GetKeyParamError) // error already set
  8102. }
  8103. //+-------------------------------------------------------------------------
  8104. // Encrypt a buffer
  8105. //--------------------------------------------------------------------------
  8106. BOOL
  8107. WINAPI
  8108. ICM_EncryptBuffer(
  8109. IN HCRYPTKEY hkeyEncrypt,
  8110. HCRYPTHASH hHash,
  8111. IN const BYTE *pbPlain,
  8112. IN DWORD cbPlain,
  8113. OUT PBYTE *ppbCipher,
  8114. OUT PDWORD pcbCipher)
  8115. {
  8116. BOOL fRet;
  8117. const BYTE *pbIn;
  8118. DWORD cbIn;
  8119. PBYTE pbOut;
  8120. DWORD cbOut;
  8121. PBYTE pbOutBuf = NULL;
  8122. DWORD cbPlainRemain;
  8123. DWORD cbBufRemain;
  8124. DWORD cbBlockLen;
  8125. BOOL fBlockCipher;
  8126. if (!ICM_GetKeyBlockSize( hkeyEncrypt, &cbBlockLen, &fBlockCipher))
  8127. goto GetKeyBlockSizeError;
  8128. // encrypt
  8129. cbBufRemain = cbPlain;
  8130. if (fBlockCipher) {
  8131. cbBufRemain += cbBlockLen;
  8132. cbBufRemain -= cbBufRemain % cbBlockLen;
  8133. }
  8134. if (NULL == (pbOutBuf = (PBYTE)ICM_Alloc( cbBufRemain)))
  8135. goto OutOfMemory;
  8136. for (pbIn=pbPlain, pbOut=pbOutBuf, cbPlainRemain=cbPlain;
  8137. (cbIn = min( cbBlockLen, cbPlainRemain)) > 0;
  8138. pbIn += cbIn, pbOut += cbOut,
  8139. cbPlainRemain -= cbIn, cbBufRemain -= cbOut) {
  8140. memcpy( pbOut, pbIn, cbIn);
  8141. cbOut = cbIn;
  8142. if (!CryptEncrypt(
  8143. hkeyEncrypt,
  8144. hHash,
  8145. cbPlainRemain <= cbBlockLen, // fFinal
  8146. 0, // dwFlags
  8147. pbOut,
  8148. &cbOut,
  8149. cbBufRemain))
  8150. goto EncryptError;
  8151. }
  8152. *ppbCipher = pbOutBuf;
  8153. *pcbCipher = (DWORD)(pbOut - pbOutBuf);
  8154. fRet = TRUE;
  8155. CommonReturn:
  8156. return fRet;
  8157. ErrorReturn:
  8158. if(NULL != pbOutBuf)
  8159. ICM_Free(pbOutBuf);
  8160. *ppbCipher = NULL;
  8161. *pcbCipher = 0;
  8162. fRet = FALSE;
  8163. goto CommonReturn;
  8164. TRACE_ERROR(GetKeyBlockSizeError) // error already set
  8165. TRACE_ERROR(EncryptError) // error already set
  8166. TRACE_ERROR(OutOfMemory) // error already set
  8167. }
  8168. //+-------------------------------------------------------------------------
  8169. // Encrypt and store the content of a message.
  8170. //--------------------------------------------------------------------------
  8171. BOOL
  8172. WINAPI
  8173. ICM_EncryptContent(
  8174. IN HCRYPTKEY hkeyContentEncryption,
  8175. HCRYPTHASH hHash,
  8176. OUT EncryptedContentInfo *peci,
  8177. IN const BYTE *pbPlain,
  8178. IN DWORD cbPlain)
  8179. {
  8180. BOOL fRet;
  8181. PBYTE pbCipher = NULL;
  8182. DWORD cbCipher;
  8183. if (!ICM_EncryptBuffer(
  8184. hkeyContentEncryption,
  8185. hHash,
  8186. pbPlain,
  8187. cbPlain,
  8188. &pbCipher,
  8189. &cbCipher))
  8190. goto EncryptBufferError;
  8191. if (0 != cbCipher) {
  8192. peci->bit_mask |= encryptedContent_present;
  8193. peci->encryptedContent.length = cbCipher;
  8194. peci->encryptedContent.value = pbCipher;
  8195. } else
  8196. ICM_Free(pbCipher);
  8197. fRet = TRUE;
  8198. CommonReturn:
  8199. return fRet;
  8200. ErrorReturn:
  8201. fRet = FALSE;
  8202. goto CommonReturn;
  8203. TRACE_ERROR(EncryptBufferError) // error already set
  8204. }
  8205. //+-------------------------------------------------------------------------
  8206. // Update the content of a signed and enveloped message.
  8207. //
  8208. // Assume all more-deeply-nested messages are DER-encoded.
  8209. //--------------------------------------------------------------------------
  8210. #if 0
  8211. BOOL
  8212. WINAPI
  8213. ICM_UpdateEncodingSignedAndEnvelopedData(
  8214. IN PCRYPT_MSG_INFO pcmi,
  8215. IN const BYTE *pbData,
  8216. IN DWORD cbData,
  8217. IN BOOL fFinal)
  8218. {
  8219. DWORD dwError = ERROR_SUCCESS;
  8220. BOOL fRet;
  8221. EncryptedContentInfo *peci;
  8222. SignedAndEnvelopedData *psed;
  8223. DWORD i;
  8224. DWORD iMax;
  8225. PBYTE pbSignature;
  8226. DWORD cbSignature;
  8227. PBYTE pbEncryptedSignature;
  8228. DWORD cbEncryptedSignature;
  8229. psed = (SignedAndEnvelopedData *)(pcmi->pvMsg);
  8230. peci = &psed->encryptedContentInfo;
  8231. // Require inner type to be Data for now
  8232. peci->contentType = aoidMessages[ CMSG_DATA - 1];
  8233. // Alloc a bigger buffer with padding and copy input to it
  8234. // encrypt the content and store it
  8235. if (!ICM_EncryptContent(
  8236. pcmi->hkeyContentCrypt,
  8237. pcmi->ahHash[0], // select the right hHash
  8238. peci,
  8239. pbData,
  8240. cbData))
  8241. goto EncryptError;
  8242. assert( 1 == psed->signerInfos.Count());
  8243. for (i=0, iMax=psed->signerInfos.Count(); i<iMax; i++) {
  8244. // Should use a stack buffer, unless it is too small
  8245. if (!CryptSignHash(
  8246. pcmi->ahHash[i],
  8247. (pcmi->dwKeySpec == 0) ? AT_SIGNATURE : pcmi->dwKeySpec,
  8248. NULL, // description ?
  8249. 0, // dwFlags
  8250. NULL, // pbSignature
  8251. &cbSignature))
  8252. goto GetSignatureSizeError;
  8253. pbSignature = (PBYTE)ICM_AllocA( cbSignature);
  8254. if (NULL == pbSignature)
  8255. goto AllocSignatureError;
  8256. if (!CryptSignHash(
  8257. pcmi->ahHash[i],
  8258. (pcmi->dwKeySpec == 0) ? AT_SIGNATURE : pcmi->dwKeySpec,
  8259. NULL, // description ?
  8260. 0, // dwFlags
  8261. pbSignature,
  8262. &cbSignature))
  8263. goto SignHashError;
  8264. // encrypt the signature
  8265. if (!ICM_EncryptBuffer(
  8266. pcmi->hkeyContentCrypt,
  8267. NULL,
  8268. pbSignature,
  8269. cbSignature,
  8270. &pbEncryptedSignature,
  8271. &cbEncryptedSignature))
  8272. goto EncryptError;
  8273. ICM_FreeA( pbSignature);
  8274. pbSignature = NULL;
  8275. if (0 > psed->signerInfos[i].encryptedDigest.Write(
  8276. pbEncryptedSignature,
  8277. cbEncryptedSignature))
  8278. goto EncryptedDigestWriteError;
  8279. ICM_Free( pbEncryptedSignature);
  8280. pbEncryptedSignature = NULL;
  8281. }
  8282. fRet = TRUE;
  8283. CommonReturn:
  8284. ICM_FreeA( pbSignature);
  8285. ICM_Free( pbEncryptedSignature);
  8286. ICM_SetLastError(dwError);
  8287. return fRet;
  8288. ErrorReturn:
  8289. dwError = GetLastError();
  8290. fRet = FALSE;
  8291. goto CommonReturn;
  8292. TRACE_ERROR(EncryptError)
  8293. TRACE_ERROR(GetSignatureSizeError)
  8294. TRACE_ERROR(AllocSignatureError)
  8295. TRACE_ERROR(SignHashError)
  8296. TRACE_ERROR(EncryptedDigestWriteError)
  8297. }
  8298. #endif
  8299. //+-------------------------------------------------------------------------
  8300. // Update the content of an enveloped message.
  8301. //
  8302. // Assume all more-deeply-nested messages are DER-encoded.
  8303. //--------------------------------------------------------------------------
  8304. BOOL
  8305. WINAPI
  8306. ICM_UpdateEncodingEnvelopedData(
  8307. IN PCRYPT_MSG_INFO pcmi,
  8308. IN const BYTE *pbData,
  8309. IN DWORD cbData,
  8310. IN BOOL fFinal)
  8311. {
  8312. BOOL fRet;
  8313. PBYTE pb;
  8314. DWORD cb;
  8315. #ifdef CMS_PKCS7
  8316. EncryptedContentInfo *peci = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  8317. #else
  8318. EncryptedContentInfo *peci = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  8319. #endif // CMS_PKCS7
  8320. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  8321. if (pcsi) {
  8322. if (!ICMS_UpdateEncodingEnvelopedData(
  8323. pcmi,
  8324. pbData,
  8325. cbData,
  8326. fFinal))
  8327. goto StreamUpdateEncodingEnvelopedDataError;
  8328. } else {
  8329. if (!fFinal)
  8330. goto InvalidArg;
  8331. // encrypt the content
  8332. if (!ICM_IsAddInnerContentOctetWrapper(pcmi)) {
  8333. if (0 > Asn1UtilExtractContent( (PBYTE)pbData, cbData, &cb, (const BYTE **)&pb))
  8334. goto ExtractContentError;
  8335. } else {
  8336. pb = (PBYTE)pbData;
  8337. cb = cbData;
  8338. }
  8339. if (!ICM_EncryptContent(
  8340. pcmi->hkeyContentCrypt,
  8341. NULL, // hHash
  8342. peci,
  8343. pb,
  8344. cb))
  8345. goto EncryptError;
  8346. }
  8347. fRet = TRUE;
  8348. CommonReturn:
  8349. return fRet;
  8350. ErrorReturn:
  8351. fRet = FALSE;
  8352. goto CommonReturn;
  8353. SET_ERROR(InvalidArg,E_INVALIDARG)
  8354. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8355. TRACE_ERROR(EncryptError) // error already set
  8356. TRACE_ERROR(StreamUpdateEncodingEnvelopedDataError) // error already set
  8357. }
  8358. //+-------------------------------------------------------------------------
  8359. // Convert Any to blob and insert at the tail of a blob list
  8360. //--------------------------------------------------------------------------
  8361. BOOL
  8362. WINAPI
  8363. ICM_InsertTailBlob(
  8364. IN OUT CBlobList *pBlobList,
  8365. IN Any *pAny)
  8366. {
  8367. DWORD dwError = ERROR_SUCCESS;
  8368. BOOL fRet;
  8369. CBlobNode *pnBlob = NULL;
  8370. PBYTE pb = NULL;
  8371. DWORD cb;
  8372. CRYPT_DATA_BLOB blob;
  8373. if (NULL == (pnBlob = new CBlobNode))
  8374. goto NewCBlobNodeError;
  8375. cb = pAny->length;
  8376. if (NULL == (pb = (PBYTE)ICM_Alloc( cb)))
  8377. goto AllocError;
  8378. memcpy( pb, pAny->value, cb);
  8379. blob.cbData = cb;
  8380. blob.pbData = pb;
  8381. pnBlob->SetData( &blob);
  8382. pBlobList->InsertTail( pnBlob);
  8383. fRet = TRUE;
  8384. CommonReturn:
  8385. ICM_SetLastError(dwError);
  8386. return fRet;
  8387. ErrorReturn:
  8388. dwError = GetLastError();
  8389. fRet = FALSE;
  8390. ICM_Free( pb);
  8391. goto CommonReturn;
  8392. SET_ERROR(NewCBlobNodeError,E_OUTOFMEMORY)
  8393. TRACE_ERROR(AllocError) // error already set
  8394. }
  8395. //+-------------------------------------------------------------------------
  8396. // Use a 0-based index to delete a blob from a list
  8397. //--------------------------------------------------------------------------
  8398. BOOL
  8399. WINAPI
  8400. ICM_DelBlobByIndex(
  8401. IN OUT CBlobList *pBlobList,
  8402. IN DWORD dwIndex)
  8403. {
  8404. BOOL fRet;
  8405. CBlobNode *pnBlob = pBlobList->Nth( dwIndex);
  8406. if (NULL == pnBlob)
  8407. goto IndexTooLargeError;
  8408. pBlobList->Remove( pnBlob);
  8409. delete pnBlob;
  8410. fRet = TRUE;
  8411. CommonReturn:
  8412. return fRet;
  8413. ErrorReturn:
  8414. fRet = FALSE;
  8415. goto CommonReturn;
  8416. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  8417. }
  8418. //+-------------------------------------------------------------------------
  8419. // Convert Any to blob and insert at the tail of a signer list
  8420. //--------------------------------------------------------------------------
  8421. BOOL
  8422. WINAPI
  8423. ICM_InsertTailSigner(
  8424. IN OUT CSignerList *pSignerList,
  8425. IN Any *pAny)
  8426. {
  8427. DWORD dwError = ERROR_SUCCESS;
  8428. BOOL fRet;
  8429. CSignerNode *pnSigner = NULL;
  8430. PBYTE pb = NULL;
  8431. DWORD cb;
  8432. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  8433. if (NULL == (pnSigner = new CSignerNode))
  8434. goto NewCSignerNodeError;
  8435. cb = pAny->length;
  8436. if (NULL == (pb = (PBYTE)ICM_Alloc( cb)))
  8437. goto AllocError;
  8438. memcpy( pb, pAny->value, cb);
  8439. sdi.blob.cbData = cb;
  8440. sdi.blob.pbData = pb;
  8441. pnSigner->SetData( &sdi);
  8442. pSignerList->InsertTail( pnSigner);
  8443. fRet = TRUE;
  8444. CommonReturn:
  8445. ICM_SetLastError(dwError);
  8446. return fRet;
  8447. ErrorReturn:
  8448. dwError = GetLastError();
  8449. ICM_Free( pb);
  8450. fRet = FALSE;
  8451. goto CommonReturn;
  8452. SET_ERROR(NewCSignerNodeError,E_OUTOFMEMORY)
  8453. TRACE_ERROR(AllocError) // error already set
  8454. }
  8455. //+-------------------------------------------------------------------------
  8456. // Convert a signed message to list form
  8457. //--------------------------------------------------------------------------
  8458. BOOL
  8459. WINAPI
  8460. ICM_GetListSignedData(
  8461. IN OUT PCRYPT_MSG_INFO pcmi,
  8462. IN SignedDataWithBlobs *psdb)
  8463. {
  8464. DWORD dwError = ERROR_SUCCESS;
  8465. BOOL fRet;
  8466. Any *pAny;
  8467. DWORD cb;
  8468. DWORD i;
  8469. PSIGNED_DATA_INFO psdi = NULL;
  8470. if (NULL == (psdi = (PSIGNED_DATA_INFO)ICM_AllocZero(
  8471. sizeof(SIGNED_DATA_INFO))))
  8472. goto SdiAllocError;
  8473. if (NULL == (psdi->pAlgidList = new CBlobList))
  8474. goto NewAlgidListError;
  8475. if (NULL == (psdi->pCertificateList = new CBlobList))
  8476. goto NewCertificateListError;
  8477. if (NULL == (psdi->pCrlList = new CBlobList))
  8478. goto NewCrlListError;
  8479. if (NULL == (psdi->pSignerList = new CSignerList))
  8480. goto NewSignerListError;
  8481. // version
  8482. psdi->version = psdb->version;
  8483. // digestAlgorithms
  8484. for (i=psdb->digestAlgorithms.count, pAny=psdb->digestAlgorithms.value;
  8485. i>0;
  8486. i--, pAny++) {
  8487. if (!ICM_InsertTailBlob( psdi->pAlgidList, pAny))
  8488. goto DigestAlgorithmInsertTailBlobError;
  8489. }
  8490. // contentInfo
  8491. cb = 0;
  8492. ICM_GetOssContentInfoData(
  8493. (ContentInfo *)&psdb->contentInfo, // same, except for NOCOPY
  8494. NULL,
  8495. &cb);
  8496. if (cb == 0)
  8497. goto GetContentInfoDataSizeError;
  8498. if (NULL == (psdi->pci = (PCONTENT_INFO)ICM_Alloc(cb)))
  8499. goto AllocContentInfoError;
  8500. if (!ICM_GetOssContentInfoData(
  8501. (ContentInfo *)&psdb->contentInfo, // same, except for NOCOPY
  8502. psdi->pci,
  8503. &cb))
  8504. goto GetContentInfoDataError;
  8505. // certificates
  8506. if (psdb->bit_mask & certificates_present) {
  8507. #ifdef OSS_CRYPT_ASN1
  8508. for (i=psdb->certificates.count, pAny=psdb->certificates.certificates;
  8509. #else
  8510. for (i=psdb->certificates.count, pAny=psdb->certificates.value;
  8511. #endif // OSS_CRYPT_ASN1
  8512. i>0;
  8513. i--, pAny++) {
  8514. if (!ICM_InsertTailBlob( psdi->pCertificateList, pAny))
  8515. goto CertInsertTailBlobError;
  8516. }
  8517. }
  8518. // crls
  8519. if (psdb->bit_mask & crls_present) {
  8520. #ifdef OSS_CRYPT_ASN1
  8521. for (i=psdb->crls.count, pAny=psdb->crls.crls;
  8522. #else
  8523. for (i=psdb->crls.count, pAny=psdb->crls.value;
  8524. #endif // OSS_CRYPT_ASN1
  8525. i>0;
  8526. i--, pAny++) {
  8527. if (!ICM_InsertTailBlob( psdi->pCrlList, pAny))
  8528. goto CrlInsertTailBlobError;
  8529. }
  8530. }
  8531. // signerInfos
  8532. for (i=psdb->signerInfos.count, pAny=psdb->signerInfos.value;
  8533. i>0;
  8534. i--, pAny++) {
  8535. if (!ICM_InsertTailSigner( psdi->pSignerList, pAny))
  8536. goto SignerInfoInsertTailBlobError;
  8537. }
  8538. fRet = TRUE;
  8539. CommonReturn:
  8540. pcmi->psdi = psdi;
  8541. ICM_SetLastError(dwError);
  8542. return fRet;
  8543. ErrorReturn:
  8544. dwError = GetLastError();
  8545. if(NULL != psdi->pSignerList)
  8546. delete psdi->pSignerList;
  8547. if(NULL != psdi->pCrlList)
  8548. delete psdi->pCrlList;
  8549. if(NULL != psdi->pCertificateList)
  8550. delete psdi->pCertificateList;
  8551. if(NULL != psdi->pAlgidList)
  8552. delete psdi->pAlgidList;
  8553. ICM_Free( psdi);
  8554. psdi = NULL;
  8555. fRet = FALSE;
  8556. goto CommonReturn;
  8557. TRACE_ERROR(DigestAlgorithmInsertTailBlobError) // error already set
  8558. TRACE_ERROR(GetContentInfoDataSizeError) // error already set
  8559. TRACE_ERROR(AllocContentInfoError) // error already set
  8560. TRACE_ERROR(GetContentInfoDataError) // error already set
  8561. TRACE_ERROR(CertInsertTailBlobError) // error already set
  8562. TRACE_ERROR(CrlInsertTailBlobError) // error already set
  8563. TRACE_ERROR(SignerInfoInsertTailBlobError) // error already set
  8564. SET_ERROR(NewSignerListError,E_OUTOFMEMORY)
  8565. SET_ERROR(NewCrlListError,E_OUTOFMEMORY)
  8566. SET_ERROR(NewCertificateListError,E_OUTOFMEMORY)
  8567. SET_ERROR(NewAlgidListError,E_OUTOFMEMORY)
  8568. SET_ERROR(SdiAllocError,E_OUTOFMEMORY)
  8569. }
  8570. //+-------------------------------------------------------------------------
  8571. // Get the CAPI algid from an encoded AlgidBlob
  8572. //--------------------------------------------------------------------------
  8573. BOOL
  8574. WINAPI
  8575. ICM_GetCapiFromAlgidBlob(
  8576. IN PCRYPT_DATA_BLOB pAlgidBlob,
  8577. OUT PDWORD pdwAlgidCapi)
  8578. {
  8579. DWORD dwError = ERROR_SUCCESS;
  8580. BOOL fRet;
  8581. ASN1error_e Asn1Err;
  8582. ASN1decoding_t pDec = ICM_GetDecoder();
  8583. AlgorithmIdentifier *poai = NULL;
  8584. if (0 != (Asn1Err = PkiAsn1Decode(
  8585. pDec,
  8586. (void **)&poai,
  8587. AlgorithmIdentifier_PDU,
  8588. pAlgidBlob->pbData,
  8589. pAlgidBlob->cbData)))
  8590. goto Asn1DecodeAlgorithmIdentifierError;
  8591. if (!(ICM_GetOssCAPI( CRYPT_HASH_ALG_OID_GROUP_ID, poai, pdwAlgidCapi) ||
  8592. ICM_GetOssCAPI( CRYPT_SIGN_ALG_OID_GROUP_ID, poai, pdwAlgidCapi)))
  8593. goto GetCAPIError;
  8594. fRet = TRUE;
  8595. CommonReturn:
  8596. PkiAsn1FreeInfo(pDec, AlgorithmIdentifier_PDU, poai);
  8597. ICM_SetLastError(dwError);
  8598. return fRet;
  8599. ErrorReturn:
  8600. dwError = GetLastError();
  8601. fRet = FALSE;
  8602. *pdwAlgidCapi = 0;
  8603. goto CommonReturn;
  8604. SET_ERROR_VAR(Asn1DecodeAlgorithmIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  8605. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  8606. }
  8607. //+-------------------------------------------------------------------------
  8608. // Create a hash list from a list of hash algid's
  8609. //--------------------------------------------------------------------------
  8610. BOOL
  8611. WINAPI
  8612. ICM_CreateHashList(
  8613. IN HCRYPTPROV hCryptProv,
  8614. IN OUT CHashList **ppHashList,
  8615. IN CBlobList *pAlgidList)
  8616. {
  8617. DWORD dwError = ERROR_SUCCESS;
  8618. BOOL fRet;
  8619. CHashList *pHashList;
  8620. CBlobNode *pBlobNode;
  8621. CHashNode *pHashNode;
  8622. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8623. if (NULL == (pHashList = new CHashList))
  8624. goto NewHashListError;
  8625. if (hCryptProv) {
  8626. for (pBlobNode=pAlgidList->Head();
  8627. pBlobNode;
  8628. pBlobNode=pBlobNode->Next()) {
  8629. if (!ICM_GetCapiFromAlgidBlob(
  8630. pBlobNode->Data(),
  8631. &HashInfo.dwAlgoCAPI))
  8632. goto GetCAPIError;
  8633. #ifndef CMS_PKCS7
  8634. HashInfo.hCryptProv = hCryptProv;
  8635. #endif // CMS_PKCS7
  8636. if (!CryptCreateHash(
  8637. hCryptProv,
  8638. HashInfo.dwAlgoCAPI,
  8639. NULL, // hKey - optional for MAC
  8640. 0, // dwFlags
  8641. &HashInfo.hHash))
  8642. goto CreateHashError;
  8643. if (NULL == (pHashNode = new CHashNode))
  8644. goto NewHashNodeError;
  8645. pHashNode->SetData( &HashInfo);
  8646. pHashList->InsertTail( pHashNode);
  8647. }
  8648. }
  8649. fRet = TRUE;
  8650. CommonReturn:
  8651. *ppHashList = pHashList;
  8652. ICM_SetLastError(dwError);
  8653. return fRet;
  8654. ErrorReturn:
  8655. dwError = GetLastError();
  8656. pHashList = NULL;
  8657. fRet = FALSE;
  8658. goto CommonReturn;
  8659. SET_ERROR(NewHashListError,E_OUTOFMEMORY)
  8660. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  8661. TRACE_ERROR(GetCAPIError) // error already set
  8662. TRACE_ERROR(CreateHashError) // error already set
  8663. }
  8664. //+-------------------------------------------------------------------------
  8665. // Update for decoding a signed message
  8666. //--------------------------------------------------------------------------
  8667. BOOL
  8668. WINAPI
  8669. ICM_UpdateDecodingSignedData(
  8670. IN OUT PCRYPT_MSG_INFO pcmi,
  8671. IN const BYTE *pbData,
  8672. IN DWORD cbData)
  8673. {
  8674. DWORD dwError = ERROR_SUCCESS;
  8675. BOOL fRet;
  8676. SignedDataWithBlobs *psdb = NULL;
  8677. PBYTE pb = NULL;
  8678. DWORD cb;
  8679. ASN1error_e Asn1Err;
  8680. ASN1decoding_t pDec = ICM_GetDecoder();
  8681. PBYTE pbDER = NULL;
  8682. DWORD cbDER;
  8683. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8684. DWORD dwExceptionCode;
  8685. // Handle MappedFile Exceptions
  8686. __try {
  8687. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8688. if (0 != (Asn1Err = PkiAsn1Decode(
  8689. pDec,
  8690. (void **)&psdb,
  8691. SignedDataWithBlobs_PDU,
  8692. pbData,
  8693. cbData)))
  8694. goto Asn1DecodeSignedDataError;
  8695. if (!ICM_GetListSignedData( pcmi, psdb))
  8696. goto GetListSignedDataError;
  8697. if (!ICM_CreateHashList(
  8698. pcmi->hCryptProv,
  8699. &pcmi->pHashList,
  8700. pcmi->psdi->pAlgidList))
  8701. goto CreateHashListError;
  8702. if (pcmi->psdi->pci->content.cbData) {
  8703. // Get the address & count of the contents octets of the DER
  8704. // encoding of the content. Since the content might be
  8705. // indefinite-length encoded, decode and re-encode as DER.
  8706. pb = pcmi->psdi->pci->content.pbData;
  8707. cb = pcmi->psdi->pci->content.cbData;
  8708. if (0 == strcmp(pszObjIdDataType,
  8709. pcmi->psdi->pci->pszContentType)
  8710. #ifdef CMS_PKCS7
  8711. || pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION
  8712. #endif // CMS_PKCS7
  8713. ) {
  8714. if (!ICM_ReEncodeAsOctetDER(
  8715. pb,
  8716. cb,
  8717. &pbDER,
  8718. &cbDER
  8719. ))
  8720. goto ReEncodeAsOctetDERError;
  8721. if (pbDER) {
  8722. pb = pbDER;
  8723. cb = cbDER;
  8724. }
  8725. }
  8726. if (0 > Asn1UtilExtractContent( pb, cb, &cb, (const BYTE **)&pb))
  8727. goto ExtractContentError;
  8728. } else {
  8729. cb = 0;
  8730. }
  8731. } else {
  8732. assert (pcmi->dwFlags & CMSG_DETACHED_FLAG);
  8733. if (!(pcmi->dwFlags & CMSG_DETACHED_FLAG))
  8734. goto NonFinalNotDetachedError;
  8735. pb = (PBYTE)pbData;
  8736. cb = cbData;
  8737. }
  8738. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  8739. goto UpdateDigestError;
  8740. fRet = TRUE;
  8741. } __except(EXCEPTION_EXECUTE_HANDLER) {
  8742. dwExceptionCode = GetExceptionCode();
  8743. goto ExceptionError;
  8744. }
  8745. CommonReturn:
  8746. PkiAsn1FreeEncoded(ICM_GetEncoder(), pbDER);
  8747. PkiAsn1FreeInfo(pDec, SignedDataWithBlobs_PDU, psdb);
  8748. ICM_SetLastError(dwError);
  8749. return fRet;
  8750. ErrorReturn:
  8751. dwError = GetLastError();
  8752. fRet = FALSE;
  8753. goto CommonReturn;
  8754. SET_ERROR_VAR(Asn1DecodeSignedDataError, PkiAsn1ErrToHr(Asn1Err))
  8755. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8756. SET_ERROR(NonFinalNotDetachedError,CRYPT_E_MSG_ERROR)
  8757. TRACE_ERROR(GetListSignedDataError) // error already set
  8758. TRACE_ERROR(CreateHashListError) // error already set
  8759. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  8760. TRACE_ERROR(UpdateDigestError) // error already set
  8761. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  8762. }
  8763. #ifdef CMS_PKCS7
  8764. //+-------------------------------------------------------------------------
  8765. // Update for decoding an enveloped message
  8766. //--------------------------------------------------------------------------
  8767. BOOL
  8768. WINAPI
  8769. ICM_UpdateDecodingEnvelopedData(
  8770. IN PCRYPT_MSG_INFO pcmi,
  8771. IN const BYTE *pbData,
  8772. IN DWORD cbData)
  8773. {
  8774. DWORD dwError = ERROR_SUCCESS;
  8775. BOOL fRet;
  8776. CmsEnvelopedData *ped = NULL;
  8777. ASN1error_e Asn1Err;
  8778. ASN1decoding_t pDec = ICM_GetDecoder();
  8779. assert (PHASE_FIRST_FINAL == pcmi->dwPhase);
  8780. if (0 != (Asn1Err = PkiAsn1Decode(
  8781. pDec,
  8782. (void **) &ped,
  8783. CmsEnvelopedData_PDU,
  8784. pbData,
  8785. cbData)))
  8786. goto Asn1DecodeError;
  8787. pcmi->pvMsg = ped;
  8788. if (NULL == (pcmi->pCertificateList = new CBlobList))
  8789. goto NewCertificateListError;
  8790. if (NULL == (pcmi->pCrlList = new CBlobList))
  8791. goto NewCrlListError;
  8792. if (ped->bit_mask & originatorInfo_present) {
  8793. OriginatorInfo *poi = &ped->originatorInfo;
  8794. DWORD i;
  8795. Any *pAny;
  8796. // certificates
  8797. if (poi->bit_mask & certificates_present) {
  8798. #ifdef OSS_CRYPT_ASN1
  8799. for (i=poi->certificates.count, pAny=poi->certificates.certificates;
  8800. #else
  8801. for (i=poi->certificates.count, pAny=poi->certificates.value;
  8802. #endif // OSS_CRYPT_ASN1
  8803. i>0;
  8804. i--, pAny++) {
  8805. if (!ICM_InsertTailBlob( pcmi->pCertificateList, pAny))
  8806. goto CertInsertTailBlobError;
  8807. }
  8808. }
  8809. // crls
  8810. if (poi->bit_mask & crls_present) {
  8811. #ifdef OSS_CRYPT_ASN1
  8812. for (i=poi->crls.count, pAny=poi->crls.crls;
  8813. #else
  8814. for (i=poi->crls.count, pAny=poi->crls.value;
  8815. #endif // OSS_CRYPT_ASN1
  8816. i>0;
  8817. i--, pAny++) {
  8818. if (!ICM_InsertTailBlob( pcmi->pCrlList, pAny))
  8819. goto CrlInsertTailBlobError;
  8820. }
  8821. }
  8822. }
  8823. fRet = TRUE;
  8824. CommonReturn:
  8825. ICM_SetLastError(dwError);
  8826. return fRet;
  8827. ErrorReturn:
  8828. dwError = GetLastError();
  8829. fRet = FALSE;
  8830. if (NULL != pcmi->pCertificateList) {
  8831. delete pcmi->pCertificateList;
  8832. pcmi->pCertificateList = NULL;
  8833. }
  8834. if (NULL != pcmi->pCrlList) {
  8835. delete pcmi->pCrlList;
  8836. pcmi->pCrlList = NULL;
  8837. }
  8838. goto CommonReturn;
  8839. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  8840. SET_ERROR(NewCertificateListError,E_OUTOFMEMORY)
  8841. SET_ERROR(NewCrlListError,E_OUTOFMEMORY)
  8842. TRACE_ERROR(CertInsertTailBlobError)
  8843. TRACE_ERROR(CrlInsertTailBlobError)
  8844. }
  8845. #else
  8846. //+-------------------------------------------------------------------------
  8847. // Update for decoding an enveloped message
  8848. //--------------------------------------------------------------------------
  8849. BOOL
  8850. WINAPI
  8851. ICM_UpdateDecodingEnvelopedData(
  8852. IN PCRYPT_MSG_INFO pcmi,
  8853. IN const BYTE *pbData,
  8854. IN DWORD cbData)
  8855. {
  8856. BOOL fRet;
  8857. EnvelopedData *ped = NULL;
  8858. ASN1error_e Asn1Err;
  8859. ASN1decoding_t pDec = ICM_GetDecoder();
  8860. assert (PHASE_FIRST_FINAL == pcmi->dwPhase);
  8861. if (0 != (Asn1Err = PkiAsn1Decode(
  8862. pDec,
  8863. (void **)&ped,
  8864. EnvelopedData_PDU,
  8865. pbData,
  8866. cbData)))
  8867. goto Asn1DecodeError;
  8868. pcmi->pvMsg = ped;
  8869. fRet = TRUE;
  8870. CommonReturn:
  8871. return fRet;
  8872. ErrorReturn:
  8873. fRet = FALSE;
  8874. goto CommonReturn;
  8875. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  8876. }
  8877. #endif // CMS_PKCS7
  8878. //+-------------------------------------------------------------------------
  8879. // Find the HashNode corresponding to a CAPI Algid
  8880. //
  8881. // NB- Does not fail.
  8882. //--------------------------------------------------------------------------
  8883. BOOL
  8884. WINAPI
  8885. ICM_FindHashNodeFromCapiAlgid(
  8886. IN CHashList *pHashList,
  8887. IN DWORD dwAlgoCAPI,
  8888. OUT CHashNode **ppnHash)
  8889. {
  8890. CHashNode *pnHash;
  8891. for (pnHash=pHashList->Head(); pnHash; pnHash=pnHash->Next()) {
  8892. if (dwAlgoCAPI == pnHash->Data()->dwAlgoCAPI)
  8893. break;
  8894. }
  8895. *ppnHash = pnHash;
  8896. if(pnHash == NULL) {
  8897. SetLastError((DWORD) CRYPT_E_UNKNOWN_ALGO);
  8898. return FALSE;
  8899. }
  8900. return TRUE;
  8901. }
  8902. //+-------------------------------------------------------------------------
  8903. // Find the HashNode corresponding to an encoded Algid
  8904. //--------------------------------------------------------------------------
  8905. BOOL
  8906. WINAPI
  8907. ICM_FindHashNodeFromEncodedAlgo(
  8908. IN CHashList *pHashList,
  8909. IN PCRYPT_DATA_BLOB pblobEncodedAlgorithm,
  8910. OUT CHashNode **ppnHash)
  8911. {
  8912. BOOL fRet;
  8913. DWORD dwAlgoCAPI;
  8914. if (!ICM_GetCapiFromAlgidBlob(
  8915. pblobEncodedAlgorithm,
  8916. &dwAlgoCAPI))
  8917. goto GetCAPIError;
  8918. fRet = ICM_FindHashNodeFromCapiAlgid( pHashList, dwAlgoCAPI, ppnHash);
  8919. CommonReturn:
  8920. return fRet;
  8921. ErrorReturn:
  8922. fRet = FALSE;
  8923. *ppnHash = NULL;
  8924. goto CommonReturn;
  8925. TRACE_ERROR(GetCAPIError) // error already set
  8926. }
  8927. //+-------------------------------------------------------------------------
  8928. // Update for decoding a digested message
  8929. //--------------------------------------------------------------------------
  8930. BOOL
  8931. WINAPI
  8932. ICM_UpdateDecodingDigestedData(
  8933. IN PCRYPT_MSG_INFO pcmi,
  8934. IN const BYTE *pbData,
  8935. IN DWORD cbData)
  8936. {
  8937. DWORD dwError = ERROR_SUCCESS;
  8938. BOOL fRet;
  8939. DigestedData *pdd = NULL;
  8940. PBYTE pb = NULL;
  8941. DWORD cb;
  8942. PBYTE pbDER = NULL;
  8943. DWORD cbDER;
  8944. ASN1error_e Asn1Err;
  8945. ASN1decoding_t pDec = ICM_GetDecoder();
  8946. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8947. CHashNode *pHashNode;
  8948. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8949. if (0 != (Asn1Err = PkiAsn1Decode(
  8950. pDec,
  8951. (void **)&pdd,
  8952. DigestedData_PDU,
  8953. pbData,
  8954. cbData)))
  8955. goto Asn1DecodeError;
  8956. pcmi->pvMsg = pdd;
  8957. if (!ICM_GetOssCAPI(
  8958. CRYPT_HASH_ALG_OID_GROUP_ID,
  8959. &pdd->digestAlgorithm,
  8960. &HashInfo.dwAlgoCAPI))
  8961. goto GetCAPIError;
  8962. #ifndef CMS_PKCS7
  8963. HashInfo.hCryptProv = pcmi->hCryptProv;
  8964. #endif // CMS_PKCS7
  8965. if (!CryptCreateHash(
  8966. pcmi->hCryptProv,
  8967. HashInfo.dwAlgoCAPI,
  8968. NULL, // hKey - optional for MAC
  8969. 0, // dwFlags
  8970. &HashInfo.hHash))
  8971. goto CreateHashError;
  8972. if (NULL == (pcmi->pHashList = new CHashList))
  8973. goto NewHashListError;
  8974. if (NULL == (pHashNode = new CHashNode))
  8975. goto NewHashNodeError;
  8976. pHashNode->SetData( &HashInfo);
  8977. pcmi->pHashList->InsertTail( pHashNode);
  8978. if (pdd->contentInfo.bit_mask & content_present) {
  8979. // Get the address & count of the contents octets of the DER
  8980. // encoding of the content. Since the content might be
  8981. // indefinite-length encoded, decode and re-encode as DER.
  8982. pb = (PBYTE)pdd->contentInfo.content.value;
  8983. cb = (DWORD)pdd->contentInfo.content.length;
  8984. if (ICM_EqualObjectIDs(
  8985. &pdd->contentInfo.contentType,
  8986. &aoidMessages[ CMSG_DATA - 1])
  8987. #ifdef CMS_PKCS7
  8988. || pdd->version >= CMSG_HASHED_DATA_V2
  8989. #endif // CMS_PKCS7
  8990. ) {
  8991. if (!ICM_ReEncodeAsOctetDER(
  8992. pb,
  8993. cb,
  8994. &pbDER,
  8995. &cbDER
  8996. ))
  8997. goto ReEncodeAsOctetDERError;
  8998. if (pbDER) {
  8999. pb = pbDER;
  9000. cb = cbDER;
  9001. }
  9002. }
  9003. if (0 > Asn1UtilExtractContent( pb, cb, &cb, (const BYTE **)&pb))
  9004. goto ExtractContentError;
  9005. } else {
  9006. cb = 0;
  9007. }
  9008. } else {
  9009. assert (pcmi->dwFlags & CMSG_DETACHED_FLAG);
  9010. if (!(pcmi->dwFlags & CMSG_DETACHED_FLAG))
  9011. goto NonFinalNotDetachedError;
  9012. pb = (PBYTE)pbData;
  9013. cb = cbData;
  9014. }
  9015. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  9016. goto UpdateDigestError;
  9017. fRet = TRUE;
  9018. CommonReturn:
  9019. PkiAsn1FreeEncoded(ICM_GetEncoder(), pbDER);
  9020. ICM_SetLastError(dwError);
  9021. return fRet;
  9022. ErrorReturn:
  9023. dwError = GetLastError();
  9024. PkiAsn1FreeInfo(pDec, DigestedData_PDU, pdd);
  9025. fRet = FALSE;
  9026. goto CommonReturn;
  9027. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  9028. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  9029. SET_ERROR(NewHashListError,E_OUTOFMEMORY)
  9030. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  9031. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  9032. SET_ERROR(NonFinalNotDetachedError,CRYPT_E_MSG_ERROR)
  9033. TRACE_ERROR(CreateHashError) // error already set
  9034. TRACE_ERROR(UpdateDigestError) // error already set
  9035. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  9036. }
  9037. //+-------------------------------------------------------------------------
  9038. // Update for decoding a data message
  9039. //--------------------------------------------------------------------------
  9040. BOOL
  9041. WINAPI
  9042. ICM_UpdateDecodingData(
  9043. IN PCRYPT_MSG_INFO pcmi,
  9044. IN const BYTE *pbData,
  9045. IN DWORD cbData)
  9046. {
  9047. DWORD dwError = ERROR_SUCCESS;
  9048. BOOL fRet;
  9049. OctetStringType *poos = NULL;
  9050. ASN1error_e Asn1Err;
  9051. ASN1decoding_t pDec = ICM_GetDecoder();
  9052. if (PHASE_FIRST_FINAL != pcmi->dwPhase)
  9053. goto NonFirstFinalError;
  9054. if (0 != (Asn1Err = PkiAsn1Decode(
  9055. pDec,
  9056. (void **)&poos,
  9057. OctetStringType_PDU,
  9058. pbData,
  9059. cbData)))
  9060. goto Asn1DecodeError;
  9061. pcmi->pvMsg = poos;
  9062. fRet = TRUE;
  9063. CommonReturn:
  9064. ICM_SetLastError(dwError);
  9065. return fRet;
  9066. ErrorReturn:
  9067. dwError = GetLastError();
  9068. PkiAsn1FreeInfo(pDec, OctetStringType_PDU, poos);
  9069. fRet = FALSE;
  9070. goto CommonReturn;
  9071. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  9072. SET_ERROR(NonFirstFinalError,CRYPT_E_MSG_ERROR)
  9073. }
  9074. //+-------------------------------------------------------------------------
  9075. // Write a buffer to a file
  9076. //--------------------------------------------------------------------------
  9077. BOOL
  9078. WINAPI
  9079. ICM_WriteBufToFile(
  9080. LPCSTR pszFileName,
  9081. PBYTE pbData,
  9082. DWORD cbData)
  9083. {
  9084. BOOL fRet;
  9085. HANDLE hFile;
  9086. DWORD cbWritten;
  9087. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_WRITE,
  9088. 0, NULL, CREATE_ALWAYS, 0, NULL))) {
  9089. goto CreateFileError;
  9090. }
  9091. if (!WriteFile( hFile, pbData, cbData, &cbWritten, NULL) ||
  9092. (cbWritten != cbData)) {
  9093. goto WriteFileError;
  9094. }
  9095. CloseHandle( hFile);
  9096. fRet = TRUE;
  9097. CommonReturn:
  9098. return fRet;
  9099. ErrorReturn:
  9100. fRet = FALSE;
  9101. goto CommonReturn;
  9102. TRACE_ERROR(CreateFileError)
  9103. TRACE_ERROR(WriteFileError)
  9104. }
  9105. //+-------------------------------------------------------------------------
  9106. // Update the content of a cryptographic message. Depending on how the
  9107. // message was opened, the content is either encoded or decoded.
  9108. //
  9109. // This function is repetitively called to append to the message content.
  9110. // fFinal is set to identify the last update. On fFinal, the encode/decode
  9111. // is completed. The encoded/decoded content and the decoded parameters
  9112. // are valid until the open and all duplicated handles are closed.
  9113. //--------------------------------------------------------------------------
  9114. BOOL
  9115. WINAPI
  9116. #ifdef DEBUG_CRYPT_ASN1_MASTER
  9117. ICMTest_NewCryptMsgUpdate(
  9118. #else
  9119. CryptMsgUpdate(
  9120. #endif
  9121. IN HCRYPTMSG hCryptMsg,
  9122. IN const BYTE *pbData,
  9123. IN DWORD cbData,
  9124. IN BOOL fFinal)
  9125. {
  9126. DWORD dwError = ERROR_SUCCESS;
  9127. BOOL fRet;
  9128. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  9129. ContentInfo *pci = NULL;
  9130. ASN1error_e Asn1Err;
  9131. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  9132. DWORD dwExceptionCode;
  9133. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  9134. // Handle MappedFile Exceptions
  9135. __try {
  9136. if (!ICM_AdvanceMsgPhase( &pcmi->dwPhase, fFinal))
  9137. goto AdvancePhaseError;
  9138. if (pcmi->fEncoding) {
  9139. if (!(((pcmi->dwFlags & CMSG_DETACHED_FLAG) &&
  9140. (PHASE_FIRST_ONGOING == pcmi->dwPhase)) ||
  9141. (pcsi && (pcmi->dwPhase < PHASE_SECOND_ONGOING)) ||
  9142. (PHASE_FIRST_FINAL == pcmi->dwPhase)))
  9143. goto EncodingPhaseError;
  9144. switch (pcmi->dwMsgType) {
  9145. case CMSG_DATA:
  9146. fRet = ICM_UpdateEncodingData(
  9147. pcmi,
  9148. pbData,
  9149. cbData,
  9150. fFinal);
  9151. break;
  9152. case CMSG_SIGNED:
  9153. fRet = ICM_UpdateEncodingSignedData(
  9154. pcmi,
  9155. pbData,
  9156. cbData,
  9157. fFinal);
  9158. break;
  9159. case CMSG_ENVELOPED:
  9160. fRet = ICM_UpdateEncodingEnvelopedData(
  9161. pcmi,
  9162. pbData,
  9163. cbData,
  9164. fFinal);
  9165. break;
  9166. case CMSG_HASHED:
  9167. fRet = ICM_UpdateEncodingDigestedData(
  9168. pcmi,
  9169. pbData,
  9170. cbData,
  9171. fFinal);
  9172. break;
  9173. case CMSG_SIGNED_AND_ENVELOPED:
  9174. #if 0
  9175. fRet = ICM_UpdateEncodingSignedAndEnvelopedData(
  9176. pcmi,
  9177. pbData,
  9178. cbData,
  9179. fFinal);
  9180. break;
  9181. #endif
  9182. case CMSG_ENCRYPTED:
  9183. goto MessageTypeNotSupportedYet;
  9184. default:
  9185. goto InvalidMsgType;
  9186. }
  9187. } else {
  9188. // decode
  9189. ASN1decoding_t pDec = ICM_GetDecoder();
  9190. LONG lth;
  9191. PBYTE pb;
  9192. DWORD cb;
  9193. if (pcsi) {
  9194. if (pcmi->dwPhase < PHASE_SECOND_ONGOING) {
  9195. fRet = ICMS_UpdateDecoding( pcmi, pbData, cbData, fFinal);
  9196. if (fRet)
  9197. goto CommonReturn;
  9198. else
  9199. goto ErrorReturn;
  9200. }
  9201. // else
  9202. // streaming detached
  9203. }
  9204. if (PHASE_FIRST_ONGOING == pcmi->dwPhase)
  9205. goto FirstOngoingDecodeError;
  9206. if ((0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)) &&
  9207. (PHASE_FIRST_FINAL != pcmi->dwPhase))
  9208. goto SecondOngoingNonDetachedError;
  9209. if ((PHASE_FIRST_FINAL == pcmi->dwPhase) &&
  9210. (0 == pcmi->dwMsgType)) {
  9211. if (0 != (Asn1Err = PkiAsn1Decode(
  9212. pDec,
  9213. (void **)&pci,
  9214. ContentInfoNC_PDU,
  9215. pbData,
  9216. cbData)))
  9217. goto Asn1DecodeContentInfoError;
  9218. if (0 == (lth = ICM_ObjIdToIndex( &pci->contentType)))
  9219. goto InvalidMsgType;
  9220. pcmi->dwMsgType = (DWORD)lth;
  9221. pb = (PBYTE)pci->content.value;
  9222. cb = pci->content.length;
  9223. } else {
  9224. pb = (PBYTE)pbData;
  9225. cb = cbData;
  9226. }
  9227. switch (pcmi->dwMsgType) {
  9228. case CMSG_DATA:
  9229. fRet = ICM_UpdateDecodingData( pcmi, pb, cb);
  9230. break;
  9231. case CMSG_SIGNED:
  9232. fRet = ICM_UpdateDecodingSignedData( pcmi, pb, cb);
  9233. break;
  9234. case CMSG_ENVELOPED:
  9235. fRet = ICM_UpdateDecodingEnvelopedData( pcmi, pb, cb);
  9236. break;
  9237. case CMSG_HASHED:
  9238. fRet = ICM_UpdateDecodingDigestedData( pcmi, pb, cb);
  9239. break;
  9240. case CMSG_SIGNED_AND_ENVELOPED:
  9241. case CMSG_ENCRYPTED:
  9242. goto MessageTypeNotSupportedYet;
  9243. default:
  9244. goto InvalidMsgType;
  9245. }
  9246. }
  9247. if (!fRet)
  9248. goto ErrorReturn;
  9249. } __except(EXCEPTION_EXECUTE_HANDLER) {
  9250. dwExceptionCode = GetExceptionCode();
  9251. goto ExceptionError;
  9252. }
  9253. CommonReturn:
  9254. if (pci)
  9255. PkiAsn1FreeInfo(ICM_GetDecoder(), ContentInfoNC_PDU, pci);
  9256. ICM_Unlock( pcmi);
  9257. ICM_SetLastError(dwError);
  9258. return fRet;
  9259. ErrorReturn:
  9260. dwError = GetLastError();
  9261. fRet = FALSE;
  9262. goto CommonReturn;
  9263. SET_ERROR(EncodingPhaseError,CRYPT_E_MSG_ERROR)
  9264. SET_ERROR(FirstOngoingDecodeError,CRYPT_E_MSG_ERROR)
  9265. SET_ERROR(SecondOngoingNonDetachedError,CRYPT_E_MSG_ERROR)
  9266. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  9267. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  9268. SET_ERROR_VAR(Asn1DecodeContentInfoError, PkiAsn1ErrToHr(Asn1Err))
  9269. TRACE_ERROR(AdvancePhaseError) // error already set
  9270. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  9271. }
  9272. BOOL
  9273. WINAPI
  9274. ICM_VerifySignature(
  9275. IN HCRYPTHASH hHash,
  9276. IN HCRYPTKEY hPubKey,
  9277. IN DWORD dwPubKeyAlgId,
  9278. IN DWORD dwPubKeyFlags,
  9279. IN PBYTE pbEncryptedDigest,
  9280. IN DWORD cbEncryptedDigest)
  9281. {
  9282. BOOL fRet;
  9283. BYTE rgbDssSignature[CERT_DSS_SIGNATURE_LEN];
  9284. PBYTE pb = NULL;
  9285. if (CALG_NO_SIGN == dwPubKeyAlgId) {
  9286. DWORD cbData;
  9287. // The encrypted digest isn't signed. It should be the same as
  9288. // the calculated hash
  9289. if (!CryptGetHashParam(
  9290. hHash,
  9291. HP_HASHVAL,
  9292. NULL,
  9293. &cbData,
  9294. 0)) // dwFlags
  9295. goto GetHashParamSizeError;
  9296. if (NULL == (pb = (PBYTE)ICM_AllocA( cbData)))
  9297. goto AllocHashParamError;
  9298. if (!CryptGetHashParam(
  9299. hHash,
  9300. HP_HASHVAL,
  9301. pb,
  9302. &cbData,
  9303. 0)) // dwFlags
  9304. goto GetHashParamError;
  9305. // Compare the calculated hash with the "encrypted digest"
  9306. if (cbData != cbEncryptedDigest ||
  9307. 0 != memcmp(pb, pbEncryptedDigest, cbData))
  9308. goto NoSignHashCompareError;
  9309. fRet = TRUE;
  9310. goto CommonReturn;
  9311. }
  9312. if (CALG_DSS_SIGN == dwPubKeyAlgId &&
  9313. 0 == (dwPubKeyFlags & CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG)) {
  9314. DWORD cbData;
  9315. // Convert from ASN.1 sequence of two integers to the CSP signature
  9316. // format.
  9317. cbData = sizeof(rgbDssSignature);
  9318. if (!CryptDecodeObject(
  9319. X509_ASN_ENCODING,
  9320. X509_DSS_SIGNATURE,
  9321. pbEncryptedDigest,
  9322. cbEncryptedDigest,
  9323. 0, // dwFlags
  9324. rgbDssSignature,
  9325. &cbData
  9326. ))
  9327. goto DecodeError;
  9328. pbEncryptedDigest = rgbDssSignature;
  9329. assert(cbData == sizeof(rgbDssSignature));
  9330. cbEncryptedDigest = sizeof(rgbDssSignature);
  9331. } else {
  9332. if (NULL == (pb = (PBYTE)ICM_AllocA( cbEncryptedDigest)))
  9333. goto AllocError;
  9334. ICM_ReverseCopy( pb, pbEncryptedDigest, cbEncryptedDigest);
  9335. pbEncryptedDigest = pb;
  9336. }
  9337. fRet = CryptVerifySignature(
  9338. hHash,
  9339. pbEncryptedDigest,
  9340. cbEncryptedDigest,
  9341. hPubKey,
  9342. NULL, // pwszDescription
  9343. 0); // dwFlags
  9344. CommonReturn:
  9345. ICM_FreeA(pb);
  9346. return fRet;
  9347. ErrorReturn:
  9348. fRet = FALSE;
  9349. goto CommonReturn;
  9350. TRACE_ERROR(GetHashParamSizeError)
  9351. TRACE_ERROR(AllocHashParamError)
  9352. TRACE_ERROR(GetHashParamError)
  9353. SET_ERROR(NoSignHashCompareError, NTE_BAD_SIGNATURE)
  9354. TRACE_ERROR(DecodeError)
  9355. TRACE_ERROR(AllocError)
  9356. }
  9357. //+-------------------------------------------------------------------------
  9358. // Verify a signature using the authenticated attributes blob
  9359. //--------------------------------------------------------------------------
  9360. BOOL
  9361. WINAPI
  9362. ICM_VerifySignatureAuthAttrBlob(
  9363. IN PCRYPT_MSG_INFO pcmi,
  9364. IN CSignerNode *pSignerNode,
  9365. IN HCRYPTPROV hCryptProv,
  9366. IN HCRYPTKEY hPubKey,
  9367. IN DWORD dwDigestAlgorithm,
  9368. IN DWORD dwPubKeyAlgorithm,
  9369. IN DWORD dwPubKeyFlags,
  9370. IN PBYTE pbEncryptedDigest,
  9371. IN DWORD cbEncryptedDigest)
  9372. {
  9373. DWORD dwError = ERROR_SUCCESS;
  9374. BOOL fRet;
  9375. SignerInfoWithAABlob *psiaab = NULL;
  9376. ASN1error_e Asn1Err;
  9377. ASN1decoding_t pDec = ICM_GetDecoder();
  9378. CRYPT_DATA_BLOB DataBlob;
  9379. HCRYPTHASH hHashAttrBlob = NULL;
  9380. PBYTE pb = NULL;
  9381. DWORD cb;
  9382. DataBlob = pSignerNode->Data()->blob;
  9383. if (0 != (Asn1Err = PkiAsn1Decode(
  9384. pDec,
  9385. (void **)&psiaab,
  9386. SignerInfoWithAABlob_PDU,
  9387. DataBlob.pbData,
  9388. DataBlob.cbData)))
  9389. goto Asn1DecodeSignerInfoWithAABlobError;
  9390. cb = psiaab->authenticatedAttributes.length;
  9391. if (NULL == (pb = (PBYTE)ICM_AllocA(cb)))
  9392. goto AuthenticatedAttributesAllocError;
  9393. memcpy( pb, psiaab->authenticatedAttributes.value, cb);
  9394. // The encoded blob should contain 0xa0 ([0] IMPLICIT) as the tag,
  9395. // but the tag needs to be 0x31 (SET OF) for the hash computation.
  9396. if (*pb != (ICM_TAG_CONTEXT_0 | ICM_TAG_CONSTRUCTED)) // [0] IMPLICIT
  9397. goto AuthAttrsTagError;
  9398. *pb = ICM_TAG_SET; // SET OF
  9399. if (!ICM_GetBlobHash(
  9400. hCryptProv,
  9401. dwDigestAlgorithm,
  9402. pb,
  9403. cb,
  9404. &hHashAttrBlob))
  9405. goto HashAttrBlobError;
  9406. if (!ICM_VerifySignature(
  9407. hHashAttrBlob,
  9408. hPubKey,
  9409. dwPubKeyAlgorithm,
  9410. dwPubKeyFlags,
  9411. pbEncryptedDigest,
  9412. cbEncryptedDigest))
  9413. goto VerifySignatureError;
  9414. fRet = TRUE;
  9415. CommonReturn:
  9416. PkiAsn1FreeInfo(pDec, SignerInfoWithAABlob_PDU, psiaab);
  9417. if (hHashAttrBlob)
  9418. CryptDestroyHash( hHashAttrBlob);
  9419. ICM_FreeA(pb);
  9420. ICM_SetLastError(dwError);
  9421. return fRet;
  9422. ErrorReturn:
  9423. dwError = GetLastError();
  9424. fRet = FALSE;
  9425. goto CommonReturn;
  9426. SET_ERROR_VAR(Asn1DecodeSignerInfoWithAABlobError, PkiAsn1ErrToHr(Asn1Err))
  9427. SET_ERROR(AuthAttrsTagError,CRYPT_E_BAD_ENCODE)
  9428. TRACE_ERROR(AuthenticatedAttributesAllocError) // error already set
  9429. TRACE_ERROR(HashAttrBlobError) // error already set
  9430. TRACE_ERROR(VerifySignatureError) // error already set
  9431. }
  9432. #ifdef CMS_PKCS7
  9433. BOOL
  9434. WINAPI
  9435. ICM_GetVerifySignatureStuff(
  9436. IN DWORD dwSignerType,
  9437. void *pvSigner,
  9438. IN OUT HCRYPTPROV *phCryptProv,
  9439. OUT HCRYPTKEY *phPubKey,
  9440. OUT DWORD *pdwPubKeyAlgId,
  9441. OUT DWORD *pdwPubKeyFlags)
  9442. {
  9443. BOOL fRet;
  9444. PCCRYPT_OID_INFO pOIDInfo;
  9445. HCRYPTPROV hCryptProv;
  9446. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL; // not allocated
  9447. CERT_PUBLIC_KEY_INFO PubKeyInfo;
  9448. BYTE *pbAllocPubKeyPara = NULL;
  9449. *pdwPubKeyAlgId = 0;
  9450. *pdwPubKeyFlags = 0;
  9451. switch (dwSignerType) {
  9452. case CMSG_VERIFY_SIGNER_PUBKEY:
  9453. pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) pvSigner;
  9454. break;
  9455. case CMSG_VERIFY_SIGNER_CHAIN:
  9456. {
  9457. PCCERT_CHAIN_CONTEXT pChain = (PCCERT_CHAIN_CONTEXT) pvSigner;
  9458. // All chains have at least the leaf certificate context
  9459. assert(pChain->cChain && pChain->rgpChain[0]->cElement);
  9460. pvSigner =
  9461. (void *) pChain->rgpChain[0]->rgpElement[0]->pCertContext;
  9462. dwSignerType = CMSG_VERIFY_SIGNER_CERT;
  9463. }
  9464. // fall through
  9465. case CMSG_VERIFY_SIGNER_CERT:
  9466. {
  9467. PCCERT_CONTEXT pSigner = (PCCERT_CONTEXT) pvSigner;
  9468. PCRYPT_OBJID_BLOB pPara;
  9469. pPubKeyInfo = &pSigner->pCertInfo->SubjectPublicKeyInfo;
  9470. pPara = &pPubKeyInfo->Algorithm.Parameters;
  9471. // Check if the public key parameters were omitted
  9472. // from the encoded certificate. If omitted, try
  9473. // to use the certificate's CERT_PUBKEY_ALG_PARA_PROP_ID
  9474. // property.
  9475. if (0 == pPara->cbData ||
  9476. ICM_TAG_NULL_OCTETS == *pPara->pbData) {
  9477. DWORD cbData;
  9478. if (CertGetCertificateContextProperty(
  9479. pSigner,
  9480. CERT_PUBKEY_ALG_PARA_PROP_ID,
  9481. NULL, // pvData
  9482. &cbData) && 0 < cbData
  9483. &&
  9484. (pbAllocPubKeyPara = (BYTE *) ICM_Alloc(
  9485. cbData))
  9486. &&
  9487. CertGetCertificateContextProperty(
  9488. pSigner,
  9489. CERT_PUBKEY_ALG_PARA_PROP_ID,
  9490. pbAllocPubKeyPara,
  9491. &cbData)) {
  9492. PubKeyInfo = *pPubKeyInfo;
  9493. PubKeyInfo.Algorithm.Parameters.pbData =
  9494. pbAllocPubKeyPara;
  9495. PubKeyInfo.Algorithm.Parameters.cbData = cbData;
  9496. pPubKeyInfo = &PubKeyInfo;
  9497. }
  9498. }
  9499. }
  9500. break;
  9501. case CMSG_VERIFY_SIGNER_NULL:
  9502. break;
  9503. default:
  9504. goto InvalidSignerType;
  9505. }
  9506. if (CMSG_VERIFY_SIGNER_NULL == dwSignerType)
  9507. ;
  9508. else if (pOIDInfo = CryptFindOIDInfo(
  9509. CRYPT_OID_INFO_OID_KEY,
  9510. pPubKeyInfo->Algorithm.pszObjId,
  9511. CRYPT_PUBKEY_ALG_OID_GROUP_ID
  9512. )) {
  9513. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  9514. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  9515. *pdwPubKeyAlgId = pOIDInfo->Algid;
  9516. if (1 <= cExtra)
  9517. *pdwPubKeyFlags = pdwExtra[0];
  9518. }
  9519. hCryptProv = *phCryptProv;
  9520. if (0 == hCryptProv) {
  9521. hCryptProv = I_CryptGetDefaultCryptProv(*pdwPubKeyAlgId);
  9522. if (0 == hCryptProv)
  9523. goto GetDefaultCryptProvError;
  9524. *phCryptProv = hCryptProv;
  9525. }
  9526. if (CMSG_VERIFY_SIGNER_NULL == dwSignerType) {
  9527. // The signature is simply the hash octets
  9528. *pdwPubKeyAlgId = CALG_NO_SIGN;
  9529. *phPubKey = NULL;
  9530. // import the signer's public key
  9531. } else if (!CryptImportPublicKeyInfo(
  9532. hCryptProv,
  9533. X509_ASN_ENCODING,
  9534. pPubKeyInfo,
  9535. phPubKey))
  9536. goto ImportKeyFailed;
  9537. fRet = TRUE;
  9538. CommonReturn:
  9539. ICM_Free(pbAllocPubKeyPara);
  9540. return fRet;
  9541. ErrorReturn:
  9542. fRet = FALSE;
  9543. *phPubKey = 0;
  9544. goto CommonReturn;
  9545. SET_ERROR(InvalidSignerType, E_INVALIDARG)
  9546. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  9547. TRACE_ERROR(ImportKeyFailed) // error already set
  9548. }
  9549. BOOL
  9550. WINAPI
  9551. ICM_FindSignerInfo(
  9552. IN PCRYPT_MSG_INFO pcmi,
  9553. IN DWORD dwIndex,
  9554. OUT PVOID *ppv);
  9555. //+-------------------------------------------------------------------------
  9556. // Verify a signature
  9557. //--------------------------------------------------------------------------
  9558. BOOL
  9559. WINAPI
  9560. ICM_ControlVerifySignatureEx(
  9561. IN PCRYPT_MSG_INFO pcmi,
  9562. IN DWORD dwFlags,
  9563. IN PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA pPara
  9564. )
  9565. {
  9566. DWORD dwError = ERROR_SUCCESS;
  9567. BOOL fRet;
  9568. SignerInfoWithBlobs *psib = NULL;
  9569. CSignerNode *pSignerNode = NULL;
  9570. HCRYPTHASH hHashAttr = NULL;
  9571. HCRYPTHASH hHashDup = NULL;
  9572. HCRYPTHASH hHash = NULL;
  9573. HCRYPTKEY hPubKey = NULL;
  9574. HCRYPTPROV hCryptProv; // doen't need to be released
  9575. DWORD dwPubKeyAlgId;
  9576. DWORD dwPubKeyFlags;
  9577. PBYTE pbHash;
  9578. ULONG cb;
  9579. Any anyValue;
  9580. DWORD cbMessageDigest;
  9581. PBYTE pbMessageDigest;
  9582. ASN1error_e Asn1Err;
  9583. ASN1decoding_t pDec = ICM_GetDecoder();
  9584. CRYPT_DATA_BLOB DataBlob;
  9585. CHashNode *pnHash;
  9586. PICM_HASH_INFO pHashInfo;
  9587. if (!ICM_FindSignerInfo(pcmi, pPara->dwSignerIndex, (PVOID *)&pSignerNode))
  9588. goto FindSignerInfoError;
  9589. DataBlob = pSignerNode->Data()->blob;
  9590. if (0 != (Asn1Err = PkiAsn1Decode(
  9591. pDec,
  9592. (void **)&psib,
  9593. SignerInfoWithBlobs_PDU,
  9594. DataBlob.pbData,
  9595. DataBlob.cbData)))
  9596. goto DecodeSignerInfoWithBlobsError;
  9597. if (!ICM_FindHashNodeFromEncodedAlgo(
  9598. pcmi->pHashList,
  9599. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  9600. &pnHash))
  9601. goto GetHashNodeFromEncodedAlgoError;
  9602. pHashInfo = pnHash->Data();
  9603. if (pPara->hCryptProv)
  9604. hCryptProv = pPara->hCryptProv;
  9605. else if (pcmi->fDefaultCryptProv)
  9606. hCryptProv = 0;
  9607. else
  9608. hCryptProv = pcmi->hCryptProv;
  9609. if (!ICM_GetVerifySignatureStuff(
  9610. pPara->dwSignerType,
  9611. pPara->pvSigner,
  9612. &hCryptProv,
  9613. &hPubKey,
  9614. &dwPubKeyAlgId,
  9615. &dwPubKeyFlags)) goto GetSignatureStuffError;
  9616. if (psib->bit_mask & authAttributes_present) {
  9617. // find the message digest attr value
  9618. if (!ICM_GetAttrValue(
  9619. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  9620. &oidMessageDigest,
  9621. &anyValue))
  9622. goto FindAttrError;
  9623. // find the message digest octets
  9624. if (!Asn1UtilExtractContent(
  9625. #ifdef OSS_CRYPT_ASN1
  9626. anyValue.value,
  9627. #else
  9628. (const BYTE *) anyValue.value,
  9629. #endif // OSS_CRYPT_ASN1
  9630. anyValue.length,
  9631. &cbMessageDigest,
  9632. (const BYTE **)&pbMessageDigest))
  9633. goto ExtractContentError;
  9634. // get the hash value computed on the data
  9635. if (!ICM_GetListHashValue( pnHash, &cb, &pbHash))
  9636. goto GetHashValueError;
  9637. // hash sizes equal?
  9638. if (cb != cbMessageDigest)
  9639. goto HashCompareSizeError;
  9640. // hash octets equal?
  9641. if (memcmp( pbMessageDigest, pbHash, cb))
  9642. goto HashCompareValueError;
  9643. // Now that we have verified the message digest octets,
  9644. // get the hash of the authenticated attributes.
  9645. // Should check the content type attribute as well.
  9646. if (!ICM_GetAttrsHash(
  9647. pHashInfo->dwAlgoCAPI,
  9648. hCryptProv,
  9649. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  9650. &hHashAttr))
  9651. goto GetAuthAttrsHashError;
  9652. hHash = hHashAttr;
  9653. } else {
  9654. if (!ICM_DupListHash( pnHash, hCryptProv, &hHashDup))
  9655. goto DupListHashError;
  9656. hHash = hHashDup;
  9657. }
  9658. // verify the hash, signature, and public key are consistent
  9659. fRet = ICM_VerifySignature(
  9660. hHash,
  9661. hPubKey,
  9662. dwPubKeyAlgId,
  9663. dwPubKeyFlags,
  9664. psib->encryptedDigest.value,
  9665. psib->encryptedDigest.length);
  9666. if (!fRet && hHashAttr) {
  9667. // The hash of the authenticated attributes failed.
  9668. // Maybe they hashed incorrectly-DER-encoded authenticated attributes
  9669. // and gave us that encoding. Hash and verify the actual encoding of
  9670. // the authattrs that they gave us. There is a bug in IE3.0 which hits
  9671. // this path, due to a bug in the then-current OSS libraries.
  9672. fRet = ICM_VerifySignatureAuthAttrBlob(
  9673. pcmi,
  9674. pSignerNode,
  9675. hCryptProv,
  9676. hPubKey,
  9677. pHashInfo->dwAlgoCAPI,
  9678. dwPubKeyAlgId,
  9679. dwPubKeyFlags,
  9680. psib->encryptedDigest.value,
  9681. psib->encryptedDigest.length);
  9682. }
  9683. if (!fRet)
  9684. goto VerifySignatureError;
  9685. CommonReturn:
  9686. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9687. if (hPubKey)
  9688. CryptDestroyKey(hPubKey);
  9689. if (hHashAttr)
  9690. CryptDestroyHash( hHashAttr);
  9691. if (hHashDup)
  9692. CryptDestroyHash( hHashDup);
  9693. ICM_SetLastError(dwError);
  9694. return fRet;
  9695. ErrorReturn:
  9696. dwError = GetLastError();
  9697. // if (hHash && (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)))
  9698. // CryptDestroyHash( hHash);
  9699. fRet = FALSE;
  9700. goto CommonReturn;
  9701. TRACE_ERROR(FindSignerInfoError) // error already set
  9702. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  9703. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  9704. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  9705. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  9706. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  9707. TRACE_ERROR(GetHashValueError) // error already set
  9708. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  9709. TRACE_ERROR(GetSignatureStuffError) // error already set
  9710. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  9711. TRACE_ERROR(DupListHashError) // error already set
  9712. TRACE_ERROR(VerifySignatureError) // error already set
  9713. dwFlags;
  9714. }
  9715. //+-------------------------------------------------------------------------
  9716. // Verify a signature
  9717. //--------------------------------------------------------------------------
  9718. BOOL
  9719. WINAPI
  9720. ICM_ControlVerifySignature(
  9721. IN PCRYPT_MSG_INFO pcmi,
  9722. IN DWORD dwFlags,
  9723. IN PCERT_INFO pci)
  9724. {
  9725. DWORD dwError = ERROR_SUCCESS;
  9726. BOOL fRet;
  9727. SignerInfoWithBlobs *psib = NULL;
  9728. CSignerNode *pSignerNode = NULL;
  9729. ULONG cbIssuer;
  9730. PBYTE pb = NULL;
  9731. ULONG cb;
  9732. ASN1error_e Asn1Err;
  9733. ASN1decoding_t pDec = ICM_GetDecoder();
  9734. CRYPT_DATA_BLOB DataBlob;
  9735. CertIdentifier *pOssCertId = NULL;
  9736. IssuerAndSerialNumber *pisn; // not allocated
  9737. DWORD dwSignerIndex;
  9738. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA ExPara;
  9739. ZEROSTRUCT(ExPara);
  9740. ExPara.cbSize = sizeof(ExPara);
  9741. // ExPara.hCryptProv =
  9742. // ExPara.dwSignerIndex =
  9743. ExPara.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  9744. ExPara.pvSigner = (void *) &pci->SubjectPublicKeyInfo;
  9745. cb = pci->SerialNumber.cbData;
  9746. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  9747. goto SerialNumberAllocError;
  9748. cbIssuer = pci->Issuer.cbData;
  9749. switch (pcmi->dwMsgType) {
  9750. case CMSG_SIGNED:
  9751. {
  9752. for (pSignerNode=pcmi->psdi->pSignerList->Head(), dwSignerIndex = 0;
  9753. pSignerNode;
  9754. pSignerNode = pSignerNode->Next(), dwSignerIndex++) {
  9755. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9756. psib = NULL;
  9757. PkiAsn1FreeInfo(pDec, CertIdentifier_PDU, pOssCertId);
  9758. pOssCertId = NULL;
  9759. DataBlob = pSignerNode->Data()->blob;
  9760. if (0 != (Asn1Err = PkiAsn1Decode(
  9761. pDec,
  9762. (void **)&psib,
  9763. SignerInfoWithBlobs_PDU,
  9764. DataBlob.pbData,
  9765. DataBlob.cbData)))
  9766. goto DecodeSignerInfoWithBlobsError;
  9767. if (0 != (Asn1Err = PkiAsn1Decode(
  9768. pDec,
  9769. (void **)&pOssCertId,
  9770. CertIdentifier_PDU,
  9771. (BYTE *) psib->sid.value,
  9772. psib->sid.length)))
  9773. goto DecodeCertIdentifierError;
  9774. switch (pOssCertId->choice) {
  9775. case issuerAndSerialNumber_chosen:
  9776. pisn = &pOssCertId->u.issuerAndSerialNumber;
  9777. if (pisn->issuer.length != cbIssuer)
  9778. break;
  9779. if (0 != memcmp( pci->Issuer.pbData,
  9780. pisn->issuer.value, cbIssuer))
  9781. break;
  9782. // We need to add an integer method to compare
  9783. // big-endian internal to a little-endian external
  9784. // value.
  9785. if (pisn->serialNumber.length != cb)
  9786. break;
  9787. ICM_ReverseCopy( pb, pisn->serialNumber.value, cb);
  9788. if (0 == memcmp( pb, pci->SerialNumber.pbData, cb))
  9789. goto VerifyFoundSigner;
  9790. break;
  9791. case subjectKeyIdentifier_chosen:
  9792. // Go for it. See if we are able to verify using
  9793. // the public key for this signer
  9794. ExPara.dwSignerIndex = dwSignerIndex;
  9795. fRet = ICM_ControlVerifySignatureEx(
  9796. pcmi,
  9797. dwFlags,
  9798. &ExPara
  9799. );
  9800. if (fRet)
  9801. goto CommonReturn;
  9802. break;
  9803. }
  9804. }
  9805. // No signer was found
  9806. break;
  9807. }
  9808. case CMSG_SIGNED_AND_ENVELOPED:
  9809. goto MessageTypeNotSupportedYet;
  9810. default:
  9811. goto InvalidMsgType;
  9812. }
  9813. assert(NULL == pSignerNode);
  9814. goto SignerNotFound;
  9815. VerifyFoundSigner:
  9816. ExPara.dwSignerIndex = dwSignerIndex;
  9817. fRet = ICM_ControlVerifySignatureEx(
  9818. pcmi,
  9819. dwFlags,
  9820. &ExPara
  9821. );
  9822. if (!fRet)
  9823. goto ErrorReturn;
  9824. CommonReturn:
  9825. ICM_FreeA( pb);
  9826. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9827. PkiAsn1FreeInfo(pDec, CertIdentifier_PDU, pOssCertId);
  9828. ICM_SetLastError(dwError);
  9829. return fRet;
  9830. ErrorReturn:
  9831. dwError = GetLastError();
  9832. fRet = FALSE;
  9833. goto CommonReturn;
  9834. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  9835. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  9836. SET_ERROR_VAR(DecodeCertIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  9837. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  9838. SET_ERROR(SignerNotFound,CRYPT_E_SIGNER_NOT_FOUND)
  9839. TRACE_ERROR(SerialNumberAllocError) // error already set
  9840. }
  9841. #else
  9842. BOOL
  9843. WINAPI
  9844. ICM_GetVerifySignatureStuff(
  9845. IN PCERT_INFO pci,
  9846. IN OUT HCRYPTPROV *phCryptProv,
  9847. OUT HCRYPTKEY *phPubKey,
  9848. OUT DWORD *pdwPubKeyAlgId,
  9849. OUT DWORD *pdwPubKeyFlags)
  9850. {
  9851. BOOL fRet;
  9852. PCCRYPT_OID_INFO pOIDInfo;
  9853. HCRYPTPROV hCryptProv;
  9854. *pdwPubKeyAlgId = 0;
  9855. *pdwPubKeyFlags = 0;
  9856. if (pOIDInfo = CryptFindOIDInfo(
  9857. CRYPT_OID_INFO_OID_KEY,
  9858. pci->SubjectPublicKeyInfo.Algorithm.pszObjId,
  9859. CRYPT_PUBKEY_ALG_OID_GROUP_ID
  9860. )) {
  9861. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  9862. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  9863. *pdwPubKeyAlgId = pOIDInfo->Algid;
  9864. if (1 <= cExtra)
  9865. *pdwPubKeyFlags = pdwExtra[0];
  9866. }
  9867. hCryptProv = *phCryptProv;
  9868. if (0 == hCryptProv) {
  9869. hCryptProv = I_CryptGetDefaultCryptProv(*pdwPubKeyAlgId);
  9870. if (0 == hCryptProv)
  9871. goto GetDefaultCryptProvError;
  9872. *phCryptProv = hCryptProv;
  9873. }
  9874. // import the signer's public key
  9875. if (!CryptImportPublicKeyInfo(
  9876. hCryptProv,
  9877. X509_ASN_ENCODING,
  9878. &pci->SubjectPublicKeyInfo,
  9879. phPubKey))
  9880. goto ImportKeyFailed;
  9881. fRet = TRUE;
  9882. CommonReturn:
  9883. return fRet;
  9884. ErrorReturn:
  9885. fRet = FALSE;
  9886. *phPubKey = 0;
  9887. goto CommonReturn;
  9888. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  9889. TRACE_ERROR(ImportKeyFailed) // error already set
  9890. }
  9891. //+-------------------------------------------------------------------------
  9892. // Verify a signature
  9893. //--------------------------------------------------------------------------
  9894. BOOL
  9895. WINAPI
  9896. ICM_ControlVerifySignature(
  9897. IN PCRYPT_MSG_INFO pcmi,
  9898. IN DWORD dwFlags,
  9899. IN PCERT_INFO pci)
  9900. {
  9901. DWORD dwError = ERROR_SUCCESS;
  9902. BOOL fRet;
  9903. SignerInfoWithBlobs *psib = NULL;
  9904. CSignerNode *pSignerNode = NULL;
  9905. SignerInfo *psi = NULL;
  9906. Any *pc; // &content
  9907. HCRYPTHASH hHashAttr = NULL;
  9908. HCRYPTHASH hHashDup = NULL;
  9909. HCRYPTHASH hHash = NULL;
  9910. HCRYPTKEY hPubKey = NULL;
  9911. HCRYPTPROV hCryptProv;
  9912. DWORD dwPubKeyAlgId;
  9913. DWORD dwPubKeyFlags;
  9914. ULONG cbIssuer;
  9915. PBYTE pbHash;
  9916. PBYTE pb = NULL;
  9917. ULONG cb;
  9918. Any anyValue;
  9919. DWORD cbMessageDigest;
  9920. PBYTE pbMessageDigest;
  9921. ASN1error_e Asn1Err;
  9922. ASN1decoding_t pDec = ICM_GetDecoder();
  9923. CRYPT_DATA_BLOB DataBlob;
  9924. IssuerAndSerialNumber *pisn = NULL;
  9925. CHashNode *pnHash;
  9926. PICM_HASH_INFO pHashInfo;
  9927. switch (pcmi->dwMsgType) {
  9928. case CMSG_SIGNED:
  9929. {
  9930. pc = (Any *)&pcmi->psdi->pci->content;
  9931. cb = pci->SerialNumber.cbData;
  9932. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  9933. goto SerialNumberAllocError;
  9934. cbIssuer = pci->Issuer.cbData;
  9935. for (pSignerNode=pcmi->psdi->pSignerList->Head();
  9936. pSignerNode;
  9937. pSignerNode = pSignerNode->Next()) {
  9938. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9939. psib = NULL;
  9940. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  9941. pisn = NULL;
  9942. DataBlob = pSignerNode->Data()->blob;
  9943. if (0 != (Asn1Err = PkiAsn1Decode(
  9944. pDec,
  9945. (void **)&psib,
  9946. SignerInfoWithBlobs_PDU,
  9947. DataBlob.pbData,
  9948. DataBlob.cbData)))
  9949. goto DecodeSignerInfoWithBlobsError;
  9950. if (0 != (Asn1Err = PkiAsn1Decode(
  9951. pDec,
  9952. (void **)&pisn,
  9953. IssuerAndSerialNumber_PDU,
  9954. (BYTE *) psib->issuerAndSerialNumber.value,
  9955. psib->issuerAndSerialNumber.length)))
  9956. goto DecodeIssuerAndSerialNumberError;
  9957. if (pisn->issuer.length != cbIssuer)
  9958. continue;
  9959. if (0 != memcmp( pci->Issuer.pbData, pisn->issuer.value, cbIssuer))
  9960. continue;
  9961. // We need to add an integer method to compare big-endian
  9962. // internal to a little-endian external value.
  9963. if (pisn->serialNumber.length != cb)
  9964. continue;
  9965. ICM_ReverseCopy( pb, pisn->serialNumber.value, cb);
  9966. if (0 != memcmp( pb, pci->SerialNumber.pbData, cb))
  9967. continue;
  9968. break;
  9969. }
  9970. // The matching signer (if found) is in psib
  9971. // If no signer found, pSignerNode == NULL
  9972. ICM_FreeA( pb);
  9973. pb = NULL;
  9974. break;
  9975. }
  9976. case CMSG_SIGNED_AND_ENVELOPED:
  9977. goto MessageTypeNotSupportedYet;
  9978. default:
  9979. goto InvalidMsgType;
  9980. }
  9981. if (NULL == pSignerNode)
  9982. goto SignerNotFound;
  9983. if (!ICM_FindHashNodeFromEncodedAlgo(
  9984. pcmi->pHashList,
  9985. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  9986. &pnHash))
  9987. goto GetHashNodeFromEncodedAlgoError;
  9988. pHashInfo = pnHash->Data();
  9989. if (pcmi->fDefaultCryptProv)
  9990. hCryptProv = 0;
  9991. else
  9992. hCryptProv = pcmi->hCryptProv;
  9993. if (!ICM_GetVerifySignatureStuff(
  9994. pci,
  9995. &hCryptProv,
  9996. &hPubKey,
  9997. &dwPubKeyAlgId,
  9998. &dwPubKeyFlags)) goto GetSignatureStuffError;
  9999. if (psib->bit_mask & authAttributes_present) {
  10000. // find the message digest attr value
  10001. if (!ICM_GetAttrValue(
  10002. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  10003. &oidMessageDigest,
  10004. &anyValue))
  10005. goto FindAttrError;
  10006. // find the message digest octets
  10007. if (!Asn1UtilExtractContent(
  10008. (BYTE *) anyValue.value,
  10009. anyValue.length,
  10010. &cbMessageDigest,
  10011. (const BYTE **)&pbMessageDigest))
  10012. goto ExtractContentError;
  10013. // get the hash value computed on the data
  10014. if (!ICM_GetListHashValue( pnHash, &cb, &pbHash))
  10015. goto GetHashValueError;
  10016. // hash sizes equal?
  10017. if (cb != cbMessageDigest)
  10018. goto HashCompareSizeError;
  10019. // hash octets equal?
  10020. if (memcmp( pbMessageDigest, pbHash, cb))
  10021. goto HashCompareValueError;
  10022. // Now that we have verified the message digest octets,
  10023. // get the hash of the authenticated attributes.
  10024. // Should check the content type attribute as well.
  10025. if (!ICM_GetAttrsHash(
  10026. pHashInfo->dwAlgoCAPI,
  10027. hCryptProv,
  10028. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  10029. &hHashAttr))
  10030. goto GetAuthAttrsHashError;
  10031. hHash = hHashAttr;
  10032. } else {
  10033. if (!ICM_DupListHash( pnHash, hCryptProv, &hHashDup))
  10034. goto DupListHashError;
  10035. hHash = hHashDup;
  10036. }
  10037. // verify the hash, signature, and public key are consistent
  10038. fRet = ICM_VerifySignature(
  10039. hHash,
  10040. hPubKey,
  10041. dwPubKeyAlgId,
  10042. dwPubKeyFlags,
  10043. psib->encryptedDigest.value,
  10044. psib->encryptedDigest.length);
  10045. if (!fRet && hHashAttr) {
  10046. // The hash of the authenticated attributes failed.
  10047. // Maybe they hashed incorrectly-DER-encoded authenticated attributes
  10048. // and gave us that encoding. Hash and verify the actual encoding of
  10049. // the authattrs that they gave us. There is a bug in IE3.0 which hits
  10050. // this path, due to a bug in the then-current OSS libraries.
  10051. fRet = ICM_VerifySignatureAuthAttrBlob(
  10052. pcmi,
  10053. pSignerNode,
  10054. hCryptProv,
  10055. hPubKey,
  10056. pHashInfo->dwAlgoCAPI,
  10057. dwPubKeyAlgId,
  10058. dwPubKeyFlags,
  10059. psib->encryptedDigest.value,
  10060. psib->encryptedDigest.length);
  10061. }
  10062. if (!fRet)
  10063. goto VerifySignatureError;
  10064. CommonReturn:
  10065. ICM_FreeA( pb);
  10066. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  10067. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  10068. if (hPubKey)
  10069. CryptDestroyKey(hPubKey);
  10070. if (hHashAttr)
  10071. CryptDestroyHash( hHashAttr);
  10072. if (hHashDup)
  10073. CryptDestroyHash( hHashDup);
  10074. ICM_SetLastError(dwError);
  10075. return fRet;
  10076. ErrorReturn:
  10077. dwError = GetLastError();
  10078. // if (hHash && (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)))
  10079. // CryptDestroyHash( hHash);
  10080. fRet = FALSE;
  10081. goto CommonReturn;
  10082. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  10083. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  10084. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  10085. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  10086. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  10087. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  10088. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  10089. SET_ERROR_VAR(DecodeIssuerAndSerialNumberError, PkiAsn1ErrToHr(Asn1Err))
  10090. SET_ERROR(SignerNotFound,CRYPT_E_SIGNER_NOT_FOUND)
  10091. TRACE_ERROR(SerialNumberAllocError) // error already set
  10092. TRACE_ERROR(GetHashValueError) // error already set
  10093. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  10094. TRACE_ERROR(GetSignatureStuffError) // error already set
  10095. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  10096. TRACE_ERROR(DupListHashError) // error already set
  10097. TRACE_ERROR(VerifySignatureError) // error already set
  10098. dwFlags;
  10099. }
  10100. #endif // CMS_PKCS7
  10101. //+-------------------------------------------------------------------------
  10102. // Verify a digest
  10103. //--------------------------------------------------------------------------
  10104. BOOL
  10105. WINAPI
  10106. ICM_ControlVerifyDigest(
  10107. IN PCRYPT_MSG_INFO pcmi,
  10108. IN DWORD dwFlags)
  10109. {
  10110. DWORD dwError = ERROR_SUCCESS;
  10111. BOOL fRet;
  10112. BYTE *pbComputedDigest = NULL;
  10113. DWORD cbComputedDigest = 0;
  10114. BYTE *pbDigest = NULL;
  10115. DWORD cbDigest = 0;
  10116. if (CMSG_HASHED != pcmi->dwMsgType)
  10117. goto InvalidMsgTypeError;
  10118. // get the computed digest
  10119. CryptMsgGetParam(
  10120. (HCRYPTMSG)pcmi,
  10121. CMSG_COMPUTED_HASH_PARAM,
  10122. 0, // dwIndex
  10123. NULL, // pvData
  10124. &cbComputedDigest);
  10125. if (0 == cbComputedDigest)
  10126. goto EmptyComputedDigestError;
  10127. if (NULL == (pbComputedDigest = (PBYTE)ICM_AllocA( cbComputedDigest)))
  10128. goto ComputedDigestAllocError;
  10129. if (!CryptMsgGetParam(
  10130. (HCRYPTMSG)pcmi,
  10131. CMSG_COMPUTED_HASH_PARAM,
  10132. 0, // dwIndex
  10133. pbComputedDigest,
  10134. &cbComputedDigest))
  10135. goto GetComputedDigestError;
  10136. // get the digest from the message
  10137. CryptMsgGetParam(
  10138. (HCRYPTMSG)pcmi,
  10139. CMSG_HASH_DATA_PARAM,
  10140. 0, // dwIndex
  10141. NULL, // pvData
  10142. &cbDigest);
  10143. if (0 == cbDigest)
  10144. goto EmptyDigestError;
  10145. if (NULL == (pbDigest = (PBYTE)ICM_AllocA( cbDigest)))
  10146. goto DigestAllocError;
  10147. if (!CryptMsgGetParam(
  10148. (HCRYPTMSG)pcmi,
  10149. CMSG_HASH_DATA_PARAM,
  10150. 0, // dwIndex
  10151. pbDigest,
  10152. &cbDigest))
  10153. goto GetDigestError;
  10154. // compare the computed digest to the digest from the message
  10155. if (cbComputedDigest != cbDigest)
  10156. goto DigestSizesUnequalError;
  10157. if (0 != memcmp( pbDigest, pbComputedDigest, cbDigest))
  10158. goto DigestsDifferError;
  10159. fRet = TRUE;
  10160. CommonReturn:
  10161. ICM_FreeA( pbComputedDigest);
  10162. ICM_FreeA( pbDigest);
  10163. ICM_SetLastError(dwError);
  10164. return fRet;
  10165. ErrorReturn:
  10166. dwError = GetLastError();
  10167. fRet = FALSE;
  10168. goto CommonReturn;
  10169. TRACE_ERROR(EmptyComputedDigestError) // error already set
  10170. TRACE_ERROR(ComputedDigestAllocError) // error already set
  10171. TRACE_ERROR(GetComputedDigestError) // error already set
  10172. TRACE_ERROR(EmptyDigestError) // error already set
  10173. TRACE_ERROR(DigestAllocError) // error already set
  10174. TRACE_ERROR(GetDigestError) // error already set
  10175. SET_ERROR(DigestSizesUnequalError,CRYPT_E_HASH_VALUE)
  10176. SET_ERROR(DigestsDifferError,CRYPT_E_HASH_VALUE)
  10177. SET_ERROR(InvalidMsgTypeError,CRYPT_E_INVALID_MSG_TYPE)
  10178. dwFlags;
  10179. }
  10180. #ifdef CMS_PKCS7
  10181. CmsRecipientInfos *
  10182. WINAPI
  10183. ICM_GetDecodedCmsRecipientInfos(
  10184. IN PCRYPT_MSG_INFO pcmi
  10185. )
  10186. {
  10187. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  10188. CmsRecipientInfos *pris = NULL;
  10189. if (pcmi->fEncoding)
  10190. goto InvalidMsgType;
  10191. if (pcsi && (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  10192. goto StreamMsgNotReadyError;
  10193. if (NULL == pcmi->pvMsg)
  10194. goto NotUpdated;
  10195. switch (pcmi->dwMsgType) {
  10196. case CMSG_ENVELOPED:
  10197. pris = &((CmsEnvelopedData *)pcmi->pvMsg)->recipientInfos;
  10198. break;
  10199. case CMSG_SIGNED_AND_ENVELOPED:
  10200. goto MessageTypeNotSupportedYet;
  10201. default:
  10202. goto InvalidMsgType;
  10203. }
  10204. CommonReturn:
  10205. return pris;
  10206. ErrorReturn:
  10207. goto CommonReturn;
  10208. SET_ERROR(InvalidMsgType, CRYPT_E_INVALID_MSG_TYPE)
  10209. SET_ERROR(NotUpdated, CRYPT_E_INVALID_MSG_TYPE)
  10210. SET_ERROR(StreamMsgNotReadyError, CRYPT_E_STREAM_MSG_NOT_READY)
  10211. SET_ERROR(MessageTypeNotSupportedYet, CRYPT_E_INVALID_MSG_TYPE)
  10212. }
  10213. BOOL
  10214. WINAPI
  10215. ICM_ConvertPkcsToCmsRecipientIndex(
  10216. IN PCRYPT_MSG_INFO pcmi,
  10217. IN DWORD dwPkcsIndex,
  10218. OUT DWORD *pdwCmsIndex
  10219. )
  10220. {
  10221. BOOL fRet;
  10222. CmsRecipientInfos *pris;
  10223. CmsRecipientInfo *pri;
  10224. DWORD dwCount;
  10225. DWORD dwCmsIndex;
  10226. DWORD i;
  10227. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10228. goto GetDecodedCmsRecipientsError;
  10229. dwCount = pris->count;
  10230. pri = pris->value;
  10231. dwCmsIndex = dwPkcsIndex;
  10232. i = 0;
  10233. for ( ; 0 < dwCount; dwCount--, pri++) {
  10234. if (keyTransRecipientInfo_chosen != pri->choice) {
  10235. // Advance past non KeyTrans recipients
  10236. dwCmsIndex++;
  10237. } else {
  10238. if (i == dwPkcsIndex)
  10239. goto SuccessReturn;
  10240. else
  10241. i++;
  10242. }
  10243. }
  10244. goto IndexTooBig;
  10245. SuccessReturn:
  10246. fRet = TRUE;
  10247. CommonReturn:
  10248. *pdwCmsIndex = dwCmsIndex;
  10249. return fRet;
  10250. ErrorReturn:
  10251. fRet = FALSE;
  10252. dwCmsIndex = 0xFFFFFFFF;
  10253. goto CommonReturn;
  10254. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10255. SET_ERROR(IndexTooBig, CRYPT_E_INVALID_INDEX)
  10256. }
  10257. BOOL
  10258. WINAPI
  10259. ICM_ConvertCmsToPkcsRecipientIndex(
  10260. IN PCRYPT_MSG_INFO pcmi,
  10261. IN DWORD dwCmsIndex,
  10262. OUT DWORD *pdwPkcsIndex
  10263. )
  10264. {
  10265. BOOL fRet;
  10266. CmsRecipientInfos *pris;
  10267. CmsRecipientInfo *pri;
  10268. DWORD dwCount;
  10269. DWORD dwPkcsIndex;
  10270. DWORD i;
  10271. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10272. goto GetDecodedCmsRecipientsError;
  10273. dwCount = pris->count;
  10274. if (dwCmsIndex >= dwCount)
  10275. goto InvalidCmsIndex;
  10276. pri = &pris->value[dwCmsIndex];
  10277. if (keyTransRecipientInfo_chosen != pri->choice)
  10278. goto InvalidPkcsIndex;
  10279. pri = pris->value;
  10280. dwPkcsIndex = 0;
  10281. for (i = 0; i < dwCmsIndex; i++, pri++) {
  10282. if (keyTransRecipientInfo_chosen == pri->choice)
  10283. dwPkcsIndex++;
  10284. }
  10285. fRet = TRUE;
  10286. CommonReturn:
  10287. *pdwPkcsIndex = dwPkcsIndex;
  10288. return fRet;
  10289. ErrorReturn:
  10290. fRet = FALSE;
  10291. dwPkcsIndex = 0xFFFFFFFF;
  10292. goto CommonReturn;
  10293. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10294. SET_ERROR(InvalidCmsIndex, CRYPT_E_INVALID_INDEX)
  10295. SET_ERROR(InvalidPkcsIndex, CRYPT_E_INVALID_INDEX)
  10296. }
  10297. BOOL
  10298. WINAPI
  10299. ICM_GetPkcsRecipientCount(
  10300. IN PCRYPT_MSG_INFO pcmi,
  10301. OUT DWORD *pdwPkcsCount
  10302. )
  10303. {
  10304. BOOL fRet;
  10305. CmsRecipientInfos *pris;
  10306. CmsRecipientInfo *pri;
  10307. DWORD dwCount;
  10308. DWORD dwPkcsCount;
  10309. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10310. goto GetDecodedCmsRecipientsError;
  10311. dwCount = pris->count;
  10312. pri = pris->value;
  10313. dwPkcsCount = 0;
  10314. for ( ; 0 < dwCount; dwCount--, pri++) {
  10315. if (keyTransRecipientInfo_chosen == pri->choice)
  10316. dwPkcsCount++;
  10317. }
  10318. fRet = TRUE;
  10319. CommonReturn:
  10320. *pdwPkcsCount = dwPkcsCount;
  10321. return fRet;
  10322. ErrorReturn:
  10323. dwPkcsCount = 0;
  10324. fRet = FALSE;
  10325. goto CommonReturn;
  10326. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10327. }
  10328. typedef BOOL (WINAPI *PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) (
  10329. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10330. IN void *pvDecryptPara,
  10331. IN DWORD dwFlags,
  10332. IN OPTIONAL void *pvReserved,
  10333. OUT HCRYPTKEY *phContentEncryptKey
  10334. );
  10335. BOOL
  10336. WINAPI
  10337. ICM_ImportContentEncryptKey(
  10338. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10339. IN void *pvDecryptPara,
  10340. IN HCRYPTOIDFUNCADDR hImportContentEncryptKeyFuncSet,
  10341. IN LPSTR pszKeyEncryptionOID,
  10342. IN PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY pDefaultImportContentEncryptKey,
  10343. OUT HCRYPTKEY *phContentEncryptKey
  10344. )
  10345. {
  10346. BOOL fRet;
  10347. DWORD i;
  10348. #define IMPORT_CONTENT_ENCRYPT_OID_CNT 3
  10349. LPSTR rgpszOID[IMPORT_CONTENT_ENCRYPT_OID_CNT] = {
  10350. NULL, // pszKeyEncryptOID!pszContentEncryptOID
  10351. pszKeyEncryptionOID,
  10352. pContentEncryptionAlgorithm->pszObjId
  10353. };
  10354. DWORD cch;
  10355. LPSTR psz;
  10356. cch = strlen(rgpszOID[1]) + 1 + strlen(rgpszOID[2]) + 1;
  10357. if (NULL == (psz = (LPSTR) ICM_Alloc(cch))) {
  10358. *phContentEncryptKey = 0;
  10359. return FALSE;
  10360. }
  10361. strcpy(psz, rgpszOID[1]);
  10362. strcat(psz, "!");
  10363. strcat(psz, rgpszOID[2]);
  10364. rgpszOID[0] = psz;
  10365. for (i = 0; i < IMPORT_CONTENT_ENCRYPT_OID_CNT; i++) {
  10366. void *pvFuncAddr;
  10367. HCRYPTOIDFUNCADDR hFuncAddr;
  10368. if (CryptGetOIDFunctionAddress(
  10369. hImportContentEncryptKeyFuncSet,
  10370. X509_ASN_ENCODING,
  10371. rgpszOID[i],
  10372. 0, // dwFlags
  10373. &pvFuncAddr,
  10374. &hFuncAddr)) {
  10375. fRet = ((PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) pvFuncAddr)(
  10376. pContentEncryptionAlgorithm,
  10377. pvDecryptPara,
  10378. 0, // dwFlags
  10379. NULL, // pvReserved
  10380. phContentEncryptKey
  10381. );
  10382. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  10383. if (fRet || E_NOTIMPL != GetLastError())
  10384. goto CommonReturn;
  10385. }
  10386. }
  10387. fRet = pDefaultImportContentEncryptKey(
  10388. pContentEncryptionAlgorithm,
  10389. pvDecryptPara,
  10390. 0, // dwFlags
  10391. NULL, // pvReserved
  10392. phContentEncryptKey
  10393. );
  10394. CommonReturn:
  10395. ICM_Free(rgpszOID[0]);
  10396. return fRet;
  10397. }
  10398. HCRYPTKEY
  10399. WINAPI
  10400. ICM_ImportEncryptedKey(
  10401. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10402. IN HCRYPTPROV hCryptProv,
  10403. IN HCRYPTKEY hUserKey,
  10404. IN ALG_ID aiEncAlg,
  10405. IN BYTE bType,
  10406. IN PCRYPT_DATA_BLOB pEncryptedKey
  10407. )
  10408. {
  10409. BOOL fRet;
  10410. DWORD dwError;
  10411. HCRYPTKEY hEncryptKey = 0;
  10412. DWORD dwAlgIdEncrypt;
  10413. DWORD dwBitLen;
  10414. BYTE rgbIV[IV_MAX_LENGTH];
  10415. DWORD cbIV;
  10416. PBYTE pbCspKey = NULL;
  10417. DWORD cbCspKey;
  10418. PUBLICKEYSTRUC *ppks;
  10419. PSIMPLEBLOBHEADER psbh;
  10420. if (!ICM_GetEncryptParameters(
  10421. pContentEncryptionAlgorithm,
  10422. &dwAlgIdEncrypt,
  10423. &dwBitLen,
  10424. rgbIV,
  10425. &cbIV))
  10426. goto GetEncryptParametersError;
  10427. cbCspKey = sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER) +
  10428. pEncryptedKey->cbData;
  10429. if (NULL == (pbCspKey = (PBYTE)ICM_AllocA( cbCspKey)))
  10430. goto CspKeyAllocError;
  10431. ppks = (PUBLICKEYSTRUC *)pbCspKey;
  10432. ppks->bType = bType;
  10433. ppks->bVersion = CUR_BLOB_VERSION;
  10434. ppks->reserved = 0;
  10435. ppks->aiKeyAlg = dwAlgIdEncrypt;
  10436. psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
  10437. psbh->aiEncAlg = aiEncAlg;
  10438. if (SYMMETRICWRAPKEYBLOB == bType)
  10439. memcpy( (PBYTE)(psbh+1), pEncryptedKey->pbData,
  10440. pEncryptedKey->cbData);
  10441. else
  10442. ICM_ReverseCopy( (PBYTE)(psbh+1), pEncryptedKey->pbData,
  10443. pEncryptedKey->cbData);
  10444. fRet = CryptImportKey(
  10445. hCryptProv,
  10446. pbCspKey,
  10447. cbCspKey,
  10448. hUserKey,
  10449. CRYPT_NO_SALT, // dwFlags
  10450. &hEncryptKey);
  10451. if (!fRet) {
  10452. hEncryptKey = 0;
  10453. goto ImportKeyFailed;
  10454. }
  10455. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  10456. // Silently ignore any errors. Not supported in earlier versions
  10457. CryptSetKeyParam(
  10458. hEncryptKey,
  10459. KP_EFFECTIVE_KEYLEN,
  10460. (PBYTE) &dwBitLen,
  10461. 0); // dwFlags
  10462. if (0 != cbIV) {
  10463. if (CALG_RC4 == dwAlgIdEncrypt) {
  10464. // For RC4, set the SALT, not the IV
  10465. BOOL fRC4Salt = TRUE;
  10466. if (IV_LENGTH == cbIV) {
  10467. // Old implementations of 40 bit or 128 bit RC4 set the
  10468. // IV which was ignored and didn't set the salt.
  10469. // Get the bit length of the imported key and don't
  10470. // set the salt for 40 or 128 bit RC4.
  10471. DWORD dwRC4BitLen;
  10472. DWORD cbKeyParamLen;
  10473. dwRC4BitLen = 0;
  10474. cbKeyParamLen = sizeof(dwRC4BitLen);
  10475. if (!CryptGetKeyParam(
  10476. hEncryptKey,
  10477. KP_KEYLEN,
  10478. (PBYTE) &dwRC4BitLen,
  10479. &cbKeyParamLen,
  10480. 0 // dwFlags
  10481. ) || 40 == dwRC4BitLen || 128 == dwRC4BitLen)
  10482. fRC4Salt = FALSE;
  10483. }
  10484. if (fRC4Salt) {
  10485. CRYPT_DATA_BLOB SaltBlob;
  10486. SaltBlob.pbData = rgbIV;
  10487. SaltBlob.cbData = cbIV;
  10488. if (!CryptSetKeyParam(
  10489. hEncryptKey,
  10490. KP_SALT_EX,
  10491. (PBYTE) &SaltBlob,
  10492. 0)) // dwFlags
  10493. goto SetSaltExError;
  10494. }
  10495. } else {
  10496. if (!CryptSetKeyParam(
  10497. hEncryptKey,
  10498. KP_IV,
  10499. rgbIV,
  10500. 0)) // dwFlags
  10501. goto SetIVError;
  10502. }
  10503. }
  10504. CommonReturn:
  10505. ICM_FreeA(pbCspKey);
  10506. return hEncryptKey;
  10507. ErrorReturn:
  10508. if (hEncryptKey) {
  10509. dwError = GetLastError();
  10510. CryptDestroyKey(hEncryptKey);
  10511. SetLastError(dwError);
  10512. hEncryptKey = 0;
  10513. }
  10514. goto CommonReturn;
  10515. TRACE_ERROR(GetEncryptParametersError)
  10516. TRACE_ERROR(ImportKeyFailed)
  10517. TRACE_ERROR(CspKeyAllocError)
  10518. TRACE_ERROR(SetSaltExError)
  10519. TRACE_ERROR(SetIVError)
  10520. }
  10521. //+-------------------------------------------------------------------------
  10522. //--------------------------------------------------------------------------
  10523. BOOL
  10524. WINAPI
  10525. #ifdef DEBUG_CRYPT_ASN1
  10526. ICMTest_DefaultImportKeyTrans(
  10527. #else
  10528. ICM_DefaultImportKeyTrans(
  10529. #endif
  10530. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10531. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  10532. IN DWORD dwFlags,
  10533. IN OPTIONAL void *pvReserved,
  10534. OUT HCRYPTKEY *phContentEncryptKey
  10535. )
  10536. {
  10537. DWORD dwError = ERROR_SUCCESS;
  10538. BOOL fRet;
  10539. HCRYPTKEY hUserKey = 0;
  10540. PCMSG_KEY_TRANS_RECIPIENT_INFO pri = pKeyTransDecryptPara->pKeyTrans;
  10541. HCRYPTPROV hCryptProv = pKeyTransDecryptPara->hCryptProv;
  10542. void *pvFuncAddr;
  10543. HCRYPTOIDFUNCADDR hFuncAddr;
  10544. if (CryptGetOIDFunctionAddress(
  10545. hOldStyleImportEncryptKeyFuncSet,
  10546. X509_ASN_ENCODING,
  10547. pContentEncryptionAlgorithm->pszObjId,
  10548. 0, // dwFlags
  10549. &pvFuncAddr,
  10550. &hFuncAddr)) {
  10551. if ((void *) ICM_DefaultImportEncryptKey == pvFuncAddr)
  10552. fRet = FALSE;
  10553. #ifdef DEBUG_CRYPT_ASN1
  10554. else if (0 == (ICMTest_GetDebugCryptAsn1Flags() &
  10555. DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  10556. fRet = FALSE;
  10557. #endif // DEBUG_CRYPT_ASN1
  10558. else
  10559. fRet = ((PFN_CMSG_IMPORT_ENCRYPT_KEY) pvFuncAddr)(
  10560. hCryptProv,
  10561. pKeyTransDecryptPara->dwKeySpec,
  10562. pContentEncryptionAlgorithm,
  10563. &pri->KeyEncryptionAlgorithm,
  10564. pri->EncryptedKey.pbData,
  10565. pri->EncryptedKey.cbData,
  10566. phContentEncryptKey);
  10567. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  10568. if (fRet)
  10569. return TRUE;
  10570. }
  10571. if (0 != pKeyTransDecryptPara->dwKeySpec) {
  10572. // Get private key to use.
  10573. if (!CryptGetUserKey(
  10574. hCryptProv,
  10575. pKeyTransDecryptPara->dwKeySpec,
  10576. &hUserKey)) {
  10577. hUserKey = 0;
  10578. goto GetUserKeyFailed;
  10579. }
  10580. }
  10581. // else
  10582. // Use the provider's default private key for decrypting
  10583. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10584. pContentEncryptionAlgorithm,
  10585. hCryptProv,
  10586. hUserKey,
  10587. CALG_RSA_KEYX,
  10588. SIMPLEBLOB,
  10589. &pri->EncryptedKey
  10590. )))
  10591. goto ImportEncryptedKeyError;
  10592. fRet = TRUE;
  10593. CommonReturn:
  10594. if (hUserKey)
  10595. CryptDestroyKey(hUserKey);
  10596. ICM_SetLastError(dwError);
  10597. return fRet;
  10598. ErrorReturn:
  10599. dwError = GetLastError();
  10600. fRet = FALSE;
  10601. goto CommonReturn;
  10602. TRACE_ERROR(GetUserKeyFailed)
  10603. TRACE_ERROR(ImportEncryptedKeyError)
  10604. }
  10605. //+-------------------------------------------------------------------------
  10606. //--------------------------------------------------------------------------
  10607. BOOL
  10608. WINAPI
  10609. ICM_DefaultImportKeyAgree(
  10610. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10611. IN PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA pKeyAgreeDecryptPara,
  10612. IN DWORD dwFlags,
  10613. IN OPTIONAL void *pvReserved,
  10614. OUT HCRYPTKEY *phContentEncryptKey
  10615. )
  10616. {
  10617. BOOL fRet;
  10618. DWORD dwError = ERROR_SUCCESS;
  10619. HCRYPTPROV hKeyAgreeProv = 0; // Doesn't need to be released
  10620. HCRYPTKEY hMyKey = 0;
  10621. HCRYPTKEY hAgreeKey = 0;
  10622. DWORD cbP;
  10623. DWORD dwKeySpec;
  10624. LPSTR pszWrapOID = NULL;
  10625. DWORD dwAlgIdWrap;
  10626. DWORD dwBitLen;
  10627. PCMSG_KEY_AGREE_RECIPIENT_INFO pri = pKeyAgreeDecryptPara->pKeyAgree;
  10628. hKeyAgreeProv = pKeyAgreeDecryptPara->hCryptProv;
  10629. dwKeySpec = pKeyAgreeDecryptPara->dwKeySpec;
  10630. if (0 == dwKeySpec)
  10631. dwKeySpec = AT_KEYEXCHANGE;
  10632. // Get my private Diffie Hellman key
  10633. if (!CryptGetUserKey(
  10634. hKeyAgreeProv,
  10635. pKeyAgreeDecryptPara->dwKeySpec,
  10636. &hMyKey)) {
  10637. hMyKey = 0;
  10638. goto GetMyKeyFailed;
  10639. }
  10640. // Get the length of P
  10641. cbP = 0;
  10642. if (!CryptGetKeyParam(
  10643. hMyKey,
  10644. KP_P,
  10645. NULL, // pbData
  10646. &cbP,
  10647. 0 // dwFlags
  10648. ) || 0 == cbP)
  10649. goto GetPLengthError;
  10650. if (!ICM_GetDhWrapEncryptParameters(
  10651. &pri->KeyEncryptionAlgorithm,
  10652. &pszWrapOID, // allocated
  10653. &dwAlgIdWrap,
  10654. &dwBitLen))
  10655. goto GetDhWrapEncryptParametersError;
  10656. if (0 == (hAgreeKey = ICM_ImportDhAgreeKey(
  10657. hKeyAgreeProv,
  10658. hMyKey,
  10659. cbP,
  10660. &pKeyAgreeDecryptPara->OriginatorPublicKey,
  10661. pszWrapOID,
  10662. dwAlgIdWrap,
  10663. dwBitLen,
  10664. &pri->UserKeyingMaterial
  10665. )))
  10666. goto ImportDhAgreeKeyError;
  10667. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10668. pContentEncryptionAlgorithm,
  10669. hKeyAgreeProv,
  10670. hAgreeKey,
  10671. dwAlgIdWrap,
  10672. SYMMETRICWRAPKEYBLOB,
  10673. &pri->rgpRecipientEncryptedKeys[
  10674. pKeyAgreeDecryptPara->dwRecipientEncryptedKeyIndex]->EncryptedKey
  10675. )))
  10676. goto ImportEncryptedKeyError;
  10677. fRet = TRUE;
  10678. CommonReturn:
  10679. ICM_Free(pszWrapOID);
  10680. if (hAgreeKey)
  10681. CryptDestroyKey(hAgreeKey);
  10682. if (hMyKey)
  10683. CryptDestroyKey(hMyKey);
  10684. ICM_SetLastError(dwError);
  10685. return fRet;
  10686. ErrorReturn:
  10687. dwError = GetLastError();
  10688. fRet = FALSE;
  10689. goto CommonReturn;
  10690. TRACE_ERROR(GetMyKeyFailed)
  10691. TRACE_ERROR(GetPLengthError)
  10692. TRACE_ERROR(GetDhWrapEncryptParametersError)
  10693. TRACE_ERROR(ImportDhAgreeKeyError)
  10694. TRACE_ERROR(ImportEncryptedKeyError)
  10695. }
  10696. //+-------------------------------------------------------------------------
  10697. //--------------------------------------------------------------------------
  10698. BOOL
  10699. WINAPI
  10700. ICM_DefaultImportMailList(
  10701. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10702. IN PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA pMailListDecryptPara,
  10703. IN DWORD dwFlags,
  10704. IN OPTIONAL void *pvReserved,
  10705. OUT HCRYPTKEY *phContentEncryptKey
  10706. )
  10707. {
  10708. BOOL fRet;
  10709. DWORD dwError = ERROR_SUCCESS;
  10710. HCRYPTPROV hMailListProv = 0; // not released
  10711. HCRYPTKEY hKeyEncryptionKey = 0; // not destroyed
  10712. PCMSG_MAIL_LIST_RECIPIENT_INFO pri = pMailListDecryptPara->pMailList;
  10713. DWORD dwAlgIdEncrypt;
  10714. DWORD dwBitLen;
  10715. hMailListProv = pMailListDecryptPara->hCryptProv;
  10716. switch (pMailListDecryptPara->dwKeyChoice) {
  10717. case CMSG_MAIL_LIST_HANDLE_KEY_CHOICE:
  10718. hKeyEncryptionKey = pMailListDecryptPara->hKeyEncryptionKey;
  10719. assert(hMailListProv && hKeyEncryptionKey);
  10720. if (0 == hMailListProv || 0 == hKeyEncryptionKey)
  10721. goto InvalidMailListHandleKeyPara;
  10722. break;
  10723. default:
  10724. goto InvalidMailListKeyChoice;
  10725. }
  10726. if (!ICM_GetWrapEncryptParameters(
  10727. &pri->KeyEncryptionAlgorithm,
  10728. &dwAlgIdEncrypt,
  10729. &dwBitLen))
  10730. goto GetWrapEncryptParametersError;
  10731. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  10732. // Silently ignore any errors. Not supported in earlier versions
  10733. CryptSetKeyParam(
  10734. hKeyEncryptionKey,
  10735. KP_EFFECTIVE_KEYLEN,
  10736. (PBYTE) &dwBitLen,
  10737. 0); // dwFlags
  10738. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10739. pContentEncryptionAlgorithm,
  10740. hMailListProv,
  10741. hKeyEncryptionKey,
  10742. dwAlgIdEncrypt,
  10743. SYMMETRICWRAPKEYBLOB,
  10744. &pri->EncryptedKey
  10745. )))
  10746. goto ImportEncryptedKeyError;
  10747. fRet = TRUE;
  10748. CommonReturn:
  10749. ICM_SetLastError(dwError);
  10750. return fRet;
  10751. ErrorReturn:
  10752. dwError = GetLastError();
  10753. fRet = FALSE;
  10754. goto CommonReturn;
  10755. SET_ERROR(InvalidMailListHandleKeyPara, E_INVALIDARG)
  10756. SET_ERROR(InvalidMailListKeyChoice, E_INVALIDARG)
  10757. TRACE_ERROR(GetWrapEncryptParametersError)
  10758. TRACE_ERROR(ImportEncryptedKeyError)
  10759. }
  10760. //+-------------------------------------------------------------------------
  10761. // Default import of the encryption key (OldStyle)
  10762. //--------------------------------------------------------------------------
  10763. BOOL
  10764. WINAPI
  10765. ICM_DefaultImportEncryptKey(
  10766. IN HCRYPTPROV hCryptProv,
  10767. IN DWORD dwKeySpec,
  10768. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  10769. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  10770. IN PBYTE pbEncodedKey,
  10771. IN DWORD cbEncodedKey,
  10772. OUT HCRYPTKEY *phEncryptKey)
  10773. {
  10774. DWORD dwError = ERROR_SUCCESS;
  10775. BOOL fRet;
  10776. HCRYPTKEY hUserKey = 0;
  10777. CRYPT_DATA_BLOB EncryptedKey;
  10778. if (0 != dwKeySpec) {
  10779. // Get private key to use.
  10780. if (!CryptGetUserKey(
  10781. hCryptProv,
  10782. dwKeySpec,
  10783. &hUserKey)) {
  10784. hUserKey = 0;
  10785. goto GetUserKeyFailed;
  10786. }
  10787. }
  10788. // else
  10789. // Use the provider's default private key for decrypting
  10790. EncryptedKey.cbData = cbEncodedKey;
  10791. EncryptedKey.pbData = pbEncodedKey;
  10792. if (0 == (*phEncryptKey = ICM_ImportEncryptedKey(
  10793. paiEncrypt,
  10794. hCryptProv,
  10795. hUserKey,
  10796. CALG_RSA_KEYX,
  10797. SIMPLEBLOB,
  10798. &EncryptedKey
  10799. )))
  10800. goto ImportEncryptedKeyError;
  10801. fRet = TRUE;
  10802. CommonReturn:
  10803. if (hUserKey)
  10804. CryptDestroyKey(hUserKey);
  10805. ICM_SetLastError(dwError);
  10806. return fRet;
  10807. ErrorReturn:
  10808. dwError = GetLastError();
  10809. fRet = FALSE;
  10810. goto CommonReturn;
  10811. TRACE_ERROR(GetUserKeyFailed)
  10812. TRACE_ERROR(ImportEncryptedKeyError)
  10813. }
  10814. //+-------------------------------------------------------------------------
  10815. // Decrypt the content using any CMS recipient type
  10816. //--------------------------------------------------------------------------
  10817. BOOL
  10818. WINAPI
  10819. ICM_ControlCmsDecrypt(
  10820. IN PCRYPT_MSG_INFO pcmi,
  10821. IN DWORD dwFlags,
  10822. IN void *pvDecryptPara,
  10823. IN HCRYPTPROV hCryptProv,
  10824. IN DWORD dwRecipientIndex,
  10825. IN HCRYPTOIDFUNCADDR hImportContentEncryptKeyFuncSet,
  10826. IN LPSTR pszKeyEncryptionOID,
  10827. IN PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY pDefaultImportContentEncryptKey
  10828. )
  10829. {
  10830. DWORD dwError = ERROR_SUCCESS;
  10831. BOOL fRet;
  10832. EncryptedContentInfo *peci = NULL;
  10833. HCRYPTKEY hkeySeal = NULL;
  10834. PBYTE pbData = NULL;
  10835. LONG cbData;
  10836. AlgorithmIdentifier *paiOssContentEncryption;
  10837. PCRYPT_ALGORITHM_IDENTIFIER paiContentEncryption = NULL;
  10838. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  10839. if( pcmi->Plaintext.pbData)
  10840. goto MessageAlreadyDecrypted;
  10841. switch (pcmi->dwMsgType) {
  10842. case CMSG_ENVELOPED:
  10843. {
  10844. CmsEnvelopedData *ped;
  10845. ped = (CmsEnvelopedData *)pcmi->pvMsg;
  10846. if (NULL == ped)
  10847. goto NotUpdated;
  10848. if (dwRecipientIndex >= ped->recipientInfos.count)
  10849. goto RecipientIndexTooLarge;
  10850. peci = &ped->encryptedContentInfo;
  10851. paiOssContentEncryption =
  10852. &ped->encryptedContentInfo.contentEncryptionAlgorithm;
  10853. break;
  10854. }
  10855. case CMSG_SIGNED_AND_ENVELOPED:
  10856. goto MessageTypeNotSupportedYet;
  10857. default:
  10858. goto InvalidMsgType;
  10859. }
  10860. if (NULL == (paiContentEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  10861. paiOssContentEncryption)))
  10862. goto GetEncryptAlgorithmError;
  10863. if (!ICM_ImportContentEncryptKey(
  10864. paiContentEncryption,
  10865. pvDecryptPara,
  10866. hImportContentEncryptKeyFuncSet,
  10867. pszKeyEncryptionOID,
  10868. pDefaultImportContentEncryptKey,
  10869. &hkeySeal))
  10870. goto ImportKeyError;
  10871. if (pcsi) {
  10872. if (!ICMS_SetDecryptKey( pcmi, hkeySeal))
  10873. goto SetDecryptKeyError; // NB- Do not trash err from callback!
  10874. hkeySeal = NULL;
  10875. } else {
  10876. // NB- For common bulk encryption algos,
  10877. // sizeof(plaintext)<=sizeof(ciphertext)
  10878. if (peci->bit_mask & encryptedContent_present)
  10879. cbData = peci->encryptedContent.length;
  10880. else
  10881. cbData = 0;
  10882. if (NULL == (pbData = (PBYTE)ICM_Alloc( cbData)))
  10883. goto EncryptedContentAllocError;
  10884. if (cbData ) {
  10885. memcpy( pbData, peci->encryptedContent.value, cbData);
  10886. if (!CryptDecrypt(
  10887. hkeySeal,
  10888. NULL,
  10889. TRUE, // fFinal
  10890. 0, // dwFlags
  10891. pbData,
  10892. (PDWORD)&cbData))
  10893. goto DecryptError;
  10894. }
  10895. CryptDestroyKey( hkeySeal);
  10896. hkeySeal = NULL;
  10897. pcmi->Plaintext.cbData = cbData;
  10898. pcmi->Plaintext.pbData = pbData;
  10899. pbData = NULL;
  10900. }
  10901. if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
  10902. pcmi->hCryptProvContentCrypt = hCryptProv;
  10903. pcmi->dwDecryptedRecipientIndex = dwRecipientIndex;
  10904. fRet = TRUE;
  10905. CommonReturn:
  10906. ICM_Free(paiContentEncryption);
  10907. ICM_Free(pbData);
  10908. if (hkeySeal)
  10909. CryptDestroyKey( hkeySeal);
  10910. ICM_SetLastError(dwError);
  10911. return fRet;
  10912. ErrorReturn:
  10913. dwError = GetLastError();
  10914. fRet = FALSE;
  10915. goto CommonReturn;
  10916. SET_ERROR(MessageAlreadyDecrypted,CRYPT_E_ALREADY_DECRYPTED)
  10917. SET_ERROR(RecipientIndexTooLarge, CRYPT_E_INVALID_INDEX)
  10918. SET_ERROR(NotUpdated, CRYPT_E_INVALID_MSG_TYPE)
  10919. SET_ERROR(InvalidMsgType, CRYPT_E_INVALID_MSG_TYPE)
  10920. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  10921. TRACE_ERROR(GetEncryptAlgorithmError)
  10922. TRACE_ERROR(ImportKeyError)
  10923. TRACE_ERROR(EncryptedContentAllocError)
  10924. TRACE_ERROR(SetDecryptKeyError)
  10925. TRACE_ERROR(DecryptError)
  10926. }
  10927. //+-------------------------------------------------------------------------
  10928. // Decrypt the content using only a PKCS 1.5 recipient type
  10929. //--------------------------------------------------------------------------
  10930. BOOL
  10931. WINAPI
  10932. ICM_ControlPkcsDecrypt(
  10933. IN PCRYPT_MSG_INFO pcmi,
  10934. IN DWORD dwFlags,
  10935. IN PCMSG_CTRL_DECRYPT_PARA pmcdp
  10936. )
  10937. {
  10938. BOOL fRet;
  10939. CMSG_CTRL_KEY_TRANS_DECRYPT_PARA KeyTransDecryptPara;
  10940. PCMSG_CMS_RECIPIENT_INFO pRecipientInfo = NULL;
  10941. DWORD dwCmsIndex;
  10942. assert( pmcdp->cbSize >= sizeof(*pmcdp));
  10943. if (pmcdp->cbSize < sizeof(*pmcdp))
  10944. goto InvalidArg;
  10945. if (!ICM_ConvertPkcsToCmsRecipientIndex(
  10946. pcmi, pmcdp->dwRecipientIndex, &dwCmsIndex))
  10947. goto ConvertPkcsToCmsRecipientIndexError;
  10948. if (NULL == (pRecipientInfo =
  10949. (PCMSG_CMS_RECIPIENT_INFO) ICM_AllocAndGetParam(
  10950. pcmi, CMSG_CMS_RECIPIENT_INFO_PARAM, dwCmsIndex)))
  10951. goto GetCmsRecipientInfoParamError;
  10952. assert(CMSG_KEY_TRANS_RECIPIENT == pRecipientInfo->dwRecipientChoice);
  10953. memset(&KeyTransDecryptPara, 0, sizeof(KeyTransDecryptPara));
  10954. KeyTransDecryptPara.cbSize = sizeof(KeyTransDecryptPara);
  10955. KeyTransDecryptPara.hCryptProv = pmcdp->hCryptProv;
  10956. KeyTransDecryptPara.dwKeySpec = pmcdp->dwKeySpec;
  10957. KeyTransDecryptPara.pKeyTrans = pRecipientInfo->pKeyTrans;
  10958. KeyTransDecryptPara.dwRecipientIndex = dwCmsIndex;
  10959. fRet = ICM_ControlCmsDecrypt(
  10960. pcmi,
  10961. dwFlags,
  10962. &KeyTransDecryptPara,
  10963. KeyTransDecryptPara.hCryptProv,
  10964. dwCmsIndex,
  10965. hImportKeyTransFuncSet,
  10966. KeyTransDecryptPara.pKeyTrans->KeyEncryptionAlgorithm.pszObjId,
  10967. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyTrans
  10968. );
  10969. CommonReturn:
  10970. ICM_Free(pRecipientInfo);
  10971. return fRet;
  10972. ErrorReturn:
  10973. fRet = FALSE;
  10974. goto CommonReturn;
  10975. SET_ERROR(InvalidArg, E_INVALIDARG)
  10976. TRACE_ERROR(ConvertPkcsToCmsRecipientIndexError)
  10977. TRACE_ERROR(GetCmsRecipientInfoParamError)
  10978. }
  10979. #else
  10980. //+-------------------------------------------------------------------------
  10981. // Default import of the encryption key
  10982. //--------------------------------------------------------------------------
  10983. BOOL
  10984. WINAPI
  10985. ICM_DefaultImportEncryptKey(
  10986. IN HCRYPTPROV hCryptProv,
  10987. IN DWORD dwKeySpec,
  10988. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  10989. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  10990. IN PBYTE pbEncodedKey,
  10991. IN DWORD cbEncodedKey,
  10992. OUT HCRYPTKEY *phEncryptKey)
  10993. {
  10994. DWORD dwError = ERROR_SUCCESS;
  10995. BOOL fRet;
  10996. HCRYPTKEY hEncryptKey = 0;
  10997. HCRYPTKEY hUserKey = 0;
  10998. DWORD dwAlgIdEncrypt;
  10999. DWORD dwAlgIdPubKey;
  11000. PBYTE pbCspKey = NULL;
  11001. DWORD cbCspKey;
  11002. PUBLICKEYSTRUC *ppks;
  11003. PSIMPLEBLOBHEADER psbh;
  11004. BYTE rgbIV[IV_LENGTH];
  11005. DWORD cbIV;
  11006. DWORD dwBitLen;
  11007. if (!ICM_GetEncryptParameters(
  11008. paiEncrypt,
  11009. &dwAlgIdEncrypt,
  11010. &dwBitLen,
  11011. rgbIV,
  11012. &cbIV))
  11013. goto GetEncryptParametersError;
  11014. #if 0
  11015. if (!ICM_GetOssCAPI(
  11016. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  11017. paiPubKey,
  11018. &dwAlgIdPubKey))
  11019. goto PubKeyGetCAPIError;
  11020. #else
  11021. // We have no idea what the right values are for the alg id's here.
  11022. dwAlgIdPubKey = CALG_RSA_KEYX;
  11023. #endif
  11024. cbCspKey = cbEncodedKey + sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  11025. if (NULL == (pbCspKey = (PBYTE)ICM_AllocA( cbCspKey)))
  11026. goto CspKeyAllocError;
  11027. ppks = (PUBLICKEYSTRUC *)pbCspKey;
  11028. ppks->bType = SIMPLEBLOB;
  11029. ppks->bVersion = CUR_BLOB_VERSION;
  11030. ppks->reserved = 0;
  11031. ppks->aiKeyAlg = dwAlgIdEncrypt;
  11032. psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
  11033. psbh->aiEncAlg = dwAlgIdPubKey;
  11034. ICM_ReverseCopy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
  11035. if (0 != dwKeySpec) {
  11036. // Get private key to use.
  11037. if (!CryptGetUserKey(
  11038. hCryptProv,
  11039. dwKeySpec,
  11040. &hUserKey)) {
  11041. hUserKey = 0;
  11042. goto GetUserKeyFailed;
  11043. }
  11044. }
  11045. // else
  11046. // Use the provider's default private key for decrypting
  11047. fRet = CryptImportKey(
  11048. hCryptProv,
  11049. pbCspKey,
  11050. cbCspKey,
  11051. hUserKey,
  11052. CRYPT_NO_SALT, // dwFlags
  11053. &hEncryptKey);
  11054. if (!fRet) {
  11055. dwError = GetLastError();
  11056. if (hUserKey) {
  11057. if (NTE_BAD_FLAGS == dwError)
  11058. // Try without salt. Previous versions didn't support
  11059. // CRYPT_NO_SALT flag
  11060. fRet = CryptImportKey(
  11061. hCryptProv,
  11062. pbCspKey,
  11063. cbCspKey,
  11064. hUserKey,
  11065. 0, // dwFlags
  11066. &hEncryptKey);
  11067. if (!fRet) {
  11068. // Try without using the specified user key. Many versions of
  11069. // the CSP don't allow a non-null hUserKey parameter.
  11070. fRet = CryptImportKey(
  11071. hCryptProv,
  11072. pbCspKey,
  11073. cbCspKey,
  11074. 0, // hUserKey
  11075. CRYPT_NO_SALT, // dwFlags
  11076. &hEncryptKey);
  11077. if (!fRet)
  11078. dwError = GetLastError();
  11079. }
  11080. }
  11081. if (!fRet && NTE_BAD_FLAGS == dwError)
  11082. // Try without user key and without CRYPT_NO_SALT flag
  11083. fRet = CryptImportKey(
  11084. hCryptProv,
  11085. pbCspKey,
  11086. cbCspKey,
  11087. 0, // hUserKey
  11088. 0, // dwFlags
  11089. &hEncryptKey);
  11090. if (!fRet && 2 >= paiEncrypt->Parameters.cbData) {
  11091. // Try importing as an NT4.0 SP3 encypted key that wasn't byte
  11092. // reversed and with zero salt.
  11093. memcpy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
  11094. fRet = CryptImportKey(
  11095. hCryptProv,
  11096. pbCspKey,
  11097. cbCspKey,
  11098. hUserKey,
  11099. 0, // dwFlags
  11100. &hEncryptKey);
  11101. if (!fRet && hUserKey) {
  11102. // Try without using the specified user key.
  11103. fRet = CryptImportKey(
  11104. hCryptProv,
  11105. pbCspKey,
  11106. cbCspKey,
  11107. 0, // hUserKey
  11108. 0, // dwFlags
  11109. &hEncryptKey);
  11110. }
  11111. }
  11112. if (!fRet) {
  11113. hEncryptKey = 0;
  11114. goto ImportKeyFailed;
  11115. }
  11116. }
  11117. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  11118. // Silently ignore any errors. Not supported in earlier versions
  11119. CryptSetKeyParam(
  11120. hEncryptKey,
  11121. KP_EFFECTIVE_KEYLEN,
  11122. (PBYTE) &dwBitLen,
  11123. 0); // dwFlags
  11124. if (0 != cbIV) {
  11125. if (!CryptSetKeyParam(
  11126. hEncryptKey,
  11127. KP_IV,
  11128. rgbIV,
  11129. 0)) // dwFlags
  11130. goto SetKeyParamError;
  11131. }
  11132. fRet = TRUE;
  11133. CommonReturn:
  11134. ICM_FreeA(pbCspKey);
  11135. if (hUserKey)
  11136. CryptDestroyKey(hUserKey);
  11137. ICM_SetLastError(dwError);
  11138. *phEncryptKey = hEncryptKey;
  11139. return fRet;
  11140. ErrorReturn:
  11141. dwError = GetLastError();
  11142. if (hEncryptKey) {
  11143. CryptDestroyKey(hEncryptKey);
  11144. hEncryptKey = 0;
  11145. }
  11146. fRet = FALSE;
  11147. goto CommonReturn;
  11148. TRACE_ERROR(GetEncryptParametersError)
  11149. //SET_ERROR(PubKeyGetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  11150. TRACE_ERROR(GetUserKeyFailed)
  11151. TRACE_ERROR(ImportKeyFailed)
  11152. TRACE_ERROR(CspKeyAllocError)
  11153. TRACE_ERROR(SetKeyParamError)
  11154. }
  11155. //+-------------------------------------------------------------------------
  11156. // Import the encryption key
  11157. //--------------------------------------------------------------------------
  11158. BOOL
  11159. WINAPI
  11160. ICM_ImportEncryptKey(
  11161. IN HCRYPTPROV hCryptProv,
  11162. IN DWORD dwKeySpec,
  11163. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  11164. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  11165. IN PBYTE pbEncodedKey,
  11166. IN DWORD cbEncodedKey,
  11167. OUT HCRYPTKEY *phEncryptKey)
  11168. {
  11169. BOOL fResult;
  11170. void *pvFuncAddr;
  11171. HCRYPTOIDFUNCADDR hFuncAddr;
  11172. if (CryptGetOIDFunctionAddress(
  11173. hImportEncryptKeyFuncSet,
  11174. X509_ASN_ENCODING,
  11175. paiEncrypt->pszObjId,
  11176. 0, // dwFlags
  11177. &pvFuncAddr,
  11178. &hFuncAddr)) {
  11179. fResult = ((PFN_CMSG_IMPORT_ENCRYPT_KEY) pvFuncAddr)(
  11180. hCryptProv,
  11181. dwKeySpec,
  11182. paiEncrypt,
  11183. paiPubKey,
  11184. pbEncodedKey,
  11185. cbEncodedKey,
  11186. phEncryptKey);
  11187. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  11188. } else
  11189. fResult = ICM_DefaultImportEncryptKey(
  11190. hCryptProv,
  11191. dwKeySpec,
  11192. paiEncrypt,
  11193. paiPubKey,
  11194. pbEncodedKey,
  11195. cbEncodedKey,
  11196. phEncryptKey);
  11197. return fResult;
  11198. }
  11199. //+-------------------------------------------------------------------------
  11200. // Decrypt the content
  11201. //--------------------------------------------------------------------------
  11202. BOOL
  11203. WINAPI
  11204. ICM_ControlDecrypt(
  11205. IN PCRYPT_MSG_INFO pcmi,
  11206. IN DWORD dwFlags,
  11207. IN void *pvCtrlPara)
  11208. {
  11209. DWORD dwError = ERROR_SUCCESS;
  11210. BOOL fRet;
  11211. PCMSG_CTRL_DECRYPT_PARA pmcdp;
  11212. RecipientInfo *pri = NULL;
  11213. EncryptedContentInfo *peci = NULL;
  11214. HCRYPTKEY hkeySeal = NULL;
  11215. PBYTE pbData = NULL;
  11216. LONG cbData;
  11217. AlgorithmIdentifier *paiOssContentEncryption;
  11218. PCRYPT_ALGORITHM_IDENTIFIER paiContentEncryption = NULL;
  11219. AlgorithmIdentifier *paiOssKeyEncryption;
  11220. PCRYPT_ALGORITHM_IDENTIFIER paiKeyEncryption = NULL;
  11221. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  11222. pmcdp = (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara;
  11223. assert( pmcdp->cbSize >= sizeof(CMSG_CTRL_DECRYPT_PARA));
  11224. if (pmcdp->cbSize < sizeof(CMSG_CTRL_DECRYPT_PARA))
  11225. goto InvalidArg;
  11226. if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
  11227. pcmi->hCryptProvContentCrypt = pmcdp->hCryptProv;
  11228. if( pcmi->Plaintext.pbData)
  11229. goto MessageAlreadyDecrypted;
  11230. switch (pcmi->dwMsgType) {
  11231. case CMSG_ENVELOPED:
  11232. {
  11233. EnvelopedData *ped;
  11234. ped = (EnvelopedData *)pcmi->pvMsg;
  11235. peci = &ped->encryptedContentInfo;
  11236. if (pmcdp->dwRecipientIndex >= ped->recipientInfos.count)
  11237. goto RecipientIndexTooLarge;
  11238. pri = ped->recipientInfos.value + pmcdp->dwRecipientIndex;
  11239. paiOssContentEncryption =
  11240. &ped->encryptedContentInfo.contentEncryptionAlgorithm;
  11241. paiOssKeyEncryption = &pri->keyEncryptionAlgorithm;
  11242. break;
  11243. }
  11244. case CMSG_SIGNED_AND_ENVELOPED:
  11245. goto MessageTypeNotSupportedYet;
  11246. default:
  11247. goto InvalidMsgType;
  11248. }
  11249. if (NULL == pri)
  11250. goto RecipientNotFound; // really NULL if not found?
  11251. if (NULL == (paiContentEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  11252. paiOssContentEncryption)))
  11253. goto GetEncryptAlgorithmError;
  11254. if (NULL == (paiKeyEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  11255. paiOssKeyEncryption)))
  11256. goto GetKeyAlgorithmError;
  11257. if (!ICM_ImportEncryptKey(
  11258. pmcdp->hCryptProv,
  11259. pmcdp->dwKeySpec,
  11260. paiContentEncryption,
  11261. paiKeyEncryption,
  11262. pri->encryptedKey.value,
  11263. pri->encryptedKey.length,
  11264. &hkeySeal))
  11265. goto ImportKeyError;
  11266. if (pcsi) {
  11267. if (!ICMS_SetDecryptKey( pcmi, hkeySeal))
  11268. goto SetDecryptKeyError; // NB- Do not trash err from callback!
  11269. hkeySeal = NULL;
  11270. } else {
  11271. // NB- For common bulk encryption algos,
  11272. // sizeof(plaintext)<=sizeof(ciphertext)
  11273. cbData = peci->encryptedContent.length;
  11274. if (NULL == (pbData = (PBYTE)ICM_Alloc( cbData)))
  11275. goto EncryptedContentAllocError;
  11276. memcpy( pbData, peci->encryptedContent.value, cbData);
  11277. if (!CryptDecrypt(
  11278. hkeySeal,
  11279. NULL,
  11280. TRUE, // fFinal
  11281. 0, // dwFlags
  11282. pbData,
  11283. (PDWORD)&cbData))
  11284. goto DecryptError;
  11285. CryptDestroyKey( hkeySeal);
  11286. hkeySeal = NULL;
  11287. pcmi->Plaintext.cbData = cbData;
  11288. pcmi->Plaintext.pbData = pbData;
  11289. pbData = NULL;
  11290. }
  11291. pcmi->dwDecryptedRecipientIndex = pmcdp->dwRecipientIndex;
  11292. fRet = TRUE;
  11293. CommonReturn:
  11294. ICM_Free(paiContentEncryption);
  11295. ICM_Free(paiKeyEncryption);
  11296. ICM_Free( pbData);
  11297. if (hkeySeal)
  11298. CryptDestroyKey( hkeySeal);
  11299. ICM_SetLastError(dwError);
  11300. return fRet;
  11301. ErrorReturn:
  11302. dwError = GetLastError();
  11303. fRet = FALSE;
  11304. goto CommonReturn;
  11305. SET_ERROR(InvalidArg,E_INVALIDARG)
  11306. SET_ERROR(MessageAlreadyDecrypted,CRYPT_E_ALREADY_DECRYPTED)
  11307. SET_ERROR(RecipientIndexTooLarge,CRYPT_E_INVALID_INDEX)
  11308. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  11309. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  11310. SET_ERROR(RecipientNotFound,CRYPT_E_RECIPIENT_NOT_FOUND)
  11311. TRACE_ERROR(GetEncryptAlgorithmError)
  11312. TRACE_ERROR(GetKeyAlgorithmError)
  11313. TRACE_ERROR(ImportKeyError)
  11314. TRACE_ERROR(EncryptedContentAllocError)
  11315. TRACE_ERROR(SetDecryptKeyError)
  11316. TRACE_ERROR(DecryptError)
  11317. }
  11318. #endif // CMS_PKCS7
  11319. //+-------------------------------------------------------------------------
  11320. // Hash the content of a message.
  11321. //--------------------------------------------------------------------------
  11322. BOOL
  11323. WINAPI
  11324. ICM_HashContent(
  11325. IN PCRYPT_MSG_INFO pcmi,
  11326. IN OUT HCRYPTHASH hHash)
  11327. {
  11328. DWORD dwError = ERROR_SUCCESS;
  11329. BOOL fRet;
  11330. HCRYPTMSG hCryptMsg = (HCRYPTMSG)pcmi;
  11331. PBYTE pbAllocData = NULL;
  11332. PBYTE pbData;
  11333. DWORD cbData;
  11334. cbData = 0;
  11335. CryptMsgGetParam(
  11336. hCryptMsg,
  11337. CMSG_CONTENT_PARAM,
  11338. 0, // dwIndex
  11339. NULL,
  11340. &cbData);
  11341. if (0 == cbData)
  11342. goto GetContentSizeError;
  11343. if (NULL == (pbAllocData = (PBYTE)ICM_Alloc(cbData)))
  11344. goto AllocContentError;
  11345. if (!CryptMsgGetParam(
  11346. hCryptMsg,
  11347. CMSG_CONTENT_PARAM,
  11348. 0, // dwIndex
  11349. pbAllocData,
  11350. &cbData))
  11351. goto GetContentError;
  11352. pbData = pbAllocData;
  11353. if (0 != strcmp(pszObjIdDataType, pcmi->psdi->pci->pszContentType)
  11354. #ifdef CMS_PKCS7
  11355. && pcmi->psdi->version < CMSG_SIGNED_DATA_CMS_VERSION
  11356. #endif // CMS_PKCS7
  11357. ) {
  11358. // Leading tag and length octets aren't included in the digest
  11359. if (0 > Asn1UtilExtractContent( pbData, cbData, &cbData,
  11360. (const BYTE **)&pbData))
  11361. goto ExtractContentError;
  11362. }
  11363. if (!ICM_UpdateDigest( hHash, pbData, cbData))
  11364. goto UpdateDigestError;
  11365. fRet = TRUE;
  11366. CommonReturn:
  11367. ICM_Free( pbAllocData);
  11368. ICM_SetLastError(dwError);
  11369. return fRet;
  11370. ErrorReturn:
  11371. dwError = GetLastError();
  11372. fRet = FALSE;
  11373. goto CommonReturn;
  11374. TRACE_ERROR(GetContentSizeError) // error already set
  11375. TRACE_ERROR(AllocContentError) // error already set
  11376. TRACE_ERROR(GetContentError) // error already set
  11377. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  11378. TRACE_ERROR(UpdateDigestError) // error already set
  11379. }
  11380. //+-------------------------------------------------------------------------
  11381. // Add a signer to a signed-data or signed-and-enveloped-data message.
  11382. //--------------------------------------------------------------------------
  11383. BOOL
  11384. WINAPI
  11385. ICM_ControlAddSigner(
  11386. IN OUT PCRYPT_MSG_INFO pcmi,
  11387. IN DWORD dwFlags,
  11388. IN PCMSG_SIGNER_ENCODE_INFO psei)
  11389. {
  11390. DWORD dwError = ERROR_SUCCESS;
  11391. BOOL fRet;
  11392. CHashNode *pnHash;
  11393. CSignerNode *pnSigner;
  11394. DWORD dwAlgoCAPI;
  11395. SignerInfo *psi = NULL;
  11396. Attribute *pAuthAttr;
  11397. DWORD cAuthAttr;
  11398. Attribute *pUnauthAttr;
  11399. DWORD cUnauthAttr;
  11400. LPSTR pszInnerContentObjID;
  11401. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  11402. AlgorithmIdentifier oaiHash;
  11403. CBlobNode *pnBlob;
  11404. CRYPT_DATA_BLOB blobHashAlgo; ZEROSTRUCT(blobHashAlgo);
  11405. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  11406. #ifdef CMS_PKCS7
  11407. SIGNER_ENCODE_DATA_INFO SignerEncodeDataInfo;
  11408. #endif // CMS_PKCS7
  11409. // if the hash algorithm matches one of the ones already in use,
  11410. // get that hash and encrypt it
  11411. // else
  11412. // hash the data again and add hash algo to top-level list
  11413. // [NB- must access data again]
  11414. // Search for a hash node with a matching hash algorithm
  11415. if (!(ICM_GetCAPI(
  11416. CRYPT_HASH_ALG_OID_GROUP_ID,
  11417. &psei->HashAlgorithm,
  11418. &dwAlgoCAPI) ||
  11419. ICM_GetCAPI(
  11420. CRYPT_SIGN_ALG_OID_GROUP_ID,
  11421. &psei->HashAlgorithm,
  11422. &dwAlgoCAPI)))
  11423. goto GetCAPIError;
  11424. // before, this could have never failed, but now it can
  11425. // only create a hash node if the hash didn't exists.
  11426. if (!ICM_FindHashNodeFromCapiAlgid( pcmi->pHashList, dwAlgoCAPI, &pnHash) &&
  11427. GetLastError() != CRYPT_E_UNKNOWN_ALGO)
  11428. goto FindHashNodeFromCapiAlgidError;
  11429. if (!pnHash) {
  11430. // New hash.
  11431. // 1. Create hash node
  11432. // 2. Hash the data
  11433. // 3. Add hash node to pcmi->pHashList
  11434. // 4. Encode this hash algo and add to pcmi->psdi->pAlgidList
  11435. HashInfo.dwAlgoCAPI = dwAlgoCAPI;
  11436. #ifndef CMS_PKCS7
  11437. HashInfo.hCryptProv = psei->hCryptProv;
  11438. #endif // CMS_PKCS7
  11439. if (!CryptCreateHash(
  11440. psei->hCryptProv,
  11441. HashInfo.dwAlgoCAPI,
  11442. NULL, // hKey - optional for MAC
  11443. 0, // dwFlags
  11444. &HashInfo.hHash))
  11445. goto CreateHashError;
  11446. if (!ICM_HashContent( pcmi, HashInfo.hHash)) // hash content
  11447. goto HashContentError;
  11448. if (NULL == (pnHash = new CHashNode))
  11449. goto NewHashNodeError;
  11450. pnHash->SetData( &HashInfo);
  11451. pcmi->pHashList->InsertTail( pnHash);
  11452. // Convert the hash algorithm to a blob and
  11453. // add to pcmi->psdi->pAlgidList.
  11454. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  11455. pcmi,
  11456. &psei->HashAlgorithm,
  11457. &oaiHash))
  11458. goto MsgAsn1ToAlgorithmIdentifierError;
  11459. if (!ICM_Asn1Encode(
  11460. AlgorithmIdentifier_PDU,
  11461. &oaiHash,
  11462. &blobHashAlgo))
  11463. goto EncodeHashAlgorithmError;
  11464. if (NULL == (pnBlob = new CBlobNode))
  11465. goto NewBlobNodeError;
  11466. pnBlob->SetData( &blobHashAlgo);
  11467. pcmi->psdi->pAlgidList->InsertTail( pnBlob);
  11468. }
  11469. // Alloc and fill in a SignerInfo
  11470. pszInnerContentObjID = pcmi->psdi->pci->pszContentType;
  11471. if (!strcmp( pszInnerContentObjID, pszObjIdDataType))
  11472. pszInnerContentObjID = NULL;
  11473. // NB - Each SignerInfo gets a non-empty authenticatedAttributes
  11474. // if the inner contentType is not data (passed in) or if
  11475. // there are authenticated attributes passed in. In this case,
  11476. // we reserve two Attribute slots at the beginning of the array
  11477. // for the content-type and message-digest Attribute values.
  11478. cAuthAttr = 0;
  11479. if (pszInnerContentObjID ||
  11480. psei->cAuthAttr ||
  11481. (dwFlags & CMSG_AUTHENTICATED_ATTRIBUTES_FLAG)) {
  11482. cAuthAttr = psei->cAuthAttr + 2; // reserve 2
  11483. }
  11484. cUnauthAttr = psei->cUnauthAttr;
  11485. psi = (SignerInfo *)ICM_AllocZero( sizeof( SignerInfo) +
  11486. cAuthAttr * sizeof( Attribute) +
  11487. cUnauthAttr * sizeof( Attribute)
  11488. );
  11489. if (NULL == psi)
  11490. goto SignerInfoAllocError;
  11491. pAuthAttr = (Attribute *)(psi + 1);
  11492. pUnauthAttr = pAuthAttr + cAuthAttr;
  11493. if (!ICM_FillAsnSignerInfo(
  11494. psei,
  11495. pcmi,
  11496. dwFlags,
  11497. pszInnerContentObjID,
  11498. psi,
  11499. &pAuthAttr,
  11500. &pUnauthAttr))
  11501. goto FillAsnSignerInfoError;
  11502. #ifdef CMS_PKCS7
  11503. SignerEncodeDataInfo.hCryptProv = psei->hCryptProv;
  11504. SignerEncodeDataInfo.dwKeySpec = psei->dwKeySpec;
  11505. SignerEncodeDataInfo.pHashNode = pnHash;
  11506. if (!ICM_FillSignerEncryptedDigest(
  11507. psi,
  11508. pszInnerContentObjID,
  11509. &SignerEncodeDataInfo,
  11510. FALSE)) // fMaxLength
  11511. goto FillSignerEncryptedDigestError;
  11512. #else
  11513. if (!ICM_FillSignerEncryptedDigest(
  11514. psi,
  11515. pszInnerContentObjID,
  11516. pnHash,
  11517. psei->dwKeySpec,
  11518. FALSE)) // fMaxLength
  11519. goto FillSignerEncryptedDigestError;
  11520. #endif // CMS_PKCS7
  11521. // Encode the signer and add to pcmi->psdi->pSignerList.
  11522. if (!ICM_Asn1Encode(
  11523. SignerInfo_PDU,
  11524. psi,
  11525. &sdi.blob))
  11526. goto EncodeSignerInfoError;
  11527. if (NULL == (pnSigner = new CSignerNode))
  11528. goto NewSignerInfoBlobNodeError;
  11529. pnSigner->SetData( &sdi);
  11530. pcmi->psdi->pSignerList->InsertTail( pnSigner);
  11531. fRet = TRUE;
  11532. CommonReturn:
  11533. if (psi) {
  11534. ICM_FreeAsnSignerInfo(psi);
  11535. ICM_Free(psi);
  11536. }
  11537. ICM_SetLastError(dwError);
  11538. return fRet;
  11539. ErrorReturn:
  11540. dwError = GetLastError();
  11541. ICM_Free(blobHashAlgo.pbData);
  11542. ICM_Free(sdi.blob.pbData);
  11543. if (HashInfo.hHash)
  11544. CryptDestroyHash(HashInfo.hHash);
  11545. fRet = FALSE;
  11546. goto CommonReturn;
  11547. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  11548. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  11549. SET_ERROR(NewBlobNodeError,E_OUTOFMEMORY)
  11550. SET_ERROR(NewSignerInfoBlobNodeError,E_OUTOFMEMORY)
  11551. TRACE_ERROR(FindHashNodeFromCapiAlgidError) // error already set
  11552. TRACE_ERROR(CreateHashError) // error already set
  11553. TRACE_ERROR(HashContentError) // error already set
  11554. TRACE_ERROR(MsgAsn1ToAlgorithmIdentifierError) // error already set
  11555. TRACE_ERROR(EncodeHashAlgorithmError) // error already set
  11556. TRACE_ERROR(SignerInfoAllocError) // error already set
  11557. TRACE_ERROR(FillAsnSignerInfoError) // error already set
  11558. TRACE_ERROR(FillSignerEncryptedDigestError) // error already set
  11559. TRACE_ERROR(EncodeSignerInfoError) // error already set
  11560. }
  11561. //+-------------------------------------------------------------------------
  11562. // Add a CMS signer info to a signed-data message.
  11563. //--------------------------------------------------------------------------
  11564. BOOL
  11565. WINAPI
  11566. ICM_ControlAddCmsSignerInfo(
  11567. IN OUT PCRYPT_MSG_INFO pcmi,
  11568. IN DWORD dwFlags,
  11569. IN PCMSG_CMS_SIGNER_INFO psi)
  11570. {
  11571. BOOL fRet;
  11572. CSignerNode *pnSigner;
  11573. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  11574. // Encode the signer
  11575. if (!ICM_CmsSignerInfoEncode(
  11576. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  11577. CMS_SIGNER_INFO,
  11578. psi,
  11579. NULL, // pbEncoded
  11580. &sdi.blob.cbData
  11581. ))
  11582. goto EncodeSignerInfoError;
  11583. if (NULL == (sdi.blob.pbData = (PBYTE) ICM_Alloc(sdi.blob.cbData)))
  11584. goto OutOfMemory;
  11585. if (!ICM_CmsSignerInfoEncode(
  11586. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  11587. CMS_SIGNER_INFO,
  11588. psi,
  11589. sdi.blob.pbData,
  11590. &sdi.blob.cbData
  11591. ))
  11592. goto EncodeSignerInfoError;
  11593. // Add to pcmi->psdi->pSignerList.
  11594. if (NULL == (pnSigner = new CSignerNode))
  11595. goto NewSignerInfoBlobNodeError;
  11596. pnSigner->SetData( &sdi);
  11597. pcmi->psdi->pSignerList->InsertTail( pnSigner);
  11598. fRet = TRUE;
  11599. CommonReturn:
  11600. return fRet;
  11601. ErrorReturn:
  11602. ICM_Free(sdi.blob.pbData);
  11603. fRet = FALSE;
  11604. goto CommonReturn;
  11605. TRACE_ERROR(OutOfMemory)
  11606. TRACE_ERROR(EncodeSignerInfoError)
  11607. SET_ERROR(NewSignerInfoBlobNodeError,E_OUTOFMEMORY)
  11608. }
  11609. //+-------------------------------------------------------------------------
  11610. // Remove a signer from a signed-data or signed-and-enveloped-data message.
  11611. //--------------------------------------------------------------------------
  11612. BOOL
  11613. WINAPI
  11614. ICM_ControlDelSigner(
  11615. IN OUT PCRYPT_MSG_INFO pcmi,
  11616. IN DWORD dwFlags,
  11617. IN DWORD dwIndex)
  11618. {
  11619. BOOL fRet;
  11620. CSignerNode *pnSigner = pcmi->psdi->pSignerList->Nth( dwIndex);
  11621. if (NULL == pnSigner)
  11622. goto IndexTooLargeError;
  11623. pcmi->psdi->pSignerList->Remove( pnSigner);
  11624. delete pnSigner;
  11625. fRet = TRUE;
  11626. CommonReturn:
  11627. return fRet;
  11628. ErrorReturn:
  11629. fRet = FALSE;
  11630. goto CommonReturn;
  11631. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11632. dwFlags;
  11633. }
  11634. //+-------------------------------------------------------------------------
  11635. // Initialize the unauthenticated attributes list. Called before doing an
  11636. // add or delete.
  11637. //--------------------------------------------------------------------------
  11638. BOOL
  11639. WINAPI
  11640. ICM_InitUnauthAttrList(
  11641. IN CSignerNode *pnSigner
  11642. )
  11643. {
  11644. DWORD dwError = ERROR_SUCCESS;
  11645. BOOL fRet;
  11646. CBlobList *plBlob = NULL;
  11647. DWORD i;
  11648. SIGNER_DATA_INFO sdi;
  11649. SignerInfoWithAttrBlobs *posib = NULL;
  11650. Any *pAny;
  11651. ASN1error_e Asn1Err;
  11652. ASN1decoding_t pDec = ICM_GetDecoder();
  11653. assert(pnSigner);
  11654. sdi = *pnSigner->Data();
  11655. if (NULL == sdi.pUnauthAttrList) {
  11656. if (NULL == (plBlob = new CBlobList))
  11657. goto NewUnauthAttrListError;
  11658. if (0 != (Asn1Err = PkiAsn1Decode(
  11659. pDec,
  11660. (void **)&posib,
  11661. SignerInfoWithAttrBlobs_PDU,
  11662. sdi.blob.pbData,
  11663. sdi.blob.cbData)))
  11664. goto DecodeSignerInfoError;
  11665. if (posib->bit_mask & unauthAttributes_present) {
  11666. for (i=posib->unauthAttributes.count, pAny=posib->unauthAttributes.value;
  11667. i>0;
  11668. i--, pAny++)
  11669. if (!ICM_InsertTailBlob( plBlob, pAny))
  11670. goto InsertOldUnauthAttrBlobError;
  11671. }
  11672. sdi.pUnauthAttrList = plBlob;
  11673. pnSigner->SetData( &sdi);
  11674. }
  11675. fRet = TRUE;
  11676. CommonReturn:
  11677. PkiAsn1FreeInfo(pDec, SignerInfoWithAttrBlobs_PDU, posib);
  11678. ICM_SetLastError(dwError);
  11679. return fRet;
  11680. ErrorReturn:
  11681. dwError = GetLastError();
  11682. if (plBlob)
  11683. delete plBlob;
  11684. fRet = FALSE;
  11685. goto CommonReturn;
  11686. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  11687. SET_ERROR(NewUnauthAttrListError,E_OUTOFMEMORY)
  11688. TRACE_ERROR(InsertOldUnauthAttrBlobError) // error already set
  11689. }
  11690. //+-------------------------------------------------------------------------
  11691. // Add an unauthenticated attribute to a SignerInfo of a signed-data or
  11692. // signed-and-enveloped-data message.
  11693. //--------------------------------------------------------------------------
  11694. BOOL
  11695. WINAPI
  11696. ICM_ControlAddUnauthAttr(
  11697. IN PCRYPT_MSG_INFO pcmi,
  11698. IN DWORD dwFlags,
  11699. IN PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA pmcasuap)
  11700. {
  11701. BOOL fRet;
  11702. CSignerNode *pnSigner;
  11703. DWORD i;
  11704. for (i=pmcasuap->dwSignerIndex,
  11705. pnSigner=pcmi->psdi->pSignerList->Head();
  11706. (i>0) && pnSigner;
  11707. i--, pnSigner = pnSigner->Next())
  11708. ;
  11709. if (NULL == pnSigner)
  11710. goto IndexTooLargeError;
  11711. if (!ICM_InitUnauthAttrList(pnSigner))
  11712. goto InitUnauthAttrListError;
  11713. assert(pnSigner->Data()->pUnauthAttrList);
  11714. if (!ICM_InsertTailBlob( pnSigner->Data()->pUnauthAttrList,
  11715. (Any *)&pmcasuap->blob))
  11716. goto InsertUnauthAttrBlobError;
  11717. fRet = TRUE;
  11718. CommonReturn:
  11719. return fRet;
  11720. ErrorReturn:
  11721. fRet = FALSE;
  11722. goto CommonReturn;
  11723. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11724. TRACE_ERROR(InitUnauthAttrListError) // error already set
  11725. TRACE_ERROR(InsertUnauthAttrBlobError) // error already set
  11726. dwFlags;
  11727. }
  11728. //+-------------------------------------------------------------------------
  11729. // Delete an unauthenticated attribute from a SignerInfo of a signed-data or
  11730. // signed-and-enveloped-data message.
  11731. //--------------------------------------------------------------------------
  11732. BOOL
  11733. WINAPI
  11734. ICM_ControlDelUnauthAttr(
  11735. IN PCRYPT_MSG_INFO pcmi,
  11736. IN DWORD dwFlags,
  11737. IN PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA pmcdsuap)
  11738. {
  11739. BOOL fRet;
  11740. CSignerNode *pnSigner;
  11741. DWORD i;
  11742. for (i=pmcdsuap->dwSignerIndex,
  11743. pnSigner=pcmi->psdi->pSignerList->Head();
  11744. (i>0) && pnSigner;
  11745. i--, pnSigner = pnSigner->Next())
  11746. ;
  11747. if (NULL == pnSigner)
  11748. goto IndexTooLargeError;
  11749. if (!ICM_InitUnauthAttrList(pnSigner))
  11750. goto InitUnauthAttrListError;
  11751. assert(pnSigner->Data()->pUnauthAttrList);
  11752. if (!ICM_DelBlobByIndex(
  11753. pnSigner->Data()->pUnauthAttrList,
  11754. pmcdsuap->dwUnauthAttrIndex))
  11755. goto DelBlobByIndexError;
  11756. fRet = TRUE;
  11757. CommonReturn:
  11758. return fRet;
  11759. ErrorReturn:
  11760. fRet = FALSE;
  11761. goto CommonReturn;
  11762. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11763. TRACE_ERROR(InitUnauthAttrListError) // error already set
  11764. TRACE_ERROR(DelBlobByIndexError) // error already set
  11765. dwFlags;
  11766. }
  11767. //+-------------------------------------------------------------------------
  11768. // Perform a special "control" function after the final CryptMsgUpdate of a
  11769. // encoded/decoded cryptographic message.
  11770. //
  11771. // The dwCtrlType parameter specifies the type of operation to be performed.
  11772. //
  11773. // The pvCtrlPara definition depends on the dwCtrlType value.
  11774. //
  11775. // See below for a list of the control operations and their pvCtrlPara
  11776. // type definition.
  11777. //--------------------------------------------------------------------------
  11778. BOOL
  11779. WINAPI
  11780. #ifdef DEBUG_CRYPT_ASN1_MASTER
  11781. ICMTest_NewCryptMsgControl(
  11782. #else
  11783. CryptMsgControl(
  11784. #endif
  11785. IN HCRYPTMSG hCryptMsg,
  11786. IN DWORD dwFlags,
  11787. IN DWORD dwCtrlType,
  11788. IN void const *pvCtrlPara)
  11789. {
  11790. BOOL fRet;
  11791. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  11792. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  11793. // Only support control for decoding
  11794. if (pcmi->fEncoding)
  11795. goto ControlForEncodingNotSupported;
  11796. switch (dwCtrlType) {
  11797. case CMSG_CTRL_VERIFY_SIGNATURE:
  11798. fRet = ICM_ControlVerifySignature(
  11799. pcmi,
  11800. dwFlags,
  11801. (PCERT_INFO)pvCtrlPara);
  11802. break;
  11803. #ifdef CMS_PKCS7
  11804. case CMSG_CTRL_VERIFY_SIGNATURE_EX:
  11805. fRet = ICM_ControlVerifySignatureEx(
  11806. pcmi,
  11807. dwFlags,
  11808. (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara);
  11809. break;
  11810. #endif // CMS_PKCS7
  11811. case CMSG_CTRL_DECRYPT:
  11812. #ifdef CMS_PKCS7
  11813. fRet = ICM_ControlPkcsDecrypt(
  11814. #else
  11815. fRet = ICM_ControlDecrypt(
  11816. #endif // CMS_PKCS7
  11817. pcmi,
  11818. dwFlags,
  11819. (PCMSG_CTRL_DECRYPT_PARA) pvCtrlPara);
  11820. break;
  11821. case CMSG_CTRL_VERIFY_HASH:
  11822. fRet = ICM_ControlVerifyDigest(
  11823. pcmi,
  11824. dwFlags);
  11825. break;
  11826. case CMSG_CTRL_ADD_SIGNER:
  11827. fRet = ICM_ControlAddSigner(
  11828. pcmi,
  11829. dwFlags,
  11830. (PCMSG_SIGNER_ENCODE_INFO)pvCtrlPara);
  11831. break;
  11832. case CMSG_CTRL_ADD_CMS_SIGNER_INFO:
  11833. fRet = ICM_ControlAddCmsSignerInfo(
  11834. pcmi,
  11835. dwFlags,
  11836. (PCMSG_CMS_SIGNER_INFO)pvCtrlPara);
  11837. break;
  11838. case CMSG_CTRL_DEL_SIGNER:
  11839. fRet = ICM_ControlDelSigner(
  11840. pcmi,
  11841. dwFlags,
  11842. *(PDWORD)pvCtrlPara);
  11843. break;
  11844. case CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR:
  11845. fRet = ICM_ControlAddUnauthAttr(
  11846. pcmi,
  11847. dwFlags,
  11848. (PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA)pvCtrlPara);
  11849. break;
  11850. case CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR:
  11851. fRet = ICM_ControlDelUnauthAttr(
  11852. pcmi,
  11853. dwFlags,
  11854. (PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA)pvCtrlPara);
  11855. break;
  11856. case CMSG_CTRL_ADD_CERT:
  11857. fRet = ICM_InsertTailBlob(
  11858. pcmi->psdi->pCertificateList,
  11859. (Any *)pvCtrlPara);
  11860. break;
  11861. case CMSG_CTRL_DEL_CERT:
  11862. {
  11863. DWORD dwIndex = *(PDWORD)pvCtrlPara;
  11864. #ifdef CMS_PKCS7
  11865. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  11866. // Advance index past attribute certs.
  11867. ICM_GetTaggedBlobAndAdvanceIndex(
  11868. pcmi->psdi->pCertificateList,
  11869. ICM_TAG_SEQ,
  11870. &dwIndex
  11871. );
  11872. #endif // CMS_PKCS7
  11873. fRet = ICM_DelBlobByIndex(
  11874. pcmi->psdi->pCertificateList,
  11875. dwIndex);
  11876. }
  11877. break;
  11878. #ifdef CMS_PKCS7
  11879. case CMSG_CTRL_ADD_ATTR_CERT:
  11880. {
  11881. Any *pAny = (Any *) pvCtrlPara;
  11882. Any AnyAttrCert;
  11883. BOOL fV3;
  11884. fV3 = (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION);
  11885. if (!(fV3 || 0 != strcmp(pszObjIdDataType,
  11886. pcmi->psdi->pci->pszContentType)))
  11887. goto InvalidMsgTypeToAddAttrCert;
  11888. AnyAttrCert.length = pAny->length;
  11889. if (0 == AnyAttrCert.length)
  11890. goto InvalidParamError;
  11891. if (NULL == (AnyAttrCert.value = (unsigned char*) ICM_Alloc(
  11892. AnyAttrCert.length)))
  11893. goto AllocError;
  11894. memcpy(AnyAttrCert.value, pAny->value, AnyAttrCert.length);
  11895. #ifdef OSS_CRYPT_ASN1
  11896. *AnyAttrCert.value = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  11897. #else
  11898. *((BYTE *) AnyAttrCert.value) = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  11899. #endif // OSS_CRYPT_ASN1
  11900. fRet = ICM_InsertTailBlob(
  11901. pcmi->psdi->pCertificateList,
  11902. &AnyAttrCert);
  11903. if (fRet && !fV3)
  11904. pcmi->psdi->version = CMSG_SIGNED_DATA_CMS_VERSION;
  11905. ICM_Free(AnyAttrCert.value);
  11906. }
  11907. break;
  11908. case CMSG_CTRL_DEL_ATTR_CERT:
  11909. if (pcmi->psdi->version < CMSG_SIGNED_DATA_CMS_VERSION)
  11910. goto NoAttrCerts;
  11911. else {
  11912. DWORD dwIndex = *(PDWORD)pvCtrlPara;
  11913. // Advance index past certs.
  11914. ICM_GetTaggedBlobAndAdvanceIndex(
  11915. pcmi->psdi->pCertificateList,
  11916. ICM_TAG_CONSTRUCTED_CONTEXT_1,
  11917. &dwIndex
  11918. );
  11919. fRet = ICM_DelBlobByIndex(
  11920. pcmi->psdi->pCertificateList,
  11921. dwIndex);
  11922. }
  11923. break;
  11924. #endif // CMS_PKCS7
  11925. case CMSG_CTRL_ADD_CRL:
  11926. fRet = ICM_InsertTailBlob(
  11927. pcmi->psdi->pCrlList,
  11928. (Any *)pvCtrlPara);
  11929. break;
  11930. case CMSG_CTRL_DEL_CRL:
  11931. fRet = ICM_DelBlobByIndex(
  11932. pcmi->psdi->pCrlList,
  11933. *(PDWORD)pvCtrlPara);
  11934. break;
  11935. #ifdef CMS_PKCS7
  11936. case CMSG_CTRL_KEY_TRANS_DECRYPT:
  11937. {
  11938. PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pmcdp =
  11939. (PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA) pvCtrlPara;
  11940. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11941. if (pmcdp->cbSize < sizeof(*pmcdp))
  11942. goto InvalidArg;
  11943. fRet = ICM_ControlCmsDecrypt(
  11944. pcmi,
  11945. dwFlags,
  11946. pmcdp,
  11947. pmcdp->hCryptProv,
  11948. pmcdp->dwRecipientIndex,
  11949. hImportKeyTransFuncSet,
  11950. pmcdp->pKeyTrans->KeyEncryptionAlgorithm.pszObjId,
  11951. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyTrans
  11952. );
  11953. }
  11954. break;
  11955. case CMSG_CTRL_KEY_AGREE_DECRYPT:
  11956. {
  11957. PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA pmcdp =
  11958. (PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA) pvCtrlPara;
  11959. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11960. if (pmcdp->cbSize < sizeof(*pmcdp))
  11961. goto InvalidArg;
  11962. fRet = ICM_ControlCmsDecrypt(
  11963. pcmi,
  11964. dwFlags,
  11965. pmcdp,
  11966. pmcdp->hCryptProv,
  11967. pmcdp->dwRecipientIndex,
  11968. hImportKeyAgreeFuncSet,
  11969. pmcdp->pKeyAgree->KeyEncryptionAlgorithm.pszObjId,
  11970. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyAgree
  11971. );
  11972. if (fRet)
  11973. pcmi->dwDecryptedRecipientEncryptedKeyIndex =
  11974. pmcdp->dwRecipientEncryptedKeyIndex;
  11975. }
  11976. break;
  11977. case CMSG_CTRL_MAIL_LIST_DECRYPT:
  11978. {
  11979. PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA pmcdp =
  11980. (PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA) pvCtrlPara;
  11981. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11982. if (pmcdp->cbSize < sizeof(*pmcdp))
  11983. goto InvalidArg;
  11984. fRet = ICM_ControlCmsDecrypt(
  11985. pcmi,
  11986. dwFlags,
  11987. pmcdp,
  11988. pmcdp->hCryptProv,
  11989. pmcdp->dwRecipientIndex,
  11990. hImportMailListFuncSet,
  11991. pmcdp->pMailList->KeyEncryptionAlgorithm.pszObjId,
  11992. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportMailList
  11993. );
  11994. }
  11995. break;
  11996. #endif // CMS_PKCS7
  11997. default:
  11998. goto InvalidCtrlType;
  11999. }
  12000. CommonReturn:
  12001. ICM_Unlock( pcmi);
  12002. return fRet;
  12003. ErrorReturn:
  12004. fRet = FALSE;
  12005. goto CommonReturn;
  12006. SET_ERROR(ControlForEncodingNotSupported,E_INVALIDARG)
  12007. SET_ERROR(InvalidCtrlType,CRYPT_E_CONTROL_TYPE)
  12008. #ifdef CMS_PKCS7
  12009. SET_ERROR(InvalidMsgTypeToAddAttrCert,CRYPT_E_INVALID_MSG_TYPE)
  12010. SET_ERROR(InvalidParamError,E_INVALIDARG)
  12011. TRACE_ERROR(AllocError)
  12012. SET_ERROR(NoAttrCerts,CRYPT_E_INVALID_INDEX)
  12013. SET_ERROR(InvalidArg,E_INVALIDARG)
  12014. #endif // CMS_PKCS7
  12015. }
  12016. //+-------------------------------------------------------------------------
  12017. // Copy out a DWORD
  12018. //--------------------------------------------------------------------------
  12019. BOOL
  12020. WINAPI
  12021. ICM_GetDWORD(
  12022. IN DWORD dwValue,
  12023. OUT void *pvData,
  12024. IN OUT DWORD *pcbData)
  12025. {
  12026. return ICM_CopyOut(
  12027. (PBYTE)&dwValue,
  12028. sizeof(DWORD),
  12029. (PBYTE)pvData,
  12030. pcbData);
  12031. }
  12032. //+-------------------------------------------------------------------------
  12033. // Get Any
  12034. //--------------------------------------------------------------------------
  12035. BOOL
  12036. WINAPI
  12037. ICM_GetOssAny(
  12038. IN Any *pany,
  12039. OUT PCRYPT_DATA_BLOB pInfo,
  12040. IN OUT BYTE **ppbExtra,
  12041. IN OUT LONG *plRemainExtra)
  12042. {
  12043. BOOL fResult = TRUE;
  12044. LONG lRemainExtra = *plRemainExtra;
  12045. BYTE *pbExtra = *ppbExtra;
  12046. LONG lAlignExtra;
  12047. LONG lData;
  12048. BOOL fNULL = FALSE;
  12049. PBYTE pbValue;
  12050. pbValue = (PBYTE) pany->value;
  12051. if ((pany->length == 2) &&
  12052. (pbValue[0] == 0x05) &&
  12053. (pbValue[1] == 0x00)) {
  12054. // Detected NULL encoding. Map to NULL blob.
  12055. fNULL = TRUE;
  12056. }
  12057. lData = fNULL ? 0 : pany->length;
  12058. lAlignExtra = INFO_LEN_ALIGN(lData);
  12059. lRemainExtra -= lAlignExtra;
  12060. if (lRemainExtra >= 0) {
  12061. if ((lData > 0) && !fNULL) {
  12062. pInfo->pbData = pbExtra;
  12063. pInfo->cbData = (DWORD) lData;
  12064. memcpy( pbExtra, pany->value, lData);
  12065. } else {
  12066. memset(pInfo, 0, sizeof(*pInfo));
  12067. }
  12068. pbExtra += lAlignExtra;
  12069. }
  12070. *plRemainExtra = lRemainExtra;
  12071. *ppbExtra = pbExtra;
  12072. return fResult;
  12073. }
  12074. //+-------------------------------------------------------------------------
  12075. // Get the data for an Attributes
  12076. //--------------------------------------------------------------------------
  12077. BOOL
  12078. WINAPI
  12079. ICM_GetAnyData(
  12080. IN Any *pAny,
  12081. OUT void *pvData,
  12082. IN OUT DWORD *pcbData)
  12083. {
  12084. BOOL fRet;
  12085. LONG lData;
  12086. LONG lRemainExtra;
  12087. PBYTE pbExtra;
  12088. PCRYPT_DATA_BLOB pBlob = (PCRYPT_DATA_BLOB)pvData;
  12089. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12090. lData = INFO_LEN_ALIGN( sizeof(CRYPT_DATA_BLOB));
  12091. lRemainExtra = (LONG)*pcbData - lData;
  12092. if (0 > lRemainExtra) {
  12093. pBlob = NULL;
  12094. pbExtra = NULL;
  12095. } else {
  12096. pbExtra = (PBYTE)pBlob + lData;
  12097. }
  12098. if (!ICM_GetOssAny( pAny, pBlob, &pbExtra, &lRemainExtra))
  12099. goto GetOssAnyError;
  12100. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12101. CommonReturn:
  12102. return fRet;
  12103. ErrorReturn:
  12104. *pcbData = 0;
  12105. fRet = FALSE;
  12106. goto CommonReturn;
  12107. TRACE_ERROR(GetOssAnyError) // error already set
  12108. }
  12109. //+-------------------------------------------------------------------------
  12110. // Get Object Identifier string
  12111. //--------------------------------------------------------------------------
  12112. BOOL
  12113. WINAPI
  12114. ICM_GetOssObjId(
  12115. IN ObjectID *poi,
  12116. OUT LPSTR *ppszObjId,
  12117. IN OUT BYTE **ppbExtra,
  12118. IN OUT LONG *plRemainExtra)
  12119. {
  12120. BOOL fRet;
  12121. LONG lRemainExtra = *plRemainExtra;
  12122. BYTE *pbExtra = *ppbExtra;
  12123. LONG lAlignExtra;
  12124. LONG lObjId;
  12125. if (!PkiAsn1FromObjectIdentifier(
  12126. poi->count,
  12127. poi->value,
  12128. NULL,
  12129. (PDWORD)&lObjId))
  12130. goto PkiAsn1FromObjectIdentifierSizeError;
  12131. lAlignExtra = INFO_LEN_ALIGN(lObjId);
  12132. lRemainExtra -= lAlignExtra;
  12133. if (lRemainExtra >= 0) {
  12134. if(lObjId > 0) {
  12135. *ppszObjId = (LPSTR) pbExtra;
  12136. if (!PkiAsn1FromObjectIdentifier(
  12137. poi->count,
  12138. poi->value,
  12139. (LPSTR)pbExtra,
  12140. (PDWORD)&lObjId))
  12141. goto PkiAsn1FromObjectIdentifierError;
  12142. } else
  12143. *ppszObjId = NULL;
  12144. pbExtra += lAlignExtra;
  12145. }
  12146. fRet = TRUE;
  12147. CommonReturn:
  12148. *plRemainExtra = lRemainExtra;
  12149. *ppbExtra = pbExtra;
  12150. return fRet;
  12151. ErrorReturn:
  12152. *ppszObjId = NULL;
  12153. fRet = FALSE;
  12154. goto CommonReturn;
  12155. SET_ERROR(PkiAsn1FromObjectIdentifierSizeError,CRYPT_E_OID_FORMAT)
  12156. SET_ERROR(PkiAsn1FromObjectIdentifierError,CRYPT_E_OID_FORMAT)
  12157. }
  12158. //+-------------------------------------------------------------------------
  12159. // Get Oss HugeInteger
  12160. //--------------------------------------------------------------------------
  12161. void
  12162. inline
  12163. WINAPI
  12164. ICM_GetOssHugeInteger(
  12165. IN HugeIntegerType *pOssHugeInteger,
  12166. OUT PCRYPT_INTEGER_BLOB pHugeInteger,
  12167. IN OUT BYTE **ppbExtra,
  12168. IN OUT LONG *plRemainExtra
  12169. )
  12170. {
  12171. PkiAsn1GetHugeInteger(pOssHugeInteger->length, pOssHugeInteger->value, 0,
  12172. pHugeInteger, ppbExtra, plRemainExtra);
  12173. }
  12174. //+-------------------------------------------------------------------------
  12175. // Get an Attribute
  12176. //--------------------------------------------------------------------------
  12177. BOOL
  12178. WINAPI
  12179. ICM_GetOssAttribute(
  12180. IN Attribute *poatr,
  12181. OUT PCRYPT_ATTRIBUTE patr,
  12182. IN OUT BYTE **ppbExtra,
  12183. IN OUT LONG *plRemainExtra)
  12184. {
  12185. BOOL fRet;
  12186. LONG lData;
  12187. DWORD i;
  12188. Any *pAny;
  12189. PCRYPT_ATTR_BLOB patrbl = NULL;
  12190. if (!ICM_GetOssObjId(&poatr->attributeType, &patr->pszObjId,
  12191. ppbExtra, plRemainExtra))
  12192. goto GetOssObjIdError;
  12193. lData = INFO_LEN_ALIGN( poatr->attributeValue.count * sizeof(CRYPT_ATTR_BLOB));
  12194. *plRemainExtra -= lData;
  12195. if (0 < *plRemainExtra) {
  12196. patr->cValue = poatr->attributeValue.count;
  12197. patr->rgValue = patrbl = (PCRYPT_ATTR_BLOB)*ppbExtra;
  12198. *ppbExtra += lData;
  12199. }
  12200. for (i=poatr->attributeValue.count, pAny=poatr->attributeValue.value;
  12201. i>0;
  12202. i--, pAny++, patrbl++) {
  12203. if (!ICM_GetOssAny(pAny, patrbl, ppbExtra, plRemainExtra))
  12204. goto GetOssAnyError;
  12205. }
  12206. fRet = TRUE;
  12207. CommonReturn:
  12208. return fRet;
  12209. ErrorReturn:
  12210. fRet = FALSE;
  12211. goto CommonReturn;
  12212. TRACE_ERROR(GetOssObjIdError) // error already set
  12213. TRACE_ERROR(GetOssAnyError) // error already set
  12214. }
  12215. //+-------------------------------------------------------------------------
  12216. // Get an CRYPT_ATTRIBUTE
  12217. //--------------------------------------------------------------------------
  12218. BOOL
  12219. WINAPI
  12220. ICM_GetATTRIBUTE(
  12221. IN Attribute *poatr,
  12222. OUT void *pvData,
  12223. IN OUT DWORD *pcbData)
  12224. {
  12225. BOOL fRet;
  12226. LONG lData;
  12227. LONG lRemainExtra;
  12228. PBYTE pbExtra;
  12229. PCRYPT_ATTRIBUTE patr = (PCRYPT_ATTRIBUTE)pvData;
  12230. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12231. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ATTRIBUTE));
  12232. lRemainExtra = (LONG)*pcbData - lData;
  12233. if (0 > lRemainExtra) {
  12234. patr = NULL;
  12235. pbExtra = NULL;
  12236. } else {
  12237. pbExtra = (PBYTE)patr + lData;
  12238. }
  12239. if (!ICM_GetOssAttribute( poatr, patr, &pbExtra, &lRemainExtra))
  12240. goto GetOssAttributeError;
  12241. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12242. CommonReturn:
  12243. return fRet;
  12244. ErrorReturn:
  12245. *pcbData = 0;
  12246. fRet = FALSE;
  12247. goto CommonReturn;
  12248. TRACE_ERROR(GetOssAttributeError) // error already set
  12249. }
  12250. //+-------------------------------------------------------------------------
  12251. // Get an Attributes
  12252. //--------------------------------------------------------------------------
  12253. BOOL
  12254. WINAPI
  12255. ICM_GetOssAttributes(
  12256. IN Attributes *poatrs,
  12257. OUT PCRYPT_ATTRIBUTES patrs,
  12258. IN OUT BYTE **ppbExtra,
  12259. IN OUT LONG *plRemainExtra)
  12260. {
  12261. BOOL fRet;
  12262. LONG lData;
  12263. DWORD i;
  12264. Attribute *poatr;
  12265. PCRYPT_ATTRIBUTE patr;
  12266. lData = INFO_LEN_ALIGN( poatrs->count * sizeof(CRYPT_ATTRIBUTE));
  12267. *plRemainExtra -= lData;
  12268. if (0 < *plRemainExtra) {
  12269. patrs->cAttr = poatrs->count;
  12270. patrs->rgAttr = patr = (PCRYPT_ATTRIBUTE)*ppbExtra;
  12271. *ppbExtra += lData;
  12272. } else {
  12273. patr = NULL;
  12274. }
  12275. for (i=poatrs->count, poatr=poatrs->value;
  12276. i>0;
  12277. i--, poatr++, patr++) {
  12278. if (!ICM_GetOssAttribute( poatr, patr, ppbExtra, plRemainExtra))
  12279. goto GetOssAttributeError;
  12280. }
  12281. fRet = TRUE;
  12282. CommonReturn:
  12283. return fRet;
  12284. ErrorReturn:
  12285. fRet = FALSE;
  12286. goto CommonReturn;
  12287. TRACE_ERROR(GetOssAttributeError) // error already set
  12288. }
  12289. //+-------------------------------------------------------------------------
  12290. // Get from an Attributes in CList form
  12291. //--------------------------------------------------------------------------
  12292. BOOL
  12293. WINAPI
  12294. ICM_GetCListAttributes(
  12295. IN CBlobList *pBlobList,
  12296. OUT PCRYPT_ATTRIBUTES patrs,
  12297. IN OUT BYTE **ppbExtra,
  12298. IN OUT LONG *plRemainExtra)
  12299. {
  12300. DWORD dwError = ERROR_SUCCESS;
  12301. BOOL fRet;
  12302. LONG lData;
  12303. CBlobNode *pBlobNode;
  12304. AttributeNC2 *poatr = NULL;
  12305. PCRYPT_ATTRIBUTE patr;
  12306. ASN1error_e Asn1Err;
  12307. ASN1decoding_t pDec = ICM_GetDecoder();
  12308. PCRYPT_DATA_BLOB pDataBlob;
  12309. lData = INFO_LEN_ALIGN( pBlobList->Length() * sizeof(CRYPT_ATTRIBUTE));
  12310. *plRemainExtra -= lData;
  12311. if (0 < *plRemainExtra) {
  12312. patrs->cAttr = pBlobList->Length();
  12313. patrs->rgAttr = patr = (PCRYPT_ATTRIBUTE)*ppbExtra;
  12314. *ppbExtra += lData;
  12315. } else {
  12316. patr = NULL;
  12317. }
  12318. for (pBlobNode=pBlobList->Head();
  12319. pBlobNode;
  12320. pBlobNode=pBlobNode->Next(), patr++) {
  12321. poatr = NULL;
  12322. pDataBlob = pBlobNode->Data();
  12323. if (0 != (Asn1Err = PkiAsn1Decode(
  12324. pDec,
  12325. (void **)&poatr,
  12326. AttributeNC2_PDU,
  12327. pDataBlob->pbData,
  12328. pDataBlob->cbData)))
  12329. goto DecodeAttributeNC2Error;
  12330. if (!ICM_GetOssAttribute(
  12331. (Attribute *)poatr, // same, except for NOCOPY
  12332. patr,
  12333. ppbExtra,
  12334. plRemainExtra))
  12335. goto GetOssAttributeError;
  12336. PkiAsn1FreeDecoded(pDec, poatr, AttributeNC2_PDU);
  12337. poatr = NULL;
  12338. }
  12339. fRet = TRUE;
  12340. CommonReturn:
  12341. PkiAsn1FreeInfo(pDec, AttributeNC2_PDU, poatr);
  12342. ICM_SetLastError(dwError);
  12343. return fRet;
  12344. ErrorReturn:
  12345. dwError = GetLastError();
  12346. fRet = FALSE;
  12347. goto CommonReturn;
  12348. SET_ERROR_VAR(DecodeAttributeNC2Error, PkiAsn1ErrToHr(Asn1Err))
  12349. TRACE_ERROR(GetOssAttributeError) // error already set
  12350. }
  12351. //+-------------------------------------------------------------------------
  12352. // Get the data for an Attributes
  12353. //--------------------------------------------------------------------------
  12354. BOOL
  12355. WINAPI
  12356. ICM_GetAttributesData(
  12357. IN Attributes *poatrs,
  12358. OUT void *pvData,
  12359. IN OUT DWORD *pcbData)
  12360. {
  12361. BOOL fRet;
  12362. LONG lData;
  12363. LONG lRemainExtra;
  12364. PBYTE pbExtra;
  12365. PCRYPT_ATTRIBUTES patrs = (PCRYPT_ATTRIBUTES)pvData;
  12366. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12367. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ATTRIBUTES));
  12368. lRemainExtra = (LONG)*pcbData - lData;
  12369. if (0 > lRemainExtra) {
  12370. patrs = NULL;
  12371. pbExtra = NULL;
  12372. } else {
  12373. pbExtra = (PBYTE)patrs + lData;
  12374. }
  12375. if (!ICM_GetOssAttributes( poatrs, patrs, &pbExtra, &lRemainExtra))
  12376. goto GetOssAttributesError;
  12377. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12378. CommonReturn:
  12379. return fRet;
  12380. ErrorReturn:
  12381. *pcbData = 0;
  12382. fRet = FALSE;
  12383. goto CommonReturn;
  12384. TRACE_ERROR(GetOssAttributesError) // error already set
  12385. }
  12386. //+-------------------------------------------------------------------------
  12387. // Get an OSS Algorithm
  12388. //--------------------------------------------------------------------------
  12389. BOOL
  12390. WINAPI
  12391. ICM_GetOssAlgorithm(
  12392. IN AlgorithmIdentifier *pai,
  12393. OUT PCRYPT_ALGORITHM_IDENTIFIER pInfo,
  12394. IN OUT BYTE **ppbExtra,
  12395. IN OUT LONG *plRemainExtra)
  12396. {
  12397. if (!ICM_GetOssObjId(&pai->algorithm, &pInfo->pszObjId,
  12398. ppbExtra, plRemainExtra))
  12399. return FALSE;
  12400. if (pai->bit_mask & parameters_present) {
  12401. if (!ICM_GetOssAny(&pai->parameters, &pInfo->Parameters,
  12402. ppbExtra, plRemainExtra))
  12403. return FALSE;
  12404. } else if (*plRemainExtra >= 0) {
  12405. memset(&pInfo->Parameters, 0, sizeof(pInfo->Parameters));
  12406. }
  12407. return TRUE;
  12408. }
  12409. //+-------------------------------------------------------------------------
  12410. // Get a ContentInfo (internal)
  12411. //--------------------------------------------------------------------------
  12412. BOOL
  12413. WINAPI
  12414. ICM_GetOssContentInfo(
  12415. IN ContentInfo *poci,
  12416. OUT PCONTENT_INFO pInfo,
  12417. IN OUT BYTE **ppbExtra,
  12418. IN OUT LONG *plRemainExtra)
  12419. {
  12420. if (!ICM_GetOssObjId(&poci->contentType, &pInfo->pszContentType,
  12421. ppbExtra, plRemainExtra))
  12422. return FALSE;
  12423. if (poci->bit_mask & content_present) {
  12424. if (!ICM_GetOssAny(&poci->content, &pInfo->content,
  12425. ppbExtra, plRemainExtra))
  12426. return FALSE;
  12427. } else {
  12428. if (pInfo) {
  12429. pInfo->content.cbData = 0;
  12430. pInfo->content.pbData = 0;
  12431. }
  12432. }
  12433. return TRUE;
  12434. }
  12435. //+-------------------------------------------------------------------------
  12436. // Get a ContentInfo
  12437. //--------------------------------------------------------------------------
  12438. BOOL
  12439. WINAPI
  12440. ICM_GetOssContentInfoData(
  12441. IN ContentInfo *poci,
  12442. OUT void *pvData,
  12443. IN OUT DWORD *pcbData)
  12444. {
  12445. BOOL fRet;
  12446. LONG lData;
  12447. LONG lRemainExtra;
  12448. PBYTE pbExtra;
  12449. PCONTENT_INFO pci = (PCONTENT_INFO)pvData;
  12450. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12451. lData = INFO_LEN_ALIGN( sizeof(CONTENT_INFO));
  12452. lRemainExtra = (LONG)*pcbData - lData;
  12453. if (0 > lRemainExtra) {
  12454. pci = NULL;
  12455. pbExtra = NULL;
  12456. } else {
  12457. pbExtra = (PBYTE)pci + lData;
  12458. }
  12459. if (!ICM_GetOssContentInfo( poci, pci, &pbExtra, &lRemainExtra))
  12460. goto GetContentInfoError;
  12461. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12462. CommonReturn:
  12463. return fRet;
  12464. ErrorReturn:
  12465. *pcbData = 0;
  12466. fRet = FALSE;
  12467. goto CommonReturn;
  12468. TRACE_ERROR(GetContentInfoError) // error already set
  12469. }
  12470. BOOL
  12471. WINAPI
  12472. ICM_GetOssIssuerAndSerialNumberFromCertId(
  12473. IN CertIdentifier *pOssCertId,
  12474. OUT PCERT_NAME_BLOB pIssuer,
  12475. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12476. IN OUT BYTE **ppbExtra,
  12477. IN OUT LONG *plRemainExtra);
  12478. //+-------------------------------------------------------------------------
  12479. // Get an Special Issuer and SerialNumber from a KeyId.
  12480. //
  12481. // Converts the KeyId to a special encoded Issuer name having a RDN with
  12482. // the szOID_KEYID_RDN OID and a CERT_RDN_OCTET_STRING value containing
  12483. // the KeyId. The SerialNumber is set to 0.
  12484. //--------------------------------------------------------------------------
  12485. BOOL
  12486. WINAPI
  12487. ICM_GetOssIssuerAndSerialNumberFromKeyId(
  12488. IN SubjectKeyIdentifier *pOssKeyId,
  12489. OUT PCERT_NAME_BLOB pIssuer,
  12490. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12491. IN OUT BYTE **ppbExtra,
  12492. IN OUT LONG *plRemainExtra)
  12493. {
  12494. BOOL fRet;
  12495. CertIdentifier OssCertId;
  12496. ASN1octet_t SerialNumber;
  12497. CERT_RDN_ATTR KeyIdAttr;
  12498. CERT_RDN KeyIdRDN;
  12499. CERT_NAME_INFO IssuerInfo;
  12500. BYTE *pbEncodedIssuer = NULL;
  12501. DWORD cbEncodedIssuer;
  12502. KeyIdAttr.pszObjId = szOID_KEYID_RDN;
  12503. KeyIdAttr.dwValueType = CERT_RDN_OCTET_STRING;
  12504. KeyIdAttr.Value.pbData = pOssKeyId->value;
  12505. KeyIdAttr.Value.cbData = pOssKeyId->length;
  12506. KeyIdRDN.cRDNAttr = 1;
  12507. KeyIdRDN.rgRDNAttr = &KeyIdAttr;
  12508. IssuerInfo.cRDN = 1;
  12509. IssuerInfo.rgRDN = &KeyIdRDN;
  12510. // Encode the special Issuer Name containing the KeyId
  12511. if (!CryptEncodeObjectEx(
  12512. X509_ASN_ENCODING,
  12513. X509_NAME,
  12514. &IssuerInfo,
  12515. CRYPT_ENCODE_ALLOC_FLAG,
  12516. &PkiEncodePara,
  12517. (void *) &pbEncodedIssuer,
  12518. &cbEncodedIssuer
  12519. ))
  12520. goto EncodeError;
  12521. OssCertId.choice = issuerAndSerialNumber_chosen;
  12522. OssCertId.u.issuerAndSerialNumber.serialNumber.length = 1;
  12523. OssCertId.u.issuerAndSerialNumber.serialNumber.value = &SerialNumber;
  12524. SerialNumber = 0;
  12525. OssCertId.u.issuerAndSerialNumber.issuer.length = cbEncodedIssuer;
  12526. OssCertId.u.issuerAndSerialNumber.issuer.value = pbEncodedIssuer;
  12527. fRet = ICM_GetOssIssuerAndSerialNumberFromCertId(
  12528. &OssCertId,
  12529. pIssuer,
  12530. pSerialNumber,
  12531. ppbExtra,
  12532. plRemainExtra
  12533. );
  12534. CommonReturn:
  12535. PkiFree(pbEncodedIssuer);
  12536. return fRet;
  12537. ErrorReturn:
  12538. fRet = FALSE;
  12539. goto CommonReturn;
  12540. TRACE_ERROR(EncodeError)
  12541. }
  12542. //+-------------------------------------------------------------------------
  12543. // Get an Issuer and SerialNumber from a CertIdentifier.
  12544. //
  12545. // Converts a KEYID choice to a special encoded Issuer name having a RDN with
  12546. // the szOID_KEYID_RDN OID and a CERT_RDN_OCTET_STRING value containing
  12547. // the KeyId. The SerialNumber is set to 0.
  12548. //--------------------------------------------------------------------------
  12549. BOOL
  12550. WINAPI
  12551. ICM_GetOssIssuerAndSerialNumberFromCertId(
  12552. IN CertIdentifier *pOssCertId,
  12553. OUT PCERT_NAME_BLOB pIssuer,
  12554. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12555. IN OUT BYTE **ppbExtra,
  12556. IN OUT LONG *plRemainExtra)
  12557. {
  12558. BOOL fRet;
  12559. switch (pOssCertId->choice) {
  12560. case issuerAndSerialNumber_chosen:
  12561. ICM_GetOssHugeInteger(
  12562. &pOssCertId->u.issuerAndSerialNumber.serialNumber,
  12563. pSerialNumber, ppbExtra, plRemainExtra);
  12564. if (!ICM_GetOssAny(&pOssCertId->u.issuerAndSerialNumber.issuer,
  12565. pIssuer, ppbExtra, plRemainExtra))
  12566. goto GetIssuerError;
  12567. break;
  12568. case subjectKeyIdentifier_chosen:
  12569. if (!ICM_GetOssIssuerAndSerialNumberFromKeyId(
  12570. &pOssCertId->u.subjectKeyIdentifier,
  12571. pIssuer, pSerialNumber, ppbExtra, plRemainExtra))
  12572. goto GetKeyIdError;
  12573. break;
  12574. default:
  12575. goto InvalidCertIdChoice;
  12576. }
  12577. fRet = TRUE;
  12578. CommonReturn:
  12579. return fRet;
  12580. ErrorReturn:
  12581. fRet = FALSE;
  12582. goto CommonReturn;
  12583. TRACE_ERROR(GetIssuerError)
  12584. TRACE_ERROR(GetKeyIdError)
  12585. SET_ERROR(InvalidCertIdChoice, CRYPT_E_BAD_ENCODE)
  12586. }
  12587. BOOL
  12588. WINAPI
  12589. ICM_GetOssIssuerAndSerialNumberForCertInfo(
  12590. IN CertIdentifier *pOssCertId,
  12591. OUT PCERT_INFO pCertInfo,
  12592. IN OUT BYTE **ppbExtra,
  12593. IN OUT LONG *plRemainExtra)
  12594. {
  12595. return ICM_GetOssIssuerAndSerialNumberFromCertId(
  12596. pOssCertId,
  12597. &pCertInfo->Issuer,
  12598. &pCertInfo->SerialNumber,
  12599. ppbExtra,
  12600. plRemainExtra
  12601. );
  12602. }
  12603. //+-------------------------------------------------------------------------
  12604. // Get an CertInfo with an updated IssuerAndSerialNumber
  12605. //--------------------------------------------------------------------------
  12606. BOOL
  12607. WINAPI
  12608. ICM_GetCertInfoIssuerAndSerialNumber(
  12609. IN CertIdentifier *pOssCertIdentifier,
  12610. OUT void *pvData,
  12611. IN OUT DWORD *pcbData)
  12612. {
  12613. BOOL fRet;
  12614. LONG lData;
  12615. PCERT_INFO pci = (PCERT_INFO)pvData;
  12616. PBYTE pbExtra;
  12617. LONG lRemainExtra;
  12618. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12619. lData = INFO_LEN_ALIGN( sizeof(CERT_INFO));
  12620. lRemainExtra = (LONG)*pcbData - lData;
  12621. if (0 > lRemainExtra) {
  12622. pci = NULL;
  12623. pbExtra = NULL;
  12624. } else {
  12625. pbExtra = (PBYTE)pci + lData;
  12626. }
  12627. if (!ICM_GetOssIssuerAndSerialNumberForCertInfo(pOssCertIdentifier,
  12628. pci, &pbExtra, &lRemainExtra))
  12629. goto GetOssIssuerAndSerialNumberError;
  12630. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12631. CommonReturn:
  12632. return fRet;
  12633. ErrorReturn:
  12634. *pcbData = 0;
  12635. fRet = FALSE;
  12636. goto CommonReturn;
  12637. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  12638. }
  12639. BOOL
  12640. WINAPI
  12641. ICM_GetOssCertIdentifier(
  12642. IN CertIdentifier *pOssCertId,
  12643. OUT PCERT_ID pCertId,
  12644. IN OUT BYTE **ppbExtra,
  12645. IN OUT LONG *plRemainExtra
  12646. );
  12647. BOOL
  12648. WINAPI
  12649. ICM_GetCertId(
  12650. IN CertIdentifier *pOssCertIdentifier,
  12651. OUT void *pvData,
  12652. IN OUT DWORD *pcbData)
  12653. {
  12654. BOOL fRet;
  12655. LONG lData;
  12656. PCERT_ID pid = (PCERT_ID)pvData;
  12657. PBYTE pbExtra;
  12658. LONG lRemainExtra;
  12659. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12660. lData = INFO_LEN_ALIGN( sizeof(CERT_ID));
  12661. lRemainExtra = (LONG)*pcbData - lData;
  12662. if (0 > lRemainExtra) {
  12663. pid = NULL;
  12664. pbExtra = NULL;
  12665. } else {
  12666. pbExtra = (PBYTE)pid + lData;
  12667. }
  12668. if (!ICM_GetOssCertIdentifier(pOssCertIdentifier,
  12669. pid, &pbExtra, &lRemainExtra))
  12670. goto GetOssCertIdentifierError;
  12671. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12672. CommonReturn:
  12673. return fRet;
  12674. ErrorReturn:
  12675. *pcbData = 0;
  12676. fRet = FALSE;
  12677. goto CommonReturn;
  12678. TRACE_ERROR(GetOssCertIdentifierError) // error already set
  12679. }
  12680. //+-------------------------------------------------------------------------
  12681. // Copy out an CRYPT_ALGORITHM_IDENTIFIER
  12682. //--------------------------------------------------------------------------
  12683. BOOL
  12684. WINAPI
  12685. ICM_GetALGORITHM_IDENTIFIER(
  12686. IN AlgorithmIdentifier *paiOss,
  12687. OUT void *pvData,
  12688. IN OUT DWORD *pcbData)
  12689. {
  12690. BOOL fRet;
  12691. LONG lData;
  12692. PCRYPT_ALGORITHM_IDENTIFIER pai = (PCRYPT_ALGORITHM_IDENTIFIER)pvData;
  12693. PBYTE pbExtra;
  12694. LONG lRemainExtra;
  12695. if (NULL == pvData)
  12696. *pcbData = 0;
  12697. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12698. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ALGORITHM_IDENTIFIER));
  12699. lRemainExtra = (LONG)*pcbData - lData;
  12700. if (0 > lRemainExtra) {
  12701. pai = NULL;
  12702. pbExtra = NULL;
  12703. } else {
  12704. pbExtra = (PBYTE)pai + lData;
  12705. }
  12706. if (!ICM_GetOssAlgorithm( paiOss, pai, &pbExtra, &lRemainExtra))
  12707. goto GetOssAlgorithmError;
  12708. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12709. CommonReturn:
  12710. return fRet;
  12711. ErrorReturn:
  12712. *pcbData = 0;
  12713. fRet = FALSE;
  12714. goto CommonReturn;
  12715. TRACE_ERROR(GetOssAlgorithmError) // error already set
  12716. }
  12717. //+-------------------------------------------------------------------------
  12718. // Get the digest in a DIGESTED message.
  12719. //--------------------------------------------------------------------------
  12720. BOOL
  12721. WINAPI
  12722. ICM_GetDigestDataParam(
  12723. IN PCRYPT_MSG_INFO pcmi,
  12724. OUT void *pvData,
  12725. IN OUT DWORD *pcbData)
  12726. {
  12727. BOOL fRet;
  12728. DigestedData *pdd;
  12729. if (CMSG_HASHED != pcmi->dwMsgType)
  12730. goto InvalidMsgType;
  12731. pdd = (DigestedData *)pcmi->pvMsg;
  12732. fRet = ICM_CopyOut(
  12733. (PBYTE)pdd->digest.value,
  12734. (DWORD)pdd->digest.length,
  12735. (PBYTE)pvData,
  12736. pcbData);
  12737. CommonReturn:
  12738. return fRet;
  12739. ErrorReturn:
  12740. *pcbData = 0;
  12741. fRet = FALSE;
  12742. goto CommonReturn;
  12743. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  12744. }
  12745. #ifdef CMS_PKCS7
  12746. HCRYPTHASH
  12747. WINAPI
  12748. ICM_GetEncodedSignerHash(
  12749. IN PCRYPT_MSG_INFO pcmi,
  12750. IN DWORD dwSignerIndex
  12751. )
  12752. {
  12753. HCRYPTHASH hHash = NULL;
  12754. SignerInfo *psi;
  12755. PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo;
  12756. CHashNode *pnHash;
  12757. PICM_HASH_INFO pHashInfo;
  12758. if (dwSignerIndex >= ((SignedData *)pcmi->pvMsg)->signerInfos.count)
  12759. goto IndexTooBig;
  12760. psi = ((SignedData *)pcmi->pvMsg)->signerInfos.value + dwSignerIndex;
  12761. pSignerEncodeDataInfo = pcmi->rgSignerEncodeDataInfo + dwSignerIndex;
  12762. pnHash = pSignerEncodeDataInfo->pHashNode;
  12763. pHashInfo = pnHash->Data();
  12764. if (psi->bit_mask & authenticatedAttributes_present) {
  12765. if (!ICM_GetAttrsHash(
  12766. pHashInfo->dwAlgoCAPI,
  12767. pSignerEncodeDataInfo->hCryptProv,
  12768. &psi->authenticatedAttributes,
  12769. &hHash))
  12770. goto GetAuthAttrsHashError;
  12771. } else {
  12772. if (!ICM_DupListHash( pnHash, pSignerEncodeDataInfo->hCryptProv,
  12773. &hHash))
  12774. goto DupListHashError;
  12775. }
  12776. CommonReturn:
  12777. return hHash;
  12778. ErrorReturn:
  12779. hHash = NULL;
  12780. goto CommonReturn;
  12781. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  12782. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  12783. TRACE_ERROR(DupListHashError) // error already set
  12784. }
  12785. HCRYPTHASH
  12786. WINAPI
  12787. ICM_GetDecodedSignerHash(
  12788. IN PCRYPT_MSG_INFO pcmi,
  12789. IN DWORD dwSignerIndex
  12790. )
  12791. {
  12792. HCRYPTHASH hHash = NULL;
  12793. DWORD dwError = ERROR_SUCCESS;
  12794. SignerInfoWithBlobs *psib = NULL;
  12795. CSignerNode *pSignerNode = NULL;
  12796. HCRYPTPROV hCryptProv; // doen't need to be released
  12797. ASN1error_e Asn1Err;
  12798. ASN1decoding_t pDec = ICM_GetDecoder();
  12799. CRYPT_DATA_BLOB DataBlob;
  12800. CHashNode *pnHash;
  12801. PICM_HASH_INFO pHashInfo;
  12802. if (!ICM_FindSignerInfo(pcmi, dwSignerIndex, (PVOID *)&pSignerNode))
  12803. goto FindSignerInfoError;
  12804. DataBlob = pSignerNode->Data()->blob;
  12805. if (0 != (Asn1Err = PkiAsn1Decode(
  12806. pDec,
  12807. (void **)&psib,
  12808. SignerInfoWithBlobs_PDU,
  12809. DataBlob.pbData,
  12810. DataBlob.cbData)))
  12811. goto DecodeSignerInfoWithBlobsError;
  12812. if (!ICM_FindHashNodeFromEncodedAlgo(
  12813. pcmi->pHashList,
  12814. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  12815. &pnHash))
  12816. goto GetHashNodeFromEncodedAlgoError;
  12817. pHashInfo = pnHash->Data();
  12818. if (pcmi->fDefaultCryptProv)
  12819. hCryptProv = 0;
  12820. else
  12821. hCryptProv = pcmi->hCryptProv;
  12822. if (0 == hCryptProv) {
  12823. hCryptProv = I_CryptGetDefaultCryptProv(0);
  12824. if (0 == hCryptProv)
  12825. goto GetDefaultCryptProvError;
  12826. }
  12827. if (psib->bit_mask & authAttributes_present) {
  12828. if (!ICM_GetAttrsHash(
  12829. pHashInfo->dwAlgoCAPI,
  12830. hCryptProv,
  12831. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  12832. &hHash))
  12833. goto GetAuthAttrsHashError;
  12834. } else {
  12835. if (!ICM_DupListHash( pnHash, hCryptProv, &hHash))
  12836. goto DupListHashError;
  12837. }
  12838. CommonReturn:
  12839. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  12840. ICM_SetLastError(dwError);
  12841. return hHash;
  12842. ErrorReturn:
  12843. dwError = GetLastError();
  12844. hHash = NULL;
  12845. goto CommonReturn;
  12846. TRACE_ERROR(FindSignerInfoError) // error already set
  12847. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  12848. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  12849. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  12850. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  12851. TRACE_ERROR(DupListHashError) // error already set
  12852. }
  12853. #endif // CMS_PKCS7
  12854. //+-------------------------------------------------------------------------
  12855. // Get the digest of the content in a DIGESTED message or for one of
  12856. // the signers in a SIGNED message
  12857. //--------------------------------------------------------------------------
  12858. BOOL
  12859. WINAPI
  12860. ICM_GetComputedDigestParam(
  12861. IN PCRYPT_MSG_INFO pcmi,
  12862. IN DWORD dwIndex,
  12863. OUT void *pvData,
  12864. IN OUT DWORD *pcbData)
  12865. {
  12866. BOOL fRet;
  12867. DWORD dwError = ERROR_SUCCESS;
  12868. HCRYPTHASH hHash = NULL;
  12869. PBYTE pbAllocHash = NULL;
  12870. DWORD cbHash;
  12871. PBYTE pbHash;
  12872. switch (pcmi->dwMsgType) {
  12873. case CMSG_HASHED:
  12874. if (!ICM_GetListHashValue(
  12875. pcmi->pHashList->Head(),
  12876. &cbHash,
  12877. &pbHash))
  12878. goto GetHashValueError;
  12879. break;
  12880. #ifdef CMS_PKCS7
  12881. case CMSG_SIGNED:
  12882. if (pcmi->fEncoding)
  12883. hHash = ICM_GetEncodedSignerHash(pcmi, dwIndex);
  12884. else
  12885. hHash = ICM_GetDecodedSignerHash(pcmi, dwIndex);
  12886. if (NULL == hHash)
  12887. goto GetSignerHashError;
  12888. if (!CryptGetHashParam(
  12889. hHash,
  12890. HP_HASHVAL,
  12891. NULL,
  12892. &cbHash,
  12893. 0)) // dwFlags
  12894. goto GetHashParamSizeError;
  12895. if (NULL == (pbAllocHash = (PBYTE)ICM_AllocA(cbHash)))
  12896. goto AllocHashParamError;
  12897. pbHash = pbAllocHash;
  12898. if (!CryptGetHashParam(
  12899. hHash,
  12900. HP_HASHVAL,
  12901. pbHash,
  12902. &cbHash,
  12903. 0)) // dwFlags
  12904. goto GetHashParamError;
  12905. break;
  12906. #endif // CMS_PKCS7
  12907. default:
  12908. goto InvalidMsgType;
  12909. }
  12910. fRet = ICM_CopyOut(
  12911. pbHash,
  12912. cbHash,
  12913. (PBYTE)pvData,
  12914. pcbData);
  12915. if (!fRet)
  12916. dwError = GetLastError();
  12917. CommonReturn:
  12918. if (hHash)
  12919. CryptDestroyHash(hHash);
  12920. ICM_FreeA(pbAllocHash);
  12921. ICM_SetLastError(dwError);
  12922. return fRet;
  12923. ErrorReturn:
  12924. dwError = GetLastError();
  12925. *pcbData = 0;
  12926. fRet = FALSE;
  12927. goto CommonReturn;
  12928. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  12929. TRACE_ERROR(GetHashValueError)
  12930. TRACE_ERROR(GetSignerHashError)
  12931. TRACE_ERROR(GetHashParamSizeError)
  12932. TRACE_ERROR(AllocHashParamError)
  12933. TRACE_ERROR(GetHashParamError)
  12934. }
  12935. //+-------------------------------------------------------------------------
  12936. // Find the SignerInfo by index, if the message type permits and if the
  12937. // index value is in range.
  12938. //
  12939. // Returns: FALSE iff fails
  12940. //--------------------------------------------------------------------------
  12941. BOOL
  12942. WINAPI
  12943. ICM_FindSignerInfo(
  12944. IN PCRYPT_MSG_INFO pcmi,
  12945. IN DWORD dwIndex,
  12946. OUT PVOID *ppv)
  12947. {
  12948. BOOL fRet;
  12949. PVOID pv;
  12950. SignerInfo *psi = NULL;
  12951. CSignerNode *pSignerNode = NULL;
  12952. DWORD i;
  12953. if (pcmi->fEncoding) {
  12954. switch (pcmi->dwMsgType) {
  12955. case CMSG_SIGNED:
  12956. if (dwIndex >= ((SignedData *)pcmi->pvMsg)->signerInfos.count)
  12957. goto IndexTooBig;
  12958. psi = ((SignedData *)pcmi->pvMsg)->signerInfos.value + dwIndex;
  12959. break;
  12960. case CMSG_SIGNED_AND_ENVELOPED:
  12961. goto MessageTypeNotSupportedYet;
  12962. default:
  12963. goto InvalidMsgType;
  12964. }
  12965. pv = psi;
  12966. } else {
  12967. switch (pcmi->dwMsgType) {
  12968. case CMSG_SIGNED:
  12969. if (NULL == pcmi->psdi)
  12970. goto InvalidSignedMessageError;
  12971. for (i=dwIndex, pSignerNode=pcmi->psdi->pSignerList->Head();
  12972. (i>0) && pSignerNode;
  12973. i--, pSignerNode=pSignerNode->Next())
  12974. ;
  12975. if (NULL == pSignerNode)
  12976. goto IndexTooBig;
  12977. break;
  12978. case CMSG_SIGNED_AND_ENVELOPED:
  12979. goto MessageTypeNotSupportedYet;
  12980. default:
  12981. goto InvalidMsgType;
  12982. }
  12983. pv = pSignerNode;
  12984. }
  12985. fRet = TRUE;
  12986. CommonReturn:
  12987. *ppv = pv;
  12988. return fRet;
  12989. ErrorReturn:
  12990. pv = NULL;
  12991. fRet = FALSE;
  12992. goto CommonReturn;
  12993. SET_ERROR(InvalidSignedMessageError, ERROR_INVALID_DATA)
  12994. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  12995. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  12996. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  12997. }
  12998. //+-------------------------------------------------------------------------
  12999. // Countersign an already-existing signature, output an encoded attribute
  13000. //--------------------------------------------------------------------------
  13001. BOOL
  13002. WINAPI
  13003. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13004. ICMTest_NewCryptMsgCountersignEncoded(
  13005. #else
  13006. CryptMsgCountersignEncoded(
  13007. #endif
  13008. IN DWORD dwEncodingType,
  13009. IN PBYTE pbSignerInfo,
  13010. IN DWORD cbSignerInfo,
  13011. IN DWORD cCountersigners,
  13012. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  13013. OUT PBYTE pbCountersignatureAttribute,
  13014. IN OUT PDWORD pcbCountersignatureAttribute)
  13015. {
  13016. DWORD dwError = ERROR_SUCCESS;
  13017. BOOL fRet;
  13018. HCRYPTMSG hCryptMsgCountersign = NULL;
  13019. CMSG_SIGNED_ENCODE_INFO EncodeInfo; ZEROSTRUCT(EncodeInfo);
  13020. EncodeInfo.cbSize = sizeof(EncodeInfo);
  13021. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA UnauthAttrPara; ZEROSTRUCT(UnauthAttrPara);
  13022. UnauthAttrPara.cbSize = sizeof(UnauthAttrPara);
  13023. Attribute oatrCountersignature; ZEROSTRUCT(oatrCountersignature);
  13024. ASN1error_e Asn1Err;
  13025. ASN1decoding_t pDec = ICM_GetDecoder();
  13026. ASN1encoding_t pEnc = ICM_GetEncoder();
  13027. PBYTE pbEncoded = NULL;
  13028. DWORD cbEncoded;
  13029. SignerInfoWithBlobs *posib = NULL;
  13030. DWORD i;
  13031. Any *pAny;
  13032. DWORD dwFlags;
  13033. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13034. goto InvalidEncodingTypeError;
  13035. // crack the SignerInfo being countersigned
  13036. if (0 != (Asn1Err = PkiAsn1Decode(
  13037. pDec,
  13038. (void **)&posib,
  13039. SignerInfoWithBlobs_PDU,
  13040. pbSignerInfo,
  13041. cbSignerInfo)))
  13042. goto DecodeSignerInfoError;
  13043. // create a new message
  13044. EncodeInfo.cSigners = cCountersigners;
  13045. EncodeInfo.rgSigners = rgCountersigners;
  13046. dwFlags = CMSG_AUTHENTICATED_ATTRIBUTES_FLAG;
  13047. if (NULL == pbCountersignatureAttribute ||
  13048. 0 == *pcbCountersignatureAttribute)
  13049. dwFlags |= CMSG_MAX_LENGTH_FLAG;
  13050. if (NULL == (hCryptMsgCountersign = CryptMsgOpenToEncode(
  13051. PKCS_7_ASN_ENCODING,
  13052. dwFlags,
  13053. CMSG_SIGNED,
  13054. &EncodeInfo,
  13055. NULL, // pszInnerContentObjID
  13056. NULL))) // pStreamInfo
  13057. goto OpenToEncodeError;
  13058. // feed encrypted digest into the new message
  13059. if (!CryptMsgUpdate(
  13060. hCryptMsgCountersign,
  13061. posib->encryptedDigest.value,
  13062. posib->encryptedDigest.length,
  13063. TRUE)) // fFinal
  13064. goto UpdateError;
  13065. oatrCountersignature.attributeType.count = SIZE_OSS_OID;
  13066. if (!PkiAsn1ToObjectIdentifier(
  13067. szOID_RSA_counterSign,
  13068. &oatrCountersignature.attributeType.count,
  13069. oatrCountersignature.attributeType.value))
  13070. goto PkiAsn1ToObjectIdentifierError;
  13071. oatrCountersignature.attributeValue.count = cCountersigners;
  13072. if (NULL == (oatrCountersignature.attributeValue.value = (Any *)ICM_AllocA(
  13073. cCountersigners * sizeof(Any))))
  13074. goto AllocCountersignersError;
  13075. // extract encoded SignerInfo's, and store
  13076. for (i=0, pAny=oatrCountersignature.attributeValue.value;
  13077. i<cCountersigners;
  13078. i++, pAny++) {
  13079. cbSignerInfo = 0;
  13080. CryptMsgGetParam(
  13081. hCryptMsgCountersign,
  13082. CMSG_ENCODED_SIGNER,
  13083. i,
  13084. NULL,
  13085. &cbSignerInfo);
  13086. if (cbSignerInfo == 0)
  13087. goto GetSignerInfoSizeError;
  13088. if (NULL == (pbSignerInfo = (PBYTE)ICM_AllocA( cbSignerInfo)))
  13089. goto AllocSignerInfoError;
  13090. if (!CryptMsgGetParam(
  13091. hCryptMsgCountersign,
  13092. CMSG_ENCODED_SIGNER,
  13093. i,
  13094. pbSignerInfo,
  13095. &cbSignerInfo))
  13096. goto GetSignerInfoError;
  13097. pAny->length = cbSignerInfo;
  13098. pAny->value = pbSignerInfo;
  13099. }
  13100. // encode the Countersignature attribute
  13101. if (0 != (Asn1Err = PkiAsn1Encode(
  13102. pEnc,
  13103. &oatrCountersignature,
  13104. AttributeNC2_PDU,
  13105. &pbEncoded,
  13106. &cbEncoded)))
  13107. goto Asn1EncodeAttributeError;
  13108. // copy out the Countersignature attribute
  13109. fRet = ICM_CopyOut(
  13110. pbEncoded,
  13111. cbEncoded,
  13112. pbCountersignatureAttribute,
  13113. pcbCountersignatureAttribute);
  13114. if (!fRet)
  13115. dwError = GetLastError();
  13116. CommonReturn:
  13117. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13118. CryptMsgClose( hCryptMsgCountersign);
  13119. if (oatrCountersignature.attributeValue.value) {
  13120. for (i=cCountersigners, pAny=oatrCountersignature.attributeValue.value;
  13121. i>0;
  13122. i--, pAny++)
  13123. ICM_FreeA( pAny->value);
  13124. ICM_FreeA( oatrCountersignature.attributeValue.value);
  13125. }
  13126. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  13127. ICM_SetLastError(dwError);
  13128. return fRet;
  13129. ErrorReturn:
  13130. dwError = GetLastError();
  13131. fRet = FALSE;
  13132. goto CommonReturn;
  13133. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13134. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13135. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  13136. SET_ERROR_VAR(Asn1EncodeAttributeError, PkiAsn1ErrToHr(Asn1Err))
  13137. TRACE_ERROR(OpenToEncodeError) // error already set
  13138. TRACE_ERROR(UpdateError) // error already set
  13139. TRACE_ERROR(AllocCountersignersError) // error already set
  13140. TRACE_ERROR(GetSignerInfoSizeError) // error already set
  13141. TRACE_ERROR(AllocSignerInfoError) // error already set
  13142. TRACE_ERROR(GetSignerInfoError) // error already set
  13143. }
  13144. //+-------------------------------------------------------------------------
  13145. // Countersign an already-existing signature in a message
  13146. //--------------------------------------------------------------------------
  13147. BOOL
  13148. WINAPI
  13149. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13150. ICMTest_NewCryptMsgCountersign(
  13151. #else
  13152. CryptMsgCountersign(
  13153. #endif
  13154. IN OUT HCRYPTMSG hCryptMsg,
  13155. IN DWORD dwIndex,
  13156. IN DWORD cCountersigners,
  13157. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners)
  13158. {
  13159. DWORD dwError = ERROR_SUCCESS;
  13160. BOOL fRet;
  13161. PBYTE pbCountersignatureAttribute = NULL;
  13162. DWORD cbCountersignatureAttribute;
  13163. PBYTE pbSignerInfo = NULL;
  13164. DWORD cbSignerInfo;
  13165. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA UnauthAttrPara; ZEROSTRUCT(UnauthAttrPara);
  13166. UnauthAttrPara.cbSize = sizeof(UnauthAttrPara);
  13167. if (((PCRYPT_MSG_INFO)hCryptMsg)->fEncoding)
  13168. goto EncodingCountersignNotSupportedError;
  13169. // extract encoded SignerInfo being countersigned from the message
  13170. cbSignerInfo = 0;
  13171. CryptMsgGetParam(
  13172. hCryptMsg,
  13173. CMSG_ENCODED_SIGNER,
  13174. dwIndex,
  13175. NULL,
  13176. &cbSignerInfo);
  13177. if (cbSignerInfo == 0)
  13178. goto GetEncodedSignerSizeError;
  13179. if (NULL == (pbSignerInfo = (PBYTE)ICM_AllocA( cbSignerInfo)))
  13180. goto AllocEncodedSignerError;
  13181. if (!CryptMsgGetParam(
  13182. hCryptMsg,
  13183. CMSG_ENCODED_SIGNER,
  13184. dwIndex,
  13185. pbSignerInfo,
  13186. &cbSignerInfo))
  13187. goto GetEncodedSignerError;
  13188. // create the countersignature blob
  13189. cbCountersignatureAttribute = 0;
  13190. CryptMsgCountersignEncoded(
  13191. PKCS_7_ASN_ENCODING,
  13192. pbSignerInfo,
  13193. cbSignerInfo,
  13194. cCountersigners,
  13195. rgCountersigners,
  13196. NULL,
  13197. &cbCountersignatureAttribute);
  13198. if (cbCountersignatureAttribute == 0)
  13199. goto GetCountersignatureAttributeSizeError;
  13200. if (NULL == (pbCountersignatureAttribute = (PBYTE)ICM_AllocA( cbCountersignatureAttribute)))
  13201. goto AllocCountersignatureAttributeError;
  13202. if (!CryptMsgCountersignEncoded(
  13203. PKCS_7_ASN_ENCODING,
  13204. pbSignerInfo,
  13205. cbSignerInfo,
  13206. cCountersigners,
  13207. rgCountersigners,
  13208. pbCountersignatureAttribute,
  13209. &cbCountersignatureAttribute))
  13210. goto GetCountersignatureAttributeError;
  13211. // add encoded Countersignature attribute to unauth attrs
  13212. UnauthAttrPara.dwSignerIndex = dwIndex;
  13213. UnauthAttrPara.blob.cbData = cbCountersignatureAttribute;
  13214. UnauthAttrPara.blob.pbData = pbCountersignatureAttribute;
  13215. if (!CryptMsgControl(
  13216. hCryptMsg,
  13217. 0, // dwFlags
  13218. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
  13219. &UnauthAttrPara))
  13220. goto AddUnauthAttrError;
  13221. fRet = TRUE;
  13222. CommonReturn:
  13223. ICM_FreeA( pbSignerInfo);
  13224. ICM_FreeA( pbCountersignatureAttribute);
  13225. ICM_SetLastError(dwError);
  13226. return fRet;
  13227. ErrorReturn:
  13228. dwError = GetLastError();
  13229. fRet = FALSE;
  13230. goto CommonReturn;
  13231. TRACE_ERROR(EncodingCountersignNotSupportedError) // error already set
  13232. TRACE_ERROR(GetEncodedSignerSizeError) // error already set
  13233. TRACE_ERROR(AllocEncodedSignerError) // error already set
  13234. TRACE_ERROR(GetEncodedSignerError) // error already set
  13235. TRACE_ERROR(GetCountersignatureAttributeSizeError) // error already set
  13236. TRACE_ERROR(AllocCountersignatureAttributeError) // error already set
  13237. TRACE_ERROR(GetCountersignatureAttributeError) // error already set
  13238. TRACE_ERROR(AddUnauthAttrError) // error already set
  13239. }
  13240. #ifdef CMS_PKCS7
  13241. //+-------------------------------------------------------------------------
  13242. // Verify a countersignature, at the SignerInfo level.
  13243. // ie. verify that pbSignerInfoCountersignature contains the encrypted
  13244. // hash of the encryptedDigest field of pbSignerInfo.
  13245. //
  13246. // hCryptProv is used to hash the encryptedDigest field of pbSignerInfo.
  13247. //
  13248. // The signer can be a CERT_PUBLIC_KEY_INFO, certificate context or a
  13249. // chain context.
  13250. //--------------------------------------------------------------------------
  13251. BOOL
  13252. WINAPI
  13253. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13254. ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  13255. #else
  13256. CryptMsgVerifyCountersignatureEncodedEx(
  13257. #endif
  13258. IN HCRYPTPROV hCryptProv,
  13259. IN DWORD dwEncodingType,
  13260. IN PBYTE pbSignerInfo,
  13261. IN DWORD cbSignerInfo,
  13262. IN PBYTE pbSignerInfoCountersignature,
  13263. IN DWORD cbSignerInfoCountersignature,
  13264. IN DWORD dwSignerType,
  13265. IN void *pvSigner,
  13266. IN DWORD dwFlags,
  13267. IN OPTIONAL void *pvReserved
  13268. )
  13269. {
  13270. DWORD dwError = ERROR_SUCCESS;
  13271. BOOL fRet;
  13272. SignerInfoWithBlobs *posib = NULL;
  13273. SignerInfoWithBlobs *posibCS = NULL;
  13274. Any anyValue;
  13275. DWORD cbMessageDigest;
  13276. PBYTE pbMessageDigest;
  13277. DWORD dwDigestAlgoCAPI;
  13278. DWORD dwPubKeyAlgId;
  13279. DWORD dwPubKeyFlags;
  13280. ASN1error_e Asn1Err;
  13281. ASN1decoding_t pDec = ICM_GetDecoder();
  13282. HCRYPTKEY hPubKey = NULL;
  13283. HCRYPTHASH hHashRaw = NULL;
  13284. HCRYPTHASH hHashAttr = NULL;
  13285. PBYTE pbHash = NULL;
  13286. DWORD cbHash;
  13287. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13288. goto InvalidEncodingTypeError;
  13289. // crack the SignerInfo being countersigned
  13290. if (0 != (Asn1Err = PkiAsn1Decode(
  13291. pDec,
  13292. (void **)&posib,
  13293. SignerInfoWithBlobs_PDU,
  13294. pbSignerInfo,
  13295. cbSignerInfo)))
  13296. goto DecodeSignerInfoError;
  13297. // crack the SignerInfo doing the countersigning
  13298. if (0 != (Asn1Err = PkiAsn1Decode(
  13299. pDec,
  13300. (void **)&posibCS,
  13301. SignerInfoWithBlobs_PDU,
  13302. pbSignerInfoCountersignature,
  13303. cbSignerInfoCountersignature)))
  13304. goto DecodeSignerInfoCSError;
  13305. if (!ICM_GetVerifySignatureStuff(
  13306. dwSignerType,
  13307. pvSigner,
  13308. &hCryptProv,
  13309. &hPubKey,
  13310. &dwPubKeyAlgId,
  13311. &dwPubKeyFlags)) goto GetSignatureStuffError;
  13312. // hash the encrypted digest
  13313. if (!ICM_GetCapiFromAlgidBlob(
  13314. (PCRYPT_DATA_BLOB)&posibCS->digestAlgorithm,
  13315. &dwDigestAlgoCAPI))
  13316. goto GetCapiFromAlgidBlobError;
  13317. if (!CryptCreateHash(
  13318. hCryptProv,
  13319. dwDigestAlgoCAPI,
  13320. NULL, // hKey - optional for MAC
  13321. 0, // dwFlags
  13322. &hHashRaw))
  13323. goto CreateHashError;
  13324. if (!ICM_UpdateDigest(
  13325. hHashRaw,
  13326. posib->encryptedDigest.value,
  13327. posib->encryptedDigest.length))
  13328. goto HashDataError;
  13329. if (0 == (posibCS->bit_mask & authAttributes_present))
  13330. goto CountersignerAuthAttributesMissingError;
  13331. // check that the message digest attr matches the hashed encrypted digest
  13332. if (!CryptGetHashParam(
  13333. hHashRaw,
  13334. HP_HASHVAL,
  13335. NULL,
  13336. &cbHash,
  13337. 0)) // dwFlags
  13338. goto GetHashParamSizeError;
  13339. if (NULL == (pbHash = (PBYTE)ICM_AllocA( cbHash)))
  13340. goto AllocHashParamError;
  13341. if (!CryptGetHashParam(
  13342. hHashRaw,
  13343. HP_HASHVAL,
  13344. pbHash,
  13345. &cbHash,
  13346. 0)) // dwFlags
  13347. goto GetHashParamError;
  13348. // find the message digest attr value
  13349. if (!ICM_GetAttrValue(
  13350. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13351. &oidMessageDigest,
  13352. &anyValue))
  13353. goto FindAttrError;
  13354. // find the message digest octets
  13355. if (!Asn1UtilExtractContent(
  13356. #ifdef OSS_CRYPT_ASN1
  13357. anyValue.value,
  13358. #else
  13359. (const BYTE *) anyValue.value,
  13360. #endif // OSS_CRYPT_ASN1
  13361. anyValue.length,
  13362. &cbMessageDigest,
  13363. (const BYTE **)&pbMessageDigest))
  13364. goto ExtractContentError;
  13365. // hash sizes equal?
  13366. if (cbHash != cbMessageDigest)
  13367. goto HashCompareSizeError;
  13368. // hash octets equal?
  13369. if (memcmp( pbMessageDigest, pbHash, cbHash))
  13370. goto HashCompareValueError;
  13371. // Now that we have verified the message digest octets,
  13372. // get the hash of the authenticated attributes.
  13373. if (!ICM_GetAttrsHash(
  13374. dwDigestAlgoCAPI,
  13375. hCryptProv,
  13376. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13377. &hHashAttr))
  13378. goto GetAuthAttrsHashError;
  13379. // verify the hash, signature, and public key are consistent
  13380. if (!ICM_VerifySignature(
  13381. hHashAttr,
  13382. hPubKey,
  13383. dwPubKeyAlgId,
  13384. dwPubKeyFlags,
  13385. posibCS->encryptedDigest.value,
  13386. posibCS->encryptedDigest.length))
  13387. goto VerifySignatureError;
  13388. fRet = TRUE;
  13389. CommonReturn:
  13390. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13391. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posibCS);
  13392. if (hHashRaw)
  13393. CryptDestroyHash( hHashRaw);
  13394. if (hHashAttr)
  13395. CryptDestroyHash( hHashAttr);
  13396. if (hPubKey)
  13397. CryptDestroyKey( hPubKey);
  13398. ICM_FreeA( pbHash);
  13399. ICM_SetLastError(dwError);
  13400. return fRet;
  13401. ErrorReturn:
  13402. dwError = GetLastError();
  13403. fRet = FALSE;
  13404. goto CommonReturn;
  13405. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13406. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13407. SET_ERROR_VAR(DecodeSignerInfoCSError, PkiAsn1ErrToHr(Asn1Err))
  13408. SET_ERROR(CountersignerAuthAttributesMissingError,CRYPT_E_AUTH_ATTR_MISSING)
  13409. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  13410. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  13411. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  13412. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  13413. TRACE_ERROR(GetCapiFromAlgidBlobError) // error already set
  13414. TRACE_ERROR(CreateHashError) // error already set
  13415. TRACE_ERROR(HashDataError) // error already set
  13416. TRACE_ERROR(GetHashParamSizeError) // error already set
  13417. TRACE_ERROR(AllocHashParamError) // error already set
  13418. TRACE_ERROR(GetHashParamError) // error already set
  13419. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  13420. TRACE_ERROR(GetSignatureStuffError) // error already set
  13421. TRACE_ERROR(VerifySignatureError) // error already set
  13422. }
  13423. //+-------------------------------------------------------------------------
  13424. // Verify a countersignature, at the SignerInfo level
  13425. //--------------------------------------------------------------------------
  13426. BOOL
  13427. WINAPI
  13428. CryptMsgVerifyCountersignatureEncoded(
  13429. IN HCRYPTPROV hCryptProv,
  13430. IN DWORD dwEncodingType,
  13431. IN PBYTE pbSignerInfo,
  13432. IN DWORD cbSignerInfo,
  13433. IN PBYTE pbSignerInfoCountersignature,
  13434. IN DWORD cbSignerInfoCountersignature,
  13435. IN PCERT_INFO pciCountersigner)
  13436. {
  13437. return CryptMsgVerifyCountersignatureEncodedEx(
  13438. hCryptProv,
  13439. dwEncodingType,
  13440. pbSignerInfo,
  13441. cbSignerInfo,
  13442. pbSignerInfoCountersignature,
  13443. cbSignerInfoCountersignature,
  13444. CMSG_VERIFY_SIGNER_PUBKEY,
  13445. (void *) &pciCountersigner->SubjectPublicKeyInfo,
  13446. 0, // dwFlags
  13447. NULL // pvReserved
  13448. );
  13449. }
  13450. #else
  13451. //+-------------------------------------------------------------------------
  13452. // Verify a countersignature, at the SignerInfo level
  13453. //--------------------------------------------------------------------------
  13454. BOOL
  13455. WINAPI
  13456. CryptMsgVerifyCountersignatureEncoded(
  13457. IN HCRYPTPROV hCryptProv,
  13458. IN DWORD dwEncodingType,
  13459. IN PBYTE pbSignerInfo,
  13460. IN DWORD cbSignerInfo,
  13461. IN PBYTE pbSignerInfoCountersignature,
  13462. IN DWORD cbSignerInfoCountersignature,
  13463. IN PCERT_INFO pciCountersigner)
  13464. {
  13465. DWORD dwError = ERROR_SUCCESS;
  13466. BOOL fRet;
  13467. SignerInfoWithBlobs *posib = NULL;
  13468. SignerInfoWithBlobs *posibCS = NULL;
  13469. Any anyValue;
  13470. DWORD cbMessageDigest;
  13471. PBYTE pbMessageDigest;
  13472. DWORD dwDigestAlgoCAPI;
  13473. DWORD dwPubKeyAlgId;
  13474. DWORD dwPubKeyFlags;
  13475. ASN1error_e Asn1Err;
  13476. ASN1decoding_t pDec = ICM_GetDecoder();
  13477. IssuerAndSerialNumber *pisn = NULL;
  13478. HCRYPTKEY hPubKey = NULL;
  13479. HCRYPTHASH hHashRaw = NULL;
  13480. HCRYPTHASH hHashAttr = NULL;
  13481. PBYTE pbHash = NULL;
  13482. DWORD cbHash;
  13483. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13484. goto InvalidEncodingTypeError;
  13485. // crack the SignerInfo being countersigned
  13486. if (0 != (Asn1Err = PkiAsn1Decode(
  13487. pDec,
  13488. (void **)&posib,
  13489. SignerInfoWithBlobs_PDU,
  13490. pbSignerInfo,
  13491. cbSignerInfo)))
  13492. goto DecodeSignerInfoError;
  13493. // crack the SignerInfo doing the countersigning
  13494. if (0 != (Asn1Err = PkiAsn1Decode(
  13495. pDec,
  13496. (void **)&posibCS,
  13497. SignerInfoWithBlobs_PDU,
  13498. pbSignerInfoCountersignature,
  13499. cbSignerInfoCountersignature)))
  13500. goto DecodeSignerInfoCSError;
  13501. // verify that the countersignature SignerInfo and the cert info are consistent
  13502. if (0 != (Asn1Err = PkiAsn1Decode(
  13503. pDec,
  13504. (void **)&pisn,
  13505. IssuerAndSerialNumber_PDU,
  13506. (BYTE *) posibCS->issuerAndSerialNumber.value,
  13507. posibCS->issuerAndSerialNumber.length)))
  13508. goto DecodeIssuerAndSerialNumberError;
  13509. if (pisn->issuer.length != pciCountersigner->Issuer.cbData)
  13510. goto IssuerSizeMismatchError;
  13511. if (0 != memcmp(
  13512. pciCountersigner->Issuer.pbData,
  13513. pisn->issuer.value,
  13514. pciCountersigner->Issuer.cbData))
  13515. goto IssuerValueMismatchError;
  13516. if (pisn->serialNumber.length != pciCountersigner->SerialNumber.cbData)
  13517. goto SerialNumberSizeMismatchError;
  13518. if (ICM_ReverseCompare(
  13519. pisn->serialNumber.value,
  13520. pciCountersigner->SerialNumber.pbData,
  13521. pciCountersigner->SerialNumber.cbData))
  13522. goto SerialNumberValueMismatchError;
  13523. if (!ICM_GetVerifySignatureStuff(
  13524. pciCountersigner,
  13525. &hCryptProv,
  13526. &hPubKey,
  13527. &dwPubKeyAlgId,
  13528. &dwPubKeyFlags)) goto GetSignatureStuffError;
  13529. // hash the encrypted digest
  13530. if (!ICM_GetCapiFromAlgidBlob(
  13531. (PCRYPT_DATA_BLOB)&posibCS->digestAlgorithm,
  13532. &dwDigestAlgoCAPI))
  13533. goto GetCapiFromAlgidBlobError;
  13534. if (!CryptCreateHash(
  13535. hCryptProv,
  13536. dwDigestAlgoCAPI,
  13537. NULL, // hKey - optional for MAC
  13538. 0, // dwFlags
  13539. &hHashRaw))
  13540. goto CreateHashError;
  13541. if (!ICM_UpdateDigest(
  13542. hHashRaw,
  13543. posib->encryptedDigest.value,
  13544. posib->encryptedDigest.length))
  13545. goto HashDataError;
  13546. if (0 == (posibCS->bit_mask & authAttributes_present))
  13547. goto CountersignerAuthAttributesMissingError;
  13548. // check that the message digest attr matches the hashed encrypted digest
  13549. if (!CryptGetHashParam(
  13550. hHashRaw,
  13551. HP_HASHVAL,
  13552. NULL,
  13553. &cbHash,
  13554. 0)) // dwFlags
  13555. goto GetHashParamSizeError;
  13556. if (NULL == (pbHash = (PBYTE)ICM_AllocA( cbHash)))
  13557. goto AllocHashParamError;
  13558. if (!CryptGetHashParam(
  13559. hHashRaw,
  13560. HP_HASHVAL,
  13561. pbHash,
  13562. &cbHash,
  13563. 0)) // dwFlags
  13564. goto GetHashParamError;
  13565. // find the message digest attr value
  13566. if (!ICM_GetAttrValue(
  13567. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13568. &oidMessageDigest,
  13569. &anyValue))
  13570. goto FindAttrError;
  13571. // find the message digest octets
  13572. if (!Asn1UtilExtractContent(
  13573. (BYTE *) anyValue.value,
  13574. anyValue.length,
  13575. &cbMessageDigest,
  13576. (const BYTE **)&pbMessageDigest))
  13577. goto ExtractContentError;
  13578. // hash sizes equal?
  13579. if (cbHash != cbMessageDigest)
  13580. goto HashCompareSizeError;
  13581. // hash octets equal?
  13582. if (memcmp( pbMessageDigest, pbHash, cbHash))
  13583. goto HashCompareValueError;
  13584. // Now that we have verified the message digest octets,
  13585. // get the hash of the authenticated attributes.
  13586. if (!ICM_GetAttrsHash(
  13587. dwDigestAlgoCAPI,
  13588. hCryptProv,
  13589. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13590. &hHashAttr))
  13591. goto GetAuthAttrsHashError;
  13592. // verify the hash, signature, and public key are consistent
  13593. if (!ICM_VerifySignature(
  13594. hHashAttr,
  13595. hPubKey,
  13596. dwPubKeyAlgId,
  13597. dwPubKeyFlags,
  13598. posibCS->encryptedDigest.value,
  13599. posibCS->encryptedDigest.length))
  13600. goto VerifySignatureError;
  13601. fRet = TRUE;
  13602. CommonReturn:
  13603. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13604. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posibCS);
  13605. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  13606. if (hHashRaw)
  13607. CryptDestroyHash( hHashRaw);
  13608. if (hHashAttr)
  13609. CryptDestroyHash( hHashAttr);
  13610. if (hPubKey)
  13611. CryptDestroyKey( hPubKey);
  13612. ICM_FreeA( pbHash);
  13613. ICM_SetLastError(dwError);
  13614. return fRet;
  13615. ErrorReturn:
  13616. dwError = GetLastError();
  13617. fRet = FALSE;
  13618. goto CommonReturn;
  13619. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13620. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13621. SET_ERROR_VAR(DecodeSignerInfoCSError, PkiAsn1ErrToHr(Asn1Err))
  13622. SET_ERROR_VAR(DecodeIssuerAndSerialNumberError, PkiAsn1ErrToHr(Asn1Err))
  13623. SET_ERROR(IssuerSizeMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13624. SET_ERROR(IssuerValueMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13625. SET_ERROR(SerialNumberSizeMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13626. SET_ERROR(SerialNumberValueMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13627. SET_ERROR(CountersignerAuthAttributesMissingError,CRYPT_E_AUTH_ATTR_MISSING)
  13628. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  13629. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  13630. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  13631. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  13632. TRACE_ERROR(GetCapiFromAlgidBlobError) // error already set
  13633. TRACE_ERROR(CreateHashError) // error already set
  13634. TRACE_ERROR(HashDataError) // error already set
  13635. TRACE_ERROR(GetHashParamSizeError) // error already set
  13636. TRACE_ERROR(AllocHashParamError) // error already set
  13637. TRACE_ERROR(GetHashParamError) // error already set
  13638. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  13639. TRACE_ERROR(GetSignatureStuffError) // error already set
  13640. TRACE_ERROR(VerifySignatureError) // error already set
  13641. }
  13642. #endif // CMS_PKCS7
  13643. //+-------------------------------------------------------------------------
  13644. // Set an OSS Any
  13645. //--------------------------------------------------------------------------
  13646. void
  13647. WINAPI
  13648. ICM_SetOssAny(
  13649. IN PCRYPT_OBJID_BLOB pInfo,
  13650. OUT OpenType *pOss
  13651. )
  13652. {
  13653. memset(pOss, 0, sizeof(*pOss));
  13654. pOss->encoded = pInfo->pbData;
  13655. pOss->length = pInfo->cbData;
  13656. }
  13657. //+-------------------------------------------------------------------------
  13658. // Encode a CMS SignerInfo
  13659. //--------------------------------------------------------------------------
  13660. STATIC
  13661. BOOL
  13662. WINAPI
  13663. ICM_CmsSignerInfoEncode(
  13664. IN DWORD dwEncodingType,
  13665. IN LPCSTR lpszStructType,
  13666. IN PCMSG_CMS_SIGNER_INFO pInfo,
  13667. OUT PBYTE pbEncoded,
  13668. IN OUT PDWORD pcbEncoded)
  13669. {
  13670. DWORD dwError = ERROR_SUCCESS;
  13671. BOOL fRet;
  13672. SignerInfo osi; ZEROSTRUCT(osi);
  13673. PCMSG_CMS_SIGNER_INFO psi = pInfo;
  13674. DWORD i;
  13675. Attribute *poatrAuth = NULL;
  13676. Attribute *poatrUnauth = NULL;
  13677. Attribute *poatr;
  13678. PCRYPT_ATTRIBUTE patr;
  13679. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13680. goto InvalidEncodingTypeError;
  13681. // version
  13682. osi.version = psi->dwVersion;
  13683. // sid
  13684. if (!ICM_SetOssCertIdentifier(
  13685. &psi->SignerId,
  13686. &osi.sid
  13687. ))
  13688. goto SetOssCertIdentifierError;
  13689. // digestAlgorithm
  13690. if (!ICM_Asn1ToAlgorithmIdentifier(
  13691. &psi->HashAlgorithm,
  13692. &osi.digestAlgorithm))
  13693. goto DigestAsn1ToAlgorithmIdentifierError;
  13694. // authenticatedAttributes
  13695. if (psi->AuthAttrs.cAttr) {
  13696. osi.bit_mask |= authenticatedAttributes_present;
  13697. osi.authenticatedAttributes.count = psi->AuthAttrs.cAttr;
  13698. if (NULL == (poatrAuth = (Attribute *)ICM_AllocA(
  13699. psi->AuthAttrs.cAttr * sizeof(Attribute))))
  13700. goto AllocAuthAttrsError;
  13701. osi.authenticatedAttributes.value = poatrAuth;
  13702. for (i=psi->AuthAttrs.cAttr, patr=psi->AuthAttrs.rgAttr, poatr=poatrAuth;
  13703. i>0;
  13704. i--, patr++, poatr++) {
  13705. if (!ICM_Asn1ToAttribute( patr, poatr))
  13706. goto Asn1AuthenticatedAttributeError;
  13707. }
  13708. }
  13709. // digestEncryptionAlgorithm
  13710. if (!ICM_FillAsnDigestEncryptionAlgorithm(
  13711. NULL, // pcmi
  13712. &psi->HashEncryptionAlgorithm,
  13713. &osi.digestEncryptionAlgorithm))
  13714. goto FillAsnDigestEncryptionAlgorithmError;
  13715. // encryptedDigest
  13716. osi.encryptedDigest.length = psi->EncryptedHash.cbData;
  13717. osi.encryptedDigest.value = psi->EncryptedHash.pbData;
  13718. // unauthenticatedAttributes
  13719. if (psi->UnauthAttrs.cAttr) {
  13720. osi.bit_mask |= unauthAttributes_present;
  13721. osi.unauthAttributes.count = psi->UnauthAttrs.cAttr;
  13722. if (NULL == (poatrUnauth = (Attribute *)ICM_AllocA(
  13723. psi->UnauthAttrs.cAttr * sizeof(Attribute))))
  13724. goto AllocUnauthAttrsError;
  13725. osi.unauthAttributes.value = poatrUnauth;
  13726. for (i=psi->UnauthAttrs.cAttr, patr=psi->UnauthAttrs.rgAttr, poatr=poatrUnauth;
  13727. i>0;
  13728. i--, patr++, poatr++) {
  13729. if (!ICM_Asn1ToAttribute( patr, poatr))
  13730. goto Asn1UnauthenticatedAttributeError;
  13731. }
  13732. }
  13733. fRet = PkiAsn1EncodeInfo(
  13734. ICM_GetEncoder(),
  13735. SignerInfo_PDU,
  13736. &osi,
  13737. pbEncoded,
  13738. pcbEncoded);
  13739. if (!fRet)
  13740. dwError = GetLastError();
  13741. CommonReturn:
  13742. ICM_FreeOssCertIdentifier(&osi.sid);
  13743. if (poatrAuth) {
  13744. for (i=psi->AuthAttrs.cAttr, poatr=poatrAuth;
  13745. i>0;
  13746. i--, poatr++)
  13747. ICM_Free( poatr->attributeValue.value);
  13748. }
  13749. if (poatrUnauth) {
  13750. for (i=psi->UnauthAttrs.cAttr, poatr=poatrUnauth;
  13751. i>0;
  13752. i--, poatr++)
  13753. ICM_Free( poatr->attributeValue.value);
  13754. }
  13755. ICM_FreeA( poatrAuth);
  13756. ICM_FreeA( poatrUnauth);
  13757. ICM_SetLastError(dwError);
  13758. return fRet;
  13759. ErrorReturn:
  13760. dwError = GetLastError();
  13761. fRet = FALSE;
  13762. *pcbEncoded = 0;
  13763. goto CommonReturn;
  13764. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13765. TRACE_ERROR(SetOssCertIdentifierError) // error already set
  13766. TRACE_ERROR(DigestAsn1ToAlgorithmIdentifierError) // error already set
  13767. TRACE_ERROR(AllocAuthAttrsError) // error already set
  13768. TRACE_ERROR(Asn1AuthenticatedAttributeError) // error already set
  13769. TRACE_ERROR(FillAsnDigestEncryptionAlgorithmError) // error already set
  13770. TRACE_ERROR(AllocUnauthAttrsError) // error already set
  13771. TRACE_ERROR(Asn1UnauthenticatedAttributeError) // error already set
  13772. lpszStructType;
  13773. }
  13774. //+-------------------------------------------------------------------------
  13775. // Encode a Pkcs SignerInfo
  13776. //--------------------------------------------------------------------------
  13777. STATIC
  13778. BOOL
  13779. WINAPI
  13780. ICM_PkcsSignerInfoEncode(
  13781. IN DWORD dwEncodingType,
  13782. IN LPCSTR lpszStructType,
  13783. IN PCMSG_SIGNER_INFO pInfo,
  13784. OUT PBYTE pbEncoded,
  13785. IN OUT PDWORD pcbEncoded)
  13786. {
  13787. CMSG_CMS_SIGNER_INFO csi;
  13788. CERT_INFO CertInfo;
  13789. csi.dwVersion = pInfo->dwVersion;
  13790. CertInfo.Issuer = pInfo->Issuer;
  13791. CertInfo.SerialNumber = pInfo->SerialNumber;
  13792. ICM_GetCertIdFromCertInfo(&CertInfo, &csi.SignerId);
  13793. csi.HashAlgorithm = pInfo->HashAlgorithm;
  13794. csi.HashEncryptionAlgorithm = pInfo->HashEncryptionAlgorithm;
  13795. csi.EncryptedHash = pInfo->EncryptedHash;
  13796. csi.AuthAttrs = pInfo->AuthAttrs;
  13797. csi.UnauthAttrs = pInfo->UnauthAttrs;
  13798. return ICM_CmsSignerInfoEncode(
  13799. dwEncodingType,
  13800. lpszStructType,
  13801. &csi,
  13802. pbEncoded,
  13803. pcbEncoded
  13804. );
  13805. }
  13806. //+-------------------------------------------------------------------------
  13807. // Get fields shared by PKCS and CMS SignerInfos
  13808. //--------------------------------------------------------------------------
  13809. BOOL
  13810. WINAPI
  13811. ICM_GetOssSharedSignerInfo(
  13812. IN SignerInfo *posi,
  13813. IN CBlobList *pUnauthAttrList,
  13814. OUT PCRYPT_ALGORITHM_IDENTIFIER pHashAlgorithm,
  13815. OUT PCRYPT_ALGORITHM_IDENTIFIER pHashEncryptionAlgorithm,
  13816. OUT PCRYPT_DATA_BLOB pEncryptedHash,
  13817. OUT PCRYPT_ATTRIBUTES pAuthAttrs,
  13818. OUT PCRYPT_ATTRIBUTES pUnauthAttrs,
  13819. IN OUT PBYTE *ppbExtra,
  13820. IN OUT LONG *plRemainExtra)
  13821. {
  13822. BOOL fRet;
  13823. if (!ICM_GetOssAlgorithm( &posi->digestAlgorithm,
  13824. pHashAlgorithm, ppbExtra, plRemainExtra))
  13825. goto GetOssHashAlgorithmError;
  13826. if (!ICM_GetOssAlgorithm( &posi->digestEncryptionAlgorithm,
  13827. pHashEncryptionAlgorithm, ppbExtra, plRemainExtra))
  13828. goto GetOssHashEncryptionAlgorithmError;
  13829. if (!ICM_GetOssAny( (Any *)&posi->encryptedDigest,
  13830. pEncryptedHash, ppbExtra, plRemainExtra))
  13831. goto GetOssEncryptedHashError;
  13832. if (posi->bit_mask & authenticatedAttributes_present) {
  13833. if (!ICM_GetOssAttributes( &posi->authenticatedAttributes,
  13834. pAuthAttrs, ppbExtra, plRemainExtra))
  13835. goto GetOssAuthAttrsError;
  13836. } else if (0 <= *plRemainExtra)
  13837. pAuthAttrs->cAttr = 0;
  13838. if (posi->bit_mask & unauthAttributes_present || pUnauthAttrList) {
  13839. if (pUnauthAttrList) {
  13840. if (!ICM_GetCListAttributes( pUnauthAttrList,
  13841. pUnauthAttrs, ppbExtra, plRemainExtra))
  13842. goto GetCListUnauthAttrsError;
  13843. } else {
  13844. if (!ICM_GetOssAttributes( &posi->unauthAttributes,
  13845. pUnauthAttrs, ppbExtra, plRemainExtra))
  13846. goto GetOssUnauthAttrsError;
  13847. }
  13848. } else if (0 <= *plRemainExtra)
  13849. pUnauthAttrs->cAttr = 0;
  13850. fRet = TRUE;
  13851. CommonReturn:
  13852. return fRet;
  13853. ErrorReturn:
  13854. fRet = FALSE;
  13855. goto CommonReturn;
  13856. TRACE_ERROR(GetOssHashAlgorithmError) // error already set
  13857. TRACE_ERROR(GetOssHashEncryptionAlgorithmError) // error already set
  13858. TRACE_ERROR(GetOssEncryptedHashError) // error already set
  13859. TRACE_ERROR(GetOssAuthAttrsError) // error already set
  13860. TRACE_ERROR(GetCListUnauthAttrsError) // error already set
  13861. TRACE_ERROR(GetOssUnauthAttrsError) // error already set
  13862. }
  13863. //+-------------------------------------------------------------------------
  13864. // Get a CMS SignerInfo
  13865. //--------------------------------------------------------------------------
  13866. BOOL
  13867. WINAPI
  13868. ICM_GetOssCmsSignerInfo(
  13869. IN SignerInfo *posi,
  13870. IN CBlobList *pUnauthAttrList,
  13871. OUT PCMSG_CMS_SIGNER_INFO psi,
  13872. IN OUT PBYTE *ppbExtra,
  13873. IN OUT LONG *plRemainExtra)
  13874. {
  13875. BOOL fRet;
  13876. if (0 <= *plRemainExtra)
  13877. psi->dwVersion = posi->version;
  13878. if (!ICM_GetOssCertIdentifier(&posi->sid, &psi->SignerId,
  13879. ppbExtra, plRemainExtra))
  13880. goto GetOssCertIdentifierError;
  13881. if (!ICM_GetOssSharedSignerInfo(
  13882. posi,
  13883. pUnauthAttrList,
  13884. &psi->HashAlgorithm,
  13885. &psi->HashEncryptionAlgorithm,
  13886. &psi->EncryptedHash,
  13887. &psi->AuthAttrs,
  13888. &psi->UnauthAttrs,
  13889. ppbExtra,
  13890. plRemainExtra))
  13891. goto GetOssSharedSignerInfoError;
  13892. fRet = TRUE;
  13893. CommonReturn:
  13894. return fRet;
  13895. ErrorReturn:
  13896. fRet = FALSE;
  13897. goto CommonReturn;
  13898. TRACE_ERROR(GetOssCertIdentifierError) // error already set
  13899. TRACE_ERROR(GetOssSharedSignerInfoError) // error already set
  13900. }
  13901. //+-------------------------------------------------------------------------
  13902. // Get a PKCS SignerInfo
  13903. //--------------------------------------------------------------------------
  13904. BOOL
  13905. WINAPI
  13906. ICM_GetOssPkcsSignerInfo(
  13907. IN SignerInfo *posi,
  13908. IN CBlobList *pUnauthAttrList,
  13909. OUT PCMSG_SIGNER_INFO psi,
  13910. IN OUT PBYTE *ppbExtra,
  13911. IN OUT LONG *plRemainExtra)
  13912. {
  13913. BOOL fRet;
  13914. if (0 <= *plRemainExtra)
  13915. psi->dwVersion = posi->version;
  13916. if (!ICM_GetOssIssuerAndSerialNumberFromCertId(&posi->sid,
  13917. &psi->Issuer, &psi->SerialNumber, ppbExtra, plRemainExtra))
  13918. goto GetOssIssuerAndSerialNumberError;
  13919. if (!ICM_GetOssSharedSignerInfo(
  13920. posi,
  13921. pUnauthAttrList,
  13922. &psi->HashAlgorithm,
  13923. &psi->HashEncryptionAlgorithm,
  13924. &psi->EncryptedHash,
  13925. &psi->AuthAttrs,
  13926. &psi->UnauthAttrs,
  13927. ppbExtra,
  13928. plRemainExtra))
  13929. goto GetOssSharedSignerInfoError;
  13930. fRet = TRUE;
  13931. CommonReturn:
  13932. return fRet;
  13933. ErrorReturn:
  13934. fRet = FALSE;
  13935. goto CommonReturn;
  13936. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  13937. TRACE_ERROR(GetOssSharedSignerInfoError) // error already set
  13938. }
  13939. //+-------------------------------------------------------------------------
  13940. // Decode a PKCS SignerInfo blob.
  13941. //
  13942. // Returns: FALSE iff fails
  13943. //--------------------------------------------------------------------------
  13944. STATIC
  13945. BOOL
  13946. WINAPI
  13947. ICM_PkcsSignerInfoDecode(
  13948. IN DWORD dwEncodingType,
  13949. IN LPCSTR lpszStructType,
  13950. IN const BYTE *pbEncoded,
  13951. IN DWORD cbEncoded,
  13952. IN DWORD dwFlags,
  13953. OUT PCMSG_SIGNER_INFO pInfo,
  13954. IN OUT DWORD *pcbInfo)
  13955. {
  13956. DWORD dwError = ERROR_SUCCESS;
  13957. BOOL fRet;
  13958. LONG lData;
  13959. SignerInfo *posi = NULL;
  13960. ASN1error_e Asn1Err;
  13961. ASN1decoding_t pDec = ICM_GetDecoder();
  13962. PCMSG_SIGNER_INFO psi = pInfo;
  13963. LONG lRemainExtra;
  13964. PBYTE pbExtra;
  13965. if (pInfo == NULL)
  13966. *pcbInfo = 0;
  13967. if (0 != (Asn1Err = PkiAsn1Decode(
  13968. pDec,
  13969. (void **)&posi,
  13970. SignerInfo_PDU,
  13971. pbEncoded,
  13972. cbEncoded)))
  13973. goto Asn1DecodeSignerInfoError;
  13974. // for lRemainExtra < 0, LENGTH_ONLY calculation
  13975. lData = INFO_LEN_ALIGN( sizeof(CMSG_SIGNER_INFO));
  13976. lRemainExtra = (LONG)*pcbInfo - lData;
  13977. if (0 > lRemainExtra) {
  13978. psi = NULL;
  13979. pbExtra = NULL;
  13980. } else {
  13981. pbExtra = (PBYTE)psi + lData;
  13982. }
  13983. if (!ICM_GetOssPkcsSignerInfo(
  13984. posi,
  13985. NULL, // pUnauthAttrList
  13986. psi, &pbExtra, &lRemainExtra))
  13987. goto GetOssSignerInfoError;
  13988. fRet = ICM_GetSizeFromExtra( lRemainExtra, pInfo, pcbInfo);
  13989. if (!fRet)
  13990. dwError = GetLastError();
  13991. CommonReturn:
  13992. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  13993. ICM_SetLastError(dwError);
  13994. return fRet;
  13995. ErrorReturn:
  13996. dwError = GetLastError();
  13997. *pcbInfo = 0;
  13998. fRet = FALSE;
  13999. goto CommonReturn;
  14000. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14001. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14002. dwFlags;
  14003. lpszStructType;
  14004. }
  14005. //+-------------------------------------------------------------------------
  14006. // Find the Pkcs SignerInfo by index, if the message type permits and if the
  14007. // index value is in range.
  14008. //
  14009. // Returns: FALSE iff fails
  14010. //--------------------------------------------------------------------------
  14011. BOOL
  14012. WINAPI
  14013. ICM_GetPkcsSignerInfo(
  14014. IN PCRYPT_MSG_INFO pcmi,
  14015. IN DWORD dwIndex,
  14016. OUT PVOID pvData,
  14017. IN OUT PDWORD pcbData)
  14018. {
  14019. DWORD dwError = ERROR_SUCCESS;
  14020. BOOL fRet;
  14021. LONG lData;
  14022. CSignerNode *pSignerNode;
  14023. SignerInfo *posi = NULL;
  14024. ASN1error_e Asn1Err;
  14025. ASN1decoding_t pDec = ICM_GetDecoder();
  14026. CRYPT_DATA_BLOB DataBlob;
  14027. PCMSG_SIGNER_INFO psi = (PCMSG_SIGNER_INFO)pvData;
  14028. LONG lRemainExtra;
  14029. PBYTE pbExtra;
  14030. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14031. goto FindSignerInfoError;
  14032. DataBlob = pSignerNode->Data()->blob;
  14033. if (0 != (Asn1Err = PkiAsn1Decode(
  14034. pDec,
  14035. (void **)&posi,
  14036. SignerInfo_PDU,
  14037. DataBlob.pbData,
  14038. DataBlob.cbData)))
  14039. goto Asn1DecodeSignerInfoError;
  14040. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14041. lData = INFO_LEN_ALIGN( sizeof(CMSG_SIGNER_INFO));
  14042. lRemainExtra = (LONG)*pcbData - lData;
  14043. if (0 > lRemainExtra) {
  14044. psi = NULL;
  14045. pbExtra = NULL;
  14046. } else {
  14047. pbExtra = (PBYTE)psi + lData;
  14048. }
  14049. if (!ICM_GetOssPkcsSignerInfo( posi, pSignerNode->Data()->pUnauthAttrList,
  14050. psi, &pbExtra, &lRemainExtra))
  14051. goto GetOssSignerInfoError;
  14052. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  14053. if (!fRet)
  14054. dwError = GetLastError();
  14055. CommonReturn:
  14056. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14057. ICM_SetLastError(dwError);
  14058. return fRet;
  14059. ErrorReturn:
  14060. dwError = GetLastError();
  14061. *pcbData = 0;
  14062. fRet = FALSE;
  14063. goto CommonReturn;
  14064. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14065. TRACE_ERROR(FindSignerInfoError) // error already set
  14066. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14067. }
  14068. //+-------------------------------------------------------------------------
  14069. // Decode a CMS SignerInfo blob.
  14070. //
  14071. // Returns: FALSE iff fails
  14072. //--------------------------------------------------------------------------
  14073. STATIC
  14074. BOOL
  14075. WINAPI
  14076. ICM_CmsSignerInfoDecode(
  14077. IN DWORD dwEncodingType,
  14078. IN LPCSTR lpszStructType,
  14079. IN const BYTE *pbEncoded,
  14080. IN DWORD cbEncoded,
  14081. IN DWORD dwFlags,
  14082. OUT PCMSG_CMS_SIGNER_INFO pInfo,
  14083. IN OUT DWORD *pcbInfo)
  14084. {
  14085. DWORD dwError = ERROR_SUCCESS;
  14086. BOOL fRet;
  14087. LONG lData;
  14088. SignerInfo *posi = NULL;
  14089. ASN1error_e Asn1Err;
  14090. ASN1decoding_t pDec = ICM_GetDecoder();
  14091. PCMSG_CMS_SIGNER_INFO psi = pInfo;
  14092. LONG lRemainExtra;
  14093. PBYTE pbExtra;
  14094. if (pInfo == NULL)
  14095. *pcbInfo = 0;
  14096. if (0 != (Asn1Err = PkiAsn1Decode(
  14097. pDec,
  14098. (void **)&posi,
  14099. SignerInfo_PDU,
  14100. pbEncoded,
  14101. cbEncoded)))
  14102. goto Asn1DecodeSignerInfoError;
  14103. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14104. lData = INFO_LEN_ALIGN( sizeof(CMSG_CMS_SIGNER_INFO));
  14105. lRemainExtra = (LONG)*pcbInfo - lData;
  14106. if (0 > lRemainExtra) {
  14107. psi = NULL;
  14108. pbExtra = NULL;
  14109. } else {
  14110. pbExtra = (PBYTE)psi + lData;
  14111. }
  14112. if (!ICM_GetOssCmsSignerInfo(
  14113. posi,
  14114. NULL, // pUnauthAttrList
  14115. psi, &pbExtra, &lRemainExtra))
  14116. goto GetOssSignerInfoError;
  14117. fRet = ICM_GetSizeFromExtra( lRemainExtra, pInfo, pcbInfo);
  14118. if (!fRet)
  14119. dwError = GetLastError();
  14120. CommonReturn:
  14121. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14122. ICM_SetLastError(dwError);
  14123. return fRet;
  14124. ErrorReturn:
  14125. dwError = GetLastError();
  14126. *pcbInfo = 0;
  14127. fRet = FALSE;
  14128. goto CommonReturn;
  14129. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14130. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14131. dwFlags;
  14132. lpszStructType;
  14133. }
  14134. //+-------------------------------------------------------------------------
  14135. // Find the CMS SignerInfo by index, if the message type permits and if the
  14136. // index value is in range.
  14137. //
  14138. // Returns: FALSE iff fails
  14139. //--------------------------------------------------------------------------
  14140. BOOL
  14141. WINAPI
  14142. ICM_GetCmsSignerInfo(
  14143. IN PCRYPT_MSG_INFO pcmi,
  14144. IN DWORD dwIndex,
  14145. OUT PVOID pvData,
  14146. IN OUT PDWORD pcbData)
  14147. {
  14148. DWORD dwError = ERROR_SUCCESS;
  14149. BOOL fRet;
  14150. LONG lData;
  14151. CSignerNode *pSignerNode;
  14152. SignerInfo *posi = NULL;
  14153. ASN1error_e Asn1Err;
  14154. ASN1decoding_t pDec = ICM_GetDecoder();
  14155. CRYPT_DATA_BLOB DataBlob;
  14156. PCMSG_CMS_SIGNER_INFO psi = (PCMSG_CMS_SIGNER_INFO)pvData;
  14157. LONG lRemainExtra;
  14158. PBYTE pbExtra;
  14159. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14160. goto FindSignerInfoError;
  14161. DataBlob = pSignerNode->Data()->blob;
  14162. if (0 != (Asn1Err = PkiAsn1Decode(
  14163. pDec,
  14164. (void **)&posi,
  14165. SignerInfo_PDU,
  14166. DataBlob.pbData,
  14167. DataBlob.cbData)))
  14168. goto Asn1DecodeSignerInfoError;
  14169. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14170. lData = INFO_LEN_ALIGN( sizeof(CMSG_CMS_SIGNER_INFO));
  14171. lRemainExtra = (LONG)*pcbData - lData;
  14172. if (0 > lRemainExtra) {
  14173. psi = NULL;
  14174. pbExtra = NULL;
  14175. } else {
  14176. pbExtra = (PBYTE)psi + lData;
  14177. }
  14178. if (!ICM_GetOssCmsSignerInfo( posi, pSignerNode->Data()->pUnauthAttrList,
  14179. psi, &pbExtra, &lRemainExtra))
  14180. goto GetOssSignerInfoError;
  14181. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  14182. if (!fRet)
  14183. dwError = GetLastError();
  14184. CommonReturn:
  14185. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14186. ICM_SetLastError(dwError);
  14187. return fRet;
  14188. ErrorReturn:
  14189. dwError = GetLastError();
  14190. *pcbData = 0;
  14191. fRet = FALSE;
  14192. goto CommonReturn;
  14193. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14194. TRACE_ERROR(FindSignerInfoError) // error already set
  14195. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14196. }
  14197. //+-------------------------------------------------------------------------
  14198. // Get the data for a field in a Signer, while encoding a message
  14199. //--------------------------------------------------------------------------
  14200. BOOL
  14201. WINAPI
  14202. ICM_GetSignerParamEncoding(
  14203. IN PCRYPT_MSG_INFO pcmi,
  14204. IN DWORD dwIndex,
  14205. IN DWORD dwParamType,
  14206. OUT PVOID pvData,
  14207. IN OUT PDWORD pcbData)
  14208. {
  14209. DWORD dwError = ERROR_SUCCESS;
  14210. BOOL fRet;
  14211. ASN1error_e Asn1Err;
  14212. ASN1encoding_t pEnc = ICM_GetEncoder();
  14213. PBYTE pbEncoded = NULL;
  14214. DWORD cbEncoded;
  14215. SignerInfo *posi = NULL;
  14216. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&posi))
  14217. goto FindSignerInfoError;
  14218. switch (dwParamType) {
  14219. case CMSG_ENCODED_SIGNER:
  14220. if (0 != (Asn1Err = PkiAsn1Encode(
  14221. pEnc,
  14222. posi,
  14223. SignerInfo_PDU,
  14224. &pbEncoded,
  14225. &cbEncoded)))
  14226. goto EncodeSignerInfoError;
  14227. break;
  14228. default:
  14229. goto InvalidParamError;
  14230. }
  14231. fRet = ICM_CopyOut(
  14232. pbEncoded,
  14233. cbEncoded,
  14234. (PBYTE)pvData,
  14235. pcbData);
  14236. if (!fRet)
  14237. dwError = GetLastError();
  14238. CommonReturn:
  14239. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  14240. ICM_SetLastError(dwError);
  14241. return fRet;
  14242. ErrorReturn:
  14243. dwError = GetLastError();
  14244. fRet = FALSE;
  14245. goto CommonReturn;
  14246. TRACE_ERROR(FindSignerInfoError) // error already set
  14247. SET_ERROR_VAR(EncodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14248. SET_ERROR(InvalidParamError,E_INVALIDARG)
  14249. }
  14250. //+-------------------------------------------------------------------------
  14251. // Get the data for a field in a Signer
  14252. //--------------------------------------------------------------------------
  14253. BOOL
  14254. WINAPI
  14255. ICM_GetSignerParam(
  14256. IN PCRYPT_MSG_INFO pcmi,
  14257. IN DWORD dwIndex,
  14258. IN DWORD dwParamType,
  14259. OUT PVOID pvData,
  14260. IN OUT PDWORD pcbData)
  14261. {
  14262. DWORD dwError = ERROR_SUCCESS;
  14263. BOOL fRet;
  14264. ASN1error_e Asn1Err;
  14265. ASN1decoding_t pDec = ICM_GetDecoder();
  14266. CRYPT_DATA_BLOB DataBlob;
  14267. ASN1uint32_t pdunumRef = 0; // invalid
  14268. SignerInfoWithBlobs *posib = NULL;
  14269. PVOID pv = NULL;
  14270. CSignerNode *pSignerNode;
  14271. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14272. goto FindSignerInfoError;
  14273. DataBlob = pSignerNode->Data()->blob;
  14274. if (0 != (Asn1Err = PkiAsn1Decode(
  14275. pDec,
  14276. (void **)&posib,
  14277. SignerInfoWithBlobs_PDU,
  14278. DataBlob.pbData,
  14279. DataBlob.cbData)))
  14280. goto DecodeSignerInfoError;
  14281. switch (dwParamType) {
  14282. case CMSG_SIGNER_INFO_PARAM:
  14283. fRet = ICM_GetPkcsSignerInfo( pcmi, dwIndex, pvData, pcbData);
  14284. break;
  14285. case CMSG_CMS_SIGNER_INFO_PARAM:
  14286. fRet = ICM_GetCmsSignerInfo( pcmi, dwIndex, pvData, pcbData);
  14287. break;
  14288. case CMSG_ENCRYPTED_DIGEST:
  14289. fRet = ICM_CopyOut(
  14290. (PBYTE)posib->encryptedDigest.value,
  14291. (DWORD)posib->encryptedDigest.length,
  14292. (PBYTE)pvData,
  14293. pcbData);
  14294. break;
  14295. case CMSG_ENCODED_SIGNER:
  14296. if (pSignerNode->Data()->pUnauthAttrList) {
  14297. // Need to re-encode with new unauth attrs
  14298. goto ReEncodedSignerNotImplementedError;
  14299. } else {
  14300. fRet = ICM_CopyOut(
  14301. pSignerNode->Data()->blob.pbData,
  14302. pSignerNode->Data()->blob.cbData,
  14303. (PBYTE)pvData,
  14304. pcbData);
  14305. }
  14306. break;
  14307. case CMSG_SIGNER_CERT_INFO_PARAM:
  14308. case CMSG_SIGNER_CERT_ID_PARAM:
  14309. pdunumRef = CertIdentifier_PDU;
  14310. if (0 != (Asn1Err = PkiAsn1Decode(
  14311. pDec,
  14312. &pv,
  14313. pdunumRef,
  14314. (BYTE *) posib->sid.value,
  14315. posib->sid.length)))
  14316. goto DecodeCertIdentifierError;
  14317. if (CMSG_SIGNER_CERT_INFO_PARAM == dwParamType)
  14318. fRet = ICM_GetCertInfoIssuerAndSerialNumber(
  14319. (CertIdentifier *)pv,
  14320. pvData,
  14321. pcbData);
  14322. else
  14323. fRet = ICM_GetCertId(
  14324. (CertIdentifier *)pv,
  14325. pvData,
  14326. pcbData);
  14327. break;
  14328. case CMSG_SIGNER_HASH_ALGORITHM_PARAM:
  14329. pdunumRef = AlgorithmIdentifierNC2_PDU;
  14330. if (0 != (Asn1Err = PkiAsn1Decode(
  14331. pDec,
  14332. &pv,
  14333. pdunumRef,
  14334. (BYTE *) posib->digestAlgorithm.value,
  14335. posib->digestAlgorithm.length)))
  14336. goto DecodeAlgorithmIdentifierNC2Error;
  14337. fRet = ICM_GetALGORITHM_IDENTIFIER(
  14338. (AlgorithmIdentifier *)pv,
  14339. pvData,
  14340. pcbData);
  14341. break;
  14342. case CMSG_SIGNER_AUTH_ATTR_PARAM:
  14343. if (posib->bit_mask & authAttributes_present)
  14344. fRet = ICM_GetAttributesData(
  14345. (Attributes *)&posib->authAttributes,
  14346. pvData,
  14347. pcbData);
  14348. else
  14349. goto AuthAttrMissingError;
  14350. break;
  14351. case CMSG_SIGNER_UNAUTH_ATTR_PARAM:
  14352. if (posib->bit_mask & unauthAttributes_present)
  14353. fRet = ICM_GetAttributesData(
  14354. (Attributes *)&posib->unauthAttributes,
  14355. pvData,
  14356. pcbData);
  14357. else
  14358. goto UnauthAttrMissingError;
  14359. break;
  14360. default:
  14361. goto InvalidParamError;
  14362. }
  14363. if (!fRet)
  14364. dwError = GetLastError();
  14365. CommonReturn:
  14366. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  14367. PkiAsn1FreeInfo(pDec, pdunumRef, pv);
  14368. ICM_SetLastError(dwError);
  14369. return fRet;
  14370. ErrorReturn:
  14371. dwError = GetLastError();
  14372. *pcbData = 0;
  14373. fRet = FALSE;
  14374. goto CommonReturn;
  14375. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14376. SET_ERROR_VAR(DecodeCertIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  14377. SET_ERROR_VAR(DecodeAlgorithmIdentifierNC2Error, PkiAsn1ErrToHr(Asn1Err))
  14378. SET_ERROR(AuthAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  14379. SET_ERROR(UnauthAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  14380. SET_ERROR(ReEncodedSignerNotImplementedError,E_INVALIDARG)
  14381. SET_ERROR(InvalidParamError,E_INVALIDARG)
  14382. TRACE_ERROR(FindSignerInfoError) // error already set
  14383. }
  14384. //+-------------------------------------------------------------------------
  14385. // Get the encoded blob for a SignerInfo
  14386. //--------------------------------------------------------------------------
  14387. BOOL
  14388. WINAPI
  14389. ICM_GetEncodedSignerInfo(
  14390. IN DWORD dwEncodingType,
  14391. IN PSIGNER_DATA_INFO pSignerInfo,
  14392. OUT PBYTE pbSignerInfo,
  14393. IN OUT PDWORD pcbSignerInfo)
  14394. {
  14395. DWORD dwError = ERROR_SUCCESS;
  14396. BOOL fRet;
  14397. SignerInfoWithAttrBlobs *posiab = NULL;
  14398. Any *pAnyAttr = NULL;
  14399. Any *pAny;
  14400. DWORD cAnyAttr;
  14401. AttributesNC unauthAttributesSave;
  14402. ZEROSTRUCT(unauthAttributesSave);
  14403. #ifdef OSS_CRYPT_ASN1
  14404. BYTE bit_maskSave = 0;
  14405. #else
  14406. ASN1uint16_t bit_maskSave = 0;
  14407. #endif // OSS_CRYPT_ASN1
  14408. ASN1error_e Asn1Err;
  14409. ASN1decoding_t pDec = ICM_GetDecoder();
  14410. ASN1encoding_t pEnc = ICM_GetEncoder();
  14411. PBYTE pbEncoded = NULL;
  14412. DWORD cbEncoded;
  14413. CBlobNode *pnBlob;
  14414. DWORD cbOut;
  14415. PBYTE pbOut;
  14416. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  14417. goto InvalidEncodingTypeError;
  14418. if (pSignerInfo->pUnauthAttrList) {
  14419. if (0 != (Asn1Err = PkiAsn1Decode(
  14420. pDec,
  14421. (void **)&posiab,
  14422. SignerInfoWithAttrBlobs_PDU,
  14423. pSignerInfo->blob.pbData,
  14424. pSignerInfo->blob.cbData)))
  14425. goto DecodeSignerInfoWithAttrBlobsError;
  14426. // We have to take into account both the case where we have added
  14427. // unauth attrs, and the case where we have removed them. There might
  14428. // have been unauth attrs in the original message, and we removed
  14429. // them all. Or, there might have been none originally, and we added
  14430. // some.
  14431. bit_maskSave = posiab->bit_mask;
  14432. unauthAttributesSave = posiab->unauthAttributes;
  14433. cAnyAttr = pSignerInfo->pUnauthAttrList->Length();
  14434. posiab->bit_mask &= ~unauthAttributes_present;
  14435. posiab->bit_mask |= (cAnyAttr > 0) ? unauthAttributes_present : 0;
  14436. if (NULL == (pAnyAttr = (Any *)ICM_AllocA( cAnyAttr * sizeof(Any))))
  14437. goto AllocAnyAttrError;
  14438. posiab->unauthAttributes.count = cAnyAttr;
  14439. posiab->unauthAttributes.value = pAnyAttr;
  14440. for (pnBlob=pSignerInfo->pUnauthAttrList->Head(), pAny=pAnyAttr;
  14441. pnBlob;
  14442. pnBlob=pnBlob->Next(), pAny++)
  14443. *pAny = *(Any *)pnBlob->Data();
  14444. if (0 != (Asn1Err = PkiAsn1Encode(
  14445. pEnc,
  14446. posiab,
  14447. SignerInfoWithAttrBlobs_PDU,
  14448. &pbEncoded,
  14449. &cbEncoded)))
  14450. goto EncodeSignerInfoWithAttrBlobsError;
  14451. cbOut = cbEncoded;
  14452. pbOut = pbEncoded;
  14453. } else {
  14454. cbOut = pSignerInfo->blob.cbData;
  14455. pbOut = pSignerInfo->blob.pbData;
  14456. }
  14457. fRet = ICM_CopyOut(
  14458. pbOut,
  14459. cbOut,
  14460. pbSignerInfo,
  14461. pcbSignerInfo);
  14462. if (!fRet)
  14463. dwError = GetLastError();
  14464. CommonReturn:
  14465. ICM_FreeA( pAnyAttr);
  14466. if (posiab) {
  14467. posiab->bit_mask = bit_maskSave;
  14468. posiab->unauthAttributes = unauthAttributesSave;
  14469. PkiAsn1FreeDecoded(pDec, posiab, SignerInfoWithAttrBlobs_PDU);
  14470. }
  14471. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  14472. ICM_SetLastError(dwError);
  14473. return fRet;
  14474. ErrorReturn:
  14475. dwError = GetLastError();
  14476. fRet = FALSE;
  14477. goto CommonReturn;
  14478. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  14479. SET_ERROR_VAR(DecodeSignerInfoWithAttrBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14480. SET_ERROR_VAR(EncodeSignerInfoWithAttrBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14481. TRACE_ERROR(AllocAnyAttrError) // error already set
  14482. }
  14483. //+-------------------------------------------------------------------------
  14484. // Get the data for a field in a Signer
  14485. //--------------------------------------------------------------------------
  14486. BOOL
  14487. WINAPI
  14488. ICM_GetEncodedMessageParam(
  14489. IN PCRYPT_MSG_INFO pcmi,
  14490. OUT PBYTE pbEncodedMessage,
  14491. IN OUT PDWORD pcbEncodedMessage)
  14492. {
  14493. DWORD dwError = ERROR_SUCCESS;
  14494. BOOL fRet;
  14495. SignedDataWithBlobs *posdb = NULL;
  14496. PSIGNED_DATA_INFO psdi = pcmi->psdi;
  14497. Any *pAny;
  14498. PSIGNER_DATA_INFO pSignerInfo;
  14499. ASN1error_e Asn1Err;
  14500. ASN1encoding_t pEnc = ICM_GetEncoder();
  14501. PBYTE pbEncodedSignedData = NULL;
  14502. DWORD cbEncodedSignedData;
  14503. PBYTE pbEncodedContentInfo = NULL;
  14504. DWORD cbEncodedContentInfo;
  14505. CSignerNode *pnSigner;
  14506. CBlobNode *pnBlob;
  14507. DWORD cb;
  14508. PBYTE pb;
  14509. DWORD i;
  14510. ContentInfo ci;
  14511. if (NULL == (posdb = (SignedDataWithBlobs *)ICM_AllocZeroA(
  14512. sizeof(SignedDataWithBlobs) +
  14513. sizeof(Any) *
  14514. (psdi->pAlgidList->Length() +
  14515. psdi->pCertificateList->Length() +
  14516. psdi->pCrlList->Length() +
  14517. psdi->pSignerList->Length()))))
  14518. goto AllocSignedDataWithBlobsError;
  14519. pAny = (Any *)(posdb + 1);
  14520. // version
  14521. posdb->version = psdi->version;
  14522. // digest algorithms
  14523. posdb->digestAlgorithms.count = psdi->pAlgidList->Length();
  14524. posdb->digestAlgorithms.value = pAny;
  14525. for (pnBlob=psdi->pAlgidList->Head();
  14526. pnBlob;
  14527. pnBlob=pnBlob->Next())
  14528. *pAny++ = *(Any *)pnBlob->Data();
  14529. // contentInfo
  14530. posdb->contentInfo.contentType.count = SIZE_OSS_OID;
  14531. if (!PkiAsn1ToObjectIdentifier(
  14532. psdi->pci->pszContentType,
  14533. &posdb->contentInfo.contentType.count,
  14534. posdb->contentInfo.contentType.value))
  14535. goto PkiAsn1ToObjectIdentifierError;
  14536. if (psdi->pci->content.cbData) {
  14537. posdb->contentInfo.bit_mask |= content_present;
  14538. posdb->contentInfo.content.length = psdi->pci->content.cbData;
  14539. posdb->contentInfo.content.value = psdi->pci->content.pbData;
  14540. }
  14541. // certificates
  14542. posdb->certificates.count = psdi->pCertificateList->Length();
  14543. #ifdef OSS_CRYPT_ASN1
  14544. posdb->certificates.certificates = pAny;
  14545. #else
  14546. posdb->certificates.value = pAny;
  14547. #endif // OSS_CRYPT_ASN1
  14548. for (pnBlob=psdi->pCertificateList->Head();
  14549. pnBlob;
  14550. pnBlob=pnBlob->Next()) {
  14551. posdb->bit_mask |= certificates_present;
  14552. *pAny++ = *(Any *)pnBlob->Data();
  14553. }
  14554. // crls
  14555. posdb->crls.count = psdi->pCrlList->Length();
  14556. #ifdef OSS_CRYPT_ASN1
  14557. posdb->crls.crls = pAny;
  14558. #else
  14559. posdb->crls.value = pAny;
  14560. #endif // OSS_CRYPT_ASN1
  14561. for (pnBlob=psdi->pCrlList->Head();
  14562. pnBlob;
  14563. pnBlob=pnBlob->Next()) {
  14564. posdb->bit_mask |= crls_present;
  14565. *pAny++ = *(Any *)pnBlob->Data();
  14566. }
  14567. // signerInfos
  14568. posdb->signerInfos.count = psdi->pSignerList->Length();
  14569. posdb->signerInfos.value = pAny;
  14570. for (pnSigner=psdi->pSignerList->Head();
  14571. pnSigner;
  14572. pnSigner=pnSigner->Next()) {
  14573. pSignerInfo = pnSigner->Data();
  14574. if (!ICM_GetEncodedSignerInfo(
  14575. PKCS_7_ASN_ENCODING,
  14576. pnSigner->Data(),
  14577. NULL,
  14578. &cb))
  14579. goto GetEncodedSignerInfoSizeError;
  14580. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  14581. goto AllocEncodedSignerInfoError;
  14582. if (!ICM_GetEncodedSignerInfo(
  14583. PKCS_7_ASN_ENCODING,
  14584. pnSigner->Data(),
  14585. pb,
  14586. &cb))
  14587. goto GetEncodedSignerInfoError;
  14588. pAny->length = cb;
  14589. pAny->value = pb;
  14590. pAny++;
  14591. }
  14592. if (0 != (Asn1Err = PkiAsn1Encode(
  14593. pEnc,
  14594. posdb,
  14595. SignedDataWithBlobs_PDU,
  14596. &pbEncodedSignedData,
  14597. &cbEncodedSignedData)))
  14598. goto EncodeSignedDataWithBlobsError;
  14599. ci.contentType.count = SIZE_OSS_OID;
  14600. if (!PkiAsn1ToObjectIdentifier(
  14601. szOID_RSA_signedData,
  14602. &ci.contentType.count,
  14603. ci.contentType.value))
  14604. goto ConvSignedDataToOidError;
  14605. ci.bit_mask = content_present;
  14606. ci.content.length = cbEncodedSignedData;
  14607. ci.content.value = pbEncodedSignedData;
  14608. if (0 != (Asn1Err = PkiAsn1Encode(
  14609. pEnc,
  14610. &ci,
  14611. ContentInfo_PDU,
  14612. &pbEncodedContentInfo,
  14613. &cbEncodedContentInfo)))
  14614. goto EncodeContentInfoError;
  14615. fRet = ICM_CopyOut(
  14616. pbEncodedContentInfo,
  14617. cbEncodedContentInfo,
  14618. pbEncodedMessage,
  14619. pcbEncodedMessage);
  14620. if (!fRet)
  14621. dwError = GetLastError();
  14622. CommonReturn:
  14623. PkiAsn1FreeEncoded(pEnc, pbEncodedSignedData);
  14624. PkiAsn1FreeEncoded(pEnc, pbEncodedContentInfo);
  14625. for (i=posdb->signerInfos.count, pAny=posdb->signerInfos.value;
  14626. i>0;
  14627. i--, pAny++)
  14628. ICM_FreeA( pAny->value);
  14629. ICM_FreeA(posdb);
  14630. ICM_SetLastError(dwError);
  14631. return fRet;
  14632. ErrorReturn:
  14633. dwError = GetLastError();
  14634. fRet = FALSE;
  14635. goto CommonReturn;
  14636. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  14637. SET_ERROR_VAR(EncodeSignedDataWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14638. SET_ERROR(ConvSignedDataToOidError,CRYPT_E_OID_FORMAT)
  14639. SET_ERROR_VAR(EncodeContentInfoError, PkiAsn1ErrToHr(Asn1Err))
  14640. TRACE_ERROR(AllocSignedDataWithBlobsError) // error already set
  14641. TRACE_ERROR(GetEncodedSignerInfoSizeError) // error already set
  14642. TRACE_ERROR(AllocEncodedSignerInfoError) // error already set
  14643. TRACE_ERROR(GetEncodedSignerInfoError) // error already set
  14644. }
  14645. #ifdef CMS_PKCS7
  14646. //+-------------------------------------------------------------------------
  14647. // Get Oss OctetString
  14648. //--------------------------------------------------------------------------
  14649. void
  14650. inline
  14651. WINAPI
  14652. ICM_GetOssOctetString(
  14653. IN OctetStringType *pOssOctetString,
  14654. OUT PCRYPT_DATA_BLOB pOctetString,
  14655. IN OUT BYTE **ppbExtra,
  14656. IN OUT LONG *plRemainExtra
  14657. )
  14658. {
  14659. PkiAsn1GetOctetString(pOssOctetString->length, pOssOctetString->value, 0,
  14660. pOctetString, ppbExtra, plRemainExtra);
  14661. }
  14662. //+-------------------------------------------------------------------------
  14663. // Get Oss BitString
  14664. //--------------------------------------------------------------------------
  14665. void
  14666. inline
  14667. WINAPI
  14668. ICM_GetOssBitString(
  14669. IN BitStringType *pOssBitString,
  14670. OUT PCRYPT_BIT_BLOB pBitString,
  14671. IN OUT BYTE **ppbExtra,
  14672. IN OUT LONG *plRemainExtra
  14673. )
  14674. {
  14675. PkiAsn1GetBitString(pOssBitString->length, pOssBitString->value, 0,
  14676. pBitString, ppbExtra, plRemainExtra);
  14677. }
  14678. //+-------------------------------------------------------------------------
  14679. // Get an Oss IssuerAndSerialNumber
  14680. //--------------------------------------------------------------------------
  14681. BOOL
  14682. WINAPI
  14683. ICM_GetOssIssuerAndSerialNumber(
  14684. IN IssuerAndSerialNumber *pOssIssuerAndSerialNumber,
  14685. OUT PCERT_ISSUER_SERIAL_NUMBER pIssuerAndSerialNumber,
  14686. IN OUT BYTE **ppbExtra,
  14687. IN OUT LONG *plRemainExtra)
  14688. {
  14689. ICM_GetOssHugeInteger(&pOssIssuerAndSerialNumber->serialNumber,
  14690. &pIssuerAndSerialNumber->SerialNumber, ppbExtra, plRemainExtra);
  14691. return ICM_GetOssAny(&pOssIssuerAndSerialNumber->issuer,
  14692. &pIssuerAndSerialNumber->Issuer, ppbExtra, plRemainExtra);
  14693. }
  14694. //+-------------------------------------------------------------------------
  14695. // Get Oss CertIdentifier
  14696. //--------------------------------------------------------------------------
  14697. BOOL
  14698. WINAPI
  14699. ICM_GetOssCertIdentifier(
  14700. IN CertIdentifier *pOssCertId,
  14701. OUT PCERT_ID pCertId,
  14702. IN OUT BYTE **ppbExtra,
  14703. IN OUT LONG *plRemainExtra
  14704. )
  14705. {
  14706. BOOL fRet;
  14707. if (0 <= *plRemainExtra) {
  14708. assert(CERT_ID_ISSUER_SERIAL_NUMBER == issuerAndSerialNumber_chosen);
  14709. assert(CERT_ID_KEY_IDENTIFIER == subjectKeyIdentifier_chosen);
  14710. pCertId->dwIdChoice = pOssCertId->choice;
  14711. }
  14712. switch (pOssCertId->choice) {
  14713. case issuerAndSerialNumber_chosen:
  14714. if (!ICM_GetOssIssuerAndSerialNumber(
  14715. &pOssCertId->u.issuerAndSerialNumber,
  14716. &pCertId->IssuerSerialNumber, ppbExtra, plRemainExtra))
  14717. goto GetOssIssuerAndSerialNumberError;
  14718. break;
  14719. case subjectKeyIdentifier_chosen:
  14720. ICM_GetOssOctetString( &pOssCertId->u.subjectKeyIdentifier,
  14721. &pCertId->KeyId, ppbExtra, plRemainExtra);
  14722. break;
  14723. default:
  14724. goto InvalidCertIdChoice;
  14725. }
  14726. fRet = TRUE;
  14727. CommonReturn:
  14728. return fRet;
  14729. ErrorReturn:
  14730. fRet = FALSE;
  14731. goto CommonReturn;
  14732. TRACE_ERROR(GetOssIssuerAndSerialNumberError)
  14733. SET_ERROR(InvalidCertIdChoice, CRYPT_E_BAD_ENCODE)
  14734. }
  14735. //+-------------------------------------------------------------------------
  14736. // Get Oss OtherKeyAttribute
  14737. //--------------------------------------------------------------------------
  14738. BOOL
  14739. WINAPI
  14740. ICM_GetOssOtherKeyAttribute(
  14741. IN OtherKeyAttribute *pOssOtherAttr,
  14742. OUT PCRYPT_ATTRIBUTE_TYPE_VALUE *ppOtherAttr,
  14743. IN OUT BYTE **ppbExtra,
  14744. IN OUT LONG *plRemainExtra
  14745. )
  14746. {
  14747. BOOL fRet;
  14748. LONG lData;
  14749. PCRYPT_ATTRIBUTE_TYPE_VALUE pOtherAttr;
  14750. lData = INFO_LEN_ALIGN(sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE));
  14751. *plRemainExtra -= lData;
  14752. if (0 <= *plRemainExtra) {
  14753. pOtherAttr = (PCRYPT_ATTRIBUTE_TYPE_VALUE) *ppbExtra;
  14754. memset(pOtherAttr, 0, sizeof(*pOtherAttr));
  14755. *ppOtherAttr = pOtherAttr;
  14756. *ppbExtra += lData;
  14757. } else
  14758. pOtherAttr = NULL;
  14759. if (!ICM_GetOssObjId(&pOssOtherAttr->keyAttrId, &pOtherAttr->pszObjId,
  14760. ppbExtra, plRemainExtra))
  14761. goto GetOssObjIdError;
  14762. if (pOssOtherAttr->bit_mask & keyAttr_present) {
  14763. if (!ICM_GetOssAny(&pOssOtherAttr->keyAttr,
  14764. &pOtherAttr->Value, ppbExtra, plRemainExtra))
  14765. goto GetOssAnyError;
  14766. }
  14767. fRet = TRUE;
  14768. CommonReturn:
  14769. return fRet;
  14770. ErrorReturn:
  14771. fRet = FALSE;
  14772. goto CommonReturn;
  14773. TRACE_ERROR(GetOssObjIdError)
  14774. TRACE_ERROR(GetOssAnyError)
  14775. }
  14776. //+-------------------------------------------------------------------------
  14777. // Get Oss KeyTransRecipientInfo
  14778. //--------------------------------------------------------------------------
  14779. BOOL
  14780. WINAPI
  14781. ICM_GetOssKeyTransRecipientInfo(
  14782. IN KeyTransRecipientInfo *pori,
  14783. OUT PCMSG_KEY_TRANS_RECIPIENT_INFO *ppri,
  14784. IN OUT BYTE **ppbExtra,
  14785. IN OUT LONG *plRemainExtra
  14786. )
  14787. {
  14788. BOOL fRet;
  14789. LONG lData;
  14790. PCMSG_KEY_TRANS_RECIPIENT_INFO pri;
  14791. lData = INFO_LEN_ALIGN(sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO));
  14792. *plRemainExtra -= lData;
  14793. if (0 <= *plRemainExtra) {
  14794. pri = (PCMSG_KEY_TRANS_RECIPIENT_INFO) *ppbExtra;
  14795. *ppri = pri;
  14796. *ppbExtra += lData;
  14797. pri->dwVersion = pori->version;
  14798. } else {
  14799. pri = NULL;
  14800. }
  14801. if (!ICM_GetOssCertIdentifier(&pori->rid, &pri->RecipientId,
  14802. ppbExtra, plRemainExtra))
  14803. goto GetOssCertIdentifierError;
  14804. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  14805. &pri->KeyEncryptionAlgorithm,
  14806. ppbExtra, plRemainExtra))
  14807. goto GetOssKeyEncryptionAlgorithmError;
  14808. ICM_GetOssOctetString(&pori->encryptedKey, &pri->EncryptedKey,
  14809. ppbExtra, plRemainExtra);
  14810. fRet = TRUE;
  14811. CommonReturn:
  14812. return fRet;
  14813. ErrorReturn:
  14814. fRet = FALSE;
  14815. goto CommonReturn;
  14816. TRACE_ERROR(GetOssCertIdentifierError)
  14817. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  14818. }
  14819. //+-------------------------------------------------------------------------
  14820. // Get Oss KeyAgreeRecipientInfo
  14821. //--------------------------------------------------------------------------
  14822. BOOL
  14823. WINAPI
  14824. ICM_GetOssKeyAgreeRecipientInfo(
  14825. IN KeyAgreeRecipientInfo *pori,
  14826. OUT PCMSG_KEY_AGREE_RECIPIENT_INFO *ppri,
  14827. IN OUT BYTE **ppbExtra,
  14828. IN OUT LONG *plRemainExtra
  14829. )
  14830. {
  14831. BOOL fRet;
  14832. LONG lData;
  14833. PCMSG_KEY_AGREE_RECIPIENT_INFO pri;
  14834. DWORD count;
  14835. OriginatorIdentifierOrKey *pooriginator;
  14836. OriginatorPublicKey *pooriginatorKey;
  14837. lData = INFO_LEN_ALIGN(sizeof(CMSG_KEY_AGREE_RECIPIENT_INFO));
  14838. *plRemainExtra -= lData;
  14839. if (0 <= *plRemainExtra) {
  14840. pri = (PCMSG_KEY_AGREE_RECIPIENT_INFO) *ppbExtra;
  14841. memset(pri, 0, sizeof(*pri));
  14842. *ppri = pri;
  14843. *ppbExtra += lData;
  14844. pri->dwVersion = pori->version;
  14845. } else {
  14846. pri = NULL;
  14847. }
  14848. pooriginator = &pori->originator;
  14849. switch (pooriginator->choice) {
  14850. case issuerAndSerialNumber_chosen:
  14851. if (!ICM_GetOssIssuerAndSerialNumber(
  14852. &pooriginator->u.issuerAndSerialNumber,
  14853. &pri->OriginatorCertId.IssuerSerialNumber,
  14854. ppbExtra, plRemainExtra))
  14855. goto GetOssOriginatorIssuerAndSerialNumberError;
  14856. if (0 <= *plRemainExtra) {
  14857. pri->OriginatorCertId.dwIdChoice =
  14858. CERT_ID_ISSUER_SERIAL_NUMBER;
  14859. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_CERT;
  14860. }
  14861. break;
  14862. case subjectKeyIdentifier_chosen:
  14863. ICM_GetOssOctetString(
  14864. &pooriginator->u.subjectKeyIdentifier,
  14865. &pri->OriginatorCertId.KeyId,
  14866. ppbExtra, plRemainExtra);
  14867. if (0 <= *plRemainExtra) {
  14868. pri->OriginatorCertId.dwIdChoice =
  14869. CERT_ID_KEY_IDENTIFIER;
  14870. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_CERT;
  14871. }
  14872. break;
  14873. case originatorKey_chosen:
  14874. pooriginatorKey = &pooriginator->u.originatorKey;
  14875. if (!ICM_GetOssAlgorithm(&pooriginatorKey->algorithm,
  14876. &pri->OriginatorPublicKeyInfo.Algorithm,
  14877. ppbExtra, plRemainExtra
  14878. ))
  14879. goto GetOssOriginatorPublicKeyAlgorithmError;
  14880. ICM_GetOssBitString(&pooriginatorKey->publicKey,
  14881. &pri->OriginatorPublicKeyInfo.PublicKey,
  14882. ppbExtra, plRemainExtra);
  14883. if (0 <= *plRemainExtra)
  14884. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY;
  14885. break;
  14886. default:
  14887. goto InvalidOriginatorChoice;
  14888. }
  14889. if (pori->bit_mask & ukm_present)
  14890. ICM_GetOssOctetString(&pori->ukm, &pri->UserKeyingMaterial,
  14891. ppbExtra, plRemainExtra);
  14892. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  14893. &pri->KeyEncryptionAlgorithm,
  14894. ppbExtra, plRemainExtra))
  14895. goto GetOssKeyEncryptionAlgorithmError;
  14896. count = pori->recipientEncryptedKeys.count;
  14897. if (0 < count) {
  14898. RecipientEncryptedKey *porek;
  14899. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO prek;
  14900. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *pprek;
  14901. lData = INFO_LEN_ALIGN(
  14902. count * sizeof(PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO) +
  14903. count * sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_INFO));
  14904. *plRemainExtra -= lData;
  14905. if (0 <= *plRemainExtra) {
  14906. pprek = (PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *) *ppbExtra;
  14907. prek = (PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO) (((PBYTE) pprek) +
  14908. (count * sizeof(PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO)));
  14909. *ppbExtra += lData;
  14910. pri->cRecipientEncryptedKeys = count;
  14911. pri->rgpRecipientEncryptedKeys = pprek;
  14912. } else {
  14913. pprek = NULL;
  14914. prek = NULL;
  14915. }
  14916. porek = pori->recipientEncryptedKeys.value;
  14917. for ( ; 0 < count; count--, porek++, prek++, pprek++) {
  14918. RecipientIdentifier *porid = &porek->rid;
  14919. if (0 <= *plRemainExtra) {
  14920. memset(prek, 0, sizeof(*prek));
  14921. *pprek = prek;
  14922. assert(issuerAndSerialNumber_chosen ==
  14923. CERT_ID_ISSUER_SERIAL_NUMBER);
  14924. assert(rKeyId_chosen ==
  14925. CERT_ID_KEY_IDENTIFIER);
  14926. prek->RecipientId.dwIdChoice = porid->choice;
  14927. }
  14928. ICM_GetOssOctetString(&porek->encryptedKey, &prek->EncryptedKey,
  14929. ppbExtra, plRemainExtra);
  14930. switch (porid->choice) {
  14931. case issuerAndSerialNumber_chosen:
  14932. if (!ICM_GetOssIssuerAndSerialNumber(
  14933. &porid->u.issuerAndSerialNumber,
  14934. &prek->RecipientId.IssuerSerialNumber,
  14935. ppbExtra, plRemainExtra))
  14936. goto GetOssIssuerAndSerialNumberError;
  14937. break;
  14938. case rKeyId_chosen:
  14939. ICM_GetOssOctetString(
  14940. &porid->u.rKeyId.subjectKeyIdentifier,
  14941. &prek->RecipientId.KeyId, ppbExtra, plRemainExtra);
  14942. if (porid->u.rKeyId.bit_mask & date_present) {
  14943. if (0 <= *plRemainExtra) {
  14944. if (!PkiAsn1FromGeneralizedTime(
  14945. &porid->u.rKeyId.date, &prek->Date))
  14946. goto ConvFromGeneralizedTimeError;
  14947. }
  14948. }
  14949. if (porid->u.rKeyId.bit_mask & other_present) {
  14950. if (!ICM_GetOssOtherKeyAttribute(
  14951. &porid->u.rKeyId.other,
  14952. &prek->pOtherAttr,
  14953. ppbExtra, plRemainExtra))
  14954. goto GetOssOtherKeyAttributeError;
  14955. }
  14956. break;
  14957. default:
  14958. goto InvalidRecipientChoice;
  14959. }
  14960. }
  14961. }
  14962. fRet = TRUE;
  14963. CommonReturn:
  14964. return fRet;
  14965. ErrorReturn:
  14966. fRet = FALSE;
  14967. goto CommonReturn;
  14968. TRACE_ERROR(GetOssOriginatorIssuerAndSerialNumberError)
  14969. TRACE_ERROR(GetOssOriginatorPublicKeyAlgorithmError)
  14970. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  14971. TRACE_ERROR(GetOssIssuerAndSerialNumberError)
  14972. TRACE_ERROR(ConvFromGeneralizedTimeError)
  14973. TRACE_ERROR(GetOssOtherKeyAttributeError)
  14974. SET_ERROR(InvalidOriginatorChoice, CRYPT_E_BAD_ENCODE)
  14975. SET_ERROR(InvalidRecipientChoice, CRYPT_E_BAD_ENCODE)
  14976. }
  14977. //+-------------------------------------------------------------------------
  14978. // Get Oss MailListRecipientInfo
  14979. //--------------------------------------------------------------------------
  14980. BOOL
  14981. WINAPI
  14982. ICM_GetOssMailListRecipientInfo(
  14983. IN MailListRecipientInfo *pori,
  14984. OUT PCMSG_MAIL_LIST_RECIPIENT_INFO *ppri,
  14985. IN OUT BYTE **ppbExtra,
  14986. IN OUT LONG *plRemainExtra
  14987. )
  14988. {
  14989. BOOL fRet;
  14990. LONG lData;
  14991. PCMSG_MAIL_LIST_RECIPIENT_INFO pri;
  14992. MailListKeyIdentifier *pomlid;
  14993. lData = INFO_LEN_ALIGN(sizeof(CMSG_MAIL_LIST_RECIPIENT_INFO));
  14994. *plRemainExtra -= lData;
  14995. if (0 <= *plRemainExtra) {
  14996. pri = (PCMSG_MAIL_LIST_RECIPIENT_INFO) *ppbExtra;
  14997. memset(pri, 0, sizeof(*pri));
  14998. *ppri = pri;
  14999. *ppbExtra += lData;
  15000. pri->dwVersion = pori->version;
  15001. } else {
  15002. pri = NULL;
  15003. }
  15004. pomlid = &pori->mlid;
  15005. ICM_GetOssOctetString(&pomlid->kekIdentifier, &pri->KeyId,
  15006. ppbExtra, plRemainExtra);
  15007. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  15008. &pri->KeyEncryptionAlgorithm,
  15009. ppbExtra, plRemainExtra))
  15010. goto GetOssKeyEncryptionAlgorithmError;
  15011. ICM_GetOssOctetString(&pori->encryptedKey, &pri->EncryptedKey,
  15012. ppbExtra, plRemainExtra);
  15013. if (pomlid->bit_mask & date_present) {
  15014. if (0 <= *plRemainExtra) {
  15015. if (!PkiAsn1FromGeneralizedTime(
  15016. &pomlid->date, &pri->Date))
  15017. goto ConvFromGeneralizedTimeError;
  15018. }
  15019. }
  15020. if (pomlid->bit_mask & other_present) {
  15021. if (!ICM_GetOssOtherKeyAttribute(
  15022. &pomlid->other,
  15023. &pri->pOtherAttr,
  15024. ppbExtra, plRemainExtra))
  15025. goto GetOssOtherKeyAttributeError;
  15026. }
  15027. fRet = TRUE;
  15028. CommonReturn:
  15029. return fRet;
  15030. ErrorReturn:
  15031. fRet = FALSE;
  15032. goto CommonReturn;
  15033. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  15034. TRACE_ERROR(ConvFromGeneralizedTimeError)
  15035. TRACE_ERROR(GetOssOtherKeyAttributeError)
  15036. }
  15037. //+-------------------------------------------------------------------------
  15038. // Copy out a CMSG_CMS_RECIPIENT_INFO
  15039. //--------------------------------------------------------------------------
  15040. BOOL
  15041. WINAPI
  15042. ICM_GetCmsRecipientInfo(
  15043. IN CmsRecipientInfo *pori,
  15044. OUT void *pvData,
  15045. IN OUT DWORD *pcbData
  15046. )
  15047. {
  15048. BOOL fRet;
  15049. LONG lData;
  15050. PCMSG_CMS_RECIPIENT_INFO pri = (PCMSG_CMS_RECIPIENT_INFO) pvData;
  15051. PBYTE pbExtra;
  15052. LONG lRemainExtra;
  15053. if (NULL == pvData)
  15054. *pcbData = 0;
  15055. // for lRemainExtra < 0, LENGTH_ONLY calculation
  15056. lData = INFO_LEN_ALIGN(sizeof(CMSG_CMS_RECIPIENT_INFO));
  15057. lRemainExtra = (LONG)*pcbData - lData;
  15058. if (0 > lRemainExtra) {
  15059. pri = NULL;
  15060. pbExtra = NULL;
  15061. } else {
  15062. assert(CMSG_KEY_TRANS_RECIPIENT == keyTransRecipientInfo_chosen);
  15063. assert(CMSG_KEY_AGREE_RECIPIENT == keyAgreeRecipientInfo_chosen);
  15064. assert(CMSG_MAIL_LIST_RECIPIENT == mailListRecipientInfo_chosen);
  15065. pri->dwRecipientChoice = pori->choice;
  15066. pbExtra = (PBYTE) pri + lData;
  15067. }
  15068. switch (pori->choice) {
  15069. case keyTransRecipientInfo_chosen:
  15070. if (!ICM_GetOssKeyTransRecipientInfo(
  15071. &pori->u.keyTransRecipientInfo,
  15072. &pri->pKeyTrans,
  15073. &pbExtra, &lRemainExtra
  15074. ))
  15075. goto GetOssKeyTransRecipientInfoError;
  15076. break;
  15077. case keyAgreeRecipientInfo_chosen:
  15078. if (!ICM_GetOssKeyAgreeRecipientInfo(
  15079. &pori->u.keyAgreeRecipientInfo,
  15080. &pri->pKeyAgree,
  15081. &pbExtra, &lRemainExtra
  15082. ))
  15083. goto GetOssKeyAgreeRecipientInfoError;
  15084. break;
  15085. case mailListRecipientInfo_chosen:
  15086. if (!ICM_GetOssMailListRecipientInfo(
  15087. &pori->u.mailListRecipientInfo,
  15088. &pri->pMailList,
  15089. &pbExtra, &lRemainExtra
  15090. ))
  15091. goto GetOssMailListRecipientInfoError;
  15092. break;
  15093. default:
  15094. goto InvalidRecipientChoice;
  15095. }
  15096. fRet = ICM_GetSizeFromExtra(lRemainExtra, pvData, pcbData);
  15097. CommonReturn:
  15098. return fRet;
  15099. ErrorReturn:
  15100. *pcbData = 0;
  15101. fRet = FALSE;
  15102. goto CommonReturn;
  15103. TRACE_ERROR(GetOssKeyTransRecipientInfoError)
  15104. TRACE_ERROR(GetOssKeyAgreeRecipientInfoError)
  15105. TRACE_ERROR(GetOssMailListRecipientInfoError)
  15106. SET_ERROR(InvalidRecipientChoice, CRYPT_E_BAD_ENCODE)
  15107. }
  15108. #endif // CMS_PKCS7
  15109. //+-------------------------------------------------------------------------
  15110. // Get a parameter after encoding/decoding a cryptographic message. Called
  15111. // after the final CryptMsgUpdate. Only the CMSG_CONTENT_PARAM and
  15112. // CMSG_COMPUTED_HASH_PARAM are valid for an encoded message.
  15113. //
  15114. // For an encoded HASHED message, the CMSG_COMPUTED_HASH_PARAM can be got
  15115. // before any CryptMsgUpdates to get its length.
  15116. //
  15117. // The pvData type definition depends on the dwParamType value.
  15118. //
  15119. // Elements pointed to by fields in the pvData structure follow the
  15120. // structure. Therefore, *pcbData may exceed the size of the structure.
  15121. //
  15122. // Upon input, if *pcbData == 0, then, *pcbData is updated with the length
  15123. // of the data and the pvData parameter is ignored.
  15124. //
  15125. // Upon return, *pcbData is updated with the length of the data.
  15126. //
  15127. // The OBJID BLOBs returned in the pvData structures point to
  15128. // their still encoded representation. The appropriate functions
  15129. // must be called to decode the information.
  15130. //
  15131. // See wincrypt.h for a list of the parameters to get.
  15132. //--------------------------------------------------------------------------
  15133. BOOL
  15134. WINAPI
  15135. #ifdef DEBUG_CRYPT_ASN1_MASTER
  15136. ICMTest_NewCryptMsgGetParam(
  15137. #else
  15138. CryptMsgGetParam(
  15139. #endif
  15140. IN HCRYPTMSG hCryptMsg,
  15141. IN DWORD dwParamType,
  15142. IN DWORD dwIndex,
  15143. OUT void *pvData,
  15144. IN OUT DWORD *pcbData)
  15145. {
  15146. DWORD dwError = ERROR_SUCCESS;
  15147. BOOL fRet;
  15148. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  15149. ASN1error_e Asn1Err;
  15150. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  15151. BOOL fBER = FALSE;
  15152. DWORD dwExceptionCode;
  15153. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  15154. // Handle MappedFile Exceptions
  15155. __try {
  15156. if (NULL == pvData)
  15157. *pcbData = 0;
  15158. #ifdef CMS_PKCS7
  15159. if (CMSG_VERSION_PARAM == dwParamType) {
  15160. int version = 0;
  15161. switch (pcmi->dwMsgType) {
  15162. case CMSG_SIGNED:
  15163. if (pcmi->fEncoding) {
  15164. if (NULL == pcmi->pvMsg)
  15165. goto InvalidMessageDataError;
  15166. version = ((SignedData *)pcmi->pvMsg)->version;
  15167. } else {
  15168. if (NULL == pcmi->psdi)
  15169. goto MessageNotDecodedError;
  15170. version = pcmi->psdi->version;
  15171. }
  15172. break;
  15173. case CMSG_ENVELOPED:
  15174. if (NULL == pcmi->pvMsg)
  15175. goto MessageNotDecodedError;
  15176. version = ((CmsEnvelopedData *)pcmi->pvMsg)->version;
  15177. break;
  15178. case CMSG_HASHED:
  15179. if (NULL == pcmi->pvMsg)
  15180. goto MessageNotDecodedError;
  15181. version = ((DigestedData *)pcmi->pvMsg)->version;
  15182. break;
  15183. case CMSG_SIGNED_AND_ENVELOPED:
  15184. goto MessageTypeNotSupportedYet;
  15185. case CMSG_ENCRYPTED:
  15186. case CMSG_DATA:
  15187. default:
  15188. goto InvalidMsgType;
  15189. }
  15190. fRet = ICM_GetDWORD(version, pvData, pcbData);
  15191. goto PreserveLengthReturn;
  15192. }
  15193. #endif // CMS_PKCS7
  15194. if (pcmi->fEncoding) {
  15195. switch (dwParamType) {
  15196. case CMSG_CONTENT_PARAM:
  15197. case CMSG_BARE_CONTENT_PARAM:
  15198. {
  15199. ContentInfo ci;
  15200. ASN1encoding_t pEnc = ICM_GetEncoder();
  15201. PBYTE pbEncoded = NULL;
  15202. DWORD cbEncoded;
  15203. PBYTE pbContent = NULL;
  15204. if (pcsi)
  15205. goto GetContentParamNotValidForStreaming;
  15206. switch (pcmi->dwMsgType) {
  15207. case CMSG_SIGNED:
  15208. if (0 == ((SignedData *) pcmi->pvMsg)->signerInfos.count)
  15209. // For a bag of certs, don't DER order
  15210. fBER = TRUE;
  15211. break;
  15212. case CMSG_DATA:
  15213. case CMSG_ENVELOPED:
  15214. case CMSG_HASHED:
  15215. break;
  15216. case CMSG_SIGNED_AND_ENVELOPED:
  15217. case CMSG_ENCRYPTED:
  15218. goto MessageTypeNotSupportedYet;
  15219. default:
  15220. goto InvalidMsgType;
  15221. }
  15222. if (fBER)
  15223. PkiAsn1SetEncodingRule(ICM_GetEncoder(), ASN1_BER_RULE_BER);
  15224. if (0 != (Asn1Err = PkiAsn1Encode(
  15225. pEnc,
  15226. pcmi->pvMsg,
  15227. aiPduNum[ pcmi->dwMsgType - 1],
  15228. &pbEncoded,
  15229. &cbEncoded))) {
  15230. goto CONTENT_PARAMAsn1EncodeError;
  15231. }
  15232. if (CMSG_CONTENT_PARAM == dwParamType) {
  15233. if (!ICM_CopyOssObjectIdentifier(
  15234. &ci.contentType,
  15235. &aoidMessages[ pcmi->dwMsgType - 1]))
  15236. goto CopyOssObjectIdentifierContentTypeError;
  15237. ci.bit_mask = content_present;
  15238. ci.content.length = cbEncoded;
  15239. ci.content.value = pbEncoded;
  15240. pbContent = pbEncoded;
  15241. if (0 != (Asn1Err = PkiAsn1Encode(
  15242. pEnc,
  15243. &ci,
  15244. ContentInfo_PDU,
  15245. &pbEncoded,
  15246. &cbEncoded))) {
  15247. PkiAsn1FreeEncoded(pEnc, pbContent);
  15248. goto Asn1EncodeSignedDataError;
  15249. }
  15250. }
  15251. fRet = ICM_CopyOut(
  15252. pbEncoded,
  15253. cbEncoded,
  15254. (PBYTE)pvData,
  15255. pcbData);
  15256. if (!fRet)
  15257. dwError = GetLastError();
  15258. if (pbContent)
  15259. PkiAsn1FreeEncoded(pEnc, pbContent);
  15260. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  15261. if (!fRet)
  15262. SetLastError(dwError);
  15263. break;
  15264. }
  15265. case CMSG_COMPUTED_HASH_PARAM:
  15266. fRet = ICM_GetComputedDigestParam( pcmi, dwIndex, pvData, pcbData);
  15267. break;
  15268. case CMSG_ENCODED_SIGNER:
  15269. switch (pcmi->dwMsgType) {
  15270. case CMSG_SIGNED:
  15271. break;
  15272. case CMSG_SIGNED_AND_ENVELOPED:
  15273. goto MessageTypeNotSupportedYet;
  15274. default:
  15275. goto InvalidMsgType;
  15276. }
  15277. fRet = ICM_GetSignerParamEncoding(
  15278. pcmi,
  15279. dwIndex,
  15280. dwParamType,
  15281. pvData,
  15282. pcbData);
  15283. break;
  15284. default:
  15285. goto InvalidMsgType;
  15286. }
  15287. } else {
  15288. //
  15289. // Decode
  15290. //
  15291. switch (dwParamType) {
  15292. case CMSG_TYPE_PARAM:
  15293. if (pcsi && (0 == pcmi->dwMsgType))
  15294. goto StreamMsgNotReadyError;
  15295. fRet = ICM_GetDWORD( pcmi->dwMsgType, pvData, pcbData);
  15296. break;
  15297. case CMSG_CONTENT_PARAM:
  15298. {
  15299. ContentInfo *pci;
  15300. PCONTENT_INFO pci2;
  15301. PBYTE pbDER = NULL;
  15302. DWORD cbDER;
  15303. PBYTE pb;
  15304. DWORD cb;
  15305. if (pcsi)
  15306. goto GetContentParamNotValidForStreaming;
  15307. switch (pcmi->dwMsgType) {
  15308. case CMSG_DATA:
  15309. {
  15310. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  15311. pb = (PBYTE)poos->value;
  15312. cb = poos->length;
  15313. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15314. break;
  15315. }
  15316. case CMSG_SIGNED:
  15317. if (NULL == pcmi->psdi)
  15318. goto InvalidSignedMessageError;
  15319. pci2 = pcmi->psdi->pci;
  15320. if (pci2->content.cbData) {
  15321. cb = pci2->content.cbData;
  15322. pb = pci2->content.pbData;
  15323. if (0 == strcmp(pszObjIdDataType,
  15324. pci2->pszContentType)
  15325. #ifdef CMS_PKCS7
  15326. || pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION
  15327. #endif // CMS_PKCS7
  15328. ) {
  15329. if (!ICM_ReEncodeAsOctetDER(
  15330. pb,
  15331. cb,
  15332. &pbDER,
  15333. &cbDER
  15334. ))
  15335. goto ReEncodeAsOctetDERError;
  15336. if (pbDER) {
  15337. if (0 > Asn1UtilExtractContent( pbDER, cbDER,
  15338. &cb, (const BYTE **)&pb)) {
  15339. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15340. goto ExtractContentError;
  15341. }
  15342. }
  15343. }
  15344. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15345. if (!fRet)
  15346. dwError = GetLastError();
  15347. if (pbDER)
  15348. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15349. if (!fRet)
  15350. SetLastError(dwError);
  15351. } else {
  15352. *pcbData = 0;
  15353. fRet = TRUE;
  15354. }
  15355. break;
  15356. case CMSG_ENVELOPED:
  15357. if (NULL == pcmi->Plaintext.pbData) {
  15358. // Hasn't been decrypted yet
  15359. EncryptedContentInfo *peci;
  15360. PBYTE pbCiphertext;
  15361. DWORD cbCiphertext;
  15362. #ifdef CMS_PKCS7
  15363. peci = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  15364. #else
  15365. peci = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  15366. #endif // CMS_PKCS7
  15367. if (peci->bit_mask & encryptedContent_present) {
  15368. pbCiphertext = peci->encryptedContent.value;
  15369. cbCiphertext = peci->encryptedContent.length;
  15370. } else {
  15371. pbCiphertext = NULL;
  15372. cbCiphertext = 0;
  15373. }
  15374. if (NULL == pvData) {
  15375. // Assume (sizeof plaintext) <=
  15376. // (sizeof ciphertext)
  15377. //
  15378. // not decrypted yet; return ciphertext size
  15379. fRet = TRUE;
  15380. // + 6 => to allow for identifier and length octets
  15381. *pcbData = cbCiphertext + 6;
  15382. } else
  15383. // Return ciphertext
  15384. fRet = ICM_CopyOut(
  15385. pbCiphertext,
  15386. cbCiphertext,
  15387. (PBYTE)pvData,
  15388. pcbData);
  15389. goto ContentCopiedOut;
  15390. }
  15391. if (!ICM_EqualObjectIDs(
  15392. #ifdef CMS_PKCS7
  15393. &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType,
  15394. &aoidMessages[ CMSG_DATA - 1])
  15395. &&
  15396. CMSG_ENVELOPED_DATA_CMS_VERSION >
  15397. ((CmsEnvelopedData *)pcmi->pvMsg)->version) {
  15398. #else
  15399. &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType,
  15400. &aoidMessages[ CMSG_DATA - 1])) {
  15401. #endif // CMS_PKCS7
  15402. // Not DATA or encapsulated, so must prepend
  15403. // identifier and length octets
  15404. fRet = ICM_CopyOutAddDERPrefix(
  15405. pcmi->Plaintext.pbData,
  15406. pcmi->Plaintext.cbData,
  15407. ICM_TAG_SEQ,
  15408. (PBYTE)pvData,
  15409. pcbData);
  15410. } else {
  15411. fRet = ICM_CopyOut(
  15412. pcmi->Plaintext.pbData,
  15413. pcmi->Plaintext.cbData,
  15414. (PBYTE)pvData,
  15415. pcbData);
  15416. }
  15417. goto ContentCopiedOut;
  15418. case CMSG_HASHED:
  15419. pci = &((DigestedData *)pcmi->pvMsg)->contentInfo;
  15420. if (pci->bit_mask & content_present) {
  15421. cb = (DWORD)pci->content.length;
  15422. pb = (PBYTE)pci->content.value;
  15423. if (ICM_EqualObjectIDs(
  15424. &pci->contentType,
  15425. &aoidMessages[ CMSG_DATA - 1])
  15426. #ifdef CMS_PKCS7
  15427. || ((DigestedData *)pcmi->pvMsg)->version >=
  15428. CMSG_HASHED_DATA_V2
  15429. #endif // CMS_PKCS7
  15430. ) {
  15431. if (!ICM_ReEncodeAsOctetDER(
  15432. pb,
  15433. cb,
  15434. &pbDER,
  15435. &cbDER
  15436. ))
  15437. goto ReEncodeAsOctetDERError;
  15438. if (pbDER) {
  15439. if (0 > Asn1UtilExtractContent( pbDER, cbDER,
  15440. &cb, (const BYTE **)&pb)) {
  15441. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15442. goto ExtractContentError;
  15443. }
  15444. }
  15445. }
  15446. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15447. if (!fRet)
  15448. dwError = GetLastError();
  15449. if (pbDER)
  15450. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15451. if (!fRet)
  15452. SetLastError(dwError);
  15453. } else {
  15454. *pcbData = 0;
  15455. fRet = TRUE;
  15456. }
  15457. break;
  15458. case CMSG_SIGNED_AND_ENVELOPED:
  15459. case CMSG_ENCRYPTED:
  15460. goto MessageTypeNotSupportedYet;
  15461. default:
  15462. goto InvalidMsgType;
  15463. }
  15464. ContentCopiedOut:
  15465. break;
  15466. }
  15467. case CMSG_INNER_CONTENT_TYPE_PARAM:
  15468. {
  15469. ContentType *pct;
  15470. switch (pcmi->dwMsgType) {
  15471. case CMSG_SIGNED:
  15472. if (NULL == pcmi->psdi)
  15473. goto InvalidSignedMessageError;
  15474. fRet = ICM_CopyOut(
  15475. (PBYTE)pcmi->psdi->pci->pszContentType,
  15476. strlen( pcmi->psdi->pci->pszContentType) + 1,
  15477. (PBYTE)pvData,
  15478. pcbData);
  15479. goto ContentTypeCopiedOut;
  15480. break;
  15481. case CMSG_ENVELOPED:
  15482. #ifdef CMS_PKCS7
  15483. pct = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType;
  15484. #else
  15485. pct = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType;
  15486. #endif // CMS_PKCS7
  15487. break;
  15488. case CMSG_HASHED:
  15489. pct = &((DigestedData *)pcmi->pvMsg)->contentInfo.contentType;
  15490. break;
  15491. case CMSG_SIGNED_AND_ENVELOPED:
  15492. case CMSG_ENCRYPTED:
  15493. goto MessageTypeNotSupportedYet;
  15494. default:
  15495. goto InvalidMsgType;
  15496. }
  15497. fRet = PkiAsn1FromObjectIdentifier(
  15498. pct->count,
  15499. pct->value,
  15500. (LPSTR)pvData,
  15501. pcbData);
  15502. ContentTypeCopiedOut:
  15503. break;
  15504. }
  15505. case CMSG_ENCODED_MESSAGE:
  15506. fRet = ICM_GetEncodedMessageParam(
  15507. pcmi,
  15508. (PBYTE)pvData,
  15509. pcbData);
  15510. break;
  15511. case CMSG_SIGNER_COUNT_PARAM:
  15512. {
  15513. DWORD cSigner;
  15514. switch (pcmi->dwMsgType) {
  15515. case CMSG_SIGNED:
  15516. if (NULL == pcmi->psdi)
  15517. goto InvalidSignedMessageError;
  15518. cSigner = pcmi->psdi->pSignerList->Length();
  15519. break;
  15520. case CMSG_SIGNED_AND_ENVELOPED:
  15521. goto MessageTypeNotSupportedYet;
  15522. default:
  15523. goto InvalidMsgType;
  15524. }
  15525. fRet = ICM_GetDWORD( cSigner, pvData, pcbData);
  15526. break;
  15527. }
  15528. case CMSG_ENCRYPTED_DIGEST:
  15529. case CMSG_ENCODED_SIGNER:
  15530. case CMSG_SIGNER_INFO_PARAM:
  15531. case CMSG_SIGNER_CERT_INFO_PARAM:
  15532. case CMSG_SIGNER_HASH_ALGORITHM_PARAM:
  15533. case CMSG_SIGNER_AUTH_ATTR_PARAM:
  15534. case CMSG_SIGNER_UNAUTH_ATTR_PARAM:
  15535. case CMSG_CMS_SIGNER_INFO_PARAM:
  15536. case CMSG_SIGNER_CERT_ID_PARAM:
  15537. switch (pcmi->dwMsgType) {
  15538. case CMSG_SIGNED:
  15539. break;
  15540. case CMSG_SIGNED_AND_ENVELOPED:
  15541. goto MessageTypeNotSupportedYet;
  15542. default:
  15543. goto InvalidMsgType;
  15544. }
  15545. fRet = ICM_GetSignerParam(
  15546. pcmi,
  15547. dwIndex,
  15548. dwParamType,
  15549. pvData,
  15550. pcbData);
  15551. break;
  15552. case CMSG_CERT_COUNT_PARAM:
  15553. {
  15554. CBlobList *pBlobList;
  15555. DWORD dwCount;
  15556. #ifdef CMS_PKCS7
  15557. BOOL fPossibleAttrCert = FALSE;
  15558. #endif // CMS_PKCS7
  15559. switch (pcmi->dwMsgType) {
  15560. case CMSG_SIGNED:
  15561. if (NULL == pcmi->psdi)
  15562. goto InvalidSignedMessageError;
  15563. pBlobList = pcmi->psdi->pCertificateList;
  15564. #ifdef CMS_PKCS7
  15565. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15566. fPossibleAttrCert = TRUE;
  15567. #endif // CMS_PKCS7
  15568. break;
  15569. #ifdef CMS_PKCS7
  15570. case CMSG_ENVELOPED:
  15571. pBlobList = pcmi->pCertificateList;
  15572. fPossibleAttrCert = TRUE;
  15573. break;
  15574. #endif // CMS_PKCS7
  15575. case CMSG_SIGNED_AND_ENVELOPED:
  15576. goto MessageTypeNotSupportedYet;
  15577. default:
  15578. goto InvalidMsgType;
  15579. }
  15580. dwCount = pBlobList->Length();
  15581. #ifdef CMS_PKCS7
  15582. if (dwCount && fPossibleAttrCert)
  15583. dwCount = ICM_GetTaggedBlobCount(
  15584. pBlobList,
  15585. ICM_TAG_SEQ
  15586. );
  15587. #endif // CMS_PKCS7
  15588. fRet = ICM_GetDWORD( dwCount, pvData, pcbData);
  15589. break;
  15590. }
  15591. case CMSG_CERT_PARAM:
  15592. {
  15593. CBlobList *pBlobList;
  15594. CBlobNode *pBlobNode;
  15595. #ifdef CMS_PKCS7
  15596. BOOL fPossibleAttrCert = FALSE;
  15597. #endif // CMS_PKCS7
  15598. switch (pcmi->dwMsgType) {
  15599. case CMSG_SIGNED:
  15600. if (NULL == pcmi->psdi)
  15601. goto InvalidSignedMessageError;
  15602. pBlobList = pcmi->psdi->pCertificateList;
  15603. #ifdef CMS_PKCS7
  15604. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15605. fPossibleAttrCert = TRUE;
  15606. #endif // CMS_PKCS7
  15607. break;
  15608. #ifdef CMS_PKCS7
  15609. case CMSG_ENVELOPED:
  15610. pBlobList = pcmi->pCertificateList;
  15611. fPossibleAttrCert = TRUE;
  15612. break;
  15613. #endif // CMS_PKCS7
  15614. case CMSG_SIGNED_AND_ENVELOPED:
  15615. goto MessageTypeNotSupportedYet;
  15616. default:
  15617. goto InvalidMsgType;
  15618. }
  15619. // Get blob at specified cert index. Index
  15620. // is advanced to the appropriate blob.
  15621. pBlobNode = ICM_GetTaggedBlobAndAdvanceIndex(
  15622. pBlobList,
  15623. #ifdef CMS_PKCS7
  15624. (BYTE)( fPossibleAttrCert ? ICM_TAG_SEQ : 0),
  15625. #else
  15626. 0, // bTag
  15627. #endif // CMS_PKCS7
  15628. &dwIndex
  15629. );
  15630. if (pBlobNode)
  15631. fRet = ICM_CopyOut(
  15632. pBlobNode->Data()->pbData,
  15633. pBlobNode->Data()->cbData,
  15634. (PBYTE)pvData,
  15635. pcbData);
  15636. else
  15637. fRet = FALSE;
  15638. break;
  15639. }
  15640. #ifdef CMS_PKCS7
  15641. case CMSG_ATTR_CERT_COUNT_PARAM:
  15642. {
  15643. CBlobList *pBlobList;
  15644. BOOL fPossibleAttrCert = FALSE;
  15645. DWORD dwCount;
  15646. switch (pcmi->dwMsgType) {
  15647. case CMSG_SIGNED:
  15648. if (NULL == pcmi->psdi)
  15649. goto InvalidSignedMessageError;
  15650. pBlobList = pcmi->psdi->pCertificateList;
  15651. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15652. fPossibleAttrCert = TRUE;
  15653. break;
  15654. case CMSG_ENVELOPED:
  15655. pBlobList = pcmi->pCertificateList;
  15656. fPossibleAttrCert = TRUE;
  15657. break;
  15658. default:
  15659. goto InvalidMsgType;
  15660. }
  15661. if (fPossibleAttrCert)
  15662. dwCount = ICM_GetTaggedBlobCount(
  15663. pBlobList,
  15664. ICM_TAG_CONSTRUCTED_CONTEXT_1
  15665. );
  15666. else
  15667. dwCount = 0;
  15668. fRet = ICM_GetDWORD( dwCount, pvData, pcbData);
  15669. break;
  15670. }
  15671. case CMSG_ATTR_CERT_PARAM:
  15672. {
  15673. CBlobList *pBlobList;
  15674. CBlobNode *pBlobNode;
  15675. BOOL fPossibleAttrCert = FALSE;
  15676. switch (pcmi->dwMsgType) {
  15677. case CMSG_SIGNED:
  15678. if (NULL == pcmi->psdi)
  15679. goto InvalidSignedMessageError;
  15680. pBlobList = pcmi->psdi->pCertificateList;
  15681. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15682. fPossibleAttrCert = TRUE;
  15683. break;
  15684. case CMSG_ENVELOPED:
  15685. pBlobList = pcmi->pCertificateList;
  15686. fPossibleAttrCert = TRUE;
  15687. break;
  15688. default:
  15689. goto InvalidMsgType;
  15690. }
  15691. if (!fPossibleAttrCert)
  15692. pBlobNode = NULL;
  15693. else
  15694. // Get blob at specified attribute cert index. Index
  15695. // is advanced to the appropriate blob
  15696. pBlobNode = ICM_GetTaggedBlobAndAdvanceIndex(
  15697. pBlobList,
  15698. ICM_TAG_CONSTRUCTED_CONTEXT_1,
  15699. &dwIndex
  15700. );
  15701. if (pBlobNode) {
  15702. fRet = ICM_CopyOut(
  15703. pBlobNode->Data()->pbData,
  15704. pBlobNode->Data()->cbData,
  15705. (PBYTE)pvData,
  15706. pcbData);
  15707. if (fRet && pvData)
  15708. *((PBYTE)pvData) = ICM_TAG_SEQ;
  15709. } else
  15710. fRet = FALSE;
  15711. break;
  15712. }
  15713. #endif // CMS_PKCS7
  15714. case CMSG_CRL_COUNT_PARAM:
  15715. {
  15716. CBlobList *pBlobList;
  15717. switch (pcmi->dwMsgType) {
  15718. case CMSG_SIGNED:
  15719. if (NULL == pcmi->psdi)
  15720. goto InvalidSignedMessageError;
  15721. pBlobList = pcmi->psdi->pCrlList;
  15722. break;
  15723. #ifdef CMS_PKCS7
  15724. case CMSG_ENVELOPED:
  15725. pBlobList = pcmi->pCrlList;
  15726. break;
  15727. #endif // CMS_PKCS7
  15728. case CMSG_SIGNED_AND_ENVELOPED:
  15729. goto MessageTypeNotSupportedYet;
  15730. default:
  15731. goto InvalidMsgType;
  15732. }
  15733. fRet = ICM_GetDWORD( pBlobList->Length(), pvData, pcbData);
  15734. break;
  15735. }
  15736. case CMSG_CRL_PARAM:
  15737. {
  15738. CBlobList *pBlobList;
  15739. CBlobNode *pBlobNode;
  15740. DWORD i;
  15741. switch (pcmi->dwMsgType) {
  15742. case CMSG_SIGNED:
  15743. if (NULL == pcmi->psdi)
  15744. goto InvalidSignedMessageError;
  15745. pBlobList = pcmi->psdi->pCrlList;
  15746. break;
  15747. #ifdef CMS_PKCS7
  15748. case CMSG_ENVELOPED:
  15749. pBlobList = pcmi->pCrlList;
  15750. break;
  15751. #endif // CMS_PKCS7
  15752. case CMSG_SIGNED_AND_ENVELOPED:
  15753. goto MessageTypeNotSupportedYet;
  15754. default:
  15755. goto InvalidMsgType;
  15756. }
  15757. // This list-walking should be a class method
  15758. for (i=dwIndex, pBlobNode=pBlobList->Head();
  15759. (i>0) && pBlobNode;
  15760. i--, pBlobNode=pBlobNode->Next())
  15761. ;
  15762. if (pBlobNode)
  15763. fRet = ICM_CopyOut(
  15764. pBlobNode->Data()->pbData,
  15765. pBlobNode->Data()->cbData,
  15766. (PBYTE)pvData,
  15767. pcbData);
  15768. else
  15769. fRet = FALSE;
  15770. break;
  15771. }
  15772. case CMSG_ENVELOPE_ALGORITHM_PARAM:
  15773. {
  15774. ContentEncryptionAlgId *pceai;
  15775. if (pcsi &&
  15776. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_ECIALGID)))
  15777. goto StreamMsgNotReadyError;
  15778. switch (pcmi->dwMsgType) {
  15779. case CMSG_ENVELOPED:
  15780. #ifdef CMS_PKCS7
  15781. pceai = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentEncryptionAlgorithm;
  15782. #else
  15783. pceai = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentEncryptionAlgorithm;
  15784. #endif // CMS_PKCS7
  15785. break;
  15786. case CMSG_SIGNED_AND_ENVELOPED:
  15787. goto MessageTypeNotSupportedYet;
  15788. default:
  15789. goto InvalidMsgType;
  15790. }
  15791. fRet = ICM_GetALGORITHM_IDENTIFIER( pceai, pvData, pcbData);
  15792. break;
  15793. }
  15794. #ifdef CMS_PKCS7
  15795. case CMSG_UNPROTECTED_ATTR_PARAM:
  15796. {
  15797. CmsEnvelopedData *ped;
  15798. ped = (CmsEnvelopedData *)pcmi->pvMsg;
  15799. if (ped && (ped->bit_mask & unprotectedAttrs_present))
  15800. fRet = ICM_GetAttributesData(
  15801. &ped->unprotectedAttrs,
  15802. pvData,
  15803. pcbData);
  15804. else
  15805. goto UnprotectedAttrMissingError;
  15806. }
  15807. break;
  15808. case CMSG_RECIPIENT_COUNT_PARAM:
  15809. {
  15810. DWORD dwPkcsCount;
  15811. if (!ICM_GetPkcsRecipientCount(pcmi, &dwPkcsCount))
  15812. goto GetPkcsRecipientCountError;
  15813. fRet = ICM_GetDWORD(dwPkcsCount, pvData, pcbData);
  15814. }
  15815. break;
  15816. case CMSG_RECIPIENT_INDEX_PARAM:
  15817. {
  15818. DWORD dwPkcsIndex;
  15819. DWORD dwCmsIndex;
  15820. DWORD cbData = sizeof(dwCmsIndex);
  15821. if (!CryptMsgGetParam(
  15822. hCryptMsg,
  15823. CMSG_CMS_RECIPIENT_INDEX_PARAM,
  15824. 0, // dwIndex
  15825. &dwCmsIndex,
  15826. &cbData))
  15827. goto GetCmsRecipientIndexError;
  15828. if (!ICM_ConvertCmsToPkcsRecipientIndex(
  15829. pcmi, dwCmsIndex, &dwPkcsIndex))
  15830. goto ConvertCmsToPkcsRecipientIndexError;
  15831. fRet = ICM_GetDWORD(
  15832. dwPkcsIndex,
  15833. pvData,
  15834. pcbData);
  15835. }
  15836. break;
  15837. case CMSG_RECIPIENT_INFO_PARAM:
  15838. {
  15839. CmsRecipientInfos *pris;
  15840. KeyTransRecipientInfo *pri;
  15841. DWORD dwCmsIndex;
  15842. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15843. goto GetDecodedCmsRecipientsError;
  15844. if (!ICM_ConvertPkcsToCmsRecipientIndex(
  15845. pcmi, dwIndex, &dwCmsIndex))
  15846. goto ConvertPkcsToCmsRecipientIndexError;
  15847. pri = &pris->value[dwCmsIndex].u.keyTransRecipientInfo;
  15848. fRet = ICM_GetCertInfoIssuerAndSerialNumber(
  15849. &pri->rid, pvData, pcbData);
  15850. break;
  15851. }
  15852. case CMSG_CMS_RECIPIENT_COUNT_PARAM:
  15853. {
  15854. CmsRecipientInfos *pris;
  15855. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15856. goto GetDecodedCmsRecipientsError;
  15857. fRet = ICM_GetDWORD(pris->count, pvData, pcbData);
  15858. }
  15859. break;
  15860. case CMSG_CMS_RECIPIENT_INDEX_PARAM:
  15861. {
  15862. CmsRecipientInfos *pris;
  15863. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15864. goto GetDecodedCmsRecipientsError;
  15865. fRet = ICM_GetDWORD(
  15866. pcmi->dwDecryptedRecipientIndex,
  15867. pvData,
  15868. pcbData);
  15869. }
  15870. break;
  15871. case CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM:
  15872. {
  15873. CmsRecipientInfos *pris;
  15874. CmsRecipientInfo *pri;
  15875. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15876. goto GetDecodedCmsRecipientsError;
  15877. pri = pris->value + pcmi->dwDecryptedRecipientIndex;
  15878. if (keyAgreeRecipientInfo_chosen != pri->choice)
  15879. goto NotKeyAgreeRecipientIndex;
  15880. fRet = ICM_GetDWORD(
  15881. pcmi->dwDecryptedRecipientEncryptedKeyIndex,
  15882. pvData,
  15883. pcbData);
  15884. }
  15885. break;
  15886. case CMSG_CMS_RECIPIENT_INFO_PARAM:
  15887. {
  15888. CmsRecipientInfos *pris;
  15889. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15890. goto GetDecodedCmsRecipientsError;
  15891. if (dwIndex >= pris->count)
  15892. goto IndexTooBig;
  15893. fRet = ICM_GetCmsRecipientInfo(pris->value + dwIndex,
  15894. pvData, pcbData);
  15895. }
  15896. break;
  15897. #else
  15898. case CMSG_RECIPIENT_COUNT_PARAM:
  15899. {
  15900. RecipientInfos *pris;
  15901. if (pcsi &&
  15902. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15903. goto StreamMsgNotReadyError;
  15904. switch (pcmi->dwMsgType) {
  15905. case CMSG_ENVELOPED:
  15906. pris = &((EnvelopedData *)pcmi->pvMsg)->recipientInfos;
  15907. break;
  15908. case CMSG_SIGNED_AND_ENVELOPED:
  15909. goto MessageTypeNotSupportedYet;
  15910. default:
  15911. goto InvalidMsgType;
  15912. }
  15913. fRet = ICM_GetDWORD( pris->count, pvData, pcbData);
  15914. break;
  15915. }
  15916. case CMSG_RECIPIENT_INDEX_PARAM:
  15917. {
  15918. if (pcsi &&
  15919. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15920. goto StreamMsgNotReadyError;
  15921. switch (pcmi->dwMsgType) {
  15922. case CMSG_ENVELOPED:
  15923. case CMSG_SIGNED_AND_ENVELOPED:
  15924. break;
  15925. default:
  15926. goto InvalidMsgType;
  15927. }
  15928. fRet = ICM_GetDWORD(
  15929. pcmi->dwDecryptedRecipientIndex,
  15930. pvData,
  15931. pcbData);
  15932. break;
  15933. }
  15934. case CMSG_RECIPIENT_INFO_PARAM:
  15935. {
  15936. RecipientInfos *pris;
  15937. RecipientInfo *pri;
  15938. PCERT_INFO pci = (PCERT_INFO)pvData;
  15939. if (pcsi &&
  15940. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15941. goto StreamMsgNotReadyError;
  15942. switch (pcmi->dwMsgType) {
  15943. case CMSG_ENVELOPED:
  15944. pris = &((EnvelopedData *)pcmi->pvMsg)->recipientInfos;
  15945. if (dwIndex >= pris->count)
  15946. goto IndexTooBig;
  15947. pri = pris->value + dwIndex;
  15948. break;
  15949. case CMSG_SIGNED_AND_ENVELOPED:
  15950. goto MessageTypeNotSupportedYet;
  15951. default:
  15952. goto InvalidMsgType;
  15953. }
  15954. // for lRemainExtra < 0, LENGTH_ONLY calculation
  15955. lData = INFO_LEN_ALIGN( sizeof(CERT_INFO));
  15956. lRemainExtra = (LONG)*pcbData - lData;
  15957. if (0 > lRemainExtra) {
  15958. pci = NULL;
  15959. pbExtra = NULL;
  15960. } else {
  15961. pbExtra = (PBYTE)pci + lData;
  15962. }
  15963. if (!ICM_GetOssIssuerAndSerialNumber(
  15964. &pri->issuerAndSerialNumber,
  15965. pci, &pbExtra, &lRemainExtra))
  15966. goto GetOssIssuerAndSerialNumberError;
  15967. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  15968. break;
  15969. }
  15970. #endif // CMS_PKCS7
  15971. case CMSG_HASH_ALGORITHM_PARAM:
  15972. fRet = ICM_GetALGORITHM_IDENTIFIER(
  15973. &((DigestedData *)pcmi->pvMsg)->digestAlgorithm,
  15974. pvData,
  15975. pcbData);
  15976. break;
  15977. case CMSG_HASH_DATA_PARAM:
  15978. fRet = ICM_GetDigestDataParam( pcmi, pvData, pcbData);
  15979. break;
  15980. case CMSG_COMPUTED_HASH_PARAM:
  15981. fRet = ICM_GetComputedDigestParam( pcmi, dwIndex, pvData, pcbData);
  15982. break;
  15983. case CMSG_ENCRYPT_PARAM:
  15984. #if 0
  15985. {
  15986. goto ParamTypeNotSupportedYet;
  15987. }
  15988. #endif
  15989. default:
  15990. goto InvalidMsgType;
  15991. }
  15992. }
  15993. #ifdef CMS_PKCS7
  15994. PreserveLengthReturn:
  15995. #endif // CMS_PKCS7
  15996. if (!fRet)
  15997. dwError = GetLastError();
  15998. } __except(EXCEPTION_EXECUTE_HANDLER) {
  15999. dwExceptionCode = GetExceptionCode();
  16000. goto ExceptionError;
  16001. }
  16002. CommonReturn:
  16003. if (fBER)
  16004. PkiAsn1SetEncodingRule(ICM_GetEncoder(), ASN1_BER_RULE_DER);
  16005. ICM_Unlock( pcmi);
  16006. ICM_SetLastError(dwError);
  16007. return fRet;
  16008. ErrorReturn:
  16009. *pcbData = 0;
  16010. fRet = FALSE;
  16011. goto CommonReturn;
  16012. StreamMsgNotReadyError:
  16013. dwError = (DWORD)CRYPT_E_STREAM_MSG_NOT_READY;
  16014. goto ErrorReturn;
  16015. SET_ERROR(GetContentParamNotValidForStreaming, E_INVALIDARG)
  16016. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  16017. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  16018. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  16019. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  16020. SET_ERROR_VAR(CONTENT_PARAMAsn1EncodeError, PkiAsn1ErrToHr(Asn1Err))
  16021. SET_ERROR_VAR(Asn1EncodeSignedDataError, PkiAsn1ErrToHr(Asn1Err))
  16022. TRACE_ERROR(CopyOssObjectIdentifierContentTypeError) // error already set
  16023. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  16024. SET_ERROR(InvalidSignedMessageError, ERROR_INVALID_DATA)
  16025. #ifdef CMS_PKCS7
  16026. SET_ERROR(MessageNotDecodedError, ERROR_INVALID_DATA)
  16027. SET_ERROR(InvalidMessageDataError, ERROR_INVALID_DATA)
  16028. TRACE_ERROR(GetDecodedCmsRecipientsError)
  16029. TRACE_ERROR(GetPkcsRecipientCountError)
  16030. TRACE_ERROR(ConvertCmsToPkcsRecipientIndexError)
  16031. TRACE_ERROR(ConvertPkcsToCmsRecipientIndexError)
  16032. TRACE_ERROR(GetCmsRecipientIndexError)
  16033. SET_ERROR(NotKeyAgreeRecipientIndex, CRYPT_E_INVALID_INDEX)
  16034. SET_ERROR(UnprotectedAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  16035. #else
  16036. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  16037. #endif // CMS_PKCS7
  16038. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  16039. }
  16040. //+=========================================================================
  16041. // Data structures and functions to test and compare the NEW Net Meeting
  16042. // ASN1 compiler and RTS with the OSS compiler and RTS.
  16043. //-=========================================================================
  16044. #ifdef DEBUG_CRYPT_ASN1
  16045. //#define DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG 0x010
  16046. //#define DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG 0x020
  16047. //#define DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG 0x100
  16048. //static BOOL fGotDebugCryptAsn1Flags = FALSE;
  16049. //static int iDebugCryptAsn1Flags = 0;
  16050. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16051. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_OPEN_TO_ENCODE)(
  16052. IN DWORD dwMsgEncodingType,
  16053. IN DWORD dwFlags,
  16054. IN DWORD dwMsgType,
  16055. IN void const *pvMsgEncodeInfo,
  16056. IN OPTIONAL LPSTR pszInnerContentObjID,
  16057. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16058. );
  16059. static PFN_CRYPT_MSG_OPEN_TO_ENCODE pfnOssCryptMsgOpenToEncode = NULL;
  16060. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_OPEN_TO_DECODE)(
  16061. IN DWORD dwMsgEncodingType,
  16062. IN DWORD dwFlags,
  16063. IN DWORD dwMsgType,
  16064. IN HCRYPTPROV hCryptProv,
  16065. IN OPTIONAL PCERT_INFO pRecipientInfo,
  16066. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16067. );
  16068. static PFN_CRYPT_MSG_OPEN_TO_DECODE pfnOssCryptMsgOpenToDecode = NULL;
  16069. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_DUPLICATE)(
  16070. IN HCRYPTMSG hCryptMsg
  16071. );
  16072. static PFN_CRYPT_MSG_DUPLICATE pfnOssCryptMsgDuplicate = NULL;
  16073. typedef BOOL (WINAPI *PFN_CRYPT_MSG_CLOSE)(
  16074. IN HCRYPTMSG hCryptMsg
  16075. );
  16076. static PFN_CRYPT_MSG_CLOSE pfnOssCryptMsgClose = NULL;
  16077. typedef BOOL (WINAPI *PFN_CRYPT_MSG_UPDATE)(
  16078. IN HCRYPTMSG hCryptMsg,
  16079. IN const BYTE *pbData,
  16080. IN DWORD cbData,
  16081. IN BOOL fFinal
  16082. );
  16083. static PFN_CRYPT_MSG_UPDATE pfnOssCryptMsgUpdate = NULL;
  16084. typedef BOOL (WINAPI *PFN_CRYPT_MSG_GET_PARAM)(
  16085. IN HCRYPTMSG hCryptMsg,
  16086. IN DWORD dwParamType,
  16087. IN DWORD dwIndex,
  16088. OUT void *pvData,
  16089. IN OUT DWORD *pcbData
  16090. );
  16091. static PFN_CRYPT_MSG_GET_PARAM pfnOssCryptMsgGetParam = NULL;
  16092. typedef BOOL (WINAPI *PFN_CRYPT_MSG_CONTROL)(
  16093. IN HCRYPTMSG hCryptMsg,
  16094. IN DWORD dwFlags,
  16095. IN DWORD dwCtrlType,
  16096. IN void const *pvCtrlPara
  16097. );
  16098. static PFN_CRYPT_MSG_CONTROL pfnOssCryptMsgControl = NULL;
  16099. #ifdef CMS_PKCS7
  16100. typedef BOOL (WINAPI *PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX)(
  16101. IN HCRYPTPROV hCryptProv,
  16102. IN DWORD dwEncodingType,
  16103. IN PBYTE pbSignerInfo,
  16104. IN DWORD cbSignerInfo,
  16105. IN PBYTE pbSignerInfoCountersignature,
  16106. IN DWORD cbSignerInfoCountersignature,
  16107. IN DWORD dwSignerType,
  16108. IN void *pvSigner,
  16109. IN DWORD dwFlags,
  16110. IN OPTIONAL void *pvReserved
  16111. );
  16112. static PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX
  16113. pfnOssCryptMsgVerifyCountersignatureEncodedEx = NULL;
  16114. #endif // CMS_PKCS7
  16115. typedef BOOL (WINAPI *PFN_CRYPT_MSG_COUNTERSIGN)(
  16116. IN OUT HCRYPTMSG hCryptMsg,
  16117. IN DWORD dwIndex,
  16118. IN DWORD cCountersigners,
  16119. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners
  16120. );
  16121. static PFN_CRYPT_MSG_COUNTERSIGN pfnOssCryptMsgCountersign = NULL;
  16122. typedef BOOL (WINAPI *PFN_CRYPT_MSG_COUNTERSIGN_ENCODED)(
  16123. IN DWORD dwEncodingType,
  16124. IN PBYTE pbSignerInfo,
  16125. IN DWORD cbSignerInfo,
  16126. IN DWORD cCountersigners,
  16127. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  16128. OUT PBYTE pbCountersignature,
  16129. IN OUT PDWORD pcbCountersignature
  16130. );
  16131. static PFN_CRYPT_MSG_COUNTERSIGN_ENCODED
  16132. pfnOssCryptMsgCountersignEncoded = NULL;
  16133. #endif // DEBUG_CRYPT_ASN1_MASTER
  16134. int
  16135. WINAPI
  16136. ICMTest_GetDebugCryptAsn1Flags()
  16137. {
  16138. if (!fGotDebugCryptAsn1Flags) {
  16139. char *pszEnvVar;
  16140. char *p;
  16141. int iFlags;
  16142. if (pszEnvVar = getenv("DEBUG_CRYPT_ASN1_FLAGS")) {
  16143. iFlags = strtol(pszEnvVar, &p, 16);
  16144. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16145. if (iFlags) {
  16146. if (NULL == (hOssCryptDll = LoadLibraryA("osscrypt.dll"))) {
  16147. iFlags = 0;
  16148. MessageBoxA(
  16149. NULL, // hwndOwner
  16150. "LoadLibrary(osscrypt.dll) failed",
  16151. "CheckCryptMessageAsn1",
  16152. MB_TOPMOST | MB_OK | MB_ICONWARNING |
  16153. MB_SERVICE_NOTIFICATION
  16154. );
  16155. } else if (NULL == (pfnOssCryptMsgOpenToEncode =
  16156. (PFN_CRYPT_MSG_OPEN_TO_ENCODE)
  16157. GetProcAddress(hOssCryptDll,
  16158. "CryptMsgOpenToEncode")) ||
  16159. NULL == (pfnOssCryptMsgOpenToDecode =
  16160. (PFN_CRYPT_MSG_OPEN_TO_DECODE)
  16161. GetProcAddress(hOssCryptDll,
  16162. "CryptMsgOpenToDecode")) ||
  16163. NULL == (pfnOssCryptMsgDuplicate =
  16164. (PFN_CRYPT_MSG_DUPLICATE)
  16165. GetProcAddress(hOssCryptDll,
  16166. "CryptMsgDuplicate")) ||
  16167. NULL == (pfnOssCryptMsgClose =
  16168. (PFN_CRYPT_MSG_CLOSE)
  16169. GetProcAddress(hOssCryptDll,
  16170. "CryptMsgClose")) ||
  16171. NULL == (pfnOssCryptMsgUpdate =
  16172. (PFN_CRYPT_MSG_UPDATE)
  16173. GetProcAddress(hOssCryptDll,
  16174. "CryptMsgUpdate")) ||
  16175. NULL == (pfnOssCryptMsgControl =
  16176. (PFN_CRYPT_MSG_CONTROL)
  16177. GetProcAddress(hOssCryptDll,
  16178. "CryptMsgControl")) ||
  16179. NULL == (pfnOssCryptMsgGetParam =
  16180. (PFN_CRYPT_MSG_GET_PARAM)
  16181. GetProcAddress(hOssCryptDll,
  16182. "CryptMsgGetParam")) ||
  16183. #ifdef CMS_PKCS7
  16184. NULL == (pfnOssCryptMsgVerifyCountersignatureEncodedEx =
  16185. (PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX)
  16186. GetProcAddress(hOssCryptDll,
  16187. "CryptMsgVerifyCountersignatureEncodedEx"))
  16188. ||
  16189. #endif // CMS_PKCS7
  16190. NULL == (pfnOssCryptMsgCountersign =
  16191. (PFN_CRYPT_MSG_COUNTERSIGN)
  16192. GetProcAddress(hOssCryptDll,
  16193. "CryptMsgCountersign")) ||
  16194. NULL == (pfnOssCryptMsgCountersignEncoded =
  16195. (PFN_CRYPT_MSG_COUNTERSIGN_ENCODED)
  16196. GetProcAddress(hOssCryptDll,
  16197. "CryptMsgCountersignEncoded"))) {
  16198. iFlags = 0;
  16199. MessageBoxA(
  16200. NULL, // hwndOwner
  16201. "GetProcAddress(osscrypt.dll) failed",
  16202. "CheckCryptMessageAsn1",
  16203. MB_TOPMOST | MB_OK | MB_ICONWARNING |
  16204. MB_SERVICE_NOTIFICATION
  16205. );
  16206. }
  16207. }
  16208. #endif // DEBUG_CRYPT_ASN1_MASTER
  16209. } else
  16210. iFlags = 0;
  16211. if (iFlags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG)
  16212. iFlags &= ~DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG;
  16213. iDebugCryptAsn1Flags = iFlags;
  16214. fGotDebugCryptAsn1Flags = TRUE;
  16215. }
  16216. return iDebugCryptAsn1Flags;
  16217. }
  16218. HCRYPTKEY
  16219. ICMTest_GetSameEncryptKey()
  16220. {
  16221. DWORD dwError = 0;
  16222. HCRYPTPROV hCryptProv; // doesn't need to be freed
  16223. HCRYPTHASH hHash = 0;
  16224. HCRYPTKEY hDeriveKey = 0;
  16225. BYTE rgbBaseData[] = {1,2,3,4,5,6,7,8};
  16226. hCryptProv = I_CryptGetDefaultCryptProvForEncrypt(
  16227. 0, // aiPubKey
  16228. CALG_RC2,
  16229. 0 // dwBitLen
  16230. );
  16231. if (0 == hCryptProv)
  16232. goto GetDefaultCryptProvError;
  16233. if (!CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
  16234. goto CreateHashError;
  16235. if (!CryptHashData(hHash, rgbBaseData, sizeof(rgbBaseData), 0))
  16236. goto HashDataError;
  16237. if (!CryptDeriveKey(hCryptProv, CALG_RC2, hHash, 0, &hDeriveKey))
  16238. goto DeriveKeyError;
  16239. CommonReturn:
  16240. if (hHash)
  16241. CryptDestroyHash(hHash);
  16242. ICM_SetLastError(dwError);
  16243. return hDeriveKey;
  16244. ErrorReturn:
  16245. dwError = GetLastError();
  16246. if (hDeriveKey) {
  16247. CryptDestroyKey(hDeriveKey);
  16248. hDeriveKey = 0;
  16249. }
  16250. goto CommonReturn;
  16251. TRACE_ERROR(GetDefaultCryptProvError)
  16252. TRACE_ERROR(CreateHashError)
  16253. TRACE_ERROR(HashDataError)
  16254. TRACE_ERROR(DeriveKeyError)
  16255. }
  16256. #ifdef CMS_PKCS7
  16257. BOOL
  16258. WINAPI
  16259. ICM_DefaultGenContentEncryptKey(
  16260. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  16261. IN DWORD dwFlags,
  16262. IN OPTIONAL void *pvReserved
  16263. )
  16264. {
  16265. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16266. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16267. return ICMTest_DefaultGenContentEncryptKey(
  16268. pContentEncryptInfo,
  16269. dwFlags,
  16270. pvReserved
  16271. );
  16272. pContentEncryptInfo->hContentEncryptKey = ICMTest_GetSameEncryptKey();
  16273. if (pContentEncryptInfo->hContentEncryptKey)
  16274. return TRUE;
  16275. else
  16276. return FALSE;
  16277. }
  16278. BOOL
  16279. WINAPI
  16280. ICM_DefaultExportKeyTrans(
  16281. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  16282. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  16283. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
  16284. IN DWORD dwFlags,
  16285. IN OPTIONAL void *pvReserved
  16286. )
  16287. {
  16288. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16289. PCRYPT_DATA_BLOB pEncryptedKey;
  16290. BYTE rgbEncryptedKey[] = {1,1,2,2,3,3,4,4,5,5};
  16291. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16292. return ICMTest_DefaultExportKeyTrans(
  16293. pContentEncryptInfo,
  16294. pKeyTransEncodeInfo,
  16295. pKeyTransEncryptInfo,
  16296. dwFlags,
  16297. pvReserved
  16298. );
  16299. pEncryptedKey = &pKeyTransEncryptInfo->EncryptedKey;
  16300. if (NULL == (pEncryptedKey->pbData = (PBYTE) ICM_Alloc(
  16301. sizeof(rgbEncryptedKey))))
  16302. return FALSE;
  16303. pEncryptedKey->cbData = sizeof(rgbEncryptedKey);
  16304. memcpy(pEncryptedKey->pbData, rgbEncryptedKey, sizeof(rgbEncryptedKey));
  16305. return TRUE;
  16306. }
  16307. BOOL
  16308. WINAPI
  16309. ICM_DefaultImportKeyTrans(
  16310. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  16311. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  16312. IN DWORD dwFlags,
  16313. IN OPTIONAL void *pvReserved,
  16314. OUT HCRYPTKEY *phContentEncryptKey
  16315. )
  16316. {
  16317. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16318. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16319. return ICMTest_DefaultImportKeyTrans(
  16320. pContentEncryptionAlgorithm,
  16321. pKeyTransDecryptPara,
  16322. dwFlags,
  16323. pvReserved,
  16324. phContentEncryptKey
  16325. );
  16326. *phContentEncryptKey = ICMTest_GetSameEncryptKey();
  16327. if (*phContentEncryptKey)
  16328. return TRUE;
  16329. else
  16330. return FALSE;
  16331. }
  16332. #endif // CMS_PKCS7
  16333. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16334. void
  16335. ICMTest_MessageBox(
  16336. IN LPSTR pszText
  16337. )
  16338. {
  16339. int id;
  16340. LPSTR pszAlloc = NULL;
  16341. DWORD cchAlloc;
  16342. static LPCSTR pszSelect =
  16343. " Select Cancel to stop future OssCryptAsn1 Cryptographic Messages.";
  16344. cchAlloc = strlen(pszText) + strlen(pszSelect) + 1;
  16345. if (pszAlloc = (LPSTR) ICM_Alloc(cchAlloc)) {
  16346. strcpy(pszAlloc, pszText);
  16347. strcat(pszAlloc, pszSelect);
  16348. pszText = pszAlloc;
  16349. }
  16350. id = MessageBoxA(
  16351. NULL, // hwndOwner
  16352. pszText,
  16353. "CheckCryptMessageAsn1",
  16354. MB_TOPMOST | MB_OKCANCEL | MB_ICONQUESTION |
  16355. MB_SERVICE_NOTIFICATION
  16356. );
  16357. if (IDCANCEL == id)
  16358. iDebugCryptAsn1Flags = 0;
  16359. ICM_Free(pszAlloc);
  16360. }
  16361. void
  16362. ICMTest_MessageBoxLastError(
  16363. IN LPSTR pszText,
  16364. IN DWORD dwOssErr,
  16365. IN DWORD dwNewErr
  16366. )
  16367. {
  16368. char szText[512];
  16369. if (dwNewErr == (DWORD) PkiAsn1ErrToHr(ASN1_ERR_BADTAG) &&
  16370. (OSS_DATA_ERROR == dwOssErr || OSS_PDU_MISMATCH == dwOssErr))
  16371. return;
  16372. if (dwNewErr == (DWORD) PkiAsn1ErrToHr(ASN1_ERR_EOD) &&
  16373. OSS_MORE_INPUT == dwOssErr)
  16374. return;
  16375. wsprintfA(szText,
  16376. "%s:: failed with different LastError Oss: %d 0x%x New: %d 0x%x.",
  16377. pszText, dwOssErr, dwOssErr, dwNewErr, dwNewErr
  16378. );
  16379. ICMTest_MessageBox(szText);
  16380. }
  16381. //+-------------------------------------------------------------------------
  16382. // Write an encoded DER blob to a file
  16383. //--------------------------------------------------------------------------
  16384. BOOL
  16385. ICMTest_WriteDERToFile(
  16386. LPCSTR pszFileName,
  16387. PBYTE pbDER,
  16388. DWORD cbDER
  16389. )
  16390. {
  16391. BOOL fResult;
  16392. // Write the Encoded Blob to the file
  16393. HANDLE hFile;
  16394. hFile = CreateFile(pszFileName,
  16395. GENERIC_WRITE,
  16396. 0, // fdwShareMode
  16397. NULL, // lpsa
  16398. CREATE_ALWAYS,
  16399. 0, // fdwAttrsAndFlags
  16400. 0); // TemplateFile
  16401. if (INVALID_HANDLE_VALUE == hFile) {
  16402. fResult = FALSE;
  16403. } else {
  16404. DWORD dwBytesWritten;
  16405. fResult = WriteFile(
  16406. hFile,
  16407. pbDER,
  16408. cbDER,
  16409. &dwBytesWritten,
  16410. NULL // lpOverlapped
  16411. );
  16412. CloseHandle(hFile);
  16413. }
  16414. return fResult;
  16415. }
  16416. #define TEST_MAGIC -12348765
  16417. // Note, in the following data structure lMagic is at the same offest as
  16418. // lRefCnt in CRYPT_MSG_INFO. lRefCnt should never be negative.
  16419. typedef struct _OSS_CRYPT_ASN1_MSG_INFO {
  16420. // The following must be ordered the same as CRYPT_MSG_INFO through
  16421. // dwEncodingType. msghlpr.cpp does a (PCRYPT_MSG_INFO) cast to
  16422. // access dwEncodingType.
  16423. CRITICAL_SECTION CriticalSection;
  16424. LONG lMagic; // lRefCnt in CRYPT_MSG_INFO
  16425. HCRYPTPROV hCryptProv; // decode
  16426. BOOL fDefaultCryptProv; // decode
  16427. DWORD dwKeySpec; // key to use in CryptSignHash
  16428. DWORD dwEncodingType; // encode
  16429. LONG lRefCnt;
  16430. union {
  16431. HCRYPTMSG hNewCryptMsg;
  16432. PCRYPT_MSG_INFO pNewcmi;
  16433. };
  16434. union {
  16435. HCRYPTMSG hOssCryptMsg;
  16436. PCRYPT_MSG_INFO pOsscmi;
  16437. };
  16438. PFN_CMSG_STREAM_OUTPUT pfnStreamOutput;
  16439. void *pvArg;
  16440. BYTE *pbOssOutput;
  16441. DWORD cbOssOutput;
  16442. BOOL fOssFinal;
  16443. BYTE *pbNewOutput;
  16444. DWORD cbNewOutput;
  16445. BOOL fNewFinal;
  16446. BOOL fDidCompare;
  16447. } OSS_CRYPT_ASN1_MSG_INFO, *POSS_CRYPT_ASN1_MSG_INFO;
  16448. BOOL
  16449. WINAPI
  16450. ICMTest_OssStreamOutput(
  16451. IN const void *pvArg,
  16452. IN BYTE *pbData,
  16453. IN DWORD cbData,
  16454. IN BOOL fFinal
  16455. )
  16456. {
  16457. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) pvArg;
  16458. assert(TEST_MAGIC == pInfo->lMagic);
  16459. assert(!pInfo->fOssFinal);
  16460. pInfo->fOssFinal = fFinal;
  16461. if (cbData) {
  16462. BYTE *pbOssOutput;
  16463. if (pbOssOutput = (BYTE *) ICM_ReAlloc(pInfo->pbOssOutput,
  16464. pInfo->cbOssOutput + cbData)) {
  16465. memcpy(pbOssOutput + pInfo->cbOssOutput, pbData, cbData);
  16466. pInfo->pbOssOutput = pbOssOutput;
  16467. pInfo->cbOssOutput += cbData;
  16468. }
  16469. }
  16470. return TRUE;
  16471. }
  16472. BOOL
  16473. WINAPI
  16474. ICMTest_NewStreamOutput(
  16475. IN const void *pvArg,
  16476. IN BYTE *pbData,
  16477. IN DWORD cbData,
  16478. IN BOOL fFinal
  16479. )
  16480. {
  16481. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) pvArg;
  16482. assert(TEST_MAGIC == pInfo->lMagic);
  16483. assert(!pInfo->fNewFinal);
  16484. pInfo->fNewFinal = fFinal;
  16485. if (cbData) {
  16486. BYTE *pbNewOutput;
  16487. if (pbNewOutput = (BYTE *) ICM_ReAlloc(pInfo->pbNewOutput,
  16488. pInfo->cbNewOutput + cbData)) {
  16489. memcpy(pbNewOutput + pInfo->cbNewOutput, pbData, cbData);
  16490. pInfo->pbNewOutput = pbNewOutput;
  16491. pInfo->cbNewOutput += cbData;
  16492. }
  16493. }
  16494. return pInfo->pfnStreamOutput(
  16495. pInfo->pvArg,
  16496. pbData,
  16497. cbData,
  16498. fFinal
  16499. );
  16500. }
  16501. void
  16502. ICMTest_CompareMessageBox(
  16503. IN LPSTR pszText,
  16504. IN BYTE *pbOss,
  16505. IN DWORD cbOss,
  16506. IN BYTE *pbNew,
  16507. IN DWORD cbNew
  16508. )
  16509. {
  16510. if (NULL == pbOss || NULL == pbNew)
  16511. return;
  16512. if (cbOss != cbNew || 0 != memcmp(pbOss, pbNew, cbNew)) {
  16513. ICMTest_WriteDERToFile("ossasn1.der", pbOss, cbOss);
  16514. ICMTest_WriteDERToFile("newasn1.der", pbNew, cbNew);
  16515. ICMTest_MessageBox(pszText);
  16516. }
  16517. }
  16518. void
  16519. ICMTest_CompareStreamOutput(
  16520. IN POSS_CRYPT_ASN1_MSG_INFO pInfo,
  16521. IN BOOL fForceCompare = FALSE
  16522. )
  16523. {
  16524. BOOL fDoCompare;
  16525. if (NULL == pInfo->pfnStreamOutput || pInfo->fDidCompare)
  16526. return;
  16527. fDoCompare = fForceCompare;
  16528. if (pInfo->fOssFinal || pInfo->fNewFinal)
  16529. fDoCompare = TRUE;
  16530. if (fDoCompare) {
  16531. if (pInfo->fOssFinal != pInfo->fNewFinal) {
  16532. if (pInfo->fOssFinal)
  16533. ICMTest_MessageBox("No fFinal on NewStreamOutput.");
  16534. else
  16535. ICMTest_MessageBox("No fFinal on OssStreamOutput.");
  16536. }
  16537. ICMTest_CompareMessageBox(
  16538. "StreamOutput compare failed. Check ossasn1.der and newasn1.der.",
  16539. pInfo->pbOssOutput,
  16540. pInfo->cbOssOutput,
  16541. pInfo->pbNewOutput,
  16542. pInfo->cbNewOutput
  16543. );
  16544. pInfo->fDidCompare = TRUE;
  16545. }
  16546. }
  16547. void
  16548. ICMTest_CompareGetParam(
  16549. IN POSS_CRYPT_ASN1_MSG_INFO pInfo,
  16550. IN DWORD dwParamType,
  16551. IN DWORD dwIndex,
  16552. IN void *pvOssData,
  16553. IN DWORD cbOssData,
  16554. IN void *pvNewData,
  16555. IN DWORD cbNewData
  16556. )
  16557. {
  16558. char szText[512];
  16559. switch (dwParamType) {
  16560. case CMSG_TYPE_PARAM:
  16561. case CMSG_CONTENT_PARAM:
  16562. case CMSG_BARE_CONTENT_PARAM:
  16563. case CMSG_INNER_CONTENT_TYPE_PARAM:
  16564. case CMSG_SIGNER_COUNT_PARAM:
  16565. case CMSG_CERT_COUNT_PARAM:
  16566. case CMSG_CERT_PARAM:
  16567. case CMSG_CRL_COUNT_PARAM:
  16568. case CMSG_CRL_PARAM:
  16569. case CMSG_RECIPIENT_COUNT_PARAM:
  16570. case CMSG_HASH_DATA_PARAM:
  16571. case CMSG_COMPUTED_HASH_PARAM:
  16572. case CMSG_ENCRYPTED_DIGEST:
  16573. case CMSG_ENCODED_SIGNER:
  16574. case CMSG_ENCODED_MESSAGE:
  16575. #ifdef CMS_PKCS7
  16576. case CMSG_VERSION_PARAM:
  16577. case CMSG_ATTR_CERT_COUNT_PARAM:
  16578. case CMSG_ATTR_CERT_PARAM:
  16579. case CMSG_CMS_RECIPIENT_COUNT_PARAM:
  16580. #endif // CMS_PKCS7
  16581. break;
  16582. default:
  16583. return;
  16584. }
  16585. if (NULL == pvOssData || NULL == pvNewData)
  16586. return;
  16587. wsprintfA(szText,
  16588. "ParamType: %d compare failed. Check ossasn1.der and newasn1.der.",
  16589. dwParamType
  16590. );
  16591. ICMTest_CompareMessageBox(
  16592. szText,
  16593. (BYTE *) pvOssData,
  16594. cbOssData,
  16595. (BYTE *) pvNewData,
  16596. cbNewData
  16597. );
  16598. }
  16599. inline
  16600. void
  16601. ICMTest_Lock(
  16602. IN POSS_CRYPT_ASN1_MSG_INFO pInfo
  16603. )
  16604. {
  16605. EnterCriticalSection( &pInfo->CriticalSection);
  16606. }
  16607. inline
  16608. void
  16609. ICMTest_Unlock(
  16610. IN POSS_CRYPT_ASN1_MSG_INFO pInfo
  16611. )
  16612. {
  16613. LeaveCriticalSection( &pInfo->CriticalSection);
  16614. }
  16615. HCRYPTMSG
  16616. WINAPI
  16617. CryptMsgOpenToEncode(
  16618. IN DWORD dwMsgEncodingType,
  16619. IN DWORD dwFlags,
  16620. IN DWORD dwMsgType,
  16621. IN void const *pvMsgEncodeInfo,
  16622. IN OPTIONAL LPSTR pszInnerContentObjID,
  16623. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16624. )
  16625. {
  16626. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16627. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  16628. POSS_CRYPT_ASN1_MSG_INFO pInfo;
  16629. CMSG_STREAM_INFO StreamInfo;
  16630. DWORD dwOssErr;
  16631. DWORD dwNewErr;
  16632. if (NULL == (pInfo = (POSS_CRYPT_ASN1_MSG_INFO) ICM_AllocZero(
  16633. sizeof(OSS_CRYPT_ASN1_MSG_INFO))))
  16634. return NULL;
  16635. pInfo->lMagic = TEST_MAGIC;
  16636. if (pStreamInfo) {
  16637. pInfo->pfnStreamOutput = pStreamInfo->pfnStreamOutput;
  16638. pInfo->pvArg = pStreamInfo->pvArg;
  16639. StreamInfo.cbContent = pStreamInfo->cbContent;
  16640. // StreamInfo.pfnStreamOutput =
  16641. StreamInfo.pvArg = pInfo;
  16642. pStreamInfo = &StreamInfo;
  16643. }
  16644. StreamInfo.pfnStreamOutput = ICMTest_NewStreamOutput;
  16645. pInfo->hNewCryptMsg = ICMTest_NewCryptMsgOpenToEncode(
  16646. dwMsgEncodingType,
  16647. dwFlags,
  16648. dwMsgType,
  16649. pvMsgEncodeInfo,
  16650. pszInnerContentObjID,
  16651. pStreamInfo
  16652. );
  16653. dwNewErr = GetLastError();
  16654. StreamInfo.pfnStreamOutput = ICMTest_OssStreamOutput;
  16655. pInfo->hOssCryptMsg = pfnOssCryptMsgOpenToEncode(
  16656. dwMsgEncodingType,
  16657. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  16658. dwMsgType,
  16659. pvMsgEncodeInfo,
  16660. pszInnerContentObjID,
  16661. pStreamInfo
  16662. );
  16663. dwOssErr = GetLastError();
  16664. if (pInfo->hNewCryptMsg) {
  16665. if (pInfo->hOssCryptMsg) {
  16666. pInfo->dwEncodingType = pInfo->pNewcmi->dwEncodingType;
  16667. InitializeCriticalSection(&pInfo->CriticalSection);
  16668. pInfo->lRefCnt = 1;
  16669. return (HCRYPTMSG) pInfo;
  16670. } else {
  16671. HCRYPTMSG hRet;
  16672. ICMTest_MessageBox("OssCryptMsgOpenToEncode failed.");
  16673. hRet = pInfo->hNewCryptMsg;
  16674. ICM_Free(pInfo);
  16675. return hRet;
  16676. }
  16677. } else {
  16678. if (pInfo->hOssCryptMsg) {
  16679. ICMTest_MessageBox("OssCryptMsgOpenToEncode succeeded while NewCryptMsgOpenToEncoded failed.");
  16680. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16681. } else if (dwOssErr != dwNewErr)
  16682. ICMTest_MessageBoxLastError("CryptMsgOpenToEncode",
  16683. dwOssErr, dwNewErr);
  16684. ICM_Free(pInfo);
  16685. SetLastError(dwNewErr);
  16686. return NULL;
  16687. }
  16688. } else if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16689. return pfnOssCryptMsgOpenToEncode(
  16690. dwMsgEncodingType,
  16691. dwFlags,
  16692. dwMsgType,
  16693. pvMsgEncodeInfo,
  16694. pszInnerContentObjID,
  16695. pStreamInfo
  16696. );
  16697. else
  16698. return ICMTest_NewCryptMsgOpenToEncode(
  16699. dwMsgEncodingType,
  16700. dwFlags,
  16701. dwMsgType,
  16702. pvMsgEncodeInfo,
  16703. pszInnerContentObjID,
  16704. pStreamInfo
  16705. );
  16706. }
  16707. HCRYPTMSG
  16708. WINAPI
  16709. CryptMsgOpenToDecode(
  16710. IN DWORD dwMsgEncodingType,
  16711. IN DWORD dwFlags,
  16712. IN DWORD dwMsgType,
  16713. IN HCRYPTPROV hCryptProv,
  16714. IN OPTIONAL PCERT_INFO pRecipientInfo,
  16715. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16716. )
  16717. {
  16718. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16719. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  16720. POSS_CRYPT_ASN1_MSG_INFO pInfo;
  16721. CMSG_STREAM_INFO StreamInfo;
  16722. DWORD dwOssErr;
  16723. DWORD dwNewErr;
  16724. if (NULL == (pInfo = (POSS_CRYPT_ASN1_MSG_INFO) ICM_AllocZero(
  16725. sizeof(OSS_CRYPT_ASN1_MSG_INFO))))
  16726. return NULL;
  16727. pInfo->lMagic = TEST_MAGIC;
  16728. if (pStreamInfo) {
  16729. pInfo->pfnStreamOutput = pStreamInfo->pfnStreamOutput;
  16730. pInfo->pvArg = pStreamInfo->pvArg;
  16731. StreamInfo.cbContent = pStreamInfo->cbContent;
  16732. // StreamInfo.pfnStreamOutput =
  16733. StreamInfo.pvArg = pInfo;
  16734. pStreamInfo = &StreamInfo;
  16735. }
  16736. StreamInfo.pfnStreamOutput = ICMTest_NewStreamOutput;
  16737. pInfo->hNewCryptMsg = ICMTest_NewCryptMsgOpenToDecode(
  16738. dwMsgEncodingType,
  16739. dwFlags,
  16740. dwMsgType,
  16741. hCryptProv,
  16742. pRecipientInfo,
  16743. pStreamInfo
  16744. );
  16745. dwNewErr = GetLastError();
  16746. StreamInfo.pfnStreamOutput = ICMTest_OssStreamOutput;
  16747. pInfo->hOssCryptMsg = pfnOssCryptMsgOpenToDecode(
  16748. dwMsgEncodingType,
  16749. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  16750. dwMsgType,
  16751. hCryptProv,
  16752. pRecipientInfo,
  16753. pStreamInfo
  16754. );
  16755. dwOssErr = GetLastError();
  16756. if (pInfo->hNewCryptMsg) {
  16757. if (pInfo->hOssCryptMsg) {
  16758. pInfo->dwEncodingType = pInfo->pNewcmi->dwEncodingType;
  16759. InitializeCriticalSection(&pInfo->CriticalSection);
  16760. pInfo->lRefCnt = 1;
  16761. return (HCRYPTMSG) pInfo;
  16762. } else {
  16763. HCRYPTMSG hRet;
  16764. ICMTest_MessageBox("OssCryptMsgOpenToDecode failed.");
  16765. hRet = pInfo->hNewCryptMsg;
  16766. ICM_Free(pInfo);
  16767. return hRet;
  16768. }
  16769. } else {
  16770. if (pInfo->hOssCryptMsg) {
  16771. ICMTest_MessageBox("OssCryptMsgOpenToDecode succeeded while NewCryptMsgOpenToDecode failed.");
  16772. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16773. } else if (dwOssErr != dwNewErr)
  16774. ICMTest_MessageBoxLastError("CryptMsgOpenToDecode",
  16775. dwOssErr, dwNewErr);
  16776. ICM_Free(pInfo);
  16777. SetLastError(dwNewErr);
  16778. return NULL;
  16779. }
  16780. } else if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16781. return pfnOssCryptMsgOpenToDecode(
  16782. dwMsgEncodingType,
  16783. dwFlags,
  16784. dwMsgType,
  16785. hCryptProv,
  16786. pRecipientInfo,
  16787. pStreamInfo
  16788. );
  16789. else
  16790. return ICMTest_NewCryptMsgOpenToDecode(
  16791. dwMsgEncodingType,
  16792. dwFlags,
  16793. dwMsgType,
  16794. hCryptProv,
  16795. pRecipientInfo,
  16796. pStreamInfo
  16797. );
  16798. }
  16799. HCRYPTMSG
  16800. WINAPI
  16801. CryptMsgDuplicate(
  16802. IN HCRYPTMSG hCryptMsg
  16803. )
  16804. {
  16805. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16806. if (pInfo && TEST_MAGIC == pInfo->lMagic) {
  16807. InterlockedIncrement(&pInfo->lRefCnt);
  16808. return hCryptMsg;
  16809. } else if (ICMTest_GetDebugCryptAsn1Flags() &
  16810. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16811. return pfnOssCryptMsgDuplicate(hCryptMsg);
  16812. else
  16813. return ICMTest_NewCryptMsgDuplicate(hCryptMsg);
  16814. }
  16815. BOOL
  16816. WINAPI
  16817. CryptMsgClose(
  16818. IN HCRYPTMSG hCryptMsg
  16819. )
  16820. {
  16821. BOOL fRet;
  16822. DWORD dwError;
  16823. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16824. if (NULL == pInfo)
  16825. return TRUE;
  16826. if (TEST_MAGIC != pInfo->lMagic) {
  16827. if (iDebugCryptAsn1Flags &
  16828. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16829. return pfnOssCryptMsgClose(hCryptMsg);
  16830. else
  16831. return ICMTest_NewCryptMsgClose(hCryptMsg);
  16832. }
  16833. if (0 != InterlockedDecrement(&pInfo->lRefCnt))
  16834. return TRUE;
  16835. // Preserve LastError
  16836. dwError = GetLastError();
  16837. assert(pInfo->hOssCryptMsg);
  16838. assert(1 == ((PCRYPT_MSG_INFO) pInfo->hOssCryptMsg)->lRefCnt);
  16839. assert(pInfo->hNewCryptMsg);
  16840. assert(1 == ((PCRYPT_MSG_INFO) pInfo->hNewCryptMsg)->lRefCnt);
  16841. ICMTest_CompareStreamOutput(pInfo, TRUE);
  16842. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16843. fRet = ICMTest_NewCryptMsgClose(pInfo->hNewCryptMsg);
  16844. ICM_Free(pInfo->pbOssOutput);
  16845. ICM_Free(pInfo->pbNewOutput);
  16846. DeleteCriticalSection(&pInfo->CriticalSection);
  16847. ICM_Free(pInfo);
  16848. SetLastError(dwError); // Preserve LastError
  16849. return fRet;
  16850. }
  16851. BOOL
  16852. WINAPI
  16853. CryptMsgUpdate(
  16854. IN HCRYPTMSG hCryptMsg,
  16855. IN const BYTE *pbData,
  16856. IN DWORD cbData,
  16857. IN BOOL fFinal
  16858. )
  16859. {
  16860. BOOL fNew;
  16861. DWORD dwNewErr;
  16862. BOOL fOss;
  16863. DWORD dwOssErr;
  16864. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16865. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  16866. if (ICMTest_GetDebugCryptAsn1Flags() &
  16867. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16868. return pfnOssCryptMsgUpdate(
  16869. hCryptMsg,
  16870. pbData,
  16871. cbData,
  16872. fFinal
  16873. );
  16874. else
  16875. return ICMTest_NewCryptMsgUpdate(
  16876. hCryptMsg,
  16877. pbData,
  16878. cbData,
  16879. fFinal
  16880. );
  16881. }
  16882. ICMTest_Lock(pInfo);
  16883. fOss = pfnOssCryptMsgUpdate(
  16884. pInfo->hOssCryptMsg,
  16885. pbData,
  16886. cbData,
  16887. fFinal
  16888. );
  16889. dwOssErr = GetLastError();
  16890. fNew = ICMTest_NewCryptMsgUpdate(
  16891. pInfo->hNewCryptMsg,
  16892. pbData,
  16893. cbData,
  16894. fFinal
  16895. );
  16896. dwNewErr = GetLastError();
  16897. if (fNew) {
  16898. if (fOss)
  16899. ICMTest_CompareStreamOutput(pInfo);
  16900. else
  16901. ICMTest_MessageBox("OssCryptMsgUpdate failed.");
  16902. } else {
  16903. if (fOss)
  16904. ICMTest_MessageBox("OssCryptMsgUpdate succeeded while NewCryptMsgUpdate failed.");
  16905. else if (dwOssErr != dwNewErr)
  16906. ICMTest_MessageBoxLastError("CryptMsgUpdate",
  16907. dwOssErr, dwNewErr);
  16908. }
  16909. ICMTest_Unlock(pInfo);
  16910. SetLastError(dwNewErr);
  16911. return fNew;
  16912. }
  16913. BOOL
  16914. WINAPI
  16915. CryptMsgGetParam(
  16916. IN HCRYPTMSG hCryptMsg,
  16917. IN DWORD dwParamType,
  16918. IN DWORD dwIndex,
  16919. OUT void *pvData,
  16920. IN OUT DWORD *pcbData
  16921. )
  16922. {
  16923. BOOL fOss;
  16924. DWORD dwOssErr;
  16925. void *pvOssData = NULL;
  16926. DWORD cbOssData;
  16927. BOOL fNew;
  16928. DWORD dwNewErr;
  16929. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16930. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  16931. if (ICMTest_GetDebugCryptAsn1Flags() &
  16932. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16933. return pfnOssCryptMsgGetParam(
  16934. hCryptMsg,
  16935. dwParamType,
  16936. dwIndex,
  16937. pvData,
  16938. pcbData
  16939. );
  16940. else
  16941. return ICMTest_NewCryptMsgGetParam(
  16942. hCryptMsg,
  16943. dwParamType,
  16944. dwIndex,
  16945. pvData,
  16946. pcbData
  16947. );
  16948. }
  16949. ICMTest_Lock(pInfo);
  16950. cbOssData = *pcbData;
  16951. if (pvData)
  16952. pvOssData = ICM_Alloc(cbOssData);
  16953. fOss = pfnOssCryptMsgGetParam(
  16954. pInfo->hOssCryptMsg,
  16955. dwParamType,
  16956. dwIndex,
  16957. pvOssData,
  16958. &cbOssData
  16959. );
  16960. dwOssErr = GetLastError();
  16961. fNew = ICMTest_NewCryptMsgGetParam(
  16962. pInfo->hNewCryptMsg,
  16963. dwParamType,
  16964. dwIndex,
  16965. pvData,
  16966. pcbData
  16967. );
  16968. dwNewErr = GetLastError();
  16969. if (fNew) {
  16970. if (fOss)
  16971. ICMTest_CompareGetParam(
  16972. pInfo,
  16973. dwParamType,
  16974. dwIndex,
  16975. pvOssData,
  16976. cbOssData,
  16977. pvData,
  16978. *pcbData
  16979. );
  16980. else
  16981. ICMTest_MessageBox("OssCryptMsgGetParam failed.");
  16982. } else {
  16983. if (fOss)
  16984. ICMTest_MessageBox("OssCryptMsgGetParam succeeded while NewCryptMsgGetParam failed.");
  16985. else if (dwOssErr != dwNewErr)
  16986. ICMTest_MessageBoxLastError("CryptMsgGetParam",
  16987. dwOssErr, dwNewErr);
  16988. }
  16989. ICMTest_Unlock(pInfo);
  16990. ICM_Free(pvOssData);
  16991. SetLastError(dwNewErr);
  16992. return fNew;
  16993. }
  16994. BOOL
  16995. WINAPI
  16996. CryptMsgControl(
  16997. IN HCRYPTMSG hCryptMsg,
  16998. IN DWORD dwFlags,
  16999. IN DWORD dwCtrlType,
  17000. IN void const *pvCtrlPara
  17001. )
  17002. {
  17003. BOOL fNew;
  17004. DWORD dwNewErr;
  17005. BOOL fOss;
  17006. DWORD dwOssErr;
  17007. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  17008. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  17009. if (ICMTest_GetDebugCryptAsn1Flags() &
  17010. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  17011. return pfnOssCryptMsgControl(
  17012. hCryptMsg,
  17013. dwFlags,
  17014. dwCtrlType,
  17015. pvCtrlPara
  17016. );
  17017. else
  17018. return ICMTest_NewCryptMsgControl(
  17019. hCryptMsg,
  17020. dwFlags,
  17021. dwCtrlType,
  17022. pvCtrlPara
  17023. );
  17024. }
  17025. ICMTest_Lock(pInfo);
  17026. fOss = pfnOssCryptMsgControl(
  17027. pInfo->hOssCryptMsg,
  17028. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  17029. dwCtrlType,
  17030. pvCtrlPara
  17031. );
  17032. dwOssErr = GetLastError();
  17033. fNew = ICMTest_NewCryptMsgControl(
  17034. pInfo->hNewCryptMsg,
  17035. dwFlags,
  17036. dwCtrlType,
  17037. pvCtrlPara
  17038. );
  17039. dwNewErr = GetLastError();
  17040. if (fNew) {
  17041. if (fOss)
  17042. ICMTest_CompareStreamOutput(pInfo);
  17043. else
  17044. ICMTest_MessageBox("OssCryptMsgControl failed.");
  17045. } else {
  17046. if (fOss)
  17047. ICMTest_MessageBox("OssCryptMsgControl succeeded while NewCryptMsgControl failed.");
  17048. else if (dwOssErr != dwNewErr)
  17049. ICMTest_MessageBoxLastError("CryptMsgControl",
  17050. dwOssErr, dwNewErr);
  17051. }
  17052. ICMTest_Unlock(pInfo);
  17053. SetLastError(dwNewErr);
  17054. return fNew;
  17055. }
  17056. #ifdef CMS_PKCS7
  17057. BOOL
  17058. WINAPI
  17059. CryptMsgVerifyCountersignatureEncodedEx(
  17060. IN HCRYPTPROV hCryptProv,
  17061. IN DWORD dwEncodingType,
  17062. IN PBYTE pbSignerInfo,
  17063. IN DWORD cbSignerInfo,
  17064. IN PBYTE pbSignerInfoCountersignature,
  17065. IN DWORD cbSignerInfoCountersignature,
  17066. IN DWORD dwSignerType,
  17067. IN void *pvSigner,
  17068. IN DWORD dwFlags,
  17069. IN OPTIONAL void *pvReserved
  17070. )
  17071. {
  17072. BOOL fOss;
  17073. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  17074. if (0 == (iOssAsn1Flags &
  17075. (DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG |
  17076. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)))
  17077. return ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  17078. hCryptProv,
  17079. dwEncodingType,
  17080. pbSignerInfo,
  17081. cbSignerInfo,
  17082. pbSignerInfoCountersignature,
  17083. cbSignerInfoCountersignature,
  17084. dwSignerType,
  17085. pvSigner,
  17086. dwFlags,
  17087. pvReserved
  17088. );
  17089. fOss = pfnOssCryptMsgVerifyCountersignatureEncodedEx(
  17090. hCryptProv,
  17091. dwEncodingType,
  17092. pbSignerInfo,
  17093. cbSignerInfo,
  17094. pbSignerInfoCountersignature,
  17095. cbSignerInfoCountersignature,
  17096. dwSignerType,
  17097. pvSigner,
  17098. dwFlags,
  17099. pvReserved
  17100. );
  17101. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17102. DWORD dwOssErr = GetLastError();
  17103. BOOL fNew;
  17104. DWORD dwNewErr;
  17105. fNew = ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  17106. hCryptProv,
  17107. dwEncodingType,
  17108. pbSignerInfo,
  17109. cbSignerInfo,
  17110. pbSignerInfoCountersignature,
  17111. cbSignerInfoCountersignature,
  17112. dwSignerType,
  17113. pvSigner,
  17114. dwFlags,
  17115. pvReserved
  17116. );
  17117. dwNewErr = GetLastError();
  17118. if (fNew) {
  17119. if (!fOss)
  17120. ICMTest_MessageBox("OssCryptMsgVerifyCountersignatureEncodedEx failed.");
  17121. } else {
  17122. if (fOss)
  17123. ICMTest_MessageBox("OssCryptMsgVerifyCountersignatureEncodedEx succeeded while NewCryptMsgVerifyCountersignatureEncodedEx failed.");
  17124. else if (dwOssErr != dwNewErr)
  17125. ICMTest_MessageBoxLastError("CryptMsgVerifyCountersignatureEncodedEx",
  17126. dwOssErr, dwNewErr);
  17127. }
  17128. SetLastError(dwOssErr);
  17129. }
  17130. return fOss;
  17131. }
  17132. #endif // CMS_PKCS7
  17133. BOOL
  17134. WINAPI
  17135. CryptMsgCountersign(
  17136. IN OUT HCRYPTMSG hCryptMsg,
  17137. IN DWORD dwIndex,
  17138. IN DWORD cCountersigners,
  17139. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners
  17140. )
  17141. {
  17142. BOOL fNew;
  17143. DWORD dwNewErr;
  17144. BOOL fOss;
  17145. DWORD dwOssErr;
  17146. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  17147. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  17148. if (ICMTest_GetDebugCryptAsn1Flags() &
  17149. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  17150. return pfnOssCryptMsgCountersign(
  17151. hCryptMsg,
  17152. dwIndex,
  17153. cCountersigners,
  17154. rgCountersigners
  17155. );
  17156. else
  17157. return ICMTest_NewCryptMsgCountersign(
  17158. hCryptMsg,
  17159. dwIndex,
  17160. cCountersigners,
  17161. rgCountersigners
  17162. );
  17163. }
  17164. ICMTest_Lock(pInfo);
  17165. fOss = pfnOssCryptMsgCountersign(
  17166. pInfo->hOssCryptMsg,
  17167. dwIndex,
  17168. cCountersigners,
  17169. rgCountersigners
  17170. );
  17171. dwOssErr = GetLastError();
  17172. fNew = ICMTest_NewCryptMsgCountersign(
  17173. pInfo->hNewCryptMsg,
  17174. dwIndex,
  17175. cCountersigners,
  17176. rgCountersigners
  17177. );
  17178. dwNewErr = GetLastError();
  17179. if (fNew) {
  17180. if (!fOss)
  17181. ICMTest_MessageBox("OssCryptMsgCountersign failed.");
  17182. } else {
  17183. if (fOss)
  17184. ICMTest_MessageBox("OssCryptMsgCountersign succeeded while NewCryptMsgCountersign failed.");
  17185. else if (dwOssErr != dwNewErr)
  17186. ICMTest_MessageBoxLastError("CryptMsgCountersign",
  17187. dwOssErr, dwNewErr);
  17188. }
  17189. ICMTest_Unlock(pInfo);
  17190. SetLastError(dwNewErr);
  17191. return fNew;
  17192. }
  17193. BOOL
  17194. WINAPI
  17195. CryptMsgCountersignEncoded(
  17196. IN DWORD dwEncodingType,
  17197. IN PBYTE pbSignerInfo,
  17198. IN DWORD cbSignerInfo,
  17199. IN DWORD cCountersigners,
  17200. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  17201. OUT PBYTE pbCountersignature,
  17202. IN OUT PDWORD pcbCountersignature
  17203. )
  17204. {
  17205. BOOL fOss;
  17206. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  17207. BYTE *pbNew = NULL;
  17208. DWORD cbNew;
  17209. if (0 == (iOssAsn1Flags &
  17210. (DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG |
  17211. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)))
  17212. return ICMTest_NewCryptMsgCountersignEncoded(
  17213. dwEncodingType,
  17214. pbSignerInfo,
  17215. cbSignerInfo,
  17216. cCountersigners,
  17217. rgCountersigners,
  17218. pbCountersignature,
  17219. pcbCountersignature
  17220. );
  17221. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17222. cbNew = *pcbCountersignature;
  17223. if (pbCountersignature)
  17224. pbNew = (BYTE *) ICM_Alloc(cbNew);
  17225. }
  17226. fOss = pfnOssCryptMsgCountersignEncoded(
  17227. dwEncodingType,
  17228. pbSignerInfo,
  17229. cbSignerInfo,
  17230. cCountersigners,
  17231. rgCountersigners,
  17232. pbCountersignature,
  17233. pcbCountersignature
  17234. );
  17235. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17236. DWORD dwOssErr = GetLastError();
  17237. BOOL fNew;
  17238. DWORD dwNewErr;
  17239. fNew = ICMTest_NewCryptMsgCountersignEncoded(
  17240. dwEncodingType,
  17241. pbSignerInfo,
  17242. cbSignerInfo,
  17243. cCountersigners,
  17244. rgCountersigners,
  17245. pbNew,
  17246. &cbNew
  17247. );
  17248. dwNewErr = GetLastError();
  17249. if (fNew) {
  17250. if (fOss)
  17251. ICMTest_CompareMessageBox(
  17252. "CountersignEncoded compare failed. Check ossasn1.der and newasn1.der.",
  17253. pbCountersignature,
  17254. *pcbCountersignature,
  17255. pbNew,
  17256. cbNew
  17257. );
  17258. else
  17259. ICMTest_MessageBox("NewCryptMsgCountersignEncoded failed.");
  17260. } else {
  17261. if (fOss)
  17262. ICMTest_MessageBox("OssCryptMsgCountersignEncoded succeeded while NewCryptMsgCountersignEncoded failed.");
  17263. else if (dwOssErr != dwNewErr)
  17264. ICMTest_MessageBoxLastError("CryptMsgCountersignEncoded",
  17265. dwOssErr, dwNewErr);
  17266. }
  17267. SetLastError(dwOssErr);
  17268. }
  17269. ICM_Free(pbNew);
  17270. return fOss;
  17271. }
  17272. #endif // DEBUG_CRYPT_ASN1_MASTER
  17273. #endif // DEBUG_CRYPT_ASN1