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

19425 lines
617 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. pcmi->fInitializedCriticalSection = FALSE;
  6834. CryptMsgClose(hcrmsg);
  6835. hcrmsg = NULL;
  6836. } else
  6837. pcmi->fInitializedCriticalSection = TRUE;
  6838. }
  6839. return hcrmsg;
  6840. ErrorReturn:
  6841. hcrmsg = NULL;
  6842. goto CommonReturn;
  6843. SET_ERROR(InvalidEncoding,E_INVALIDARG)
  6844. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  6845. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  6846. }
  6847. //+-------------------------------------------------------------------------
  6848. // Open a cryptographic message for decoding
  6849. //
  6850. // hCryptProv specifies the crypto provider to use for hashing and/or
  6851. // decrypting the message. If hCryptProv is NULL, a default crypt provider
  6852. // is used.
  6853. //
  6854. // Currently pRecipientInfo isn't used and should be set to NULL.
  6855. //
  6856. // The pStreamInfo parameter needs to be set to stream the decoded content
  6857. // output.
  6858. //--------------------------------------------------------------------------
  6859. HCRYPTMSG
  6860. WINAPI
  6861. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6862. ICMTest_NewCryptMsgOpenToDecode(
  6863. #else
  6864. CryptMsgOpenToDecode(
  6865. #endif
  6866. IN DWORD dwEncodingType,
  6867. IN DWORD dwFlags,
  6868. IN DWORD dwMsgType,
  6869. IN HCRYPTPROV hCryptProv,
  6870. IN PCERT_INFO pRecipientInfo,
  6871. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo)
  6872. {
  6873. DWORD dwError = ERROR_SUCCESS;
  6874. HCRYPTMSG hcrmsg;
  6875. PCRYPT_MSG_INFO pcmi = NULL;
  6876. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  6877. goto InvalidEncodingTypeError;
  6878. if (NULL != pRecipientInfo)
  6879. goto RecipientInfoNotSupportedYet;
  6880. if (NULL == (pcmi = (PCRYPT_MSG_INFO)ICM_AllocZero( sizeof( CRYPT_MSG_INFO))))
  6881. goto AllocCmsgError;
  6882. if (0 == hCryptProv) {
  6883. pcmi->fDefaultCryptProv = TRUE;
  6884. pcmi->hCryptProv = I_CryptGetDefaultCryptProv(0);
  6885. if (0 == pcmi->hCryptProv)
  6886. goto GetDefaultCryptProvError;
  6887. } else
  6888. pcmi->hCryptProv = hCryptProv;
  6889. pcmi->dwEncodingType = dwEncodingType;
  6890. pcmi->dwMsgType = dwMsgType;
  6891. pcmi->dwFlags = dwFlags;
  6892. pcmi->dwPhase = PHASE_FIRST_ONGOING;
  6893. if (pStreamInfo &&
  6894. (NULL == (pcmi->pStreamInfo = (PCMSG_STREAM_INFO)ICM_DupMem(
  6895. pStreamInfo,
  6896. sizeof(*pStreamInfo)))))
  6897. goto DupStreamInfoError;
  6898. if (!Pki_InitializeCriticalSection( &pcmi->CriticalSection))
  6899. goto InitializeCriticalSectionError;
  6900. pcmi->fInitializedCriticalSection = TRUE;
  6901. pcmi->lRefCnt = 1;
  6902. hcrmsg = (HCRYPTMSG)pcmi;
  6903. CommonReturn:
  6904. ICM_SetLastError(dwError);
  6905. return hcrmsg;
  6906. ErrorReturn:
  6907. dwError = GetLastError();
  6908. ICM_Free( pcmi);
  6909. hcrmsg = NULL;
  6910. goto CommonReturn;
  6911. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  6912. SET_ERROR(RecipientInfoNotSupportedYet,E_INVALIDARG)
  6913. TRACE_ERROR(AllocCmsgError) // error already set
  6914. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  6915. TRACE_ERROR(DupStreamInfoError) // error already set
  6916. TRACE_ERROR(InitializeCriticalSectionError) // error already set
  6917. }
  6918. //+-------------------------------------------------------------------------
  6919. // Duplicate a cryptographic message handle
  6920. //--------------------------------------------------------------------------
  6921. HCRYPTMSG
  6922. WINAPI
  6923. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6924. ICMTest_NewCryptMsgDuplicate(
  6925. #else
  6926. CryptMsgDuplicate(
  6927. #endif
  6928. IN HCRYPTMSG hCryptMsg
  6929. )
  6930. {
  6931. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  6932. if (pcmi)
  6933. InterlockedIncrement(&pcmi->lRefCnt);
  6934. return hCryptMsg;
  6935. }
  6936. //+-------------------------------------------------------------------------
  6937. // Close a cryptographic message handle
  6938. //
  6939. // NB- Must preserve LastError.
  6940. //--------------------------------------------------------------------------
  6941. BOOL
  6942. WINAPI
  6943. #ifdef DEBUG_CRYPT_ASN1_MASTER
  6944. ICMTest_NewCryptMsgClose(
  6945. #else
  6946. CryptMsgClose(
  6947. #endif
  6948. IN HCRYPTMSG hCryptMsg)
  6949. {
  6950. DWORD dwError;
  6951. BOOL fRet;
  6952. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  6953. PCMSG_STREAM_INFO pcsi;
  6954. if (NULL == hCryptMsg)
  6955. return TRUE;
  6956. if (0 != InterlockedDecrement(&pcmi->lRefCnt))
  6957. return TRUE;
  6958. // Preserve LastError
  6959. dwError = GetLastError();
  6960. pcsi = pcmi->pStreamInfo;
  6961. switch (pcmi->dwMsgType) {
  6962. case CMSG_DATA:
  6963. {
  6964. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  6965. if (!poos)
  6966. break;
  6967. if (pcmi->fEncoding) {
  6968. ICM_Free( poos->value);
  6969. ICM_Free( poos);
  6970. } else {
  6971. PkiAsn1FreeInfo( ICM_GetDecoder(), OctetStringType_PDU, poos);
  6972. }
  6973. break;
  6974. }
  6975. case CMSG_SIGNED:
  6976. {
  6977. SignedData *psd = (SignedData *)pcmi->pvMsg;
  6978. if (!(psd || pcmi->psdi))
  6979. break;
  6980. if (pcmi->fEncoding) {
  6981. if (psd->signerInfos.value) {
  6982. SignerInfo *psi;
  6983. DWORD i;
  6984. for (i=psd->signerInfos.count, psi=psd->signerInfos.value;
  6985. i>0;
  6986. i--, psi++)
  6987. ICM_FreeAsnSignerInfo(psi);
  6988. ICM_Free( psd->signerInfos.value);
  6989. }
  6990. if (ICM_IsAddInnerContentOctetWrapper(pcmi) &&
  6991. psd->contentInfo.content.length &&
  6992. psd->contentInfo.content.value)
  6993. PkiAsn1FreeEncoded( ICM_GetEncoder(),
  6994. psd->contentInfo.content.value);
  6995. if (psd->digestAlgorithms.count && psd->digestAlgorithms.value)
  6996. ICM_Free( psd->digestAlgorithms.value);
  6997. ICM_Free( psd);
  6998. ICM_Free( pcmi->pszInnerContentObjID);
  6999. } else {
  7000. // decoding
  7001. delete pcmi->psdi->pAlgidList;
  7002. delete pcmi->psdi->pCertificateList;
  7003. delete pcmi->psdi->pCrlList;
  7004. delete pcmi->psdi->pSignerList;
  7005. ICM_Free( pcmi->psdi->pci);
  7006. ICM_Free( pcmi->psdi);
  7007. }
  7008. if (pcmi->pHashList)
  7009. delete pcmi->pHashList;
  7010. #ifdef CMS_PKCS7
  7011. if (pcmi->rgSignerEncodeDataInfo) {
  7012. assert(pcmi->cSignerEncodeDataInfo);
  7013. if (pcmi->dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) {
  7014. DWORD i;
  7015. for (i = 0; i < pcmi->cSignerEncodeDataInfo; i++) {
  7016. if (pcmi->rgSignerEncodeDataInfo[i].hCryptProv)
  7017. CryptReleaseContext(
  7018. pcmi->rgSignerEncodeDataInfo[i].hCryptProv, 0);
  7019. }
  7020. }
  7021. ICM_Free(pcmi->rgSignerEncodeDataInfo);
  7022. }
  7023. #endif // CMS_PKCS7
  7024. break;
  7025. }
  7026. case CMSG_ENVELOPED:
  7027. {
  7028. #ifdef CMS_PKCS7
  7029. CmsEnvelopedData *ped = (CmsEnvelopedData *)pcmi->pvMsg;
  7030. #else
  7031. EnvelopedData *ped = (EnvelopedData *)pcmi->pvMsg;
  7032. RecipientInfo *pri;
  7033. #endif // CMS_PKCS7
  7034. DWORD i;
  7035. if (pcmi->hkeyContentCrypt)
  7036. CryptDestroyKey( pcmi->hkeyContentCrypt);
  7037. ICM_Free( pcmi->Plaintext.pbData);
  7038. #ifndef CMS_PKCS7
  7039. ICM_Free( pcmi->pbEncryptParameters);
  7040. #endif // CMS_PKCS7
  7041. if (pcmi->fEncoding) {
  7042. #ifdef CMS_PKCS7
  7043. ICM_FreeOssCmsRecipientInfos(&ped->recipientInfos);
  7044. if (ped->unprotectedAttrs.value) {
  7045. Attribute *poatr;
  7046. for (i=ped->unprotectedAttrs.count,
  7047. poatr=ped->unprotectedAttrs.value;
  7048. i>0;
  7049. i--, poatr++) {
  7050. ICM_Free(poatr->attributeValue.value);
  7051. }
  7052. ICM_Free(ped->unprotectedAttrs.value);
  7053. }
  7054. #else
  7055. for (i=ped->recipientInfos.count, pri=ped->recipientInfos.value;
  7056. i>0;
  7057. i--, pri++)
  7058. ICM_Free( pri->encryptedKey.value);
  7059. ICM_Free( ped->recipientInfos.value);
  7060. #endif // CMS_PKCS7
  7061. ICM_Free( ped->encryptedContentInfo.encryptedContent.value);
  7062. ICM_Free( ped);
  7063. ICM_Free( pcmi->pszInnerContentObjID);
  7064. } else {
  7065. // decoding
  7066. #ifdef CMS_PKCS7
  7067. if (NULL != pcmi->pCertificateList)
  7068. delete pcmi->pCertificateList;
  7069. if (NULL != pcmi->pCrlList)
  7070. delete pcmi->pCrlList;
  7071. #endif // CMS_PKCS7
  7072. if (pcsi) {
  7073. ICM_Free( ped);
  7074. } else {
  7075. #ifdef CMS_PKCS7
  7076. PkiAsn1FreeInfo( ICM_GetDecoder(), CmsEnvelopedData_PDU, ped);
  7077. #else
  7078. PkiAsn1FreeInfo( ICM_GetDecoder(), EnvelopedData_PDU, ped);
  7079. #endif // CMS_PKCS7
  7080. }
  7081. }
  7082. break;
  7083. }
  7084. case CMSG_HASHED:
  7085. {
  7086. DigestedData *pdd = (DigestedData *)pcmi->pvMsg;
  7087. if (pcmi->fEncoding) {
  7088. if (ICM_IsAddInnerContentOctetWrapper(pcmi) &&
  7089. pdd->contentInfo.content.length &&
  7090. pdd->contentInfo.content.value)
  7091. PkiAsn1FreeEncoded( ICM_GetEncoder(),
  7092. pdd->contentInfo.content.value);
  7093. ICM_Free ((DigestedData *)pcmi->pvMsg);
  7094. ICM_Free( pcmi->pszInnerContentObjID);
  7095. } else {
  7096. // decoding
  7097. PkiAsn1FreeInfo( ICM_GetDecoder(), DigestedData_PDU,
  7098. (DigestedData *)pcmi->pvMsg);
  7099. }
  7100. if (pcmi->pHashList)
  7101. delete pcmi->pHashList;
  7102. break;
  7103. }
  7104. case CMSG_SIGNED_AND_ENVELOPED:
  7105. case CMSG_ENCRYPTED:
  7106. goto MessageTypeNotSupportedYet;
  7107. default:
  7108. goto InvalidMsgType;
  7109. }
  7110. fRet = TRUE;
  7111. CommonReturn:
  7112. #ifdef CMS_PKCS7
  7113. if (pcmi->pFreeList)
  7114. delete pcmi->pFreeList;
  7115. #endif // CMS_PKCS7
  7116. if (pcmi->plDecodeInfo)
  7117. delete pcmi->plDecodeInfo;
  7118. ICM_Free( pcmi->pStreamInfo);
  7119. ICM_Free( pcmi->bufOutput.pbData);
  7120. ICM_Free( pcmi->bufCrypt.pbData);
  7121. ICM_Free( pcmi->bufPendingCrypt.pbData);
  7122. ICM_Free( pcmi->bufDecode.pbData);
  7123. ICM_Free( pcmi->bufEncode.pbData);
  7124. if (pcmi->pooid)
  7125. PkiAsn1FreeDecoded(ICM_GetDecoder(), pcmi->pooid,
  7126. ObjectIdentifierType_PDU);
  7127. if ((pcmi->dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG) &&
  7128. !pcmi->fDefaultCryptProv && pcmi->hCryptProv)
  7129. CryptReleaseContext(pcmi->hCryptProv, 0);
  7130. if (pcmi->hCryptProvContentCrypt)
  7131. CryptReleaseContext(pcmi->hCryptProvContentCrypt, 0);
  7132. if (pcmi->fInitializedCriticalSection)
  7133. DeleteCriticalSection( &pcmi->CriticalSection);
  7134. ICM_Free( hCryptMsg);
  7135. SetLastError(dwError); // Preserve LastError
  7136. return fRet;
  7137. ErrorReturn:
  7138. fRet = TRUE;
  7139. goto CommonReturn;
  7140. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  7141. TRACE_ERROR(InvalidMsgType)
  7142. }
  7143. //+-------------------------------------------------------------------------
  7144. // Since the encoding might be indefinite-length encoded,
  7145. // decode and re-encode as DER.
  7146. //
  7147. // Returns: FALSE iff fails
  7148. //
  7149. // NB: The caller of this routine needs to call
  7150. // PkiAsn1FreeEncoded( ICM_GetEncoder(), pbOut);
  7151. //--------------------------------------------------------------------------
  7152. BOOL
  7153. WINAPI
  7154. ICM_ReEncodeAsOctetDER(
  7155. IN PBYTE pbIn,
  7156. IN DWORD cbIn,
  7157. OUT PBYTE *ppbOut,
  7158. OUT DWORD *pcbOut)
  7159. {
  7160. DWORD dwError = ERROR_SUCCESS;
  7161. BOOL fRet;
  7162. ASN1error_e Asn1Err;
  7163. ASN1decoding_t pDec = ICM_GetDecoder();
  7164. PVOID pvMsg = NULL;
  7165. DWORD dwExceptionCode;
  7166. // Handle MappedFile Exceptions
  7167. __try {
  7168. if (0 != (Asn1Err = PkiAsn1Decode(pDec, (void **)&pvMsg,
  7169. OctetStringType_PDU, pbIn, cbIn)))
  7170. goto DecodeInnerContentError;
  7171. if (0 != (Asn1Err = PkiAsn1Encode(ICM_GetEncoder(), pvMsg,
  7172. OctetStringType_PDU, ppbOut, pcbOut)))
  7173. goto EncodeInnerContentError;
  7174. fRet = TRUE;
  7175. } __except(EXCEPTION_EXECUTE_HANDLER) {
  7176. dwExceptionCode = GetExceptionCode();
  7177. goto ExceptionError;
  7178. }
  7179. CommonReturn:
  7180. PkiAsn1FreeInfo(pDec, OctetStringType_PDU, pvMsg);
  7181. ICM_SetLastError(dwError);
  7182. return fRet;
  7183. ErrorReturn:
  7184. *ppbOut = NULL;
  7185. *pcbOut = 0;
  7186. dwError = GetLastError();
  7187. fRet = FALSE;
  7188. goto CommonReturn;
  7189. SET_ERROR_VAR(DecodeInnerContentError, PkiAsn1ErrToHr(Asn1Err))
  7190. SET_ERROR_VAR(EncodeInnerContentError, PkiAsn1ErrToHr(Asn1Err))
  7191. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  7192. }
  7193. //+-------------------------------------------------------------------------
  7194. // Update the digest
  7195. //
  7196. // Returns:
  7197. // FALSE iff error
  7198. //--------------------------------------------------------------------------
  7199. BOOL
  7200. WINAPI
  7201. ICM_UpdateDigest(
  7202. IN HCRYPTHASH hHash,
  7203. IN const BYTE *pbData,
  7204. IN DWORD cbData)
  7205. {
  7206. BOOL fRet;
  7207. if (0 != cbData)
  7208. fRet = CryptHashData(
  7209. hHash,
  7210. pbData,
  7211. cbData,
  7212. 0); // dwFlags
  7213. else
  7214. fRet = TRUE;
  7215. if (!fRet)
  7216. goto HashDataError;
  7217. CommonReturn:
  7218. return fRet;
  7219. ErrorReturn:
  7220. goto CommonReturn;
  7221. TRACE_ERROR(HashDataError) // error already set
  7222. }
  7223. //+-------------------------------------------------------------------------
  7224. // Update the digests in a list
  7225. //
  7226. // Returns:
  7227. // FALSE iff error
  7228. //--------------------------------------------------------------------------
  7229. BOOL
  7230. WINAPI
  7231. ICM_UpdateListDigest(
  7232. IN CHashList *pHashList,
  7233. IN const BYTE *pbData,
  7234. IN DWORD cbData)
  7235. {
  7236. BOOL fRet;
  7237. CHashNode *pnHash;
  7238. if (pHashList) {
  7239. for (pnHash=pHashList->Head(); pnHash; pnHash=pnHash->Next()) {
  7240. if (!ICM_UpdateDigest( pnHash->Data()->hHash, pbData, cbData))
  7241. goto UpdateDigestError;
  7242. }
  7243. }
  7244. fRet = TRUE;
  7245. CommonReturn:
  7246. return fRet;
  7247. ErrorReturn:
  7248. fRet = FALSE;
  7249. goto CommonReturn;
  7250. TRACE_ERROR(UpdateDigestError) // error already set
  7251. }
  7252. //+-------------------------------------------------------------------------
  7253. // Alloc and sign a hash.
  7254. //
  7255. // Returns: FALSE iff failed
  7256. //--------------------------------------------------------------------------
  7257. BOOL
  7258. WINAPI
  7259. ICM_AllocAndSignHash(
  7260. IN HCRYPTHASH hHash,
  7261. IN DWORD dwKeySpec,
  7262. IN DWORD dwAlgIdPubKey,
  7263. IN DWORD dwPubKeyFlags,
  7264. IN BOOL fMaxLength,
  7265. OUT PBYTE *ppbSignature,
  7266. OUT DWORD *pcbSignature)
  7267. {
  7268. DWORD dwError = ERROR_SUCCESS;
  7269. BOOL fRet;
  7270. PBYTE pbSignature = NULL;
  7271. DWORD cbSignature = 0;
  7272. if (dwKeySpec == 0)
  7273. dwKeySpec = AT_SIGNATURE;
  7274. if (CALG_NO_SIGN == dwAlgIdPubKey) {
  7275. if (!CryptGetHashParam(
  7276. hHash,
  7277. HP_HASHVAL,
  7278. NULL,
  7279. &cbSignature,
  7280. 0)) // dwFlags
  7281. goto GetHashParamSizeError;
  7282. if (NULL == (pbSignature = (PBYTE)ICM_Alloc( cbSignature)))
  7283. goto AllocHashParamError;
  7284. if (!CryptGetHashParam(
  7285. hHash,
  7286. HP_HASHVAL,
  7287. pbSignature,
  7288. &cbSignature,
  7289. 0)) // dwFlags
  7290. goto GetHashParamError;
  7291. } else if (CALG_DSS_SIGN == dwAlgIdPubKey &&
  7292. 0 == (dwPubKeyFlags & CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG)) {
  7293. DWORD cbData;
  7294. BYTE rgbDssSignature[CERT_DSS_SIGNATURE_LEN];
  7295. cbData = sizeof(rgbDssSignature);
  7296. if (!CryptSignHash(
  7297. hHash,
  7298. dwKeySpec,
  7299. NULL, // sDescription
  7300. 0, // dwFlags
  7301. rgbDssSignature,
  7302. &cbData
  7303. )) goto SignHashError;
  7304. assert(cbData == sizeof(rgbDssSignature));
  7305. if (NULL == (pbSignature = (PBYTE)ICM_Alloc(
  7306. CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN)))
  7307. goto AllocSignatureError;
  7308. // Convert from the CSP signature format to an ASN.1 sequence of
  7309. // two integers
  7310. cbSignature = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN;
  7311. if (!CryptEncodeObject(
  7312. X509_ASN_ENCODING,
  7313. X509_DSS_SIGNATURE,
  7314. rgbDssSignature,
  7315. pbSignature,
  7316. &cbSignature
  7317. )) goto EncodeDssSignatureError;
  7318. if (fMaxLength) {
  7319. int cbRemain;
  7320. assert(CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN >= cbSignature);
  7321. cbRemain = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN - cbSignature;
  7322. if (cbRemain > 0) {
  7323. memset(pbSignature + cbSignature, 0, cbRemain);
  7324. cbSignature = CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN;
  7325. }
  7326. }
  7327. } else {
  7328. if (!CryptSignHash(
  7329. hHash,
  7330. dwKeySpec,
  7331. NULL, // description ?
  7332. 0, // dwFlags
  7333. NULL, // pbSignature
  7334. &cbSignature))
  7335. goto SignHashSizeError;
  7336. if (NULL == (pbSignature = (PBYTE)ICM_Alloc( cbSignature)))
  7337. goto AllocSignatureError;
  7338. if (!CryptSignHash(
  7339. hHash,
  7340. dwKeySpec,
  7341. NULL, // description ?
  7342. 0, // dwFlags
  7343. pbSignature,
  7344. &cbSignature))
  7345. goto SignHashError;
  7346. ICM_ReverseInPlace( pbSignature, cbSignature);
  7347. }
  7348. fRet = TRUE;
  7349. CommonReturn:
  7350. *ppbSignature = pbSignature;
  7351. *pcbSignature = cbSignature;
  7352. ICM_SetLastError(dwError);
  7353. return fRet;
  7354. ErrorReturn:
  7355. dwError = GetLastError();
  7356. ICM_Free( pbSignature);
  7357. pbSignature = NULL;
  7358. cbSignature = 0;
  7359. fRet = FALSE;
  7360. goto CommonReturn;
  7361. TRACE_ERROR(GetHashParamSizeError) // error already set
  7362. TRACE_ERROR(AllocHashParamError) // error already set
  7363. TRACE_ERROR(GetHashParamError) // error already set
  7364. TRACE_ERROR(SignHashSizeError) // error already set
  7365. TRACE_ERROR(AllocSignatureError) // error already set
  7366. TRACE_ERROR(SignHashError) // error already set
  7367. TRACE_ERROR(EncodeDssSignatureError) // error already set
  7368. }
  7369. //+-------------------------------------------------------------------------
  7370. // Get the hash of a blob.
  7371. //
  7372. // Returns: FALSE iff failed
  7373. //--------------------------------------------------------------------------
  7374. BOOL
  7375. WINAPI
  7376. ICM_GetBlobHash(
  7377. IN HCRYPTPROV hCryptProv,
  7378. IN DWORD dwDigestAlgorithm,
  7379. IN PBYTE pb,
  7380. IN DWORD cb,
  7381. OUT HCRYPTHASH *phHash)
  7382. {
  7383. BOOL fRet;
  7384. HCRYPTHASH hHash;
  7385. if (!CryptCreateHash(
  7386. hCryptProv,
  7387. dwDigestAlgorithm,
  7388. NULL, // hKey - optional for MAC
  7389. 0, // dwFlags
  7390. &hHash))
  7391. goto CreateHashError;
  7392. if (!ICM_UpdateDigest( hHash, pb, cb))
  7393. goto UpdateDigestError;
  7394. fRet = TRUE;
  7395. CommonReturn:
  7396. *phHash = hHash;
  7397. return fRet;
  7398. ErrorReturn:
  7399. hHash = NULL;
  7400. fRet = FALSE;
  7401. goto CommonReturn;
  7402. TRACE_ERROR(CreateHashError) // error already set
  7403. TRACE_ERROR(UpdateDigestError) // error already set
  7404. }
  7405. //+-------------------------------------------------------------------------
  7406. // Get the hash of an OSS Attributes. This is used to hash the authenticated
  7407. // attributes for a Signed or SignedAndEnveloped message.
  7408. //
  7409. // Returns: FALSE iff failed
  7410. //--------------------------------------------------------------------------
  7411. BOOL
  7412. WINAPI
  7413. ICM_GetAttrsHash(
  7414. IN DWORD dwDigestAlgorithm,
  7415. IN HCRYPTPROV hCryptProv,
  7416. IN Attributes *possAttrs,
  7417. OUT HCRYPTHASH *phHash)
  7418. {
  7419. DWORD dwError = ERROR_SUCCESS;
  7420. BOOL fRet;
  7421. ASN1error_e Asn1Err;
  7422. ASN1encoding_t pEnc = ICM_GetEncoder();
  7423. PBYTE pbEncoded = NULL;
  7424. DWORD cbEncoded;
  7425. HCRYPTHASH hHash;
  7426. if (!CryptCreateHash(
  7427. hCryptProv,
  7428. dwDigestAlgorithm,
  7429. NULL, // hKey - optional for MAC
  7430. 0, // dwFlags
  7431. &hHash))
  7432. goto CreateHashError;
  7433. if (0 != (Asn1Err = PkiAsn1Encode(
  7434. pEnc,
  7435. possAttrs,
  7436. Attributes_PDU,
  7437. &pbEncoded,
  7438. &cbEncoded)))
  7439. goto EncodeAttributesError;
  7440. if (!ICM_UpdateDigest(
  7441. hHash,
  7442. pbEncoded,
  7443. cbEncoded))
  7444. goto UpdateDigestAttributesError;
  7445. fRet = TRUE;
  7446. CommonReturn:
  7447. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7448. *phHash = hHash;
  7449. ICM_SetLastError(dwError);
  7450. return fRet;
  7451. ErrorReturn:
  7452. dwError = GetLastError();
  7453. hHash = NULL;
  7454. fRet = FALSE;
  7455. goto CommonReturn;
  7456. SET_ERROR_VAR(EncodeAttributesError, PkiAsn1ErrToHr(Asn1Err))
  7457. TRACE_ERROR(CreateHashError) // error already set
  7458. TRACE_ERROR(UpdateDigestAttributesError) // error already set
  7459. }
  7460. //+-------------------------------------------------------------------------
  7461. // Compare 2 OSS object id's.
  7462. //
  7463. // Returns: FALSE iff !equal
  7464. //--------------------------------------------------------------------------
  7465. BOOL
  7466. WINAPI
  7467. ICM_EqualObjectIDs(
  7468. IN ObjectID *poid1,
  7469. IN ObjectID *poid2)
  7470. {
  7471. BOOL fRet;
  7472. DWORD i;
  7473. PDWORD pdw1;
  7474. PDWORD pdw2;
  7475. if (poid1->count != poid2->count)
  7476. goto Unequal;
  7477. for (i=poid1->count, pdw1=poid1->value, pdw2=poid2->value;
  7478. (i>0) && (*pdw1==*pdw2);
  7479. i--, pdw1++, pdw2++)
  7480. ;
  7481. if (i>0)
  7482. goto Unequal;
  7483. fRet = TRUE; // equal
  7484. CommonReturn:
  7485. return fRet;
  7486. Unequal:
  7487. fRet = FALSE; // !equal
  7488. goto CommonReturn;
  7489. }
  7490. //+-------------------------------------------------------------------------
  7491. // Get the value of an Attribute of a given type.
  7492. //
  7493. // Returns: FALSE iff fails
  7494. //
  7495. // NB- Does not set error
  7496. //--------------------------------------------------------------------------
  7497. BOOL
  7498. WINAPI
  7499. ICM_GetAttrValue(
  7500. IN Attributes *poatrs,
  7501. IN ObjectID *poid,
  7502. OUT Any *panyValue)
  7503. {
  7504. BOOL fRet;
  7505. DWORD i;
  7506. Attribute *poatr;
  7507. for (i=poatrs->count, poatr=poatrs->value; i>0; i--, poatr++) {
  7508. if (ICM_EqualObjectIDs( &poatr->attributeType, poid))
  7509. break;
  7510. }
  7511. if (0 == i)
  7512. goto AttributeNotFoundError;
  7513. *panyValue = *poatr->attributeValue.value;
  7514. fRet = TRUE;
  7515. CommonReturn:
  7516. return fRet;
  7517. ErrorReturn:
  7518. panyValue->length = 0;
  7519. fRet = FALSE;
  7520. goto CommonReturn;
  7521. TRACE_ERROR(AttributeNotFoundError)
  7522. }
  7523. //+-------------------------------------------------------------------------
  7524. // Fill in the content-type and message-digest authenticated attributes,
  7525. // which are required in a SignedData or SignedAndEnvelopedData message.
  7526. //
  7527. // Returns: FALSE iff failed
  7528. //--------------------------------------------------------------------------
  7529. BOOL
  7530. WINAPI
  7531. ICM_FillReqAuthAttrs(
  7532. IN OPTIONAL LPSTR pszInnerContentObjID,
  7533. IN CHashNode *pnHash,
  7534. IN OUT Attribute *possAttr)
  7535. {
  7536. BOOL fRet;
  7537. CRYPT_ATTRIBUTE atr;
  7538. CRYPT_ATTR_BLOB atrblob;
  7539. ASN1error_e Asn1Err;
  7540. ASN1encoding_t pEnc = ICM_GetEncoder();
  7541. PBYTE pbEncoded;
  7542. DWORD cbEncoded;
  7543. ObjectID ossObjID;
  7544. OctetStringType ost;
  7545. // NB - When psi->authenticatedAttributes was created,
  7546. // the first 2 slots were reserved for the
  7547. // content-type and message-digest attributes.
  7548. // content-type attribute
  7549. ossObjID.count = sizeof(ossObjID.value)/sizeof(ossObjID.value[0]);
  7550. if (!PkiAsn1ToObjectIdentifier(
  7551. pszInnerContentObjID ? pszInnerContentObjID : pszObjIdDataType,
  7552. &ossObjID.count,
  7553. ossObjID.value))
  7554. goto ConvToObjectIdentifierError;
  7555. if (0 != (Asn1Err = PkiAsn1Encode(
  7556. pEnc,
  7557. &ossObjID,
  7558. ObjectIdentifierType_PDU,
  7559. &pbEncoded,
  7560. &cbEncoded)))
  7561. goto EncodeObjectIdentifierError;
  7562. atr.pszObjId = pszObjIdContentType;
  7563. atr.cValue = 1;
  7564. atr.rgValue = &atrblob;
  7565. atrblob.cbData = cbEncoded;
  7566. atrblob.pbData = pbEncoded;
  7567. fRet = ICM_Asn1ToAttribute( &atr, possAttr);
  7568. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7569. if (!fRet)
  7570. goto ContentTypeAsn1ToAttributeError;
  7571. // message-digest attribute
  7572. if (!ICM_GetListHashValue( pnHash, (DWORD*)&ost.length, &ost.value))
  7573. goto GetHashValueError;
  7574. if (0 != (Asn1Err = PkiAsn1Encode(
  7575. pEnc,
  7576. &ost,
  7577. OctetStringType_PDU,
  7578. &pbEncoded,
  7579. &cbEncoded)))
  7580. goto EncodeOctetStringError;
  7581. atr.pszObjId = pszObjIdMessageDigest;
  7582. atr.cValue = 1;
  7583. atr.rgValue = &atrblob;
  7584. atrblob.cbData = cbEncoded;
  7585. atrblob.pbData = pbEncoded;
  7586. fRet = ICM_Asn1ToAttribute( &atr, possAttr + 1);
  7587. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  7588. if (!fRet)
  7589. goto MsgDigestAsn1ToAttributeError;
  7590. fRet = TRUE;
  7591. CommonReturn:
  7592. return fRet;
  7593. ErrorReturn:
  7594. fRet = FALSE;
  7595. goto CommonReturn;
  7596. SET_ERROR_VAR(EncodeObjectIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  7597. SET_ERROR_VAR(EncodeOctetStringError, PkiAsn1ErrToHr(Asn1Err))
  7598. SET_ERROR(ConvToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  7599. TRACE_ERROR(ContentTypeAsn1ToAttributeError) // error already set
  7600. TRACE_ERROR(GetHashValueError) // error already set
  7601. TRACE_ERROR(MsgDigestAsn1ToAttributeError) // error already set
  7602. }
  7603. //+-------------------------------------------------------------------------
  7604. // Fill the inner ContentInfo.
  7605. //--------------------------------------------------------------------------
  7606. BOOL
  7607. WINAPI
  7608. ICM_FillInnerContentInfo(
  7609. OUT ContentInfo *pci,
  7610. IN OPTIONAL LPSTR pszInnerID,
  7611. IN DWORD cbData,
  7612. IN const BYTE *pbData,
  7613. IN BOOL fAddInnerContentOctetWrapper // CMS_PKCS7
  7614. )
  7615. {
  7616. BOOL fRet;
  7617. ASN1error_e Asn1Err;
  7618. PBYTE pbEncoded;
  7619. DWORD cbEncoded;
  7620. OctetStringType ost;
  7621. pci->contentType.count = sizeof(pci->contentType.value)/sizeof(pci->contentType.value[0]);
  7622. if (!PkiAsn1ToObjectIdentifier(
  7623. pszInnerID ? pszInnerID : pszObjIdDataType,
  7624. &pci->contentType.count,
  7625. pci->contentType.value))
  7626. goto PkiAsn1ToObjectIdentifierError;
  7627. if (0 != cbData) {
  7628. pci->bit_mask |= content_present;
  7629. if (!fAddInnerContentOctetWrapper) {
  7630. pci->content.length = cbData;
  7631. pci->content.value = (PBYTE)pbData;
  7632. } else {
  7633. ost.length = cbData;
  7634. ost.value = (PBYTE)pbData;
  7635. if (0 != (Asn1Err = PkiAsn1Encode(
  7636. ICM_GetEncoder(),
  7637. &ost,
  7638. OctetStringType_PDU,
  7639. &pbEncoded,
  7640. &cbEncoded)))
  7641. goto EncodeOctetStringError;
  7642. pci->content.length = cbEncoded;
  7643. pci->content.value = pbEncoded;
  7644. }
  7645. }
  7646. fRet = TRUE;
  7647. CommonReturn:
  7648. return fRet;
  7649. ErrorReturn:
  7650. fRet = FALSE;
  7651. goto CommonReturn;
  7652. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  7653. SET_ERROR_VAR(EncodeOctetStringError, PkiAsn1ErrToHr(Asn1Err))
  7654. }
  7655. #ifdef CMS_PKCS7
  7656. //+-------------------------------------------------------------------------
  7657. // Fill in the encrypted digest in a signer info.
  7658. //--------------------------------------------------------------------------
  7659. BOOL
  7660. WINAPI
  7661. ICM_FillSignerEncryptedDigest(
  7662. IN SignerInfo *psi,
  7663. IN OPTIONAL LPSTR pszInnerContentObjID,
  7664. IN PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo,
  7665. IN BOOL fMaxLength)
  7666. {
  7667. DWORD dwError = ERROR_SUCCESS;
  7668. BOOL fRet;
  7669. HCRYPTHASH hHash;
  7670. HCRYPTHASH hHashAttr = NULL;
  7671. HCRYPTHASH hHashDup = NULL;
  7672. PBYTE pbSignature = NULL;
  7673. DWORD cbSignature;
  7674. CHashNode *pnHash = pSignerEncodeDataInfo->pHashNode;
  7675. PICM_HASH_INFO pHashInfo = pnHash->Data();
  7676. PCCRYPT_OID_INFO pOIDInfo;
  7677. DWORD dwAlgIdPubKey;
  7678. DWORD dwPubKeyFlags;
  7679. if (psi->bit_mask & authenticatedAttributes_present) {
  7680. if (!ICM_FillReqAuthAttrs(
  7681. pszInnerContentObjID,
  7682. pSignerEncodeDataInfo->pHashNode,
  7683. psi->authenticatedAttributes.value))
  7684. goto FillReqAuthAttrsError;
  7685. if (!ICM_GetAttrsHash(
  7686. pHashInfo->dwAlgoCAPI,
  7687. pSignerEncodeDataInfo->hCryptProv,
  7688. &psi->authenticatedAttributes,
  7689. &hHashAttr))
  7690. goto GetAuthAttrsHashError;
  7691. hHash = hHashAttr;
  7692. } else {
  7693. if (!ICM_DupListHash( pnHash, pSignerEncodeDataInfo->hCryptProv,
  7694. &hHashDup))
  7695. goto DupListHashError;
  7696. hHash = hHashDup;
  7697. }
  7698. dwAlgIdPubKey = 0;
  7699. dwPubKeyFlags = 0;
  7700. if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  7701. &psi->digestEncryptionAlgorithm)) {
  7702. dwAlgIdPubKey = pOIDInfo->Algid;
  7703. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  7704. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7705. dwPubKeyFlags = pdwExtra[0];
  7706. }
  7707. } else if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_SIGN_ALG_OID_GROUP_ID,
  7708. &psi->digestEncryptionAlgorithm)) {
  7709. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  7710. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7711. if (1 <= cExtra) {
  7712. dwAlgIdPubKey = pdwExtra[0];
  7713. if (2 <= cExtra)
  7714. dwPubKeyFlags = pdwExtra[1];
  7715. }
  7716. }
  7717. if (!ICM_AllocAndSignHash( hHash, pSignerEncodeDataInfo->dwKeySpec,
  7718. dwAlgIdPubKey, dwPubKeyFlags, fMaxLength,
  7719. &pbSignature, &cbSignature))
  7720. goto AllocAndSignHashError;
  7721. psi->encryptedDigest.length = cbSignature;
  7722. psi->encryptedDigest.value = pbSignature;
  7723. pbSignature = NULL;
  7724. fRet = TRUE;
  7725. CommonReturn:
  7726. if (hHashAttr)
  7727. CryptDestroyHash( hHashAttr);
  7728. if (hHashDup)
  7729. CryptDestroyHash( hHashDup);
  7730. ICM_Free(pbSignature);
  7731. ICM_SetLastError(dwError);
  7732. return fRet;
  7733. ErrorReturn:
  7734. dwError = GetLastError();
  7735. fRet = FALSE;
  7736. goto CommonReturn;
  7737. TRACE_ERROR(FillReqAuthAttrsError) // error already set
  7738. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  7739. TRACE_ERROR(DupListHashError) // error already set
  7740. TRACE_ERROR(AllocAndSignHashError) // error already set
  7741. }
  7742. BOOL
  7743. WINAPI
  7744. ICM_FillSignerEncodeEncryptedDigests(
  7745. IN PCRYPT_MSG_INFO pcmi,
  7746. IN BOOL fMaxLength)
  7747. {
  7748. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  7749. DWORD cSignerEncodeDataInfo = pcmi->cSignerEncodeDataInfo;
  7750. PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo =
  7751. pcmi->rgSignerEncodeDataInfo;
  7752. SignedData *psd = (SignedData *)pcmi->pvMsg;
  7753. SignerInfo *psi = psd->signerInfos.value;
  7754. assert(psd->signerInfos.count == cSignerEncodeDataInfo);
  7755. for ( ; 0 < cSignerEncodeDataInfo;
  7756. cSignerEncodeDataInfo--,
  7757. pSignerEncodeDataInfo++,
  7758. psi++) {
  7759. if (!ICM_FillSignerEncryptedDigest(
  7760. psi,
  7761. pszInnerContentObjID,
  7762. pSignerEncodeDataInfo,
  7763. fMaxLength))
  7764. return FALSE;
  7765. }
  7766. return TRUE;
  7767. }
  7768. #else
  7769. //+-------------------------------------------------------------------------
  7770. // Fill in the encrypted digest in a signer info.
  7771. //--------------------------------------------------------------------------
  7772. BOOL
  7773. WINAPI
  7774. ICM_FillSignerEncryptedDigest(
  7775. IN SignerInfo *psi,
  7776. IN OPTIONAL LPSTR pszInnerContentObjID,
  7777. IN CHashNode *pnHash,
  7778. IN DWORD dwKeySpec,
  7779. IN BOOL fMaxLength)
  7780. {
  7781. DWORD dwError = ERROR_SUCCESS;
  7782. BOOL fRet;
  7783. HCRYPTHASH hHash;
  7784. HCRYPTHASH hHashAttr = NULL;
  7785. HCRYPTHASH hHashDup = NULL;
  7786. PBYTE pbSignature = NULL;
  7787. DWORD cbSignature;
  7788. PICM_HASH_INFO pHashInfo = pnHash->Data();
  7789. PCCRYPT_OID_INFO pOIDInfo;
  7790. DWORD dwAlgIdPubKey;
  7791. DWORD dwPubKeyFlags;
  7792. if (psi->bit_mask & authenticatedAttributes_present) {
  7793. if (!ICM_FillReqAuthAttrs(
  7794. pszInnerContentObjID,
  7795. pnHash,
  7796. psi->authenticatedAttributes.value))
  7797. goto FillReqAuthAttrsError;
  7798. if (!ICM_GetAttrsHash(
  7799. pHashInfo->dwAlgoCAPI,
  7800. pHashInfo->hCryptProv,
  7801. &psi->authenticatedAttributes,
  7802. &hHashAttr))
  7803. goto GetAuthAttrsHashError;
  7804. hHash = hHashAttr;
  7805. } else {
  7806. if (!ICM_DupListHash( pnHash, pHashInfo->hCryptProv, &hHashDup))
  7807. goto DupListHashError;
  7808. hHash = hHashDup;
  7809. }
  7810. dwAlgIdPubKey = 0;
  7811. dwPubKeyFlags = 0;
  7812. if (pOIDInfo = ICM_GetOssOIDInfo(CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  7813. &psi->digestEncryptionAlgorithm)) {
  7814. dwAlgIdPubKey = pOIDInfo->Algid;
  7815. if (1 <= pOIDInfo->ExtraInfo.cbData / sizeof(DWORD)) {
  7816. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  7817. dwPubKeyFlags = pdwExtra[0];
  7818. }
  7819. }
  7820. if (!ICM_AllocAndSignHash( hHash, dwKeySpec,
  7821. dwAlgIdPubKey, dwPubKeyFlags, fMaxLength,
  7822. &pbSignature, &cbSignature))
  7823. goto AllocAndSignHashError;
  7824. psi->encryptedDigest.length = cbSignature;
  7825. psi->encryptedDigest.value = pbSignature;
  7826. pbSignature = NULL;
  7827. fRet = TRUE;
  7828. CommonReturn:
  7829. if (hHashAttr)
  7830. CryptDestroyHash( hHashAttr);
  7831. if (hHashDup)
  7832. CryptDestroyHash( hHashDup);
  7833. ICM_Free(pbSignature);
  7834. ICM_SetLastError(dwError);
  7835. return fRet;
  7836. ErrorReturn:
  7837. dwError = GetLastError();
  7838. fRet = FALSE;
  7839. goto CommonReturn;
  7840. TRACE_ERROR(FillReqAuthAttrsError) // error already set
  7841. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  7842. TRACE_ERROR(DupListHashError) // error already set
  7843. TRACE_ERROR(AllocAndSignHashError) // error already set
  7844. }
  7845. #endif // CMS_PKCS7
  7846. //+-------------------------------------------------------------------------
  7847. // Update the content of a signed message.
  7848. //
  7849. // Assume all more-deeply-nested messages are DER-encoded.
  7850. //--------------------------------------------------------------------------
  7851. BOOL
  7852. WINAPI
  7853. ICM_UpdateEncodingSignedData(
  7854. IN PCRYPT_MSG_INFO pcmi,
  7855. IN const BYTE *pbData,
  7856. IN DWORD cbData,
  7857. IN BOOL fFinal)
  7858. {
  7859. BOOL fRet;
  7860. SignedData *psd = (SignedData *)pcmi->pvMsg;
  7861. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  7862. PBYTE pb;
  7863. DWORD cb;
  7864. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  7865. BOOL fAddInnerContentOctetWrapper; // CMS_PKCS7
  7866. if (pcsi) {
  7867. if (!ICMS_UpdateEncodingSignedData( pcmi, (PBYTE)pbData, cbData, fFinal))
  7868. goto StreamUpdateEncodingSignedDataError;
  7869. } else {
  7870. psd->contentInfo.bit_mask = 0;
  7871. fAddInnerContentOctetWrapper = ICM_IsAddInnerContentOctetWrapper(pcmi);
  7872. if (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG) &&
  7873. !fAddInnerContentOctetWrapper && pbData) {
  7874. // must be encoded, hash only the contents octets
  7875. if (0 > Asn1UtilExtractContent(
  7876. (PBYTE)pbData,
  7877. cbData,
  7878. &cb,
  7879. (const BYTE **)&pb))
  7880. goto ExtractContentError;
  7881. } else {
  7882. cb = cbData;
  7883. pb = (PBYTE)pbData;
  7884. }
  7885. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  7886. goto UpdateDigestError;
  7887. if (fFinal) {
  7888. if (pcmi->dwFlags & CMSG_DETACHED_FLAG) {
  7889. if (!ICM_FillInnerContentInfo(
  7890. &psd->contentInfo,
  7891. pszInnerContentObjID,
  7892. 0, // cbData
  7893. NULL, // pbData
  7894. FALSE)) // fAddInnerContentOctetWrapper
  7895. goto DetachedFillInnerContentInfoError;
  7896. } else {
  7897. if (!ICM_FillInnerContentInfo(
  7898. &psd->contentInfo,
  7899. pszInnerContentObjID,
  7900. cbData,
  7901. (PBYTE)pbData,
  7902. fAddInnerContentOctetWrapper
  7903. ))
  7904. goto FillInnerContentInfoError;
  7905. }
  7906. #ifdef CMS_PKCS7
  7907. if (pcmi->rgSignerEncodeDataInfo) {
  7908. BOOL fMaxLength =
  7909. (0 != (pcmi->dwFlags & CMSG_MAX_LENGTH_FLAG));
  7910. if (!ICM_FillSignerEncodeEncryptedDigests(
  7911. pcmi,
  7912. fMaxLength))
  7913. goto FillSignerEncodeEncryptedDigestsError;
  7914. }
  7915. #else
  7916. if (pcmi->pHashList) {
  7917. BOOL fMaxLength =
  7918. (0 != (pcmi->dwFlags & CMSG_MAX_LENGTH_FLAG));
  7919. if (!ICM_FillSignerEncryptedDigest(
  7920. psd->signerInfos.value,
  7921. pszInnerContentObjID,
  7922. pcmi->pHashList->Head(),
  7923. pcmi->dwKeySpec,
  7924. fMaxLength))
  7925. goto FillSignerEncryptedDigestError;
  7926. }
  7927. #endif // CMS_PKCS7
  7928. }
  7929. }
  7930. fRet = TRUE;
  7931. CommonReturn:
  7932. return fRet;
  7933. ErrorReturn:
  7934. fRet = FALSE;
  7935. goto CommonReturn;
  7936. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  7937. TRACE_ERROR(UpdateDigestError) // error already set
  7938. TRACE_ERROR(DetachedFillInnerContentInfoError) // error already set
  7939. TRACE_ERROR(FillInnerContentInfoError) // error already set
  7940. TRACE_ERROR(StreamUpdateEncodingSignedDataError) // error already set
  7941. #ifdef CMS_PKCS7
  7942. TRACE_ERROR(FillSignerEncodeEncryptedDigestsError) // error already set
  7943. #else
  7944. TRACE_ERROR(FillSignerEncryptedDigestError) // error already set
  7945. #endif // CMS_PKCS7
  7946. }
  7947. //+-------------------------------------------------------------------------
  7948. // Update the content of a data message.
  7949. //--------------------------------------------------------------------------
  7950. BOOL
  7951. WINAPI
  7952. ICM_UpdateEncodingData(
  7953. IN PCRYPT_MSG_INFO pcmi,
  7954. IN const BYTE *pbData,
  7955. IN DWORD cbData,
  7956. IN BOOL fFinal)
  7957. {
  7958. DWORD dwError = ERROR_SUCCESS;
  7959. BOOL fRet;
  7960. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  7961. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  7962. if (!pcsi) {
  7963. if (!fFinal)
  7964. goto NotFinalNotSupportedError;
  7965. poos->length = cbData;
  7966. if (NULL == (poos->value = (PBYTE)ICM_DupMem( (PBYTE)pbData, cbData)))
  7967. goto AllocOctetStringError;
  7968. }
  7969. if (pcsi && !ICMS_UpdateEncodingData( pcmi, (PBYTE)pbData, cbData, fFinal))
  7970. goto StreamUpdateEncodingDataError;
  7971. fRet = TRUE;
  7972. CommonReturn:
  7973. ICM_SetLastError(dwError);
  7974. return fRet;
  7975. ErrorReturn:
  7976. dwError = GetLastError();
  7977. ICM_Free( poos->value);
  7978. fRet = FALSE;
  7979. goto CommonReturn;
  7980. SET_ERROR(NotFinalNotSupportedError,E_INVALIDARG)
  7981. TRACE_ERROR(AllocOctetStringError) // error already set
  7982. TRACE_ERROR(StreamUpdateEncodingDataError) // error already set
  7983. }
  7984. //+-------------------------------------------------------------------------
  7985. // Update the content of a digested message.
  7986. //
  7987. // Assume all more-deeply-nested messages are DER-encoded.
  7988. //--------------------------------------------------------------------------
  7989. BOOL
  7990. WINAPI
  7991. ICM_UpdateEncodingDigestedData(
  7992. IN PCRYPT_MSG_INFO pcmi,
  7993. IN const BYTE *pbData,
  7994. IN DWORD cbData,
  7995. IN BOOL fFinal)
  7996. {
  7997. BOOL fRet;
  7998. DigestedData *pdd = (DigestedData *)pcmi->pvMsg;
  7999. PBYTE pb;
  8000. DWORD cb;
  8001. LPSTR pszInnerContentObjID = pcmi->pszInnerContentObjID;
  8002. BOOL fAddInnerContentOctetWrapper; // CMS_PKCS7
  8003. pdd->contentInfo.bit_mask = 0;
  8004. if (pcmi->dwFlags & CMSG_DETACHED_FLAG) {
  8005. // must be non-encoded
  8006. if (!ICM_UpdateListDigest( pcmi->pHashList, pbData, cbData))
  8007. goto DetachedUpdateDigestError;
  8008. if (!ICM_FillInnerContentInfo(
  8009. &pdd->contentInfo,
  8010. pszInnerContentObjID,
  8011. 0, // cbData
  8012. NULL, // pbData
  8013. FALSE // fAddInnerContentOctetWrapper
  8014. ))
  8015. goto DetachedFillInnerContentInfoError;
  8016. } else {
  8017. fAddInnerContentOctetWrapper = ICM_IsAddInnerContentOctetWrapper(pcmi);
  8018. if (!fAddInnerContentOctetWrapper && pbData) {
  8019. // must be encoded, hash only the contents octets
  8020. if (0 > Asn1UtilExtractContent( (PBYTE)pbData, cbData, &cb,
  8021. (const BYTE **)&pb))
  8022. goto ExtractContentError;
  8023. } else {
  8024. cb = cbData;
  8025. pb = (PBYTE)pbData;
  8026. }
  8027. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  8028. goto UpdateDigestError;
  8029. if (!ICM_FillInnerContentInfo(
  8030. &pdd->contentInfo,
  8031. pszInnerContentObjID,
  8032. cbData,
  8033. (PBYTE)pbData,
  8034. fAddInnerContentOctetWrapper
  8035. ))
  8036. goto FillInnerContentInfoError;
  8037. }
  8038. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8039. if (!ICM_GetListHashValue(
  8040. pcmi->pHashList->Head(),
  8041. (DWORD*)&pdd->digest.length,
  8042. &pdd->digest.value))
  8043. goto GetHashValueError;
  8044. }
  8045. fRet = TRUE;
  8046. CommonReturn:
  8047. return fRet;
  8048. ErrorReturn:
  8049. fRet = FALSE;
  8050. goto CommonReturn;
  8051. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8052. TRACE_ERROR(DetachedUpdateDigestError) // error already set
  8053. TRACE_ERROR(UpdateDigestError) // error already set
  8054. TRACE_ERROR(DetachedFillInnerContentInfoError) // error already set
  8055. TRACE_ERROR(FillInnerContentInfoError) // error already set
  8056. TRACE_ERROR(GetHashValueError) // error already set
  8057. fFinal;
  8058. }
  8059. //+-------------------------------------------------------------------------
  8060. // Get the block size for an encryption algorithm
  8061. //--------------------------------------------------------------------------
  8062. BOOL
  8063. WINAPI
  8064. ICM_GetKeyBlockSize(
  8065. IN HCRYPTKEY hkeyEncrypt,
  8066. OUT PDWORD pcbBlockSize,
  8067. OUT OPTIONAL PBOOL pfBlockCipher)
  8068. {
  8069. BOOL fRet;
  8070. BOOL fBlockCipher;
  8071. DWORD cbBlockSize;
  8072. DWORD cbKeyParamLen;
  8073. // Get key's blocksize.
  8074. // Encryption will pad the output data to be blocksize aligned,
  8075. // in the case of a block cipher.
  8076. cbBlockSize = 0;
  8077. cbKeyParamLen = sizeof( cbBlockSize);
  8078. if (!CryptGetKeyParam(
  8079. hkeyEncrypt,
  8080. KP_BLOCKLEN,
  8081. (PBYTE)&cbBlockSize,
  8082. &cbKeyParamLen,
  8083. 0)) // dwFlags
  8084. goto GetKeyParamError;
  8085. if (0 == cbBlockSize) {
  8086. // stream cipher
  8087. fBlockCipher = FALSE;
  8088. cbBlockSize = 8; // convenient size
  8089. } else {
  8090. // block cipher
  8091. fBlockCipher = TRUE;
  8092. cbBlockSize /= 8; // convert from bits to bytes
  8093. }
  8094. fRet = TRUE;
  8095. CommonReturn:
  8096. *pcbBlockSize = cbBlockSize;
  8097. if (pfBlockCipher)
  8098. *pfBlockCipher = fBlockCipher;
  8099. return fRet;
  8100. ErrorReturn:
  8101. cbBlockSize = 0;
  8102. fBlockCipher = FALSE;
  8103. fRet = FALSE;
  8104. goto CommonReturn;
  8105. TRACE_ERROR(GetKeyParamError) // error already set
  8106. }
  8107. //+-------------------------------------------------------------------------
  8108. // Encrypt a buffer
  8109. //--------------------------------------------------------------------------
  8110. BOOL
  8111. WINAPI
  8112. ICM_EncryptBuffer(
  8113. IN HCRYPTKEY hkeyEncrypt,
  8114. HCRYPTHASH hHash,
  8115. IN const BYTE *pbPlain,
  8116. IN DWORD cbPlain,
  8117. OUT PBYTE *ppbCipher,
  8118. OUT PDWORD pcbCipher)
  8119. {
  8120. BOOL fRet;
  8121. const BYTE *pbIn;
  8122. DWORD cbIn;
  8123. PBYTE pbOut;
  8124. DWORD cbOut;
  8125. PBYTE pbOutBuf = NULL;
  8126. DWORD cbPlainRemain;
  8127. DWORD cbBufRemain;
  8128. DWORD cbBlockLen;
  8129. BOOL fBlockCipher;
  8130. if (!ICM_GetKeyBlockSize( hkeyEncrypt, &cbBlockLen, &fBlockCipher))
  8131. goto GetKeyBlockSizeError;
  8132. // encrypt
  8133. cbBufRemain = cbPlain;
  8134. if (fBlockCipher) {
  8135. cbBufRemain += cbBlockLen;
  8136. cbBufRemain -= cbBufRemain % cbBlockLen;
  8137. }
  8138. if (NULL == (pbOutBuf = (PBYTE)ICM_Alloc( cbBufRemain)))
  8139. goto OutOfMemory;
  8140. for (pbIn=pbPlain, pbOut=pbOutBuf, cbPlainRemain=cbPlain;
  8141. (cbIn = min( cbBlockLen, cbPlainRemain)) > 0;
  8142. pbIn += cbIn, pbOut += cbOut,
  8143. cbPlainRemain -= cbIn, cbBufRemain -= cbOut) {
  8144. memcpy( pbOut, pbIn, cbIn);
  8145. cbOut = cbIn;
  8146. if (!CryptEncrypt(
  8147. hkeyEncrypt,
  8148. hHash,
  8149. cbPlainRemain <= cbBlockLen, // fFinal
  8150. 0, // dwFlags
  8151. pbOut,
  8152. &cbOut,
  8153. cbBufRemain))
  8154. goto EncryptError;
  8155. }
  8156. *ppbCipher = pbOutBuf;
  8157. *pcbCipher = (DWORD)(pbOut - pbOutBuf);
  8158. fRet = TRUE;
  8159. CommonReturn:
  8160. return fRet;
  8161. ErrorReturn:
  8162. if(NULL != pbOutBuf)
  8163. ICM_Free(pbOutBuf);
  8164. *ppbCipher = NULL;
  8165. *pcbCipher = 0;
  8166. fRet = FALSE;
  8167. goto CommonReturn;
  8168. TRACE_ERROR(GetKeyBlockSizeError) // error already set
  8169. TRACE_ERROR(EncryptError) // error already set
  8170. TRACE_ERROR(OutOfMemory) // error already set
  8171. }
  8172. //+-------------------------------------------------------------------------
  8173. // Encrypt and store the content of a message.
  8174. //--------------------------------------------------------------------------
  8175. BOOL
  8176. WINAPI
  8177. ICM_EncryptContent(
  8178. IN HCRYPTKEY hkeyContentEncryption,
  8179. HCRYPTHASH hHash,
  8180. OUT EncryptedContentInfo *peci,
  8181. IN const BYTE *pbPlain,
  8182. IN DWORD cbPlain)
  8183. {
  8184. BOOL fRet;
  8185. PBYTE pbCipher = NULL;
  8186. DWORD cbCipher;
  8187. if (!ICM_EncryptBuffer(
  8188. hkeyContentEncryption,
  8189. hHash,
  8190. pbPlain,
  8191. cbPlain,
  8192. &pbCipher,
  8193. &cbCipher))
  8194. goto EncryptBufferError;
  8195. if (0 != cbCipher) {
  8196. peci->bit_mask |= encryptedContent_present;
  8197. peci->encryptedContent.length = cbCipher;
  8198. peci->encryptedContent.value = pbCipher;
  8199. } else
  8200. ICM_Free(pbCipher);
  8201. fRet = TRUE;
  8202. CommonReturn:
  8203. return fRet;
  8204. ErrorReturn:
  8205. fRet = FALSE;
  8206. goto CommonReturn;
  8207. TRACE_ERROR(EncryptBufferError) // error already set
  8208. }
  8209. //+-------------------------------------------------------------------------
  8210. // Update the content of a signed and enveloped message.
  8211. //
  8212. // Assume all more-deeply-nested messages are DER-encoded.
  8213. //--------------------------------------------------------------------------
  8214. #if 0
  8215. BOOL
  8216. WINAPI
  8217. ICM_UpdateEncodingSignedAndEnvelopedData(
  8218. IN PCRYPT_MSG_INFO pcmi,
  8219. IN const BYTE *pbData,
  8220. IN DWORD cbData,
  8221. IN BOOL fFinal)
  8222. {
  8223. DWORD dwError = ERROR_SUCCESS;
  8224. BOOL fRet;
  8225. EncryptedContentInfo *peci;
  8226. SignedAndEnvelopedData *psed;
  8227. DWORD i;
  8228. DWORD iMax;
  8229. PBYTE pbSignature;
  8230. DWORD cbSignature;
  8231. PBYTE pbEncryptedSignature;
  8232. DWORD cbEncryptedSignature;
  8233. psed = (SignedAndEnvelopedData *)(pcmi->pvMsg);
  8234. peci = &psed->encryptedContentInfo;
  8235. // Require inner type to be Data for now
  8236. peci->contentType = aoidMessages[ CMSG_DATA - 1];
  8237. // Alloc a bigger buffer with padding and copy input to it
  8238. // encrypt the content and store it
  8239. if (!ICM_EncryptContent(
  8240. pcmi->hkeyContentCrypt,
  8241. pcmi->ahHash[0], // select the right hHash
  8242. peci,
  8243. pbData,
  8244. cbData))
  8245. goto EncryptError;
  8246. assert( 1 == psed->signerInfos.Count());
  8247. for (i=0, iMax=psed->signerInfos.Count(); i<iMax; i++) {
  8248. // Should use a stack buffer, unless it is too small
  8249. if (!CryptSignHash(
  8250. pcmi->ahHash[i],
  8251. (pcmi->dwKeySpec == 0) ? AT_SIGNATURE : pcmi->dwKeySpec,
  8252. NULL, // description ?
  8253. 0, // dwFlags
  8254. NULL, // pbSignature
  8255. &cbSignature))
  8256. goto GetSignatureSizeError;
  8257. pbSignature = (PBYTE)ICM_AllocA( cbSignature);
  8258. if (NULL == pbSignature)
  8259. goto AllocSignatureError;
  8260. if (!CryptSignHash(
  8261. pcmi->ahHash[i],
  8262. (pcmi->dwKeySpec == 0) ? AT_SIGNATURE : pcmi->dwKeySpec,
  8263. NULL, // description ?
  8264. 0, // dwFlags
  8265. pbSignature,
  8266. &cbSignature))
  8267. goto SignHashError;
  8268. // encrypt the signature
  8269. if (!ICM_EncryptBuffer(
  8270. pcmi->hkeyContentCrypt,
  8271. NULL,
  8272. pbSignature,
  8273. cbSignature,
  8274. &pbEncryptedSignature,
  8275. &cbEncryptedSignature))
  8276. goto EncryptError;
  8277. ICM_FreeA( pbSignature);
  8278. pbSignature = NULL;
  8279. if (0 > psed->signerInfos[i].encryptedDigest.Write(
  8280. pbEncryptedSignature,
  8281. cbEncryptedSignature))
  8282. goto EncryptedDigestWriteError;
  8283. ICM_Free( pbEncryptedSignature);
  8284. pbEncryptedSignature = NULL;
  8285. }
  8286. fRet = TRUE;
  8287. CommonReturn:
  8288. ICM_FreeA( pbSignature);
  8289. ICM_Free( pbEncryptedSignature);
  8290. ICM_SetLastError(dwError);
  8291. return fRet;
  8292. ErrorReturn:
  8293. dwError = GetLastError();
  8294. fRet = FALSE;
  8295. goto CommonReturn;
  8296. TRACE_ERROR(EncryptError)
  8297. TRACE_ERROR(GetSignatureSizeError)
  8298. TRACE_ERROR(AllocSignatureError)
  8299. TRACE_ERROR(SignHashError)
  8300. TRACE_ERROR(EncryptedDigestWriteError)
  8301. }
  8302. #endif
  8303. //+-------------------------------------------------------------------------
  8304. // Update the content of an enveloped message.
  8305. //
  8306. // Assume all more-deeply-nested messages are DER-encoded.
  8307. //--------------------------------------------------------------------------
  8308. BOOL
  8309. WINAPI
  8310. ICM_UpdateEncodingEnvelopedData(
  8311. IN PCRYPT_MSG_INFO pcmi,
  8312. IN const BYTE *pbData,
  8313. IN DWORD cbData,
  8314. IN BOOL fFinal)
  8315. {
  8316. BOOL fRet;
  8317. PBYTE pb;
  8318. DWORD cb;
  8319. #ifdef CMS_PKCS7
  8320. EncryptedContentInfo *peci = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  8321. #else
  8322. EncryptedContentInfo *peci = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  8323. #endif // CMS_PKCS7
  8324. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  8325. if (pcsi) {
  8326. if (!ICMS_UpdateEncodingEnvelopedData(
  8327. pcmi,
  8328. pbData,
  8329. cbData,
  8330. fFinal))
  8331. goto StreamUpdateEncodingEnvelopedDataError;
  8332. } else {
  8333. if (!fFinal)
  8334. goto InvalidArg;
  8335. // encrypt the content
  8336. if (!ICM_IsAddInnerContentOctetWrapper(pcmi)) {
  8337. if (0 > Asn1UtilExtractContent( (PBYTE)pbData, cbData, &cb, (const BYTE **)&pb))
  8338. goto ExtractContentError;
  8339. } else {
  8340. pb = (PBYTE)pbData;
  8341. cb = cbData;
  8342. }
  8343. if (!ICM_EncryptContent(
  8344. pcmi->hkeyContentCrypt,
  8345. NULL, // hHash
  8346. peci,
  8347. pb,
  8348. cb))
  8349. goto EncryptError;
  8350. }
  8351. fRet = TRUE;
  8352. CommonReturn:
  8353. return fRet;
  8354. ErrorReturn:
  8355. fRet = FALSE;
  8356. goto CommonReturn;
  8357. SET_ERROR(InvalidArg,E_INVALIDARG)
  8358. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8359. TRACE_ERROR(EncryptError) // error already set
  8360. TRACE_ERROR(StreamUpdateEncodingEnvelopedDataError) // error already set
  8361. }
  8362. //+-------------------------------------------------------------------------
  8363. // Convert Any to blob and insert at the tail of a blob list
  8364. //--------------------------------------------------------------------------
  8365. BOOL
  8366. WINAPI
  8367. ICM_InsertTailBlob(
  8368. IN OUT CBlobList *pBlobList,
  8369. IN Any *pAny)
  8370. {
  8371. DWORD dwError = ERROR_SUCCESS;
  8372. BOOL fRet;
  8373. CBlobNode *pnBlob = NULL;
  8374. PBYTE pb = NULL;
  8375. DWORD cb;
  8376. CRYPT_DATA_BLOB blob;
  8377. if (NULL == (pnBlob = new CBlobNode))
  8378. goto NewCBlobNodeError;
  8379. cb = pAny->length;
  8380. if (NULL == (pb = (PBYTE)ICM_Alloc( cb)))
  8381. goto AllocError;
  8382. memcpy( pb, pAny->value, cb);
  8383. blob.cbData = cb;
  8384. blob.pbData = pb;
  8385. pnBlob->SetData( &blob);
  8386. pBlobList->InsertTail( pnBlob);
  8387. fRet = TRUE;
  8388. CommonReturn:
  8389. ICM_SetLastError(dwError);
  8390. return fRet;
  8391. ErrorReturn:
  8392. dwError = GetLastError();
  8393. fRet = FALSE;
  8394. ICM_Free( pb);
  8395. goto CommonReturn;
  8396. SET_ERROR(NewCBlobNodeError,E_OUTOFMEMORY)
  8397. TRACE_ERROR(AllocError) // error already set
  8398. }
  8399. //+-------------------------------------------------------------------------
  8400. // Use a 0-based index to delete a blob from a list
  8401. //--------------------------------------------------------------------------
  8402. BOOL
  8403. WINAPI
  8404. ICM_DelBlobByIndex(
  8405. IN OUT CBlobList *pBlobList,
  8406. IN DWORD dwIndex)
  8407. {
  8408. BOOL fRet;
  8409. CBlobNode *pnBlob = pBlobList->Nth( dwIndex);
  8410. if (NULL == pnBlob)
  8411. goto IndexTooLargeError;
  8412. pBlobList->Remove( pnBlob);
  8413. delete pnBlob;
  8414. fRet = TRUE;
  8415. CommonReturn:
  8416. return fRet;
  8417. ErrorReturn:
  8418. fRet = FALSE;
  8419. goto CommonReturn;
  8420. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  8421. }
  8422. //+-------------------------------------------------------------------------
  8423. // Convert Any to blob and insert at the tail of a signer list
  8424. //--------------------------------------------------------------------------
  8425. BOOL
  8426. WINAPI
  8427. ICM_InsertTailSigner(
  8428. IN OUT CSignerList *pSignerList,
  8429. IN Any *pAny)
  8430. {
  8431. DWORD dwError = ERROR_SUCCESS;
  8432. BOOL fRet;
  8433. CSignerNode *pnSigner = NULL;
  8434. PBYTE pb = NULL;
  8435. DWORD cb;
  8436. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  8437. if (NULL == (pnSigner = new CSignerNode))
  8438. goto NewCSignerNodeError;
  8439. cb = pAny->length;
  8440. if (NULL == (pb = (PBYTE)ICM_Alloc( cb)))
  8441. goto AllocError;
  8442. memcpy( pb, pAny->value, cb);
  8443. sdi.blob.cbData = cb;
  8444. sdi.blob.pbData = pb;
  8445. pnSigner->SetData( &sdi);
  8446. pSignerList->InsertTail( pnSigner);
  8447. fRet = TRUE;
  8448. CommonReturn:
  8449. ICM_SetLastError(dwError);
  8450. return fRet;
  8451. ErrorReturn:
  8452. dwError = GetLastError();
  8453. ICM_Free( pb);
  8454. fRet = FALSE;
  8455. goto CommonReturn;
  8456. SET_ERROR(NewCSignerNodeError,E_OUTOFMEMORY)
  8457. TRACE_ERROR(AllocError) // error already set
  8458. }
  8459. //+-------------------------------------------------------------------------
  8460. // Convert a signed message to list form
  8461. //--------------------------------------------------------------------------
  8462. BOOL
  8463. WINAPI
  8464. ICM_GetListSignedData(
  8465. IN OUT PCRYPT_MSG_INFO pcmi,
  8466. IN SignedDataWithBlobs *psdb)
  8467. {
  8468. DWORD dwError = ERROR_SUCCESS;
  8469. BOOL fRet;
  8470. Any *pAny;
  8471. DWORD cb;
  8472. DWORD i;
  8473. PSIGNED_DATA_INFO psdi = NULL;
  8474. if (NULL == (psdi = (PSIGNED_DATA_INFO)ICM_AllocZero(
  8475. sizeof(SIGNED_DATA_INFO))))
  8476. goto SdiAllocError;
  8477. if (NULL == (psdi->pAlgidList = new CBlobList))
  8478. goto NewAlgidListError;
  8479. if (NULL == (psdi->pCertificateList = new CBlobList))
  8480. goto NewCertificateListError;
  8481. if (NULL == (psdi->pCrlList = new CBlobList))
  8482. goto NewCrlListError;
  8483. if (NULL == (psdi->pSignerList = new CSignerList))
  8484. goto NewSignerListError;
  8485. // version
  8486. psdi->version = psdb->version;
  8487. // digestAlgorithms
  8488. for (i=psdb->digestAlgorithms.count, pAny=psdb->digestAlgorithms.value;
  8489. i>0;
  8490. i--, pAny++) {
  8491. if (!ICM_InsertTailBlob( psdi->pAlgidList, pAny))
  8492. goto DigestAlgorithmInsertTailBlobError;
  8493. }
  8494. // contentInfo
  8495. cb = 0;
  8496. ICM_GetOssContentInfoData(
  8497. (ContentInfo *)&psdb->contentInfo, // same, except for NOCOPY
  8498. NULL,
  8499. &cb);
  8500. if (cb == 0)
  8501. goto GetContentInfoDataSizeError;
  8502. if (NULL == (psdi->pci = (PCONTENT_INFO)ICM_Alloc(cb)))
  8503. goto AllocContentInfoError;
  8504. if (!ICM_GetOssContentInfoData(
  8505. (ContentInfo *)&psdb->contentInfo, // same, except for NOCOPY
  8506. psdi->pci,
  8507. &cb))
  8508. goto GetContentInfoDataError;
  8509. // certificates
  8510. if (psdb->bit_mask & certificates_present) {
  8511. #ifdef OSS_CRYPT_ASN1
  8512. for (i=psdb->certificates.count, pAny=psdb->certificates.certificates;
  8513. #else
  8514. for (i=psdb->certificates.count, pAny=psdb->certificates.value;
  8515. #endif // OSS_CRYPT_ASN1
  8516. i>0;
  8517. i--, pAny++) {
  8518. if (!ICM_InsertTailBlob( psdi->pCertificateList, pAny))
  8519. goto CertInsertTailBlobError;
  8520. }
  8521. }
  8522. // crls
  8523. if (psdb->bit_mask & crls_present) {
  8524. #ifdef OSS_CRYPT_ASN1
  8525. for (i=psdb->crls.count, pAny=psdb->crls.crls;
  8526. #else
  8527. for (i=psdb->crls.count, pAny=psdb->crls.value;
  8528. #endif // OSS_CRYPT_ASN1
  8529. i>0;
  8530. i--, pAny++) {
  8531. if (!ICM_InsertTailBlob( psdi->pCrlList, pAny))
  8532. goto CrlInsertTailBlobError;
  8533. }
  8534. }
  8535. // signerInfos
  8536. for (i=psdb->signerInfos.count, pAny=psdb->signerInfos.value;
  8537. i>0;
  8538. i--, pAny++) {
  8539. if (!ICM_InsertTailSigner( psdi->pSignerList, pAny))
  8540. goto SignerInfoInsertTailBlobError;
  8541. }
  8542. fRet = TRUE;
  8543. CommonReturn:
  8544. pcmi->psdi = psdi;
  8545. ICM_SetLastError(dwError);
  8546. return fRet;
  8547. ErrorReturn:
  8548. dwError = GetLastError();
  8549. if (NULL != psdi) {
  8550. if(NULL != psdi->pSignerList)
  8551. delete psdi->pSignerList;
  8552. if(NULL != psdi->pCrlList)
  8553. delete psdi->pCrlList;
  8554. if(NULL != psdi->pCertificateList)
  8555. delete psdi->pCertificateList;
  8556. if(NULL != psdi->pAlgidList)
  8557. delete psdi->pAlgidList;
  8558. ICM_Free( psdi);
  8559. psdi = NULL;
  8560. }
  8561. fRet = FALSE;
  8562. goto CommonReturn;
  8563. TRACE_ERROR(DigestAlgorithmInsertTailBlobError) // error already set
  8564. TRACE_ERROR(GetContentInfoDataSizeError) // error already set
  8565. TRACE_ERROR(AllocContentInfoError) // error already set
  8566. TRACE_ERROR(GetContentInfoDataError) // error already set
  8567. TRACE_ERROR(CertInsertTailBlobError) // error already set
  8568. TRACE_ERROR(CrlInsertTailBlobError) // error already set
  8569. TRACE_ERROR(SignerInfoInsertTailBlobError) // error already set
  8570. SET_ERROR(NewSignerListError,E_OUTOFMEMORY)
  8571. SET_ERROR(NewCrlListError,E_OUTOFMEMORY)
  8572. SET_ERROR(NewCertificateListError,E_OUTOFMEMORY)
  8573. SET_ERROR(NewAlgidListError,E_OUTOFMEMORY)
  8574. SET_ERROR(SdiAllocError,E_OUTOFMEMORY)
  8575. }
  8576. //+-------------------------------------------------------------------------
  8577. // Get the CAPI algid from an encoded AlgidBlob
  8578. //--------------------------------------------------------------------------
  8579. BOOL
  8580. WINAPI
  8581. ICM_GetCapiFromAlgidBlob(
  8582. IN PCRYPT_DATA_BLOB pAlgidBlob,
  8583. OUT PDWORD pdwAlgidCapi)
  8584. {
  8585. DWORD dwError = ERROR_SUCCESS;
  8586. BOOL fRet;
  8587. ASN1error_e Asn1Err;
  8588. ASN1decoding_t pDec = ICM_GetDecoder();
  8589. AlgorithmIdentifier *poai = NULL;
  8590. if (0 != (Asn1Err = PkiAsn1Decode(
  8591. pDec,
  8592. (void **)&poai,
  8593. AlgorithmIdentifier_PDU,
  8594. pAlgidBlob->pbData,
  8595. pAlgidBlob->cbData)))
  8596. goto Asn1DecodeAlgorithmIdentifierError;
  8597. if (!(ICM_GetOssCAPI( CRYPT_HASH_ALG_OID_GROUP_ID, poai, pdwAlgidCapi) ||
  8598. ICM_GetOssCAPI( CRYPT_SIGN_ALG_OID_GROUP_ID, poai, pdwAlgidCapi)))
  8599. goto GetCAPIError;
  8600. fRet = TRUE;
  8601. CommonReturn:
  8602. PkiAsn1FreeInfo(pDec, AlgorithmIdentifier_PDU, poai);
  8603. ICM_SetLastError(dwError);
  8604. return fRet;
  8605. ErrorReturn:
  8606. dwError = GetLastError();
  8607. fRet = FALSE;
  8608. *pdwAlgidCapi = 0;
  8609. goto CommonReturn;
  8610. SET_ERROR_VAR(Asn1DecodeAlgorithmIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  8611. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  8612. }
  8613. //+-------------------------------------------------------------------------
  8614. // Create a hash list from a list of hash algid's
  8615. //--------------------------------------------------------------------------
  8616. BOOL
  8617. WINAPI
  8618. ICM_CreateHashList(
  8619. IN HCRYPTPROV hCryptProv,
  8620. IN OUT CHashList **ppHashList,
  8621. IN CBlobList *pAlgidList)
  8622. {
  8623. DWORD dwError = ERROR_SUCCESS;
  8624. BOOL fRet;
  8625. CHashList *pHashList;
  8626. CBlobNode *pBlobNode;
  8627. CHashNode *pHashNode;
  8628. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8629. if (NULL == (pHashList = new CHashList))
  8630. goto NewHashListError;
  8631. if (hCryptProv) {
  8632. for (pBlobNode=pAlgidList->Head();
  8633. pBlobNode;
  8634. pBlobNode=pBlobNode->Next()) {
  8635. if (!ICM_GetCapiFromAlgidBlob(
  8636. pBlobNode->Data(),
  8637. &HashInfo.dwAlgoCAPI))
  8638. goto GetCAPIError;
  8639. #ifndef CMS_PKCS7
  8640. HashInfo.hCryptProv = hCryptProv;
  8641. #endif // CMS_PKCS7
  8642. if (!CryptCreateHash(
  8643. hCryptProv,
  8644. HashInfo.dwAlgoCAPI,
  8645. NULL, // hKey - optional for MAC
  8646. 0, // dwFlags
  8647. &HashInfo.hHash))
  8648. goto CreateHashError;
  8649. if (NULL == (pHashNode = new CHashNode))
  8650. goto NewHashNodeError;
  8651. pHashNode->SetData( &HashInfo);
  8652. pHashList->InsertTail( pHashNode);
  8653. }
  8654. }
  8655. fRet = TRUE;
  8656. CommonReturn:
  8657. *ppHashList = pHashList;
  8658. ICM_SetLastError(dwError);
  8659. return fRet;
  8660. ErrorReturn:
  8661. dwError = GetLastError();
  8662. pHashList = NULL;
  8663. fRet = FALSE;
  8664. goto CommonReturn;
  8665. SET_ERROR(NewHashListError,E_OUTOFMEMORY)
  8666. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  8667. TRACE_ERROR(GetCAPIError) // error already set
  8668. TRACE_ERROR(CreateHashError) // error already set
  8669. }
  8670. //+-------------------------------------------------------------------------
  8671. // Update for decoding a signed message
  8672. //--------------------------------------------------------------------------
  8673. BOOL
  8674. WINAPI
  8675. ICM_UpdateDecodingSignedData(
  8676. IN OUT PCRYPT_MSG_INFO pcmi,
  8677. IN const BYTE *pbData,
  8678. IN DWORD cbData)
  8679. {
  8680. DWORD dwError = ERROR_SUCCESS;
  8681. BOOL fRet;
  8682. SignedDataWithBlobs *psdb = NULL;
  8683. PBYTE pb = NULL;
  8684. DWORD cb;
  8685. ASN1error_e Asn1Err;
  8686. ASN1decoding_t pDec = ICM_GetDecoder();
  8687. PBYTE pbDER = NULL;
  8688. DWORD cbDER;
  8689. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8690. DWORD dwExceptionCode;
  8691. // Handle MappedFile Exceptions
  8692. __try {
  8693. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8694. if (0 != (Asn1Err = PkiAsn1Decode(
  8695. pDec,
  8696. (void **)&psdb,
  8697. SignedDataWithBlobs_PDU,
  8698. pbData,
  8699. cbData)))
  8700. goto Asn1DecodeSignedDataError;
  8701. if (!ICM_GetListSignedData( pcmi, psdb))
  8702. goto GetListSignedDataError;
  8703. if (!ICM_CreateHashList(
  8704. pcmi->hCryptProv,
  8705. &pcmi->pHashList,
  8706. pcmi->psdi->pAlgidList))
  8707. goto CreateHashListError;
  8708. if (pcmi->psdi->pci->content.cbData) {
  8709. // Get the address & count of the contents octets of the DER
  8710. // encoding of the content. Since the content might be
  8711. // indefinite-length encoded, decode and re-encode as DER.
  8712. pb = pcmi->psdi->pci->content.pbData;
  8713. cb = pcmi->psdi->pci->content.cbData;
  8714. if (0 == strcmp(pszObjIdDataType,
  8715. pcmi->psdi->pci->pszContentType)
  8716. #ifdef CMS_PKCS7
  8717. || pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION
  8718. #endif // CMS_PKCS7
  8719. ) {
  8720. if (!ICM_ReEncodeAsOctetDER(
  8721. pb,
  8722. cb,
  8723. &pbDER,
  8724. &cbDER
  8725. ))
  8726. goto ReEncodeAsOctetDERError;
  8727. if (pbDER) {
  8728. pb = pbDER;
  8729. cb = cbDER;
  8730. }
  8731. }
  8732. if (0 > Asn1UtilExtractContent( pb, cb, &cb, (const BYTE **)&pb))
  8733. goto ExtractContentError;
  8734. } else {
  8735. cb = 0;
  8736. }
  8737. } else {
  8738. assert (pcmi->dwFlags & CMSG_DETACHED_FLAG);
  8739. if (!(pcmi->dwFlags & CMSG_DETACHED_FLAG))
  8740. goto NonFinalNotDetachedError;
  8741. pb = (PBYTE)pbData;
  8742. cb = cbData;
  8743. }
  8744. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  8745. goto UpdateDigestError;
  8746. fRet = TRUE;
  8747. } __except(EXCEPTION_EXECUTE_HANDLER) {
  8748. dwExceptionCode = GetExceptionCode();
  8749. goto ExceptionError;
  8750. }
  8751. CommonReturn:
  8752. PkiAsn1FreeEncoded(ICM_GetEncoder(), pbDER);
  8753. PkiAsn1FreeInfo(pDec, SignedDataWithBlobs_PDU, psdb);
  8754. ICM_SetLastError(dwError);
  8755. return fRet;
  8756. ErrorReturn:
  8757. dwError = GetLastError();
  8758. fRet = FALSE;
  8759. goto CommonReturn;
  8760. SET_ERROR_VAR(Asn1DecodeSignedDataError, PkiAsn1ErrToHr(Asn1Err))
  8761. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  8762. SET_ERROR(NonFinalNotDetachedError,CRYPT_E_MSG_ERROR)
  8763. TRACE_ERROR(GetListSignedDataError) // error already set
  8764. TRACE_ERROR(CreateHashListError) // error already set
  8765. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  8766. TRACE_ERROR(UpdateDigestError) // error already set
  8767. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  8768. }
  8769. #ifdef CMS_PKCS7
  8770. //+-------------------------------------------------------------------------
  8771. // Update for decoding an enveloped message
  8772. //--------------------------------------------------------------------------
  8773. BOOL
  8774. WINAPI
  8775. ICM_UpdateDecodingEnvelopedData(
  8776. IN PCRYPT_MSG_INFO pcmi,
  8777. IN const BYTE *pbData,
  8778. IN DWORD cbData)
  8779. {
  8780. DWORD dwError = ERROR_SUCCESS;
  8781. BOOL fRet;
  8782. CmsEnvelopedData *ped = NULL;
  8783. ASN1error_e Asn1Err;
  8784. ASN1decoding_t pDec = ICM_GetDecoder();
  8785. assert (PHASE_FIRST_FINAL == pcmi->dwPhase);
  8786. if (0 != (Asn1Err = PkiAsn1Decode(
  8787. pDec,
  8788. (void **) &ped,
  8789. CmsEnvelopedData_PDU,
  8790. pbData,
  8791. cbData)))
  8792. goto Asn1DecodeError;
  8793. pcmi->pvMsg = ped;
  8794. if (NULL == (pcmi->pCertificateList = new CBlobList))
  8795. goto NewCertificateListError;
  8796. if (NULL == (pcmi->pCrlList = new CBlobList))
  8797. goto NewCrlListError;
  8798. if (ped->bit_mask & originatorInfo_present) {
  8799. OriginatorInfo *poi = &ped->originatorInfo;
  8800. DWORD i;
  8801. Any *pAny;
  8802. // certificates
  8803. if (poi->bit_mask & certificates_present) {
  8804. #ifdef OSS_CRYPT_ASN1
  8805. for (i=poi->certificates.count, pAny=poi->certificates.certificates;
  8806. #else
  8807. for (i=poi->certificates.count, pAny=poi->certificates.value;
  8808. #endif // OSS_CRYPT_ASN1
  8809. i>0;
  8810. i--, pAny++) {
  8811. if (!ICM_InsertTailBlob( pcmi->pCertificateList, pAny))
  8812. goto CertInsertTailBlobError;
  8813. }
  8814. }
  8815. // crls
  8816. if (poi->bit_mask & crls_present) {
  8817. #ifdef OSS_CRYPT_ASN1
  8818. for (i=poi->crls.count, pAny=poi->crls.crls;
  8819. #else
  8820. for (i=poi->crls.count, pAny=poi->crls.value;
  8821. #endif // OSS_CRYPT_ASN1
  8822. i>0;
  8823. i--, pAny++) {
  8824. if (!ICM_InsertTailBlob( pcmi->pCrlList, pAny))
  8825. goto CrlInsertTailBlobError;
  8826. }
  8827. }
  8828. }
  8829. fRet = TRUE;
  8830. CommonReturn:
  8831. ICM_SetLastError(dwError);
  8832. return fRet;
  8833. ErrorReturn:
  8834. dwError = GetLastError();
  8835. fRet = FALSE;
  8836. if (NULL != pcmi->pCertificateList) {
  8837. delete pcmi->pCertificateList;
  8838. pcmi->pCertificateList = NULL;
  8839. }
  8840. if (NULL != pcmi->pCrlList) {
  8841. delete pcmi->pCrlList;
  8842. pcmi->pCrlList = NULL;
  8843. }
  8844. goto CommonReturn;
  8845. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  8846. SET_ERROR(NewCertificateListError,E_OUTOFMEMORY)
  8847. SET_ERROR(NewCrlListError,E_OUTOFMEMORY)
  8848. TRACE_ERROR(CertInsertTailBlobError)
  8849. TRACE_ERROR(CrlInsertTailBlobError)
  8850. }
  8851. #else
  8852. //+-------------------------------------------------------------------------
  8853. // Update for decoding an enveloped message
  8854. //--------------------------------------------------------------------------
  8855. BOOL
  8856. WINAPI
  8857. ICM_UpdateDecodingEnvelopedData(
  8858. IN PCRYPT_MSG_INFO pcmi,
  8859. IN const BYTE *pbData,
  8860. IN DWORD cbData)
  8861. {
  8862. BOOL fRet;
  8863. EnvelopedData *ped = NULL;
  8864. ASN1error_e Asn1Err;
  8865. ASN1decoding_t pDec = ICM_GetDecoder();
  8866. assert (PHASE_FIRST_FINAL == pcmi->dwPhase);
  8867. if (0 != (Asn1Err = PkiAsn1Decode(
  8868. pDec,
  8869. (void **)&ped,
  8870. EnvelopedData_PDU,
  8871. pbData,
  8872. cbData)))
  8873. goto Asn1DecodeError;
  8874. pcmi->pvMsg = ped;
  8875. fRet = TRUE;
  8876. CommonReturn:
  8877. return fRet;
  8878. ErrorReturn:
  8879. fRet = FALSE;
  8880. goto CommonReturn;
  8881. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  8882. }
  8883. #endif // CMS_PKCS7
  8884. //+-------------------------------------------------------------------------
  8885. // Find the HashNode corresponding to a CAPI Algid
  8886. //
  8887. // NB- Does not fail.
  8888. //--------------------------------------------------------------------------
  8889. BOOL
  8890. WINAPI
  8891. ICM_FindHashNodeFromCapiAlgid(
  8892. IN CHashList *pHashList,
  8893. IN DWORD dwAlgoCAPI,
  8894. OUT CHashNode **ppnHash)
  8895. {
  8896. CHashNode *pnHash;
  8897. for (pnHash=pHashList->Head(); pnHash; pnHash=pnHash->Next()) {
  8898. if (dwAlgoCAPI == pnHash->Data()->dwAlgoCAPI)
  8899. break;
  8900. }
  8901. *ppnHash = pnHash;
  8902. if(pnHash == NULL) {
  8903. SetLastError((DWORD) CRYPT_E_UNKNOWN_ALGO);
  8904. return FALSE;
  8905. }
  8906. return TRUE;
  8907. }
  8908. //+-------------------------------------------------------------------------
  8909. // Find the HashNode corresponding to an encoded Algid
  8910. //--------------------------------------------------------------------------
  8911. BOOL
  8912. WINAPI
  8913. ICM_FindHashNodeFromEncodedAlgo(
  8914. IN CHashList *pHashList,
  8915. IN PCRYPT_DATA_BLOB pblobEncodedAlgorithm,
  8916. OUT CHashNode **ppnHash)
  8917. {
  8918. BOOL fRet;
  8919. DWORD dwAlgoCAPI;
  8920. if (!ICM_GetCapiFromAlgidBlob(
  8921. pblobEncodedAlgorithm,
  8922. &dwAlgoCAPI))
  8923. goto GetCAPIError;
  8924. fRet = ICM_FindHashNodeFromCapiAlgid( pHashList, dwAlgoCAPI, ppnHash);
  8925. CommonReturn:
  8926. return fRet;
  8927. ErrorReturn:
  8928. fRet = FALSE;
  8929. *ppnHash = NULL;
  8930. goto CommonReturn;
  8931. TRACE_ERROR(GetCAPIError) // error already set
  8932. }
  8933. //+-------------------------------------------------------------------------
  8934. // Update for decoding a digested message
  8935. //--------------------------------------------------------------------------
  8936. BOOL
  8937. WINAPI
  8938. ICM_UpdateDecodingDigestedData(
  8939. IN PCRYPT_MSG_INFO pcmi,
  8940. IN const BYTE *pbData,
  8941. IN DWORD cbData)
  8942. {
  8943. DWORD dwError = ERROR_SUCCESS;
  8944. BOOL fRet;
  8945. DigestedData *pdd = NULL;
  8946. PBYTE pb = NULL;
  8947. DWORD cb;
  8948. PBYTE pbDER = NULL;
  8949. DWORD cbDER;
  8950. ASN1error_e Asn1Err;
  8951. ASN1decoding_t pDec = ICM_GetDecoder();
  8952. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  8953. CHashNode *pHashNode;
  8954. if (PHASE_FIRST_FINAL == pcmi->dwPhase) {
  8955. if (0 != (Asn1Err = PkiAsn1Decode(
  8956. pDec,
  8957. (void **)&pdd,
  8958. DigestedData_PDU,
  8959. pbData,
  8960. cbData)))
  8961. goto Asn1DecodeError;
  8962. pcmi->pvMsg = pdd;
  8963. if (!ICM_GetOssCAPI(
  8964. CRYPT_HASH_ALG_OID_GROUP_ID,
  8965. &pdd->digestAlgorithm,
  8966. &HashInfo.dwAlgoCAPI))
  8967. goto GetCAPIError;
  8968. #ifndef CMS_PKCS7
  8969. HashInfo.hCryptProv = pcmi->hCryptProv;
  8970. #endif // CMS_PKCS7
  8971. if (!CryptCreateHash(
  8972. pcmi->hCryptProv,
  8973. HashInfo.dwAlgoCAPI,
  8974. NULL, // hKey - optional for MAC
  8975. 0, // dwFlags
  8976. &HashInfo.hHash))
  8977. goto CreateHashError;
  8978. if (NULL == (pcmi->pHashList = new CHashList))
  8979. goto NewHashListError;
  8980. if (NULL == (pHashNode = new CHashNode))
  8981. goto NewHashNodeError;
  8982. pHashNode->SetData( &HashInfo);
  8983. pcmi->pHashList->InsertTail( pHashNode);
  8984. if (pdd->contentInfo.bit_mask & content_present) {
  8985. // Get the address & count of the contents octets of the DER
  8986. // encoding of the content. Since the content might be
  8987. // indefinite-length encoded, decode and re-encode as DER.
  8988. pb = (PBYTE)pdd->contentInfo.content.value;
  8989. cb = (DWORD)pdd->contentInfo.content.length;
  8990. if (ICM_EqualObjectIDs(
  8991. &pdd->contentInfo.contentType,
  8992. &aoidMessages[ CMSG_DATA - 1])
  8993. #ifdef CMS_PKCS7
  8994. || pdd->version >= CMSG_HASHED_DATA_V2
  8995. #endif // CMS_PKCS7
  8996. ) {
  8997. if (!ICM_ReEncodeAsOctetDER(
  8998. pb,
  8999. cb,
  9000. &pbDER,
  9001. &cbDER
  9002. ))
  9003. goto ReEncodeAsOctetDERError;
  9004. if (pbDER) {
  9005. pb = pbDER;
  9006. cb = cbDER;
  9007. }
  9008. }
  9009. if (0 > Asn1UtilExtractContent( pb, cb, &cb, (const BYTE **)&pb))
  9010. goto ExtractContentError;
  9011. } else {
  9012. cb = 0;
  9013. }
  9014. } else {
  9015. assert (pcmi->dwFlags & CMSG_DETACHED_FLAG);
  9016. if (!(pcmi->dwFlags & CMSG_DETACHED_FLAG))
  9017. goto NonFinalNotDetachedError;
  9018. pb = (PBYTE)pbData;
  9019. cb = cbData;
  9020. }
  9021. if (!ICM_UpdateListDigest( pcmi->pHashList, pb, cb))
  9022. goto UpdateDigestError;
  9023. fRet = TRUE;
  9024. CommonReturn:
  9025. PkiAsn1FreeEncoded(ICM_GetEncoder(), pbDER);
  9026. ICM_SetLastError(dwError);
  9027. return fRet;
  9028. ErrorReturn:
  9029. dwError = GetLastError();
  9030. PkiAsn1FreeInfo(pDec, DigestedData_PDU, pdd);
  9031. pcmi->pvMsg = NULL;
  9032. fRet = FALSE;
  9033. goto CommonReturn;
  9034. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  9035. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  9036. SET_ERROR(NewHashListError,E_OUTOFMEMORY)
  9037. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  9038. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  9039. SET_ERROR(NonFinalNotDetachedError,CRYPT_E_MSG_ERROR)
  9040. TRACE_ERROR(CreateHashError) // error already set
  9041. TRACE_ERROR(UpdateDigestError) // error already set
  9042. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  9043. }
  9044. //+-------------------------------------------------------------------------
  9045. // Update for decoding a data message
  9046. //--------------------------------------------------------------------------
  9047. BOOL
  9048. WINAPI
  9049. ICM_UpdateDecodingData(
  9050. IN PCRYPT_MSG_INFO pcmi,
  9051. IN const BYTE *pbData,
  9052. IN DWORD cbData)
  9053. {
  9054. DWORD dwError = ERROR_SUCCESS;
  9055. BOOL fRet;
  9056. OctetStringType *poos = NULL;
  9057. ASN1error_e Asn1Err;
  9058. ASN1decoding_t pDec = ICM_GetDecoder();
  9059. if (PHASE_FIRST_FINAL != pcmi->dwPhase)
  9060. goto NonFirstFinalError;
  9061. if (0 != (Asn1Err = PkiAsn1Decode(
  9062. pDec,
  9063. (void **)&poos,
  9064. OctetStringType_PDU,
  9065. pbData,
  9066. cbData)))
  9067. goto Asn1DecodeError;
  9068. pcmi->pvMsg = poos;
  9069. fRet = TRUE;
  9070. CommonReturn:
  9071. ICM_SetLastError(dwError);
  9072. return fRet;
  9073. ErrorReturn:
  9074. dwError = GetLastError();
  9075. PkiAsn1FreeInfo(pDec, OctetStringType_PDU, poos);
  9076. fRet = FALSE;
  9077. goto CommonReturn;
  9078. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  9079. SET_ERROR(NonFirstFinalError,CRYPT_E_MSG_ERROR)
  9080. }
  9081. //+-------------------------------------------------------------------------
  9082. // Write a buffer to a file
  9083. //--------------------------------------------------------------------------
  9084. BOOL
  9085. WINAPI
  9086. ICM_WriteBufToFile(
  9087. LPCSTR pszFileName,
  9088. PBYTE pbData,
  9089. DWORD cbData)
  9090. {
  9091. BOOL fRet;
  9092. HANDLE hFile;
  9093. DWORD cbWritten;
  9094. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_WRITE,
  9095. 0, NULL, CREATE_ALWAYS, 0, NULL))) {
  9096. goto CreateFileError;
  9097. }
  9098. if (!WriteFile( hFile, pbData, cbData, &cbWritten, NULL) ||
  9099. (cbWritten != cbData)) {
  9100. goto WriteFileError;
  9101. }
  9102. CloseHandle( hFile);
  9103. fRet = TRUE;
  9104. CommonReturn:
  9105. return fRet;
  9106. ErrorReturn:
  9107. fRet = FALSE;
  9108. goto CommonReturn;
  9109. TRACE_ERROR(CreateFileError)
  9110. TRACE_ERROR(WriteFileError)
  9111. }
  9112. //+-------------------------------------------------------------------------
  9113. // Update the content of a cryptographic message. Depending on how the
  9114. // message was opened, the content is either encoded or decoded.
  9115. //
  9116. // This function is repetitively called to append to the message content.
  9117. // fFinal is set to identify the last update. On fFinal, the encode/decode
  9118. // is completed. The encoded/decoded content and the decoded parameters
  9119. // are valid until the open and all duplicated handles are closed.
  9120. //--------------------------------------------------------------------------
  9121. BOOL
  9122. WINAPI
  9123. #ifdef DEBUG_CRYPT_ASN1_MASTER
  9124. ICMTest_NewCryptMsgUpdate(
  9125. #else
  9126. CryptMsgUpdate(
  9127. #endif
  9128. IN HCRYPTMSG hCryptMsg,
  9129. IN const BYTE *pbData,
  9130. IN DWORD cbData,
  9131. IN BOOL fFinal)
  9132. {
  9133. DWORD dwError = ERROR_SUCCESS;
  9134. BOOL fRet;
  9135. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  9136. ContentInfo *pci = NULL;
  9137. ASN1error_e Asn1Err;
  9138. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  9139. DWORD dwExceptionCode;
  9140. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  9141. // Handle MappedFile Exceptions
  9142. __try {
  9143. if (!ICM_AdvanceMsgPhase( &pcmi->dwPhase, fFinal))
  9144. goto AdvancePhaseError;
  9145. if (pcmi->fEncoding) {
  9146. if (!(((pcmi->dwFlags & CMSG_DETACHED_FLAG) &&
  9147. (PHASE_FIRST_ONGOING == pcmi->dwPhase)) ||
  9148. (pcsi && (pcmi->dwPhase < PHASE_SECOND_ONGOING)) ||
  9149. (PHASE_FIRST_FINAL == pcmi->dwPhase)))
  9150. goto EncodingPhaseError;
  9151. switch (pcmi->dwMsgType) {
  9152. case CMSG_DATA:
  9153. fRet = ICM_UpdateEncodingData(
  9154. pcmi,
  9155. pbData,
  9156. cbData,
  9157. fFinal);
  9158. break;
  9159. case CMSG_SIGNED:
  9160. fRet = ICM_UpdateEncodingSignedData(
  9161. pcmi,
  9162. pbData,
  9163. cbData,
  9164. fFinal);
  9165. break;
  9166. case CMSG_ENVELOPED:
  9167. fRet = ICM_UpdateEncodingEnvelopedData(
  9168. pcmi,
  9169. pbData,
  9170. cbData,
  9171. fFinal);
  9172. break;
  9173. case CMSG_HASHED:
  9174. fRet = ICM_UpdateEncodingDigestedData(
  9175. pcmi,
  9176. pbData,
  9177. cbData,
  9178. fFinal);
  9179. break;
  9180. case CMSG_SIGNED_AND_ENVELOPED:
  9181. #if 0
  9182. fRet = ICM_UpdateEncodingSignedAndEnvelopedData(
  9183. pcmi,
  9184. pbData,
  9185. cbData,
  9186. fFinal);
  9187. break;
  9188. #endif
  9189. case CMSG_ENCRYPTED:
  9190. goto MessageTypeNotSupportedYet;
  9191. default:
  9192. goto InvalidMsgType;
  9193. }
  9194. } else {
  9195. // decode
  9196. ASN1decoding_t pDec = ICM_GetDecoder();
  9197. LONG lth;
  9198. PBYTE pb;
  9199. DWORD cb;
  9200. if (pcsi) {
  9201. if (pcmi->dwPhase < PHASE_SECOND_ONGOING) {
  9202. fRet = ICMS_UpdateDecoding( pcmi, pbData, cbData, fFinal);
  9203. if (fRet)
  9204. goto CommonReturn;
  9205. else
  9206. goto ErrorReturn;
  9207. }
  9208. // else
  9209. // streaming detached
  9210. }
  9211. if (PHASE_FIRST_ONGOING == pcmi->dwPhase)
  9212. goto FirstOngoingDecodeError;
  9213. if ((0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)) &&
  9214. (PHASE_FIRST_FINAL != pcmi->dwPhase))
  9215. goto SecondOngoingNonDetachedError;
  9216. if ((PHASE_FIRST_FINAL == pcmi->dwPhase) &&
  9217. (0 == pcmi->dwMsgType)) {
  9218. if (0 != (Asn1Err = PkiAsn1Decode(
  9219. pDec,
  9220. (void **)&pci,
  9221. ContentInfoNC_PDU,
  9222. pbData,
  9223. cbData)))
  9224. goto Asn1DecodeContentInfoError;
  9225. if (0 == (lth = ICM_ObjIdToIndex( &pci->contentType)))
  9226. goto InvalidMsgType;
  9227. pcmi->dwMsgType = (DWORD)lth;
  9228. pb = (PBYTE)pci->content.value;
  9229. cb = pci->content.length;
  9230. } else {
  9231. pb = (PBYTE)pbData;
  9232. cb = cbData;
  9233. }
  9234. switch (pcmi->dwMsgType) {
  9235. case CMSG_DATA:
  9236. fRet = ICM_UpdateDecodingData( pcmi, pb, cb);
  9237. break;
  9238. case CMSG_SIGNED:
  9239. fRet = ICM_UpdateDecodingSignedData( pcmi, pb, cb);
  9240. break;
  9241. case CMSG_ENVELOPED:
  9242. fRet = ICM_UpdateDecodingEnvelopedData( pcmi, pb, cb);
  9243. break;
  9244. case CMSG_HASHED:
  9245. fRet = ICM_UpdateDecodingDigestedData( pcmi, pb, cb);
  9246. break;
  9247. case CMSG_SIGNED_AND_ENVELOPED:
  9248. case CMSG_ENCRYPTED:
  9249. goto MessageTypeNotSupportedYet;
  9250. default:
  9251. goto InvalidMsgType;
  9252. }
  9253. }
  9254. if (!fRet)
  9255. goto ErrorReturn;
  9256. } __except(EXCEPTION_EXECUTE_HANDLER) {
  9257. dwExceptionCode = GetExceptionCode();
  9258. goto ExceptionError;
  9259. }
  9260. CommonReturn:
  9261. if (pci)
  9262. PkiAsn1FreeInfo(ICM_GetDecoder(), ContentInfoNC_PDU, pci);
  9263. ICM_Unlock( pcmi);
  9264. ICM_SetLastError(dwError);
  9265. return fRet;
  9266. ErrorReturn:
  9267. dwError = GetLastError();
  9268. fRet = FALSE;
  9269. goto CommonReturn;
  9270. SET_ERROR(EncodingPhaseError,CRYPT_E_MSG_ERROR)
  9271. SET_ERROR(FirstOngoingDecodeError,CRYPT_E_MSG_ERROR)
  9272. SET_ERROR(SecondOngoingNonDetachedError,CRYPT_E_MSG_ERROR)
  9273. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  9274. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  9275. SET_ERROR_VAR(Asn1DecodeContentInfoError, PkiAsn1ErrToHr(Asn1Err))
  9276. TRACE_ERROR(AdvancePhaseError) // error already set
  9277. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  9278. }
  9279. BOOL
  9280. WINAPI
  9281. ICM_VerifySignature(
  9282. IN HCRYPTHASH hHash,
  9283. IN HCRYPTKEY hPubKey,
  9284. IN DWORD dwPubKeyAlgId,
  9285. IN DWORD dwPubKeyFlags,
  9286. IN PBYTE pbEncryptedDigest,
  9287. IN DWORD cbEncryptedDigest)
  9288. {
  9289. BOOL fRet;
  9290. BYTE rgbDssSignature[CERT_DSS_SIGNATURE_LEN];
  9291. PBYTE pb = NULL;
  9292. if (CALG_NO_SIGN == dwPubKeyAlgId) {
  9293. DWORD cbData;
  9294. // The encrypted digest isn't signed. It should be the same as
  9295. // the calculated hash
  9296. if (!CryptGetHashParam(
  9297. hHash,
  9298. HP_HASHVAL,
  9299. NULL,
  9300. &cbData,
  9301. 0)) // dwFlags
  9302. goto GetHashParamSizeError;
  9303. if (NULL == (pb = (PBYTE)ICM_AllocA( cbData)))
  9304. goto AllocHashParamError;
  9305. if (!CryptGetHashParam(
  9306. hHash,
  9307. HP_HASHVAL,
  9308. pb,
  9309. &cbData,
  9310. 0)) // dwFlags
  9311. goto GetHashParamError;
  9312. // Compare the calculated hash with the "encrypted digest"
  9313. if (cbData != cbEncryptedDigest ||
  9314. 0 != memcmp(pb, pbEncryptedDigest, cbData))
  9315. goto NoSignHashCompareError;
  9316. fRet = TRUE;
  9317. goto CommonReturn;
  9318. }
  9319. if (CALG_DSS_SIGN == dwPubKeyAlgId &&
  9320. 0 == (dwPubKeyFlags & CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG)) {
  9321. DWORD cbData;
  9322. // Convert from ASN.1 sequence of two integers to the CSP signature
  9323. // format.
  9324. cbData = sizeof(rgbDssSignature);
  9325. if (!CryptDecodeObject(
  9326. X509_ASN_ENCODING,
  9327. X509_DSS_SIGNATURE,
  9328. pbEncryptedDigest,
  9329. cbEncryptedDigest,
  9330. 0, // dwFlags
  9331. rgbDssSignature,
  9332. &cbData
  9333. ))
  9334. goto DecodeError;
  9335. pbEncryptedDigest = rgbDssSignature;
  9336. assert(cbData == sizeof(rgbDssSignature));
  9337. cbEncryptedDigest = sizeof(rgbDssSignature);
  9338. } else {
  9339. if (NULL == (pb = (PBYTE)ICM_AllocA( cbEncryptedDigest)))
  9340. goto AllocError;
  9341. ICM_ReverseCopy( pb, pbEncryptedDigest, cbEncryptedDigest);
  9342. pbEncryptedDigest = pb;
  9343. }
  9344. fRet = CryptVerifySignature(
  9345. hHash,
  9346. pbEncryptedDigest,
  9347. cbEncryptedDigest,
  9348. hPubKey,
  9349. NULL, // pwszDescription
  9350. 0); // dwFlags
  9351. CommonReturn:
  9352. ICM_FreeA(pb);
  9353. return fRet;
  9354. ErrorReturn:
  9355. fRet = FALSE;
  9356. goto CommonReturn;
  9357. TRACE_ERROR(GetHashParamSizeError)
  9358. TRACE_ERROR(AllocHashParamError)
  9359. TRACE_ERROR(GetHashParamError)
  9360. SET_ERROR(NoSignHashCompareError, NTE_BAD_SIGNATURE)
  9361. TRACE_ERROR(DecodeError)
  9362. TRACE_ERROR(AllocError)
  9363. }
  9364. //+-------------------------------------------------------------------------
  9365. // Verify a signature using the authenticated attributes blob
  9366. //--------------------------------------------------------------------------
  9367. BOOL
  9368. WINAPI
  9369. ICM_VerifySignatureAuthAttrBlob(
  9370. IN PCRYPT_MSG_INFO pcmi,
  9371. IN CSignerNode *pSignerNode,
  9372. IN HCRYPTPROV hCryptProv,
  9373. IN HCRYPTKEY hPubKey,
  9374. IN DWORD dwDigestAlgorithm,
  9375. IN DWORD dwPubKeyAlgorithm,
  9376. IN DWORD dwPubKeyFlags,
  9377. IN PBYTE pbEncryptedDigest,
  9378. IN DWORD cbEncryptedDigest)
  9379. {
  9380. DWORD dwError = ERROR_SUCCESS;
  9381. BOOL fRet;
  9382. SignerInfoWithAABlob *psiaab = NULL;
  9383. ASN1error_e Asn1Err;
  9384. ASN1decoding_t pDec = ICM_GetDecoder();
  9385. CRYPT_DATA_BLOB DataBlob;
  9386. HCRYPTHASH hHashAttrBlob = NULL;
  9387. PBYTE pb = NULL;
  9388. DWORD cb;
  9389. DataBlob = pSignerNode->Data()->blob;
  9390. if (0 != (Asn1Err = PkiAsn1Decode(
  9391. pDec,
  9392. (void **)&psiaab,
  9393. SignerInfoWithAABlob_PDU,
  9394. DataBlob.pbData,
  9395. DataBlob.cbData)))
  9396. goto Asn1DecodeSignerInfoWithAABlobError;
  9397. cb = psiaab->authenticatedAttributes.length;
  9398. if (NULL == (pb = (PBYTE)ICM_AllocA(cb)))
  9399. goto AuthenticatedAttributesAllocError;
  9400. memcpy( pb, psiaab->authenticatedAttributes.value, cb);
  9401. // The encoded blob should contain 0xa0 ([0] IMPLICIT) as the tag,
  9402. // but the tag needs to be 0x31 (SET OF) for the hash computation.
  9403. if (*pb != (ICM_TAG_CONTEXT_0 | ICM_TAG_CONSTRUCTED)) // [0] IMPLICIT
  9404. goto AuthAttrsTagError;
  9405. *pb = ICM_TAG_SET; // SET OF
  9406. if (!ICM_GetBlobHash(
  9407. hCryptProv,
  9408. dwDigestAlgorithm,
  9409. pb,
  9410. cb,
  9411. &hHashAttrBlob))
  9412. goto HashAttrBlobError;
  9413. if (!ICM_VerifySignature(
  9414. hHashAttrBlob,
  9415. hPubKey,
  9416. dwPubKeyAlgorithm,
  9417. dwPubKeyFlags,
  9418. pbEncryptedDigest,
  9419. cbEncryptedDigest))
  9420. goto VerifySignatureError;
  9421. fRet = TRUE;
  9422. CommonReturn:
  9423. PkiAsn1FreeInfo(pDec, SignerInfoWithAABlob_PDU, psiaab);
  9424. if (hHashAttrBlob)
  9425. CryptDestroyHash( hHashAttrBlob);
  9426. ICM_FreeA(pb);
  9427. ICM_SetLastError(dwError);
  9428. return fRet;
  9429. ErrorReturn:
  9430. dwError = GetLastError();
  9431. fRet = FALSE;
  9432. goto CommonReturn;
  9433. SET_ERROR_VAR(Asn1DecodeSignerInfoWithAABlobError, PkiAsn1ErrToHr(Asn1Err))
  9434. SET_ERROR(AuthAttrsTagError,CRYPT_E_BAD_ENCODE)
  9435. TRACE_ERROR(AuthenticatedAttributesAllocError) // error already set
  9436. TRACE_ERROR(HashAttrBlobError) // error already set
  9437. TRACE_ERROR(VerifySignatureError) // error already set
  9438. }
  9439. #ifdef CMS_PKCS7
  9440. BOOL
  9441. WINAPI
  9442. ICM_GetVerifySignatureStuff(
  9443. IN DWORD dwSignerType,
  9444. void *pvSigner,
  9445. IN OUT HCRYPTPROV *phCryptProv,
  9446. OUT HCRYPTKEY *phPubKey,
  9447. OUT DWORD *pdwPubKeyAlgId,
  9448. OUT DWORD *pdwPubKeyFlags)
  9449. {
  9450. BOOL fRet;
  9451. PCCRYPT_OID_INFO pOIDInfo;
  9452. HCRYPTPROV hCryptProv;
  9453. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL; // not allocated
  9454. CERT_PUBLIC_KEY_INFO PubKeyInfo;
  9455. BYTE *pbAllocPubKeyPara = NULL;
  9456. *pdwPubKeyAlgId = 0;
  9457. *pdwPubKeyFlags = 0;
  9458. switch (dwSignerType) {
  9459. case CMSG_VERIFY_SIGNER_PUBKEY:
  9460. pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) pvSigner;
  9461. break;
  9462. case CMSG_VERIFY_SIGNER_CHAIN:
  9463. {
  9464. PCCERT_CHAIN_CONTEXT pChain = (PCCERT_CHAIN_CONTEXT) pvSigner;
  9465. // All chains have at least the leaf certificate context
  9466. assert(pChain->cChain && pChain->rgpChain[0]->cElement);
  9467. pvSigner =
  9468. (void *) pChain->rgpChain[0]->rgpElement[0]->pCertContext;
  9469. dwSignerType = CMSG_VERIFY_SIGNER_CERT;
  9470. }
  9471. // fall through
  9472. case CMSG_VERIFY_SIGNER_CERT:
  9473. {
  9474. PCCERT_CONTEXT pSigner = (PCCERT_CONTEXT) pvSigner;
  9475. PCRYPT_OBJID_BLOB pPara;
  9476. pPubKeyInfo = &pSigner->pCertInfo->SubjectPublicKeyInfo;
  9477. pPara = &pPubKeyInfo->Algorithm.Parameters;
  9478. // Check if the public key parameters were omitted
  9479. // from the encoded certificate. If omitted, try
  9480. // to use the certificate's CERT_PUBKEY_ALG_PARA_PROP_ID
  9481. // property.
  9482. if (0 == pPara->cbData ||
  9483. ICM_TAG_NULL_OCTETS == *pPara->pbData) {
  9484. DWORD cbData;
  9485. if (CertGetCertificateContextProperty(
  9486. pSigner,
  9487. CERT_PUBKEY_ALG_PARA_PROP_ID,
  9488. NULL, // pvData
  9489. &cbData) && 0 < cbData
  9490. &&
  9491. (pbAllocPubKeyPara = (BYTE *) ICM_Alloc(
  9492. cbData))
  9493. &&
  9494. CertGetCertificateContextProperty(
  9495. pSigner,
  9496. CERT_PUBKEY_ALG_PARA_PROP_ID,
  9497. pbAllocPubKeyPara,
  9498. &cbData)) {
  9499. PubKeyInfo = *pPubKeyInfo;
  9500. PubKeyInfo.Algorithm.Parameters.pbData =
  9501. pbAllocPubKeyPara;
  9502. PubKeyInfo.Algorithm.Parameters.cbData = cbData;
  9503. pPubKeyInfo = &PubKeyInfo;
  9504. }
  9505. }
  9506. }
  9507. break;
  9508. case CMSG_VERIFY_SIGNER_NULL:
  9509. break;
  9510. default:
  9511. goto InvalidSignerType;
  9512. }
  9513. if (CMSG_VERIFY_SIGNER_NULL == dwSignerType)
  9514. ;
  9515. else if (pOIDInfo = CryptFindOIDInfo(
  9516. CRYPT_OID_INFO_OID_KEY,
  9517. pPubKeyInfo->Algorithm.pszObjId,
  9518. CRYPT_PUBKEY_ALG_OID_GROUP_ID
  9519. )) {
  9520. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  9521. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  9522. *pdwPubKeyAlgId = pOIDInfo->Algid;
  9523. if (1 <= cExtra)
  9524. *pdwPubKeyFlags = pdwExtra[0];
  9525. }
  9526. hCryptProv = *phCryptProv;
  9527. if (0 == hCryptProv) {
  9528. hCryptProv = I_CryptGetDefaultCryptProv(*pdwPubKeyAlgId);
  9529. if (0 == hCryptProv)
  9530. goto GetDefaultCryptProvError;
  9531. *phCryptProv = hCryptProv;
  9532. }
  9533. if (CMSG_VERIFY_SIGNER_NULL == dwSignerType) {
  9534. // The signature is simply the hash octets
  9535. *pdwPubKeyAlgId = CALG_NO_SIGN;
  9536. *phPubKey = NULL;
  9537. // import the signer's public key
  9538. } else if (!CryptImportPublicKeyInfo(
  9539. hCryptProv,
  9540. X509_ASN_ENCODING,
  9541. pPubKeyInfo,
  9542. phPubKey))
  9543. goto ImportKeyFailed;
  9544. fRet = TRUE;
  9545. CommonReturn:
  9546. ICM_Free(pbAllocPubKeyPara);
  9547. return fRet;
  9548. ErrorReturn:
  9549. fRet = FALSE;
  9550. *phPubKey = 0;
  9551. goto CommonReturn;
  9552. SET_ERROR(InvalidSignerType, E_INVALIDARG)
  9553. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  9554. TRACE_ERROR(ImportKeyFailed) // error already set
  9555. }
  9556. BOOL
  9557. WINAPI
  9558. ICM_FindSignerInfo(
  9559. IN PCRYPT_MSG_INFO pcmi,
  9560. IN DWORD dwIndex,
  9561. OUT PVOID *ppv);
  9562. //+-------------------------------------------------------------------------
  9563. // Verify a signature
  9564. //--------------------------------------------------------------------------
  9565. BOOL
  9566. WINAPI
  9567. ICM_ControlVerifySignatureEx(
  9568. IN PCRYPT_MSG_INFO pcmi,
  9569. IN DWORD dwFlags,
  9570. IN PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA pPara
  9571. )
  9572. {
  9573. DWORD dwError = ERROR_SUCCESS;
  9574. BOOL fRet;
  9575. SignerInfoWithBlobs *psib = NULL;
  9576. CSignerNode *pSignerNode = NULL;
  9577. HCRYPTHASH hHashAttr = NULL;
  9578. HCRYPTHASH hHashDup = NULL;
  9579. HCRYPTHASH hHash = NULL;
  9580. HCRYPTKEY hPubKey = NULL;
  9581. HCRYPTPROV hCryptProv; // doen't need to be released
  9582. DWORD dwPubKeyAlgId;
  9583. DWORD dwPubKeyFlags;
  9584. PBYTE pbHash;
  9585. ULONG cb;
  9586. Any anyValue;
  9587. DWORD cbMessageDigest;
  9588. PBYTE pbMessageDigest;
  9589. ASN1error_e Asn1Err;
  9590. ASN1decoding_t pDec = ICM_GetDecoder();
  9591. CRYPT_DATA_BLOB DataBlob;
  9592. CHashNode *pnHash;
  9593. PICM_HASH_INFO pHashInfo;
  9594. if (!ICM_FindSignerInfo(pcmi, pPara->dwSignerIndex, (PVOID *)&pSignerNode))
  9595. goto FindSignerInfoError;
  9596. DataBlob = pSignerNode->Data()->blob;
  9597. if (0 != (Asn1Err = PkiAsn1Decode(
  9598. pDec,
  9599. (void **)&psib,
  9600. SignerInfoWithBlobs_PDU,
  9601. DataBlob.pbData,
  9602. DataBlob.cbData)))
  9603. goto DecodeSignerInfoWithBlobsError;
  9604. if (!ICM_FindHashNodeFromEncodedAlgo(
  9605. pcmi->pHashList,
  9606. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  9607. &pnHash))
  9608. goto GetHashNodeFromEncodedAlgoError;
  9609. pHashInfo = pnHash->Data();
  9610. if (pPara->hCryptProv)
  9611. hCryptProv = pPara->hCryptProv;
  9612. else if (pcmi->fDefaultCryptProv)
  9613. hCryptProv = 0;
  9614. else
  9615. hCryptProv = pcmi->hCryptProv;
  9616. if (!ICM_GetVerifySignatureStuff(
  9617. pPara->dwSignerType,
  9618. pPara->pvSigner,
  9619. &hCryptProv,
  9620. &hPubKey,
  9621. &dwPubKeyAlgId,
  9622. &dwPubKeyFlags)) goto GetSignatureStuffError;
  9623. if (psib->bit_mask & authAttributes_present) {
  9624. // find the message digest attr value
  9625. if (!ICM_GetAttrValue(
  9626. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  9627. &oidMessageDigest,
  9628. &anyValue))
  9629. goto FindAttrError;
  9630. // find the message digest octets
  9631. if (!Asn1UtilExtractContent(
  9632. #ifdef OSS_CRYPT_ASN1
  9633. anyValue.value,
  9634. #else
  9635. (const BYTE *) anyValue.value,
  9636. #endif // OSS_CRYPT_ASN1
  9637. anyValue.length,
  9638. &cbMessageDigest,
  9639. (const BYTE **)&pbMessageDigest))
  9640. goto ExtractContentError;
  9641. // get the hash value computed on the data
  9642. if (!ICM_GetListHashValue( pnHash, &cb, &pbHash))
  9643. goto GetHashValueError;
  9644. // hash sizes equal?
  9645. if (cb != cbMessageDigest)
  9646. goto HashCompareSizeError;
  9647. // hash octets equal?
  9648. if (memcmp( pbMessageDigest, pbHash, cb))
  9649. goto HashCompareValueError;
  9650. // Now that we have verified the message digest octets,
  9651. // get the hash of the authenticated attributes.
  9652. // Should check the content type attribute as well.
  9653. if (!ICM_GetAttrsHash(
  9654. pHashInfo->dwAlgoCAPI,
  9655. hCryptProv,
  9656. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  9657. &hHashAttr))
  9658. goto GetAuthAttrsHashError;
  9659. hHash = hHashAttr;
  9660. } else {
  9661. if (!ICM_DupListHash( pnHash, hCryptProv, &hHashDup))
  9662. goto DupListHashError;
  9663. hHash = hHashDup;
  9664. }
  9665. // verify the hash, signature, and public key are consistent
  9666. fRet = ICM_VerifySignature(
  9667. hHash,
  9668. hPubKey,
  9669. dwPubKeyAlgId,
  9670. dwPubKeyFlags,
  9671. psib->encryptedDigest.value,
  9672. psib->encryptedDigest.length);
  9673. if (!fRet && hHashAttr) {
  9674. // The hash of the authenticated attributes failed.
  9675. // Maybe they hashed incorrectly-DER-encoded authenticated attributes
  9676. // and gave us that encoding. Hash and verify the actual encoding of
  9677. // the authattrs that they gave us. There is a bug in IE3.0 which hits
  9678. // this path, due to a bug in the then-current OSS libraries.
  9679. fRet = ICM_VerifySignatureAuthAttrBlob(
  9680. pcmi,
  9681. pSignerNode,
  9682. hCryptProv,
  9683. hPubKey,
  9684. pHashInfo->dwAlgoCAPI,
  9685. dwPubKeyAlgId,
  9686. dwPubKeyFlags,
  9687. psib->encryptedDigest.value,
  9688. psib->encryptedDigest.length);
  9689. }
  9690. if (!fRet)
  9691. goto VerifySignatureError;
  9692. CommonReturn:
  9693. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9694. if (hPubKey)
  9695. CryptDestroyKey(hPubKey);
  9696. if (hHashAttr)
  9697. CryptDestroyHash( hHashAttr);
  9698. if (hHashDup)
  9699. CryptDestroyHash( hHashDup);
  9700. ICM_SetLastError(dwError);
  9701. return fRet;
  9702. ErrorReturn:
  9703. dwError = GetLastError();
  9704. // if (hHash && (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)))
  9705. // CryptDestroyHash( hHash);
  9706. fRet = FALSE;
  9707. goto CommonReturn;
  9708. TRACE_ERROR(FindSignerInfoError) // error already set
  9709. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  9710. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  9711. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  9712. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  9713. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  9714. TRACE_ERROR(GetHashValueError) // error already set
  9715. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  9716. TRACE_ERROR(GetSignatureStuffError) // error already set
  9717. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  9718. TRACE_ERROR(DupListHashError) // error already set
  9719. TRACE_ERROR(VerifySignatureError) // error already set
  9720. dwFlags;
  9721. }
  9722. //+-------------------------------------------------------------------------
  9723. // Verify a signature
  9724. //--------------------------------------------------------------------------
  9725. BOOL
  9726. WINAPI
  9727. ICM_ControlVerifySignature(
  9728. IN PCRYPT_MSG_INFO pcmi,
  9729. IN DWORD dwFlags,
  9730. IN PCERT_INFO pci)
  9731. {
  9732. DWORD dwError = ERROR_SUCCESS;
  9733. BOOL fRet;
  9734. SignerInfoWithBlobs *psib = NULL;
  9735. CSignerNode *pSignerNode = NULL;
  9736. ULONG cbIssuer;
  9737. PBYTE pb = NULL;
  9738. ULONG cb;
  9739. ASN1error_e Asn1Err;
  9740. ASN1decoding_t pDec = ICM_GetDecoder();
  9741. CRYPT_DATA_BLOB DataBlob;
  9742. CertIdentifier *pOssCertId = NULL;
  9743. IssuerAndSerialNumber *pisn; // not allocated
  9744. DWORD dwSignerIndex;
  9745. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA ExPara;
  9746. ZEROSTRUCT(ExPara);
  9747. ExPara.cbSize = sizeof(ExPara);
  9748. // ExPara.hCryptProv =
  9749. // ExPara.dwSignerIndex =
  9750. ExPara.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  9751. ExPara.pvSigner = (void *) &pci->SubjectPublicKeyInfo;
  9752. cb = pci->SerialNumber.cbData;
  9753. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  9754. goto SerialNumberAllocError;
  9755. cbIssuer = pci->Issuer.cbData;
  9756. switch (pcmi->dwMsgType) {
  9757. case CMSG_SIGNED:
  9758. {
  9759. for (pSignerNode=pcmi->psdi->pSignerList->Head(), dwSignerIndex = 0;
  9760. pSignerNode;
  9761. pSignerNode = pSignerNode->Next(), dwSignerIndex++) {
  9762. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9763. psib = NULL;
  9764. PkiAsn1FreeInfo(pDec, CertIdentifier_PDU, pOssCertId);
  9765. pOssCertId = NULL;
  9766. DataBlob = pSignerNode->Data()->blob;
  9767. if (0 != (Asn1Err = PkiAsn1Decode(
  9768. pDec,
  9769. (void **)&psib,
  9770. SignerInfoWithBlobs_PDU,
  9771. DataBlob.pbData,
  9772. DataBlob.cbData)))
  9773. goto DecodeSignerInfoWithBlobsError;
  9774. if (0 != (Asn1Err = PkiAsn1Decode(
  9775. pDec,
  9776. (void **)&pOssCertId,
  9777. CertIdentifier_PDU,
  9778. (BYTE *) psib->sid.value,
  9779. psib->sid.length)))
  9780. goto DecodeCertIdentifierError;
  9781. switch (pOssCertId->choice) {
  9782. case issuerAndSerialNumber_chosen:
  9783. pisn = &pOssCertId->u.issuerAndSerialNumber;
  9784. if (pisn->issuer.length != cbIssuer)
  9785. break;
  9786. if (0 != memcmp( pci->Issuer.pbData,
  9787. pisn->issuer.value, cbIssuer))
  9788. break;
  9789. // We need to add an integer method to compare
  9790. // big-endian internal to a little-endian external
  9791. // value.
  9792. if (pisn->serialNumber.length != cb)
  9793. break;
  9794. ICM_ReverseCopy( pb, pisn->serialNumber.value, cb);
  9795. if (0 == memcmp( pb, pci->SerialNumber.pbData, cb))
  9796. goto VerifyFoundSigner;
  9797. break;
  9798. case subjectKeyIdentifier_chosen:
  9799. // Go for it. See if we are able to verify using
  9800. // the public key for this signer
  9801. ExPara.dwSignerIndex = dwSignerIndex;
  9802. fRet = ICM_ControlVerifySignatureEx(
  9803. pcmi,
  9804. dwFlags,
  9805. &ExPara
  9806. );
  9807. if (fRet)
  9808. goto CommonReturn;
  9809. break;
  9810. }
  9811. }
  9812. // No signer was found
  9813. break;
  9814. }
  9815. case CMSG_SIGNED_AND_ENVELOPED:
  9816. goto MessageTypeNotSupportedYet;
  9817. default:
  9818. goto InvalidMsgType;
  9819. }
  9820. assert(NULL == pSignerNode);
  9821. goto SignerNotFound;
  9822. VerifyFoundSigner:
  9823. ExPara.dwSignerIndex = dwSignerIndex;
  9824. fRet = ICM_ControlVerifySignatureEx(
  9825. pcmi,
  9826. dwFlags,
  9827. &ExPara
  9828. );
  9829. if (!fRet)
  9830. goto ErrorReturn;
  9831. CommonReturn:
  9832. ICM_FreeA( pb);
  9833. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9834. PkiAsn1FreeInfo(pDec, CertIdentifier_PDU, pOssCertId);
  9835. ICM_SetLastError(dwError);
  9836. return fRet;
  9837. ErrorReturn:
  9838. dwError = GetLastError();
  9839. fRet = FALSE;
  9840. goto CommonReturn;
  9841. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  9842. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  9843. SET_ERROR_VAR(DecodeCertIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  9844. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  9845. SET_ERROR(SignerNotFound,CRYPT_E_SIGNER_NOT_FOUND)
  9846. TRACE_ERROR(SerialNumberAllocError) // error already set
  9847. }
  9848. #else
  9849. BOOL
  9850. WINAPI
  9851. ICM_GetVerifySignatureStuff(
  9852. IN PCERT_INFO pci,
  9853. IN OUT HCRYPTPROV *phCryptProv,
  9854. OUT HCRYPTKEY *phPubKey,
  9855. OUT DWORD *pdwPubKeyAlgId,
  9856. OUT DWORD *pdwPubKeyFlags)
  9857. {
  9858. BOOL fRet;
  9859. PCCRYPT_OID_INFO pOIDInfo;
  9860. HCRYPTPROV hCryptProv;
  9861. *pdwPubKeyAlgId = 0;
  9862. *pdwPubKeyFlags = 0;
  9863. if (pOIDInfo = CryptFindOIDInfo(
  9864. CRYPT_OID_INFO_OID_KEY,
  9865. pci->SubjectPublicKeyInfo.Algorithm.pszObjId,
  9866. CRYPT_PUBKEY_ALG_OID_GROUP_ID
  9867. )) {
  9868. DWORD cExtra = pOIDInfo->ExtraInfo.cbData / sizeof(DWORD);
  9869. DWORD *pdwExtra = (DWORD *) pOIDInfo->ExtraInfo.pbData;
  9870. *pdwPubKeyAlgId = pOIDInfo->Algid;
  9871. if (1 <= cExtra)
  9872. *pdwPubKeyFlags = pdwExtra[0];
  9873. }
  9874. hCryptProv = *phCryptProv;
  9875. if (0 == hCryptProv) {
  9876. hCryptProv = I_CryptGetDefaultCryptProv(*pdwPubKeyAlgId);
  9877. if (0 == hCryptProv)
  9878. goto GetDefaultCryptProvError;
  9879. *phCryptProv = hCryptProv;
  9880. }
  9881. // import the signer's public key
  9882. if (!CryptImportPublicKeyInfo(
  9883. hCryptProv,
  9884. X509_ASN_ENCODING,
  9885. &pci->SubjectPublicKeyInfo,
  9886. phPubKey))
  9887. goto ImportKeyFailed;
  9888. fRet = TRUE;
  9889. CommonReturn:
  9890. return fRet;
  9891. ErrorReturn:
  9892. fRet = FALSE;
  9893. *phPubKey = 0;
  9894. goto CommonReturn;
  9895. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  9896. TRACE_ERROR(ImportKeyFailed) // error already set
  9897. }
  9898. //+-------------------------------------------------------------------------
  9899. // Verify a signature
  9900. //--------------------------------------------------------------------------
  9901. BOOL
  9902. WINAPI
  9903. ICM_ControlVerifySignature(
  9904. IN PCRYPT_MSG_INFO pcmi,
  9905. IN DWORD dwFlags,
  9906. IN PCERT_INFO pci)
  9907. {
  9908. DWORD dwError = ERROR_SUCCESS;
  9909. BOOL fRet;
  9910. SignerInfoWithBlobs *psib = NULL;
  9911. CSignerNode *pSignerNode = NULL;
  9912. SignerInfo *psi = NULL;
  9913. Any *pc; // &content
  9914. HCRYPTHASH hHashAttr = NULL;
  9915. HCRYPTHASH hHashDup = NULL;
  9916. HCRYPTHASH hHash = NULL;
  9917. HCRYPTKEY hPubKey = NULL;
  9918. HCRYPTPROV hCryptProv;
  9919. DWORD dwPubKeyAlgId;
  9920. DWORD dwPubKeyFlags;
  9921. ULONG cbIssuer;
  9922. PBYTE pbHash;
  9923. PBYTE pb = NULL;
  9924. ULONG cb;
  9925. Any anyValue;
  9926. DWORD cbMessageDigest;
  9927. PBYTE pbMessageDigest;
  9928. ASN1error_e Asn1Err;
  9929. ASN1decoding_t pDec = ICM_GetDecoder();
  9930. CRYPT_DATA_BLOB DataBlob;
  9931. IssuerAndSerialNumber *pisn = NULL;
  9932. CHashNode *pnHash;
  9933. PICM_HASH_INFO pHashInfo;
  9934. switch (pcmi->dwMsgType) {
  9935. case CMSG_SIGNED:
  9936. {
  9937. pc = (Any *)&pcmi->psdi->pci->content;
  9938. cb = pci->SerialNumber.cbData;
  9939. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  9940. goto SerialNumberAllocError;
  9941. cbIssuer = pci->Issuer.cbData;
  9942. for (pSignerNode=pcmi->psdi->pSignerList->Head();
  9943. pSignerNode;
  9944. pSignerNode = pSignerNode->Next()) {
  9945. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  9946. psib = NULL;
  9947. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  9948. pisn = NULL;
  9949. DataBlob = pSignerNode->Data()->blob;
  9950. if (0 != (Asn1Err = PkiAsn1Decode(
  9951. pDec,
  9952. (void **)&psib,
  9953. SignerInfoWithBlobs_PDU,
  9954. DataBlob.pbData,
  9955. DataBlob.cbData)))
  9956. goto DecodeSignerInfoWithBlobsError;
  9957. if (0 != (Asn1Err = PkiAsn1Decode(
  9958. pDec,
  9959. (void **)&pisn,
  9960. IssuerAndSerialNumber_PDU,
  9961. (BYTE *) psib->issuerAndSerialNumber.value,
  9962. psib->issuerAndSerialNumber.length)))
  9963. goto DecodeIssuerAndSerialNumberError;
  9964. if (pisn->issuer.length != cbIssuer)
  9965. continue;
  9966. if (0 != memcmp( pci->Issuer.pbData, pisn->issuer.value, cbIssuer))
  9967. continue;
  9968. // We need to add an integer method to compare big-endian
  9969. // internal to a little-endian external value.
  9970. if (pisn->serialNumber.length != cb)
  9971. continue;
  9972. ICM_ReverseCopy( pb, pisn->serialNumber.value, cb);
  9973. if (0 != memcmp( pb, pci->SerialNumber.pbData, cb))
  9974. continue;
  9975. break;
  9976. }
  9977. // The matching signer (if found) is in psib
  9978. // If no signer found, pSignerNode == NULL
  9979. ICM_FreeA( pb);
  9980. pb = NULL;
  9981. break;
  9982. }
  9983. case CMSG_SIGNED_AND_ENVELOPED:
  9984. goto MessageTypeNotSupportedYet;
  9985. default:
  9986. goto InvalidMsgType;
  9987. }
  9988. if (NULL == pSignerNode)
  9989. goto SignerNotFound;
  9990. if (!ICM_FindHashNodeFromEncodedAlgo(
  9991. pcmi->pHashList,
  9992. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  9993. &pnHash))
  9994. goto GetHashNodeFromEncodedAlgoError;
  9995. pHashInfo = pnHash->Data();
  9996. if (pcmi->fDefaultCryptProv)
  9997. hCryptProv = 0;
  9998. else
  9999. hCryptProv = pcmi->hCryptProv;
  10000. if (!ICM_GetVerifySignatureStuff(
  10001. pci,
  10002. &hCryptProv,
  10003. &hPubKey,
  10004. &dwPubKeyAlgId,
  10005. &dwPubKeyFlags)) goto GetSignatureStuffError;
  10006. if (psib->bit_mask & authAttributes_present) {
  10007. // find the message digest attr value
  10008. if (!ICM_GetAttrValue(
  10009. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  10010. &oidMessageDigest,
  10011. &anyValue))
  10012. goto FindAttrError;
  10013. // find the message digest octets
  10014. if (!Asn1UtilExtractContent(
  10015. (BYTE *) anyValue.value,
  10016. anyValue.length,
  10017. &cbMessageDigest,
  10018. (const BYTE **)&pbMessageDigest))
  10019. goto ExtractContentError;
  10020. // get the hash value computed on the data
  10021. if (!ICM_GetListHashValue( pnHash, &cb, &pbHash))
  10022. goto GetHashValueError;
  10023. // hash sizes equal?
  10024. if (cb != cbMessageDigest)
  10025. goto HashCompareSizeError;
  10026. // hash octets equal?
  10027. if (memcmp( pbMessageDigest, pbHash, cb))
  10028. goto HashCompareValueError;
  10029. // Now that we have verified the message digest octets,
  10030. // get the hash of the authenticated attributes.
  10031. // Should check the content type attribute as well.
  10032. if (!ICM_GetAttrsHash(
  10033. pHashInfo->dwAlgoCAPI,
  10034. hCryptProv,
  10035. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  10036. &hHashAttr))
  10037. goto GetAuthAttrsHashError;
  10038. hHash = hHashAttr;
  10039. } else {
  10040. if (!ICM_DupListHash( pnHash, hCryptProv, &hHashDup))
  10041. goto DupListHashError;
  10042. hHash = hHashDup;
  10043. }
  10044. // verify the hash, signature, and public key are consistent
  10045. fRet = ICM_VerifySignature(
  10046. hHash,
  10047. hPubKey,
  10048. dwPubKeyAlgId,
  10049. dwPubKeyFlags,
  10050. psib->encryptedDigest.value,
  10051. psib->encryptedDigest.length);
  10052. if (!fRet && hHashAttr) {
  10053. // The hash of the authenticated attributes failed.
  10054. // Maybe they hashed incorrectly-DER-encoded authenticated attributes
  10055. // and gave us that encoding. Hash and verify the actual encoding of
  10056. // the authattrs that they gave us. There is a bug in IE3.0 which hits
  10057. // this path, due to a bug in the then-current OSS libraries.
  10058. fRet = ICM_VerifySignatureAuthAttrBlob(
  10059. pcmi,
  10060. pSignerNode,
  10061. hCryptProv,
  10062. hPubKey,
  10063. pHashInfo->dwAlgoCAPI,
  10064. dwPubKeyAlgId,
  10065. dwPubKeyFlags,
  10066. psib->encryptedDigest.value,
  10067. psib->encryptedDigest.length);
  10068. }
  10069. if (!fRet)
  10070. goto VerifySignatureError;
  10071. CommonReturn:
  10072. ICM_FreeA( pb);
  10073. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  10074. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  10075. if (hPubKey)
  10076. CryptDestroyKey(hPubKey);
  10077. if (hHashAttr)
  10078. CryptDestroyHash( hHashAttr);
  10079. if (hHashDup)
  10080. CryptDestroyHash( hHashDup);
  10081. ICM_SetLastError(dwError);
  10082. return fRet;
  10083. ErrorReturn:
  10084. dwError = GetLastError();
  10085. // if (hHash && (0 == (pcmi->dwFlags & CMSG_DETACHED_FLAG)))
  10086. // CryptDestroyHash( hHash);
  10087. fRet = FALSE;
  10088. goto CommonReturn;
  10089. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  10090. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  10091. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  10092. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  10093. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  10094. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  10095. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  10096. SET_ERROR_VAR(DecodeIssuerAndSerialNumberError, PkiAsn1ErrToHr(Asn1Err))
  10097. SET_ERROR(SignerNotFound,CRYPT_E_SIGNER_NOT_FOUND)
  10098. TRACE_ERROR(SerialNumberAllocError) // error already set
  10099. TRACE_ERROR(GetHashValueError) // error already set
  10100. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  10101. TRACE_ERROR(GetSignatureStuffError) // error already set
  10102. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  10103. TRACE_ERROR(DupListHashError) // error already set
  10104. TRACE_ERROR(VerifySignatureError) // error already set
  10105. dwFlags;
  10106. }
  10107. #endif // CMS_PKCS7
  10108. //+-------------------------------------------------------------------------
  10109. // Verify a digest
  10110. //--------------------------------------------------------------------------
  10111. BOOL
  10112. WINAPI
  10113. ICM_ControlVerifyDigest(
  10114. IN PCRYPT_MSG_INFO pcmi,
  10115. IN DWORD dwFlags)
  10116. {
  10117. DWORD dwError = ERROR_SUCCESS;
  10118. BOOL fRet;
  10119. BYTE *pbComputedDigest = NULL;
  10120. DWORD cbComputedDigest = 0;
  10121. BYTE *pbDigest = NULL;
  10122. DWORD cbDigest = 0;
  10123. if (CMSG_HASHED != pcmi->dwMsgType)
  10124. goto InvalidMsgTypeError;
  10125. // get the computed digest
  10126. CryptMsgGetParam(
  10127. (HCRYPTMSG)pcmi,
  10128. CMSG_COMPUTED_HASH_PARAM,
  10129. 0, // dwIndex
  10130. NULL, // pvData
  10131. &cbComputedDigest);
  10132. if (0 == cbComputedDigest)
  10133. goto EmptyComputedDigestError;
  10134. if (NULL == (pbComputedDigest = (PBYTE)ICM_AllocA( cbComputedDigest)))
  10135. goto ComputedDigestAllocError;
  10136. if (!CryptMsgGetParam(
  10137. (HCRYPTMSG)pcmi,
  10138. CMSG_COMPUTED_HASH_PARAM,
  10139. 0, // dwIndex
  10140. pbComputedDigest,
  10141. &cbComputedDigest))
  10142. goto GetComputedDigestError;
  10143. // get the digest from the message
  10144. CryptMsgGetParam(
  10145. (HCRYPTMSG)pcmi,
  10146. CMSG_HASH_DATA_PARAM,
  10147. 0, // dwIndex
  10148. NULL, // pvData
  10149. &cbDigest);
  10150. if (0 == cbDigest)
  10151. goto EmptyDigestError;
  10152. if (NULL == (pbDigest = (PBYTE)ICM_AllocA( cbDigest)))
  10153. goto DigestAllocError;
  10154. if (!CryptMsgGetParam(
  10155. (HCRYPTMSG)pcmi,
  10156. CMSG_HASH_DATA_PARAM,
  10157. 0, // dwIndex
  10158. pbDigest,
  10159. &cbDigest))
  10160. goto GetDigestError;
  10161. // compare the computed digest to the digest from the message
  10162. if (cbComputedDigest != cbDigest)
  10163. goto DigestSizesUnequalError;
  10164. if (0 != memcmp( pbDigest, pbComputedDigest, cbDigest))
  10165. goto DigestsDifferError;
  10166. fRet = TRUE;
  10167. CommonReturn:
  10168. ICM_FreeA( pbComputedDigest);
  10169. ICM_FreeA( pbDigest);
  10170. ICM_SetLastError(dwError);
  10171. return fRet;
  10172. ErrorReturn:
  10173. dwError = GetLastError();
  10174. fRet = FALSE;
  10175. goto CommonReturn;
  10176. TRACE_ERROR(EmptyComputedDigestError) // error already set
  10177. TRACE_ERROR(ComputedDigestAllocError) // error already set
  10178. TRACE_ERROR(GetComputedDigestError) // error already set
  10179. TRACE_ERROR(EmptyDigestError) // error already set
  10180. TRACE_ERROR(DigestAllocError) // error already set
  10181. TRACE_ERROR(GetDigestError) // error already set
  10182. SET_ERROR(DigestSizesUnequalError,CRYPT_E_HASH_VALUE)
  10183. SET_ERROR(DigestsDifferError,CRYPT_E_HASH_VALUE)
  10184. SET_ERROR(InvalidMsgTypeError,CRYPT_E_INVALID_MSG_TYPE)
  10185. dwFlags;
  10186. }
  10187. #ifdef CMS_PKCS7
  10188. CmsRecipientInfos *
  10189. WINAPI
  10190. ICM_GetDecodedCmsRecipientInfos(
  10191. IN PCRYPT_MSG_INFO pcmi
  10192. )
  10193. {
  10194. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  10195. CmsRecipientInfos *pris = NULL;
  10196. if (pcmi->fEncoding)
  10197. goto InvalidMsgType;
  10198. if (pcsi && (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  10199. goto StreamMsgNotReadyError;
  10200. if (NULL == pcmi->pvMsg)
  10201. goto NotUpdated;
  10202. switch (pcmi->dwMsgType) {
  10203. case CMSG_ENVELOPED:
  10204. pris = &((CmsEnvelopedData *)pcmi->pvMsg)->recipientInfos;
  10205. break;
  10206. case CMSG_SIGNED_AND_ENVELOPED:
  10207. goto MessageTypeNotSupportedYet;
  10208. default:
  10209. goto InvalidMsgType;
  10210. }
  10211. CommonReturn:
  10212. return pris;
  10213. ErrorReturn:
  10214. goto CommonReturn;
  10215. SET_ERROR(InvalidMsgType, CRYPT_E_INVALID_MSG_TYPE)
  10216. SET_ERROR(NotUpdated, CRYPT_E_INVALID_MSG_TYPE)
  10217. SET_ERROR(StreamMsgNotReadyError, CRYPT_E_STREAM_MSG_NOT_READY)
  10218. SET_ERROR(MessageTypeNotSupportedYet, CRYPT_E_INVALID_MSG_TYPE)
  10219. }
  10220. BOOL
  10221. WINAPI
  10222. ICM_ConvertPkcsToCmsRecipientIndex(
  10223. IN PCRYPT_MSG_INFO pcmi,
  10224. IN DWORD dwPkcsIndex,
  10225. OUT DWORD *pdwCmsIndex
  10226. )
  10227. {
  10228. BOOL fRet;
  10229. CmsRecipientInfos *pris;
  10230. CmsRecipientInfo *pri;
  10231. DWORD dwCount;
  10232. DWORD dwCmsIndex;
  10233. DWORD i;
  10234. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10235. goto GetDecodedCmsRecipientsError;
  10236. dwCount = pris->count;
  10237. pri = pris->value;
  10238. dwCmsIndex = dwPkcsIndex;
  10239. i = 0;
  10240. for ( ; 0 < dwCount; dwCount--, pri++) {
  10241. if (keyTransRecipientInfo_chosen != pri->choice) {
  10242. // Advance past non KeyTrans recipients
  10243. dwCmsIndex++;
  10244. } else {
  10245. if (i == dwPkcsIndex)
  10246. goto SuccessReturn;
  10247. else
  10248. i++;
  10249. }
  10250. }
  10251. goto IndexTooBig;
  10252. SuccessReturn:
  10253. fRet = TRUE;
  10254. CommonReturn:
  10255. *pdwCmsIndex = dwCmsIndex;
  10256. return fRet;
  10257. ErrorReturn:
  10258. fRet = FALSE;
  10259. dwCmsIndex = 0xFFFFFFFF;
  10260. goto CommonReturn;
  10261. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10262. SET_ERROR(IndexTooBig, CRYPT_E_INVALID_INDEX)
  10263. }
  10264. BOOL
  10265. WINAPI
  10266. ICM_ConvertCmsToPkcsRecipientIndex(
  10267. IN PCRYPT_MSG_INFO pcmi,
  10268. IN DWORD dwCmsIndex,
  10269. OUT DWORD *pdwPkcsIndex
  10270. )
  10271. {
  10272. BOOL fRet;
  10273. CmsRecipientInfos *pris;
  10274. CmsRecipientInfo *pri;
  10275. DWORD dwCount;
  10276. DWORD dwPkcsIndex;
  10277. DWORD i;
  10278. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10279. goto GetDecodedCmsRecipientsError;
  10280. dwCount = pris->count;
  10281. if (dwCmsIndex >= dwCount)
  10282. goto InvalidCmsIndex;
  10283. pri = &pris->value[dwCmsIndex];
  10284. if (keyTransRecipientInfo_chosen != pri->choice)
  10285. goto InvalidPkcsIndex;
  10286. pri = pris->value;
  10287. dwPkcsIndex = 0;
  10288. for (i = 0; i < dwCmsIndex; i++, pri++) {
  10289. if (keyTransRecipientInfo_chosen == pri->choice)
  10290. dwPkcsIndex++;
  10291. }
  10292. fRet = TRUE;
  10293. CommonReturn:
  10294. *pdwPkcsIndex = dwPkcsIndex;
  10295. return fRet;
  10296. ErrorReturn:
  10297. fRet = FALSE;
  10298. dwPkcsIndex = 0xFFFFFFFF;
  10299. goto CommonReturn;
  10300. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10301. SET_ERROR(InvalidCmsIndex, CRYPT_E_INVALID_INDEX)
  10302. SET_ERROR(InvalidPkcsIndex, CRYPT_E_INVALID_INDEX)
  10303. }
  10304. BOOL
  10305. WINAPI
  10306. ICM_GetPkcsRecipientCount(
  10307. IN PCRYPT_MSG_INFO pcmi,
  10308. OUT DWORD *pdwPkcsCount
  10309. )
  10310. {
  10311. BOOL fRet;
  10312. CmsRecipientInfos *pris;
  10313. CmsRecipientInfo *pri;
  10314. DWORD dwCount;
  10315. DWORD dwPkcsCount;
  10316. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  10317. goto GetDecodedCmsRecipientsError;
  10318. dwCount = pris->count;
  10319. pri = pris->value;
  10320. dwPkcsCount = 0;
  10321. for ( ; 0 < dwCount; dwCount--, pri++) {
  10322. if (keyTransRecipientInfo_chosen == pri->choice)
  10323. dwPkcsCount++;
  10324. }
  10325. fRet = TRUE;
  10326. CommonReturn:
  10327. *pdwPkcsCount = dwPkcsCount;
  10328. return fRet;
  10329. ErrorReturn:
  10330. dwPkcsCount = 0;
  10331. fRet = FALSE;
  10332. goto CommonReturn;
  10333. TRACE_ERROR(GetDecodedCmsRecipientsError)
  10334. }
  10335. typedef BOOL (WINAPI *PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) (
  10336. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10337. IN void *pvDecryptPara,
  10338. IN DWORD dwFlags,
  10339. IN OPTIONAL void *pvReserved,
  10340. OUT HCRYPTKEY *phContentEncryptKey
  10341. );
  10342. BOOL
  10343. WINAPI
  10344. ICM_ImportContentEncryptKey(
  10345. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10346. IN void *pvDecryptPara,
  10347. IN HCRYPTOIDFUNCADDR hImportContentEncryptKeyFuncSet,
  10348. IN LPSTR pszKeyEncryptionOID,
  10349. IN PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY pDefaultImportContentEncryptKey,
  10350. OUT HCRYPTKEY *phContentEncryptKey
  10351. )
  10352. {
  10353. BOOL fRet;
  10354. DWORD i;
  10355. #define IMPORT_CONTENT_ENCRYPT_OID_CNT 3
  10356. LPSTR rgpszOID[IMPORT_CONTENT_ENCRYPT_OID_CNT] = {
  10357. NULL, // pszKeyEncryptOID!pszContentEncryptOID
  10358. pszKeyEncryptionOID,
  10359. pContentEncryptionAlgorithm->pszObjId
  10360. };
  10361. DWORD cch;
  10362. LPSTR psz;
  10363. cch = strlen(rgpszOID[1]) + 1 + strlen(rgpszOID[2]) + 1;
  10364. if (NULL == (psz = (LPSTR) ICM_Alloc(cch))) {
  10365. *phContentEncryptKey = 0;
  10366. return FALSE;
  10367. }
  10368. strcpy(psz, rgpszOID[1]);
  10369. strcat(psz, "!");
  10370. strcat(psz, rgpszOID[2]);
  10371. rgpszOID[0] = psz;
  10372. for (i = 0; i < IMPORT_CONTENT_ENCRYPT_OID_CNT; i++) {
  10373. void *pvFuncAddr;
  10374. HCRYPTOIDFUNCADDR hFuncAddr;
  10375. if (CryptGetOIDFunctionAddress(
  10376. hImportContentEncryptKeyFuncSet,
  10377. X509_ASN_ENCODING,
  10378. rgpszOID[i],
  10379. 0, // dwFlags
  10380. &pvFuncAddr,
  10381. &hFuncAddr)) {
  10382. fRet = ((PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) pvFuncAddr)(
  10383. pContentEncryptionAlgorithm,
  10384. pvDecryptPara,
  10385. 0, // dwFlags
  10386. NULL, // pvReserved
  10387. phContentEncryptKey
  10388. );
  10389. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  10390. if (fRet || E_NOTIMPL != GetLastError())
  10391. goto CommonReturn;
  10392. }
  10393. }
  10394. fRet = pDefaultImportContentEncryptKey(
  10395. pContentEncryptionAlgorithm,
  10396. pvDecryptPara,
  10397. 0, // dwFlags
  10398. NULL, // pvReserved
  10399. phContentEncryptKey
  10400. );
  10401. CommonReturn:
  10402. ICM_Free(rgpszOID[0]);
  10403. return fRet;
  10404. }
  10405. HCRYPTKEY
  10406. WINAPI
  10407. ICM_ImportEncryptedKey(
  10408. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10409. IN HCRYPTPROV hCryptProv,
  10410. IN HCRYPTKEY hUserKey,
  10411. IN ALG_ID aiEncAlg,
  10412. IN BYTE bType,
  10413. IN PCRYPT_DATA_BLOB pEncryptedKey
  10414. )
  10415. {
  10416. BOOL fRet;
  10417. DWORD dwError;
  10418. HCRYPTKEY hEncryptKey = 0;
  10419. DWORD dwAlgIdEncrypt;
  10420. DWORD dwBitLen;
  10421. BYTE rgbIV[IV_MAX_LENGTH];
  10422. DWORD cbIV;
  10423. PBYTE pbCspKey = NULL;
  10424. DWORD cbCspKey;
  10425. PUBLICKEYSTRUC *ppks;
  10426. PSIMPLEBLOBHEADER psbh;
  10427. if (!ICM_GetEncryptParameters(
  10428. pContentEncryptionAlgorithm,
  10429. &dwAlgIdEncrypt,
  10430. &dwBitLen,
  10431. rgbIV,
  10432. &cbIV))
  10433. goto GetEncryptParametersError;
  10434. cbCspKey = sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER) +
  10435. pEncryptedKey->cbData;
  10436. if (NULL == (pbCspKey = (PBYTE)ICM_AllocA( cbCspKey)))
  10437. goto CspKeyAllocError;
  10438. ppks = (PUBLICKEYSTRUC *)pbCspKey;
  10439. ppks->bType = bType;
  10440. ppks->bVersion = CUR_BLOB_VERSION;
  10441. ppks->reserved = 0;
  10442. ppks->aiKeyAlg = dwAlgIdEncrypt;
  10443. psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
  10444. psbh->aiEncAlg = aiEncAlg;
  10445. if (SYMMETRICWRAPKEYBLOB == bType)
  10446. memcpy( (PBYTE)(psbh+1), pEncryptedKey->pbData,
  10447. pEncryptedKey->cbData);
  10448. else
  10449. ICM_ReverseCopy( (PBYTE)(psbh+1), pEncryptedKey->pbData,
  10450. pEncryptedKey->cbData);
  10451. fRet = CryptImportKey(
  10452. hCryptProv,
  10453. pbCspKey,
  10454. cbCspKey,
  10455. hUserKey,
  10456. CRYPT_NO_SALT, // dwFlags
  10457. &hEncryptKey);
  10458. if (!fRet) {
  10459. hEncryptKey = 0;
  10460. goto ImportKeyFailed;
  10461. }
  10462. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  10463. // Silently ignore any errors. Not supported in earlier versions
  10464. CryptSetKeyParam(
  10465. hEncryptKey,
  10466. KP_EFFECTIVE_KEYLEN,
  10467. (PBYTE) &dwBitLen,
  10468. 0); // dwFlags
  10469. if (0 != cbIV) {
  10470. if (CALG_RC4 == dwAlgIdEncrypt) {
  10471. // For RC4, set the SALT, not the IV
  10472. BOOL fRC4Salt = TRUE;
  10473. if (IV_LENGTH == cbIV) {
  10474. // Old implementations of 40 bit or 128 bit RC4 set the
  10475. // IV which was ignored and didn't set the salt.
  10476. // Get the bit length of the imported key and don't
  10477. // set the salt for 40 or 128 bit RC4.
  10478. DWORD dwRC4BitLen;
  10479. DWORD cbKeyParamLen;
  10480. dwRC4BitLen = 0;
  10481. cbKeyParamLen = sizeof(dwRC4BitLen);
  10482. if (!CryptGetKeyParam(
  10483. hEncryptKey,
  10484. KP_KEYLEN,
  10485. (PBYTE) &dwRC4BitLen,
  10486. &cbKeyParamLen,
  10487. 0 // dwFlags
  10488. ) || 40 == dwRC4BitLen || 128 == dwRC4BitLen)
  10489. fRC4Salt = FALSE;
  10490. }
  10491. if (fRC4Salt) {
  10492. CRYPT_DATA_BLOB SaltBlob;
  10493. SaltBlob.pbData = rgbIV;
  10494. SaltBlob.cbData = cbIV;
  10495. if (!CryptSetKeyParam(
  10496. hEncryptKey,
  10497. KP_SALT_EX,
  10498. (PBYTE) &SaltBlob,
  10499. 0)) // dwFlags
  10500. goto SetSaltExError;
  10501. }
  10502. } else {
  10503. if (!CryptSetKeyParam(
  10504. hEncryptKey,
  10505. KP_IV,
  10506. rgbIV,
  10507. 0)) // dwFlags
  10508. goto SetIVError;
  10509. }
  10510. }
  10511. CommonReturn:
  10512. ICM_FreeA(pbCspKey);
  10513. return hEncryptKey;
  10514. ErrorReturn:
  10515. if (hEncryptKey) {
  10516. dwError = GetLastError();
  10517. CryptDestroyKey(hEncryptKey);
  10518. SetLastError(dwError);
  10519. hEncryptKey = 0;
  10520. }
  10521. goto CommonReturn;
  10522. TRACE_ERROR(GetEncryptParametersError)
  10523. TRACE_ERROR(ImportKeyFailed)
  10524. TRACE_ERROR(CspKeyAllocError)
  10525. TRACE_ERROR(SetSaltExError)
  10526. TRACE_ERROR(SetIVError)
  10527. }
  10528. //+-------------------------------------------------------------------------
  10529. //--------------------------------------------------------------------------
  10530. BOOL
  10531. WINAPI
  10532. #ifdef DEBUG_CRYPT_ASN1
  10533. ICMTest_DefaultImportKeyTrans(
  10534. #else
  10535. ICM_DefaultImportKeyTrans(
  10536. #endif
  10537. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10538. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  10539. IN DWORD dwFlags,
  10540. IN OPTIONAL void *pvReserved,
  10541. OUT HCRYPTKEY *phContentEncryptKey
  10542. )
  10543. {
  10544. DWORD dwError = ERROR_SUCCESS;
  10545. BOOL fRet;
  10546. HCRYPTKEY hUserKey = 0;
  10547. PCMSG_KEY_TRANS_RECIPIENT_INFO pri = pKeyTransDecryptPara->pKeyTrans;
  10548. HCRYPTPROV hCryptProv = pKeyTransDecryptPara->hCryptProv;
  10549. void *pvFuncAddr;
  10550. HCRYPTOIDFUNCADDR hFuncAddr;
  10551. if (CryptGetOIDFunctionAddress(
  10552. hOldStyleImportEncryptKeyFuncSet,
  10553. X509_ASN_ENCODING,
  10554. pContentEncryptionAlgorithm->pszObjId,
  10555. 0, // dwFlags
  10556. &pvFuncAddr,
  10557. &hFuncAddr)) {
  10558. if ((void *) ICM_DefaultImportEncryptKey == pvFuncAddr)
  10559. fRet = FALSE;
  10560. #ifdef DEBUG_CRYPT_ASN1
  10561. else if (0 == (ICMTest_GetDebugCryptAsn1Flags() &
  10562. DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  10563. fRet = FALSE;
  10564. #endif // DEBUG_CRYPT_ASN1
  10565. else
  10566. fRet = ((PFN_CMSG_IMPORT_ENCRYPT_KEY) pvFuncAddr)(
  10567. hCryptProv,
  10568. pKeyTransDecryptPara->dwKeySpec,
  10569. pContentEncryptionAlgorithm,
  10570. &pri->KeyEncryptionAlgorithm,
  10571. pri->EncryptedKey.pbData,
  10572. pri->EncryptedKey.cbData,
  10573. phContentEncryptKey);
  10574. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  10575. if (fRet)
  10576. return TRUE;
  10577. }
  10578. if (0 != pKeyTransDecryptPara->dwKeySpec) {
  10579. // Get private key to use.
  10580. if (!CryptGetUserKey(
  10581. hCryptProv,
  10582. pKeyTransDecryptPara->dwKeySpec,
  10583. &hUserKey)) {
  10584. hUserKey = 0;
  10585. goto GetUserKeyFailed;
  10586. }
  10587. }
  10588. // else
  10589. // Use the provider's default private key for decrypting
  10590. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10591. pContentEncryptionAlgorithm,
  10592. hCryptProv,
  10593. hUserKey,
  10594. CALG_RSA_KEYX,
  10595. SIMPLEBLOB,
  10596. &pri->EncryptedKey
  10597. )))
  10598. goto ImportEncryptedKeyError;
  10599. fRet = TRUE;
  10600. CommonReturn:
  10601. if (hUserKey)
  10602. CryptDestroyKey(hUserKey);
  10603. ICM_SetLastError(dwError);
  10604. return fRet;
  10605. ErrorReturn:
  10606. dwError = GetLastError();
  10607. fRet = FALSE;
  10608. goto CommonReturn;
  10609. TRACE_ERROR(GetUserKeyFailed)
  10610. TRACE_ERROR(ImportEncryptedKeyError)
  10611. }
  10612. //+-------------------------------------------------------------------------
  10613. //--------------------------------------------------------------------------
  10614. BOOL
  10615. WINAPI
  10616. ICM_DefaultImportKeyAgree(
  10617. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10618. IN PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA pKeyAgreeDecryptPara,
  10619. IN DWORD dwFlags,
  10620. IN OPTIONAL void *pvReserved,
  10621. OUT HCRYPTKEY *phContentEncryptKey
  10622. )
  10623. {
  10624. BOOL fRet;
  10625. DWORD dwError = ERROR_SUCCESS;
  10626. HCRYPTPROV hKeyAgreeProv = 0; // Doesn't need to be released
  10627. HCRYPTKEY hMyKey = 0;
  10628. HCRYPTKEY hAgreeKey = 0;
  10629. DWORD cbP;
  10630. DWORD dwKeySpec;
  10631. LPSTR pszWrapOID = NULL;
  10632. DWORD dwAlgIdWrap;
  10633. DWORD dwBitLen;
  10634. PCMSG_KEY_AGREE_RECIPIENT_INFO pri = pKeyAgreeDecryptPara->pKeyAgree;
  10635. hKeyAgreeProv = pKeyAgreeDecryptPara->hCryptProv;
  10636. dwKeySpec = pKeyAgreeDecryptPara->dwKeySpec;
  10637. if (0 == dwKeySpec)
  10638. dwKeySpec = AT_KEYEXCHANGE;
  10639. // Get my private Diffie Hellman key
  10640. if (!CryptGetUserKey(
  10641. hKeyAgreeProv,
  10642. pKeyAgreeDecryptPara->dwKeySpec,
  10643. &hMyKey)) {
  10644. hMyKey = 0;
  10645. goto GetMyKeyFailed;
  10646. }
  10647. // Get the length of P
  10648. cbP = 0;
  10649. if (!CryptGetKeyParam(
  10650. hMyKey,
  10651. KP_P,
  10652. NULL, // pbData
  10653. &cbP,
  10654. 0 // dwFlags
  10655. ) || 0 == cbP)
  10656. goto GetPLengthError;
  10657. if (!ICM_GetDhWrapEncryptParameters(
  10658. &pri->KeyEncryptionAlgorithm,
  10659. &pszWrapOID, // allocated
  10660. &dwAlgIdWrap,
  10661. &dwBitLen))
  10662. goto GetDhWrapEncryptParametersError;
  10663. if (0 == (hAgreeKey = ICM_ImportDhAgreeKey(
  10664. hKeyAgreeProv,
  10665. hMyKey,
  10666. cbP,
  10667. &pKeyAgreeDecryptPara->OriginatorPublicKey,
  10668. pszWrapOID,
  10669. dwAlgIdWrap,
  10670. dwBitLen,
  10671. &pri->UserKeyingMaterial
  10672. )))
  10673. goto ImportDhAgreeKeyError;
  10674. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10675. pContentEncryptionAlgorithm,
  10676. hKeyAgreeProv,
  10677. hAgreeKey,
  10678. dwAlgIdWrap,
  10679. SYMMETRICWRAPKEYBLOB,
  10680. &pri->rgpRecipientEncryptedKeys[
  10681. pKeyAgreeDecryptPara->dwRecipientEncryptedKeyIndex]->EncryptedKey
  10682. )))
  10683. goto ImportEncryptedKeyError;
  10684. fRet = TRUE;
  10685. CommonReturn:
  10686. ICM_Free(pszWrapOID);
  10687. if (hAgreeKey)
  10688. CryptDestroyKey(hAgreeKey);
  10689. if (hMyKey)
  10690. CryptDestroyKey(hMyKey);
  10691. ICM_SetLastError(dwError);
  10692. return fRet;
  10693. ErrorReturn:
  10694. dwError = GetLastError();
  10695. fRet = FALSE;
  10696. goto CommonReturn;
  10697. TRACE_ERROR(GetMyKeyFailed)
  10698. TRACE_ERROR(GetPLengthError)
  10699. TRACE_ERROR(GetDhWrapEncryptParametersError)
  10700. TRACE_ERROR(ImportDhAgreeKeyError)
  10701. TRACE_ERROR(ImportEncryptedKeyError)
  10702. }
  10703. //+-------------------------------------------------------------------------
  10704. //--------------------------------------------------------------------------
  10705. BOOL
  10706. WINAPI
  10707. ICM_DefaultImportMailList(
  10708. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  10709. IN PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA pMailListDecryptPara,
  10710. IN DWORD dwFlags,
  10711. IN OPTIONAL void *pvReserved,
  10712. OUT HCRYPTKEY *phContentEncryptKey
  10713. )
  10714. {
  10715. BOOL fRet;
  10716. DWORD dwError = ERROR_SUCCESS;
  10717. HCRYPTPROV hMailListProv = 0; // not released
  10718. HCRYPTKEY hKeyEncryptionKey = 0; // not destroyed
  10719. PCMSG_MAIL_LIST_RECIPIENT_INFO pri = pMailListDecryptPara->pMailList;
  10720. DWORD dwAlgIdEncrypt;
  10721. DWORD dwBitLen;
  10722. hMailListProv = pMailListDecryptPara->hCryptProv;
  10723. switch (pMailListDecryptPara->dwKeyChoice) {
  10724. case CMSG_MAIL_LIST_HANDLE_KEY_CHOICE:
  10725. hKeyEncryptionKey = pMailListDecryptPara->hKeyEncryptionKey;
  10726. assert(hMailListProv && hKeyEncryptionKey);
  10727. if (0 == hMailListProv || 0 == hKeyEncryptionKey)
  10728. goto InvalidMailListHandleKeyPara;
  10729. break;
  10730. default:
  10731. goto InvalidMailListKeyChoice;
  10732. }
  10733. if (!ICM_GetWrapEncryptParameters(
  10734. &pri->KeyEncryptionAlgorithm,
  10735. &dwAlgIdEncrypt,
  10736. &dwBitLen))
  10737. goto GetWrapEncryptParametersError;
  10738. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  10739. // Silently ignore any errors. Not supported in earlier versions
  10740. CryptSetKeyParam(
  10741. hKeyEncryptionKey,
  10742. KP_EFFECTIVE_KEYLEN,
  10743. (PBYTE) &dwBitLen,
  10744. 0); // dwFlags
  10745. if (0 == (*phContentEncryptKey = ICM_ImportEncryptedKey(
  10746. pContentEncryptionAlgorithm,
  10747. hMailListProv,
  10748. hKeyEncryptionKey,
  10749. dwAlgIdEncrypt,
  10750. SYMMETRICWRAPKEYBLOB,
  10751. &pri->EncryptedKey
  10752. )))
  10753. goto ImportEncryptedKeyError;
  10754. fRet = TRUE;
  10755. CommonReturn:
  10756. ICM_SetLastError(dwError);
  10757. return fRet;
  10758. ErrorReturn:
  10759. dwError = GetLastError();
  10760. fRet = FALSE;
  10761. goto CommonReturn;
  10762. SET_ERROR(InvalidMailListHandleKeyPara, E_INVALIDARG)
  10763. SET_ERROR(InvalidMailListKeyChoice, E_INVALIDARG)
  10764. TRACE_ERROR(GetWrapEncryptParametersError)
  10765. TRACE_ERROR(ImportEncryptedKeyError)
  10766. }
  10767. //+-------------------------------------------------------------------------
  10768. // Default import of the encryption key (OldStyle)
  10769. //--------------------------------------------------------------------------
  10770. BOOL
  10771. WINAPI
  10772. ICM_DefaultImportEncryptKey(
  10773. IN HCRYPTPROV hCryptProv,
  10774. IN DWORD dwKeySpec,
  10775. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  10776. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  10777. IN PBYTE pbEncodedKey,
  10778. IN DWORD cbEncodedKey,
  10779. OUT HCRYPTKEY *phEncryptKey)
  10780. {
  10781. DWORD dwError = ERROR_SUCCESS;
  10782. BOOL fRet;
  10783. HCRYPTKEY hUserKey = 0;
  10784. CRYPT_DATA_BLOB EncryptedKey;
  10785. if (0 != dwKeySpec) {
  10786. // Get private key to use.
  10787. if (!CryptGetUserKey(
  10788. hCryptProv,
  10789. dwKeySpec,
  10790. &hUserKey)) {
  10791. hUserKey = 0;
  10792. goto GetUserKeyFailed;
  10793. }
  10794. }
  10795. // else
  10796. // Use the provider's default private key for decrypting
  10797. EncryptedKey.cbData = cbEncodedKey;
  10798. EncryptedKey.pbData = pbEncodedKey;
  10799. if (0 == (*phEncryptKey = ICM_ImportEncryptedKey(
  10800. paiEncrypt,
  10801. hCryptProv,
  10802. hUserKey,
  10803. CALG_RSA_KEYX,
  10804. SIMPLEBLOB,
  10805. &EncryptedKey
  10806. )))
  10807. goto ImportEncryptedKeyError;
  10808. fRet = TRUE;
  10809. CommonReturn:
  10810. if (hUserKey)
  10811. CryptDestroyKey(hUserKey);
  10812. ICM_SetLastError(dwError);
  10813. return fRet;
  10814. ErrorReturn:
  10815. dwError = GetLastError();
  10816. fRet = FALSE;
  10817. goto CommonReturn;
  10818. TRACE_ERROR(GetUserKeyFailed)
  10819. TRACE_ERROR(ImportEncryptedKeyError)
  10820. }
  10821. //+-------------------------------------------------------------------------
  10822. // Decrypt the content using any CMS recipient type
  10823. //--------------------------------------------------------------------------
  10824. BOOL
  10825. WINAPI
  10826. ICM_ControlCmsDecrypt(
  10827. IN PCRYPT_MSG_INFO pcmi,
  10828. IN DWORD dwFlags,
  10829. IN void *pvDecryptPara,
  10830. IN HCRYPTPROV hCryptProv,
  10831. IN DWORD dwRecipientIndex,
  10832. IN HCRYPTOIDFUNCADDR hImportContentEncryptKeyFuncSet,
  10833. IN LPSTR pszKeyEncryptionOID,
  10834. IN PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY pDefaultImportContentEncryptKey
  10835. )
  10836. {
  10837. DWORD dwError = ERROR_SUCCESS;
  10838. BOOL fRet;
  10839. EncryptedContentInfo *peci = NULL;
  10840. HCRYPTKEY hkeySeal = NULL;
  10841. PBYTE pbData = NULL;
  10842. LONG cbData;
  10843. AlgorithmIdentifier *paiOssContentEncryption;
  10844. PCRYPT_ALGORITHM_IDENTIFIER paiContentEncryption = NULL;
  10845. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  10846. if( pcmi->Plaintext.pbData)
  10847. goto MessageAlreadyDecrypted;
  10848. switch (pcmi->dwMsgType) {
  10849. case CMSG_ENVELOPED:
  10850. {
  10851. CmsEnvelopedData *ped;
  10852. ped = (CmsEnvelopedData *)pcmi->pvMsg;
  10853. if (NULL == ped)
  10854. goto NotUpdated;
  10855. if (dwRecipientIndex >= ped->recipientInfos.count)
  10856. goto RecipientIndexTooLarge;
  10857. peci = &ped->encryptedContentInfo;
  10858. paiOssContentEncryption =
  10859. &ped->encryptedContentInfo.contentEncryptionAlgorithm;
  10860. break;
  10861. }
  10862. case CMSG_SIGNED_AND_ENVELOPED:
  10863. goto MessageTypeNotSupportedYet;
  10864. default:
  10865. goto InvalidMsgType;
  10866. }
  10867. if (NULL == (paiContentEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  10868. paiOssContentEncryption)))
  10869. goto GetEncryptAlgorithmError;
  10870. if (!ICM_ImportContentEncryptKey(
  10871. paiContentEncryption,
  10872. pvDecryptPara,
  10873. hImportContentEncryptKeyFuncSet,
  10874. pszKeyEncryptionOID,
  10875. pDefaultImportContentEncryptKey,
  10876. &hkeySeal))
  10877. goto ImportKeyError;
  10878. if (pcsi) {
  10879. if (!ICMS_SetDecryptKey( pcmi, hkeySeal))
  10880. goto SetDecryptKeyError; // NB- Do not trash err from callback!
  10881. hkeySeal = NULL;
  10882. } else {
  10883. // NB- For common bulk encryption algos,
  10884. // sizeof(plaintext)<=sizeof(ciphertext)
  10885. if (peci->bit_mask & encryptedContent_present)
  10886. cbData = peci->encryptedContent.length;
  10887. else
  10888. cbData = 0;
  10889. if (NULL == (pbData = (PBYTE)ICM_Alloc( cbData)))
  10890. goto EncryptedContentAllocError;
  10891. if (cbData ) {
  10892. memcpy( pbData, peci->encryptedContent.value, cbData);
  10893. if (!CryptDecrypt(
  10894. hkeySeal,
  10895. NULL,
  10896. TRUE, // fFinal
  10897. 0, // dwFlags
  10898. pbData,
  10899. (PDWORD)&cbData))
  10900. goto DecryptError;
  10901. }
  10902. CryptDestroyKey( hkeySeal);
  10903. hkeySeal = NULL;
  10904. pcmi->Plaintext.cbData = cbData;
  10905. pcmi->Plaintext.pbData = pbData;
  10906. pbData = NULL;
  10907. }
  10908. if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
  10909. pcmi->hCryptProvContentCrypt = hCryptProv;
  10910. pcmi->dwDecryptedRecipientIndex = dwRecipientIndex;
  10911. fRet = TRUE;
  10912. CommonReturn:
  10913. ICM_Free(paiContentEncryption);
  10914. ICM_Free(pbData);
  10915. if (hkeySeal)
  10916. CryptDestroyKey( hkeySeal);
  10917. ICM_SetLastError(dwError);
  10918. return fRet;
  10919. ErrorReturn:
  10920. dwError = GetLastError();
  10921. fRet = FALSE;
  10922. goto CommonReturn;
  10923. SET_ERROR(MessageAlreadyDecrypted,CRYPT_E_ALREADY_DECRYPTED)
  10924. SET_ERROR(RecipientIndexTooLarge, CRYPT_E_INVALID_INDEX)
  10925. SET_ERROR(NotUpdated, CRYPT_E_INVALID_MSG_TYPE)
  10926. SET_ERROR(InvalidMsgType, CRYPT_E_INVALID_MSG_TYPE)
  10927. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  10928. TRACE_ERROR(GetEncryptAlgorithmError)
  10929. TRACE_ERROR(ImportKeyError)
  10930. TRACE_ERROR(EncryptedContentAllocError)
  10931. TRACE_ERROR(SetDecryptKeyError)
  10932. TRACE_ERROR(DecryptError)
  10933. }
  10934. //+-------------------------------------------------------------------------
  10935. // Decrypt the content using only a PKCS 1.5 recipient type
  10936. //--------------------------------------------------------------------------
  10937. BOOL
  10938. WINAPI
  10939. ICM_ControlPkcsDecrypt(
  10940. IN PCRYPT_MSG_INFO pcmi,
  10941. IN DWORD dwFlags,
  10942. IN PCMSG_CTRL_DECRYPT_PARA pmcdp
  10943. )
  10944. {
  10945. BOOL fRet;
  10946. CMSG_CTRL_KEY_TRANS_DECRYPT_PARA KeyTransDecryptPara;
  10947. PCMSG_CMS_RECIPIENT_INFO pRecipientInfo = NULL;
  10948. DWORD dwCmsIndex;
  10949. assert( pmcdp->cbSize >= sizeof(*pmcdp));
  10950. if (pmcdp->cbSize < sizeof(*pmcdp))
  10951. goto InvalidArg;
  10952. if (!ICM_ConvertPkcsToCmsRecipientIndex(
  10953. pcmi, pmcdp->dwRecipientIndex, &dwCmsIndex))
  10954. goto ConvertPkcsToCmsRecipientIndexError;
  10955. if (NULL == (pRecipientInfo =
  10956. (PCMSG_CMS_RECIPIENT_INFO) ICM_AllocAndGetParam(
  10957. pcmi, CMSG_CMS_RECIPIENT_INFO_PARAM, dwCmsIndex)))
  10958. goto GetCmsRecipientInfoParamError;
  10959. assert(CMSG_KEY_TRANS_RECIPIENT == pRecipientInfo->dwRecipientChoice);
  10960. memset(&KeyTransDecryptPara, 0, sizeof(KeyTransDecryptPara));
  10961. KeyTransDecryptPara.cbSize = sizeof(KeyTransDecryptPara);
  10962. KeyTransDecryptPara.hCryptProv = pmcdp->hCryptProv;
  10963. KeyTransDecryptPara.dwKeySpec = pmcdp->dwKeySpec;
  10964. KeyTransDecryptPara.pKeyTrans = pRecipientInfo->pKeyTrans;
  10965. KeyTransDecryptPara.dwRecipientIndex = dwCmsIndex;
  10966. fRet = ICM_ControlCmsDecrypt(
  10967. pcmi,
  10968. dwFlags,
  10969. &KeyTransDecryptPara,
  10970. KeyTransDecryptPara.hCryptProv,
  10971. dwCmsIndex,
  10972. hImportKeyTransFuncSet,
  10973. KeyTransDecryptPara.pKeyTrans->KeyEncryptionAlgorithm.pszObjId,
  10974. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyTrans
  10975. );
  10976. CommonReturn:
  10977. ICM_Free(pRecipientInfo);
  10978. return fRet;
  10979. ErrorReturn:
  10980. fRet = FALSE;
  10981. goto CommonReturn;
  10982. SET_ERROR(InvalidArg, E_INVALIDARG)
  10983. TRACE_ERROR(ConvertPkcsToCmsRecipientIndexError)
  10984. TRACE_ERROR(GetCmsRecipientInfoParamError)
  10985. }
  10986. #else
  10987. //+-------------------------------------------------------------------------
  10988. // Default import of the encryption key
  10989. //--------------------------------------------------------------------------
  10990. BOOL
  10991. WINAPI
  10992. ICM_DefaultImportEncryptKey(
  10993. IN HCRYPTPROV hCryptProv,
  10994. IN DWORD dwKeySpec,
  10995. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  10996. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  10997. IN PBYTE pbEncodedKey,
  10998. IN DWORD cbEncodedKey,
  10999. OUT HCRYPTKEY *phEncryptKey)
  11000. {
  11001. DWORD dwError = ERROR_SUCCESS;
  11002. BOOL fRet;
  11003. HCRYPTKEY hEncryptKey = 0;
  11004. HCRYPTKEY hUserKey = 0;
  11005. DWORD dwAlgIdEncrypt;
  11006. DWORD dwAlgIdPubKey;
  11007. PBYTE pbCspKey = NULL;
  11008. DWORD cbCspKey;
  11009. PUBLICKEYSTRUC *ppks;
  11010. PSIMPLEBLOBHEADER psbh;
  11011. BYTE rgbIV[IV_LENGTH];
  11012. DWORD cbIV;
  11013. DWORD dwBitLen;
  11014. if (!ICM_GetEncryptParameters(
  11015. paiEncrypt,
  11016. &dwAlgIdEncrypt,
  11017. &dwBitLen,
  11018. rgbIV,
  11019. &cbIV))
  11020. goto GetEncryptParametersError;
  11021. #if 0
  11022. if (!ICM_GetOssCAPI(
  11023. CRYPT_PUBKEY_ALG_OID_GROUP_ID,
  11024. paiPubKey,
  11025. &dwAlgIdPubKey))
  11026. goto PubKeyGetCAPIError;
  11027. #else
  11028. // We have no idea what the right values are for the alg id's here.
  11029. dwAlgIdPubKey = CALG_RSA_KEYX;
  11030. #endif
  11031. cbCspKey = cbEncodedKey + sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  11032. if (NULL == (pbCspKey = (PBYTE)ICM_AllocA( cbCspKey)))
  11033. goto CspKeyAllocError;
  11034. ppks = (PUBLICKEYSTRUC *)pbCspKey;
  11035. ppks->bType = SIMPLEBLOB;
  11036. ppks->bVersion = CUR_BLOB_VERSION;
  11037. ppks->reserved = 0;
  11038. ppks->aiKeyAlg = dwAlgIdEncrypt;
  11039. psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
  11040. psbh->aiEncAlg = dwAlgIdPubKey;
  11041. ICM_ReverseCopy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
  11042. if (0 != dwKeySpec) {
  11043. // Get private key to use.
  11044. if (!CryptGetUserKey(
  11045. hCryptProv,
  11046. dwKeySpec,
  11047. &hUserKey)) {
  11048. hUserKey = 0;
  11049. goto GetUserKeyFailed;
  11050. }
  11051. }
  11052. // else
  11053. // Use the provider's default private key for decrypting
  11054. fRet = CryptImportKey(
  11055. hCryptProv,
  11056. pbCspKey,
  11057. cbCspKey,
  11058. hUserKey,
  11059. CRYPT_NO_SALT, // dwFlags
  11060. &hEncryptKey);
  11061. if (!fRet) {
  11062. dwError = GetLastError();
  11063. if (hUserKey) {
  11064. if (NTE_BAD_FLAGS == dwError)
  11065. // Try without salt. Previous versions didn't support
  11066. // CRYPT_NO_SALT flag
  11067. fRet = CryptImportKey(
  11068. hCryptProv,
  11069. pbCspKey,
  11070. cbCspKey,
  11071. hUserKey,
  11072. 0, // dwFlags
  11073. &hEncryptKey);
  11074. if (!fRet) {
  11075. // Try without using the specified user key. Many versions of
  11076. // the CSP don't allow a non-null hUserKey parameter.
  11077. fRet = CryptImportKey(
  11078. hCryptProv,
  11079. pbCspKey,
  11080. cbCspKey,
  11081. 0, // hUserKey
  11082. CRYPT_NO_SALT, // dwFlags
  11083. &hEncryptKey);
  11084. if (!fRet)
  11085. dwError = GetLastError();
  11086. }
  11087. }
  11088. if (!fRet && NTE_BAD_FLAGS == dwError)
  11089. // Try without user key and without CRYPT_NO_SALT flag
  11090. fRet = CryptImportKey(
  11091. hCryptProv,
  11092. pbCspKey,
  11093. cbCspKey,
  11094. 0, // hUserKey
  11095. 0, // dwFlags
  11096. &hEncryptKey);
  11097. if (!fRet && 2 >= paiEncrypt->Parameters.cbData) {
  11098. // Try importing as an NT4.0 SP3 encypted key that wasn't byte
  11099. // reversed and with zero salt.
  11100. memcpy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
  11101. fRet = CryptImportKey(
  11102. hCryptProv,
  11103. pbCspKey,
  11104. cbCspKey,
  11105. hUserKey,
  11106. 0, // dwFlags
  11107. &hEncryptKey);
  11108. if (!fRet && hUserKey) {
  11109. // Try without using the specified user key.
  11110. fRet = CryptImportKey(
  11111. hCryptProv,
  11112. pbCspKey,
  11113. cbCspKey,
  11114. 0, // hUserKey
  11115. 0, // dwFlags
  11116. &hEncryptKey);
  11117. }
  11118. }
  11119. if (!fRet) {
  11120. hEncryptKey = 0;
  11121. goto ImportKeyFailed;
  11122. }
  11123. }
  11124. if (CALG_RC2 == dwAlgIdEncrypt && 0 != dwBitLen)
  11125. // Silently ignore any errors. Not supported in earlier versions
  11126. CryptSetKeyParam(
  11127. hEncryptKey,
  11128. KP_EFFECTIVE_KEYLEN,
  11129. (PBYTE) &dwBitLen,
  11130. 0); // dwFlags
  11131. if (0 != cbIV) {
  11132. if (!CryptSetKeyParam(
  11133. hEncryptKey,
  11134. KP_IV,
  11135. rgbIV,
  11136. 0)) // dwFlags
  11137. goto SetKeyParamError;
  11138. }
  11139. fRet = TRUE;
  11140. CommonReturn:
  11141. ICM_FreeA(pbCspKey);
  11142. if (hUserKey)
  11143. CryptDestroyKey(hUserKey);
  11144. ICM_SetLastError(dwError);
  11145. *phEncryptKey = hEncryptKey;
  11146. return fRet;
  11147. ErrorReturn:
  11148. dwError = GetLastError();
  11149. if (hEncryptKey) {
  11150. CryptDestroyKey(hEncryptKey);
  11151. hEncryptKey = 0;
  11152. }
  11153. fRet = FALSE;
  11154. goto CommonReturn;
  11155. TRACE_ERROR(GetEncryptParametersError)
  11156. //SET_ERROR(PubKeyGetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  11157. TRACE_ERROR(GetUserKeyFailed)
  11158. TRACE_ERROR(ImportKeyFailed)
  11159. TRACE_ERROR(CspKeyAllocError)
  11160. TRACE_ERROR(SetKeyParamError)
  11161. }
  11162. //+-------------------------------------------------------------------------
  11163. // Import the encryption key
  11164. //--------------------------------------------------------------------------
  11165. BOOL
  11166. WINAPI
  11167. ICM_ImportEncryptKey(
  11168. IN HCRYPTPROV hCryptProv,
  11169. IN DWORD dwKeySpec,
  11170. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  11171. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  11172. IN PBYTE pbEncodedKey,
  11173. IN DWORD cbEncodedKey,
  11174. OUT HCRYPTKEY *phEncryptKey)
  11175. {
  11176. BOOL fResult;
  11177. void *pvFuncAddr;
  11178. HCRYPTOIDFUNCADDR hFuncAddr;
  11179. if (CryptGetOIDFunctionAddress(
  11180. hImportEncryptKeyFuncSet,
  11181. X509_ASN_ENCODING,
  11182. paiEncrypt->pszObjId,
  11183. 0, // dwFlags
  11184. &pvFuncAddr,
  11185. &hFuncAddr)) {
  11186. fResult = ((PFN_CMSG_IMPORT_ENCRYPT_KEY) pvFuncAddr)(
  11187. hCryptProv,
  11188. dwKeySpec,
  11189. paiEncrypt,
  11190. paiPubKey,
  11191. pbEncodedKey,
  11192. cbEncodedKey,
  11193. phEncryptKey);
  11194. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  11195. } else
  11196. fResult = ICM_DefaultImportEncryptKey(
  11197. hCryptProv,
  11198. dwKeySpec,
  11199. paiEncrypt,
  11200. paiPubKey,
  11201. pbEncodedKey,
  11202. cbEncodedKey,
  11203. phEncryptKey);
  11204. return fResult;
  11205. }
  11206. //+-------------------------------------------------------------------------
  11207. // Decrypt the content
  11208. //--------------------------------------------------------------------------
  11209. BOOL
  11210. WINAPI
  11211. ICM_ControlDecrypt(
  11212. IN PCRYPT_MSG_INFO pcmi,
  11213. IN DWORD dwFlags,
  11214. IN void *pvCtrlPara)
  11215. {
  11216. DWORD dwError = ERROR_SUCCESS;
  11217. BOOL fRet;
  11218. PCMSG_CTRL_DECRYPT_PARA pmcdp;
  11219. RecipientInfo *pri = NULL;
  11220. EncryptedContentInfo *peci = NULL;
  11221. HCRYPTKEY hkeySeal = NULL;
  11222. PBYTE pbData = NULL;
  11223. LONG cbData;
  11224. AlgorithmIdentifier *paiOssContentEncryption;
  11225. PCRYPT_ALGORITHM_IDENTIFIER paiContentEncryption = NULL;
  11226. AlgorithmIdentifier *paiOssKeyEncryption;
  11227. PCRYPT_ALGORITHM_IDENTIFIER paiKeyEncryption = NULL;
  11228. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  11229. pmcdp = (PCMSG_CTRL_DECRYPT_PARA)pvCtrlPara;
  11230. assert( pmcdp->cbSize >= sizeof(CMSG_CTRL_DECRYPT_PARA));
  11231. if (pmcdp->cbSize < sizeof(CMSG_CTRL_DECRYPT_PARA))
  11232. goto InvalidArg;
  11233. if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
  11234. pcmi->hCryptProvContentCrypt = pmcdp->hCryptProv;
  11235. if( pcmi->Plaintext.pbData)
  11236. goto MessageAlreadyDecrypted;
  11237. switch (pcmi->dwMsgType) {
  11238. case CMSG_ENVELOPED:
  11239. {
  11240. EnvelopedData *ped;
  11241. ped = (EnvelopedData *)pcmi->pvMsg;
  11242. peci = &ped->encryptedContentInfo;
  11243. if (pmcdp->dwRecipientIndex >= ped->recipientInfos.count)
  11244. goto RecipientIndexTooLarge;
  11245. pri = ped->recipientInfos.value + pmcdp->dwRecipientIndex;
  11246. paiOssContentEncryption =
  11247. &ped->encryptedContentInfo.contentEncryptionAlgorithm;
  11248. paiOssKeyEncryption = &pri->keyEncryptionAlgorithm;
  11249. break;
  11250. }
  11251. case CMSG_SIGNED_AND_ENVELOPED:
  11252. goto MessageTypeNotSupportedYet;
  11253. default:
  11254. goto InvalidMsgType;
  11255. }
  11256. if (NULL == pri)
  11257. goto RecipientNotFound; // really NULL if not found?
  11258. if (NULL == (paiContentEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  11259. paiOssContentEncryption)))
  11260. goto GetEncryptAlgorithmError;
  11261. if (NULL == (paiKeyEncryption = ICM_AllocAndGetALGORITHM_IDENTIFIER(
  11262. paiOssKeyEncryption)))
  11263. goto GetKeyAlgorithmError;
  11264. if (!ICM_ImportEncryptKey(
  11265. pmcdp->hCryptProv,
  11266. pmcdp->dwKeySpec,
  11267. paiContentEncryption,
  11268. paiKeyEncryption,
  11269. pri->encryptedKey.value,
  11270. pri->encryptedKey.length,
  11271. &hkeySeal))
  11272. goto ImportKeyError;
  11273. if (pcsi) {
  11274. if (!ICMS_SetDecryptKey( pcmi, hkeySeal))
  11275. goto SetDecryptKeyError; // NB- Do not trash err from callback!
  11276. hkeySeal = NULL;
  11277. } else {
  11278. // NB- For common bulk encryption algos,
  11279. // sizeof(plaintext)<=sizeof(ciphertext)
  11280. cbData = peci->encryptedContent.length;
  11281. if (NULL == (pbData = (PBYTE)ICM_Alloc( cbData)))
  11282. goto EncryptedContentAllocError;
  11283. memcpy( pbData, peci->encryptedContent.value, cbData);
  11284. if (!CryptDecrypt(
  11285. hkeySeal,
  11286. NULL,
  11287. TRUE, // fFinal
  11288. 0, // dwFlags
  11289. pbData,
  11290. (PDWORD)&cbData))
  11291. goto DecryptError;
  11292. CryptDestroyKey( hkeySeal);
  11293. hkeySeal = NULL;
  11294. pcmi->Plaintext.cbData = cbData;
  11295. pcmi->Plaintext.pbData = pbData;
  11296. pbData = NULL;
  11297. }
  11298. pcmi->dwDecryptedRecipientIndex = pmcdp->dwRecipientIndex;
  11299. fRet = TRUE;
  11300. CommonReturn:
  11301. ICM_Free(paiContentEncryption);
  11302. ICM_Free(paiKeyEncryption);
  11303. ICM_Free( pbData);
  11304. if (hkeySeal)
  11305. CryptDestroyKey( hkeySeal);
  11306. ICM_SetLastError(dwError);
  11307. return fRet;
  11308. ErrorReturn:
  11309. dwError = GetLastError();
  11310. fRet = FALSE;
  11311. goto CommonReturn;
  11312. SET_ERROR(InvalidArg,E_INVALIDARG)
  11313. SET_ERROR(MessageAlreadyDecrypted,CRYPT_E_ALREADY_DECRYPTED)
  11314. SET_ERROR(RecipientIndexTooLarge,CRYPT_E_INVALID_INDEX)
  11315. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  11316. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  11317. SET_ERROR(RecipientNotFound,CRYPT_E_RECIPIENT_NOT_FOUND)
  11318. TRACE_ERROR(GetEncryptAlgorithmError)
  11319. TRACE_ERROR(GetKeyAlgorithmError)
  11320. TRACE_ERROR(ImportKeyError)
  11321. TRACE_ERROR(EncryptedContentAllocError)
  11322. TRACE_ERROR(SetDecryptKeyError)
  11323. TRACE_ERROR(DecryptError)
  11324. }
  11325. #endif // CMS_PKCS7
  11326. //+-------------------------------------------------------------------------
  11327. // Hash the content of a message.
  11328. //--------------------------------------------------------------------------
  11329. BOOL
  11330. WINAPI
  11331. ICM_HashContent(
  11332. IN PCRYPT_MSG_INFO pcmi,
  11333. IN OUT HCRYPTHASH hHash)
  11334. {
  11335. DWORD dwError = ERROR_SUCCESS;
  11336. BOOL fRet;
  11337. HCRYPTMSG hCryptMsg = (HCRYPTMSG)pcmi;
  11338. PBYTE pbAllocData = NULL;
  11339. PBYTE pbData;
  11340. DWORD cbData;
  11341. cbData = 0;
  11342. CryptMsgGetParam(
  11343. hCryptMsg,
  11344. CMSG_CONTENT_PARAM,
  11345. 0, // dwIndex
  11346. NULL,
  11347. &cbData);
  11348. if (0 == cbData)
  11349. goto GetContentSizeError;
  11350. if (NULL == (pbAllocData = (PBYTE)ICM_Alloc(cbData)))
  11351. goto AllocContentError;
  11352. if (!CryptMsgGetParam(
  11353. hCryptMsg,
  11354. CMSG_CONTENT_PARAM,
  11355. 0, // dwIndex
  11356. pbAllocData,
  11357. &cbData))
  11358. goto GetContentError;
  11359. pbData = pbAllocData;
  11360. if (0 != strcmp(pszObjIdDataType, pcmi->psdi->pci->pszContentType)
  11361. #ifdef CMS_PKCS7
  11362. && pcmi->psdi->version < CMSG_SIGNED_DATA_CMS_VERSION
  11363. #endif // CMS_PKCS7
  11364. ) {
  11365. // Leading tag and length octets aren't included in the digest
  11366. if (0 > Asn1UtilExtractContent( pbData, cbData, &cbData,
  11367. (const BYTE **)&pbData))
  11368. goto ExtractContentError;
  11369. }
  11370. if (!ICM_UpdateDigest( hHash, pbData, cbData))
  11371. goto UpdateDigestError;
  11372. fRet = TRUE;
  11373. CommonReturn:
  11374. ICM_Free( pbAllocData);
  11375. ICM_SetLastError(dwError);
  11376. return fRet;
  11377. ErrorReturn:
  11378. dwError = GetLastError();
  11379. fRet = FALSE;
  11380. goto CommonReturn;
  11381. TRACE_ERROR(GetContentSizeError) // error already set
  11382. TRACE_ERROR(AllocContentError) // error already set
  11383. TRACE_ERROR(GetContentError) // error already set
  11384. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  11385. TRACE_ERROR(UpdateDigestError) // error already set
  11386. }
  11387. //+-------------------------------------------------------------------------
  11388. // Add a signer to a signed-data or signed-and-enveloped-data message.
  11389. //--------------------------------------------------------------------------
  11390. BOOL
  11391. WINAPI
  11392. ICM_ControlAddSigner(
  11393. IN OUT PCRYPT_MSG_INFO pcmi,
  11394. IN DWORD dwFlags,
  11395. IN PCMSG_SIGNER_ENCODE_INFO psei)
  11396. {
  11397. DWORD dwError = ERROR_SUCCESS;
  11398. BOOL fRet;
  11399. CHashNode *pnHash;
  11400. CSignerNode *pnSigner;
  11401. DWORD dwAlgoCAPI;
  11402. SignerInfo *psi = NULL;
  11403. Attribute *pAuthAttr;
  11404. DWORD cAuthAttr;
  11405. Attribute *pUnauthAttr;
  11406. DWORD cUnauthAttr;
  11407. LPSTR pszInnerContentObjID;
  11408. ICM_HASH_INFO HashInfo; ZEROSTRUCT(HashInfo);
  11409. AlgorithmIdentifier oaiHash;
  11410. CBlobNode *pnBlob;
  11411. CRYPT_DATA_BLOB blobHashAlgo; ZEROSTRUCT(blobHashAlgo);
  11412. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  11413. #ifdef CMS_PKCS7
  11414. SIGNER_ENCODE_DATA_INFO SignerEncodeDataInfo;
  11415. #endif // CMS_PKCS7
  11416. // if the hash algorithm matches one of the ones already in use,
  11417. // get that hash and encrypt it
  11418. // else
  11419. // hash the data again and add hash algo to top-level list
  11420. // [NB- must access data again]
  11421. // Search for a hash node with a matching hash algorithm
  11422. if (!(ICM_GetCAPI(
  11423. CRYPT_HASH_ALG_OID_GROUP_ID,
  11424. &psei->HashAlgorithm,
  11425. &dwAlgoCAPI) ||
  11426. ICM_GetCAPI(
  11427. CRYPT_SIGN_ALG_OID_GROUP_ID,
  11428. &psei->HashAlgorithm,
  11429. &dwAlgoCAPI)))
  11430. goto GetCAPIError;
  11431. // before, this could have never failed, but now it can
  11432. // only create a hash node if the hash didn't exists.
  11433. if (!ICM_FindHashNodeFromCapiAlgid( pcmi->pHashList, dwAlgoCAPI, &pnHash) &&
  11434. GetLastError() != CRYPT_E_UNKNOWN_ALGO)
  11435. goto FindHashNodeFromCapiAlgidError;
  11436. if (!pnHash) {
  11437. // New hash.
  11438. // 1. Create hash node
  11439. // 2. Hash the data
  11440. // 3. Add hash node to pcmi->pHashList
  11441. // 4. Encode this hash algo and add to pcmi->psdi->pAlgidList
  11442. HashInfo.dwAlgoCAPI = dwAlgoCAPI;
  11443. #ifndef CMS_PKCS7
  11444. HashInfo.hCryptProv = psei->hCryptProv;
  11445. #endif // CMS_PKCS7
  11446. if (!CryptCreateHash(
  11447. psei->hCryptProv,
  11448. HashInfo.dwAlgoCAPI,
  11449. NULL, // hKey - optional for MAC
  11450. 0, // dwFlags
  11451. &HashInfo.hHash))
  11452. goto CreateHashError;
  11453. if (!ICM_HashContent( pcmi, HashInfo.hHash)) // hash content
  11454. goto HashContentError;
  11455. if (NULL == (pnHash = new CHashNode))
  11456. goto NewHashNodeError;
  11457. pnHash->SetData( &HashInfo);
  11458. pcmi->pHashList->InsertTail( pnHash);
  11459. // Convert the hash algorithm to a blob and
  11460. // add to pcmi->psdi->pAlgidList.
  11461. if (!ICM_MsgAsn1ToAlgorithmIdentifier(
  11462. pcmi,
  11463. &psei->HashAlgorithm,
  11464. &oaiHash))
  11465. goto MsgAsn1ToAlgorithmIdentifierError;
  11466. if (!ICM_Asn1Encode(
  11467. AlgorithmIdentifier_PDU,
  11468. &oaiHash,
  11469. &blobHashAlgo))
  11470. goto EncodeHashAlgorithmError;
  11471. if (NULL == (pnBlob = new CBlobNode))
  11472. goto NewBlobNodeError;
  11473. pnBlob->SetData( &blobHashAlgo);
  11474. pcmi->psdi->pAlgidList->InsertTail( pnBlob);
  11475. }
  11476. // Alloc and fill in a SignerInfo
  11477. pszInnerContentObjID = pcmi->psdi->pci->pszContentType;
  11478. if (!strcmp( pszInnerContentObjID, pszObjIdDataType))
  11479. pszInnerContentObjID = NULL;
  11480. // NB - Each SignerInfo gets a non-empty authenticatedAttributes
  11481. // if the inner contentType is not data (passed in) or if
  11482. // there are authenticated attributes passed in. In this case,
  11483. // we reserve two Attribute slots at the beginning of the array
  11484. // for the content-type and message-digest Attribute values.
  11485. cAuthAttr = 0;
  11486. if (pszInnerContentObjID ||
  11487. psei->cAuthAttr ||
  11488. (dwFlags & CMSG_AUTHENTICATED_ATTRIBUTES_FLAG)) {
  11489. cAuthAttr = psei->cAuthAttr + 2; // reserve 2
  11490. }
  11491. cUnauthAttr = psei->cUnauthAttr;
  11492. psi = (SignerInfo *)ICM_AllocZero( sizeof( SignerInfo) +
  11493. cAuthAttr * sizeof( Attribute) +
  11494. cUnauthAttr * sizeof( Attribute)
  11495. );
  11496. if (NULL == psi)
  11497. goto SignerInfoAllocError;
  11498. pAuthAttr = (Attribute *)(psi + 1);
  11499. pUnauthAttr = pAuthAttr + cAuthAttr;
  11500. if (!ICM_FillAsnSignerInfo(
  11501. psei,
  11502. pcmi,
  11503. dwFlags,
  11504. pszInnerContentObjID,
  11505. psi,
  11506. &pAuthAttr,
  11507. &pUnauthAttr))
  11508. goto FillAsnSignerInfoError;
  11509. #ifdef CMS_PKCS7
  11510. SignerEncodeDataInfo.hCryptProv = psei->hCryptProv;
  11511. SignerEncodeDataInfo.dwKeySpec = psei->dwKeySpec;
  11512. SignerEncodeDataInfo.pHashNode = pnHash;
  11513. if (!ICM_FillSignerEncryptedDigest(
  11514. psi,
  11515. pszInnerContentObjID,
  11516. &SignerEncodeDataInfo,
  11517. FALSE)) // fMaxLength
  11518. goto FillSignerEncryptedDigestError;
  11519. #else
  11520. if (!ICM_FillSignerEncryptedDigest(
  11521. psi,
  11522. pszInnerContentObjID,
  11523. pnHash,
  11524. psei->dwKeySpec,
  11525. FALSE)) // fMaxLength
  11526. goto FillSignerEncryptedDigestError;
  11527. #endif // CMS_PKCS7
  11528. // Encode the signer and add to pcmi->psdi->pSignerList.
  11529. if (!ICM_Asn1Encode(
  11530. SignerInfo_PDU,
  11531. psi,
  11532. &sdi.blob))
  11533. goto EncodeSignerInfoError;
  11534. if (NULL == (pnSigner = new CSignerNode))
  11535. goto NewSignerInfoBlobNodeError;
  11536. pnSigner->SetData( &sdi);
  11537. pcmi->psdi->pSignerList->InsertTail( pnSigner);
  11538. fRet = TRUE;
  11539. CommonReturn:
  11540. if (psi) {
  11541. ICM_FreeAsnSignerInfo(psi);
  11542. ICM_Free(psi);
  11543. }
  11544. ICM_SetLastError(dwError);
  11545. return fRet;
  11546. ErrorReturn:
  11547. dwError = GetLastError();
  11548. ICM_Free(blobHashAlgo.pbData);
  11549. ICM_Free(sdi.blob.pbData);
  11550. if (HashInfo.hHash)
  11551. CryptDestroyHash(HashInfo.hHash);
  11552. fRet = FALSE;
  11553. goto CommonReturn;
  11554. SET_ERROR(GetCAPIError,CRYPT_E_UNKNOWN_ALGO)
  11555. SET_ERROR(NewHashNodeError,E_OUTOFMEMORY)
  11556. SET_ERROR(NewBlobNodeError,E_OUTOFMEMORY)
  11557. SET_ERROR(NewSignerInfoBlobNodeError,E_OUTOFMEMORY)
  11558. TRACE_ERROR(FindHashNodeFromCapiAlgidError) // error already set
  11559. TRACE_ERROR(CreateHashError) // error already set
  11560. TRACE_ERROR(HashContentError) // error already set
  11561. TRACE_ERROR(MsgAsn1ToAlgorithmIdentifierError) // error already set
  11562. TRACE_ERROR(EncodeHashAlgorithmError) // error already set
  11563. TRACE_ERROR(SignerInfoAllocError) // error already set
  11564. TRACE_ERROR(FillAsnSignerInfoError) // error already set
  11565. TRACE_ERROR(FillSignerEncryptedDigestError) // error already set
  11566. TRACE_ERROR(EncodeSignerInfoError) // error already set
  11567. }
  11568. //+-------------------------------------------------------------------------
  11569. // Add a CMS signer info to a signed-data message.
  11570. //--------------------------------------------------------------------------
  11571. BOOL
  11572. WINAPI
  11573. ICM_ControlAddCmsSignerInfo(
  11574. IN OUT PCRYPT_MSG_INFO pcmi,
  11575. IN DWORD dwFlags,
  11576. IN PCMSG_CMS_SIGNER_INFO psi)
  11577. {
  11578. BOOL fRet;
  11579. CSignerNode *pnSigner;
  11580. SIGNER_DATA_INFO sdi; ZEROSTRUCT(sdi);
  11581. // Encode the signer
  11582. if (!ICM_CmsSignerInfoEncode(
  11583. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  11584. CMS_SIGNER_INFO,
  11585. psi,
  11586. NULL, // pbEncoded
  11587. &sdi.blob.cbData
  11588. ))
  11589. goto EncodeSignerInfoError;
  11590. if (NULL == (sdi.blob.pbData = (PBYTE) ICM_Alloc(sdi.blob.cbData)))
  11591. goto OutOfMemory;
  11592. if (!ICM_CmsSignerInfoEncode(
  11593. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  11594. CMS_SIGNER_INFO,
  11595. psi,
  11596. sdi.blob.pbData,
  11597. &sdi.blob.cbData
  11598. ))
  11599. goto EncodeSignerInfoError;
  11600. // Add to pcmi->psdi->pSignerList.
  11601. if (NULL == (pnSigner = new CSignerNode))
  11602. goto NewSignerInfoBlobNodeError;
  11603. pnSigner->SetData( &sdi);
  11604. pcmi->psdi->pSignerList->InsertTail( pnSigner);
  11605. fRet = TRUE;
  11606. CommonReturn:
  11607. return fRet;
  11608. ErrorReturn:
  11609. ICM_Free(sdi.blob.pbData);
  11610. fRet = FALSE;
  11611. goto CommonReturn;
  11612. TRACE_ERROR(OutOfMemory)
  11613. TRACE_ERROR(EncodeSignerInfoError)
  11614. SET_ERROR(NewSignerInfoBlobNodeError,E_OUTOFMEMORY)
  11615. }
  11616. //+-------------------------------------------------------------------------
  11617. // Remove a signer from a signed-data or signed-and-enveloped-data message.
  11618. //--------------------------------------------------------------------------
  11619. BOOL
  11620. WINAPI
  11621. ICM_ControlDelSigner(
  11622. IN OUT PCRYPT_MSG_INFO pcmi,
  11623. IN DWORD dwFlags,
  11624. IN DWORD dwIndex)
  11625. {
  11626. BOOL fRet;
  11627. CSignerNode *pnSigner = pcmi->psdi->pSignerList->Nth( dwIndex);
  11628. if (NULL == pnSigner)
  11629. goto IndexTooLargeError;
  11630. pcmi->psdi->pSignerList->Remove( pnSigner);
  11631. delete pnSigner;
  11632. fRet = TRUE;
  11633. CommonReturn:
  11634. return fRet;
  11635. ErrorReturn:
  11636. fRet = FALSE;
  11637. goto CommonReturn;
  11638. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11639. dwFlags;
  11640. }
  11641. //+-------------------------------------------------------------------------
  11642. // Initialize the unauthenticated attributes list. Called before doing an
  11643. // add or delete.
  11644. //--------------------------------------------------------------------------
  11645. BOOL
  11646. WINAPI
  11647. ICM_InitUnauthAttrList(
  11648. IN CSignerNode *pnSigner
  11649. )
  11650. {
  11651. DWORD dwError = ERROR_SUCCESS;
  11652. BOOL fRet;
  11653. CBlobList *plBlob = NULL;
  11654. DWORD i;
  11655. SIGNER_DATA_INFO sdi;
  11656. SignerInfoWithAttrBlobs *posib = NULL;
  11657. Any *pAny;
  11658. ASN1error_e Asn1Err;
  11659. ASN1decoding_t pDec = ICM_GetDecoder();
  11660. assert(pnSigner);
  11661. sdi = *pnSigner->Data();
  11662. if (NULL == sdi.pUnauthAttrList) {
  11663. if (NULL == (plBlob = new CBlobList))
  11664. goto NewUnauthAttrListError;
  11665. if (0 != (Asn1Err = PkiAsn1Decode(
  11666. pDec,
  11667. (void **)&posib,
  11668. SignerInfoWithAttrBlobs_PDU,
  11669. sdi.blob.pbData,
  11670. sdi.blob.cbData)))
  11671. goto DecodeSignerInfoError;
  11672. if (posib->bit_mask & unauthAttributes_present) {
  11673. for (i=posib->unauthAttributes.count, pAny=posib->unauthAttributes.value;
  11674. i>0;
  11675. i--, pAny++)
  11676. if (!ICM_InsertTailBlob( plBlob, pAny))
  11677. goto InsertOldUnauthAttrBlobError;
  11678. }
  11679. sdi.pUnauthAttrList = plBlob;
  11680. pnSigner->SetData( &sdi);
  11681. }
  11682. fRet = TRUE;
  11683. CommonReturn:
  11684. PkiAsn1FreeInfo(pDec, SignerInfoWithAttrBlobs_PDU, posib);
  11685. ICM_SetLastError(dwError);
  11686. return fRet;
  11687. ErrorReturn:
  11688. dwError = GetLastError();
  11689. if (plBlob)
  11690. delete plBlob;
  11691. fRet = FALSE;
  11692. goto CommonReturn;
  11693. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  11694. SET_ERROR(NewUnauthAttrListError,E_OUTOFMEMORY)
  11695. TRACE_ERROR(InsertOldUnauthAttrBlobError) // error already set
  11696. }
  11697. //+-------------------------------------------------------------------------
  11698. // Add an unauthenticated attribute to a SignerInfo of a signed-data or
  11699. // signed-and-enveloped-data message.
  11700. //--------------------------------------------------------------------------
  11701. BOOL
  11702. WINAPI
  11703. ICM_ControlAddUnauthAttr(
  11704. IN PCRYPT_MSG_INFO pcmi,
  11705. IN DWORD dwFlags,
  11706. IN PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA pmcasuap)
  11707. {
  11708. BOOL fRet;
  11709. CSignerNode *pnSigner;
  11710. DWORD i;
  11711. for (i=pmcasuap->dwSignerIndex,
  11712. pnSigner=pcmi->psdi->pSignerList->Head();
  11713. (i>0) && pnSigner;
  11714. i--, pnSigner = pnSigner->Next())
  11715. ;
  11716. if (NULL == pnSigner)
  11717. goto IndexTooLargeError;
  11718. if (!ICM_InitUnauthAttrList(pnSigner))
  11719. goto InitUnauthAttrListError;
  11720. assert(pnSigner->Data()->pUnauthAttrList);
  11721. if (!ICM_InsertTailBlob( pnSigner->Data()->pUnauthAttrList,
  11722. (Any *)&pmcasuap->blob))
  11723. goto InsertUnauthAttrBlobError;
  11724. fRet = TRUE;
  11725. CommonReturn:
  11726. return fRet;
  11727. ErrorReturn:
  11728. fRet = FALSE;
  11729. goto CommonReturn;
  11730. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11731. TRACE_ERROR(InitUnauthAttrListError) // error already set
  11732. TRACE_ERROR(InsertUnauthAttrBlobError) // error already set
  11733. dwFlags;
  11734. }
  11735. //+-------------------------------------------------------------------------
  11736. // Delete an unauthenticated attribute from a SignerInfo of a signed-data or
  11737. // signed-and-enveloped-data message.
  11738. //--------------------------------------------------------------------------
  11739. BOOL
  11740. WINAPI
  11741. ICM_ControlDelUnauthAttr(
  11742. IN PCRYPT_MSG_INFO pcmi,
  11743. IN DWORD dwFlags,
  11744. IN PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA pmcdsuap)
  11745. {
  11746. BOOL fRet;
  11747. CSignerNode *pnSigner;
  11748. DWORD i;
  11749. for (i=pmcdsuap->dwSignerIndex,
  11750. pnSigner=pcmi->psdi->pSignerList->Head();
  11751. (i>0) && pnSigner;
  11752. i--, pnSigner = pnSigner->Next())
  11753. ;
  11754. if (NULL == pnSigner)
  11755. goto IndexTooLargeError;
  11756. if (!ICM_InitUnauthAttrList(pnSigner))
  11757. goto InitUnauthAttrListError;
  11758. assert(pnSigner->Data()->pUnauthAttrList);
  11759. if (!ICM_DelBlobByIndex(
  11760. pnSigner->Data()->pUnauthAttrList,
  11761. pmcdsuap->dwUnauthAttrIndex))
  11762. goto DelBlobByIndexError;
  11763. fRet = TRUE;
  11764. CommonReturn:
  11765. return fRet;
  11766. ErrorReturn:
  11767. fRet = FALSE;
  11768. goto CommonReturn;
  11769. SET_ERROR(IndexTooLargeError,CRYPT_E_INVALID_INDEX)
  11770. TRACE_ERROR(InitUnauthAttrListError) // error already set
  11771. TRACE_ERROR(DelBlobByIndexError) // error already set
  11772. dwFlags;
  11773. }
  11774. //+-------------------------------------------------------------------------
  11775. // Perform a special "control" function after the final CryptMsgUpdate of a
  11776. // encoded/decoded cryptographic message.
  11777. //
  11778. // The dwCtrlType parameter specifies the type of operation to be performed.
  11779. //
  11780. // The pvCtrlPara definition depends on the dwCtrlType value.
  11781. //
  11782. // See below for a list of the control operations and their pvCtrlPara
  11783. // type definition.
  11784. //--------------------------------------------------------------------------
  11785. BOOL
  11786. WINAPI
  11787. #ifdef DEBUG_CRYPT_ASN1_MASTER
  11788. ICMTest_NewCryptMsgControl(
  11789. #else
  11790. CryptMsgControl(
  11791. #endif
  11792. IN HCRYPTMSG hCryptMsg,
  11793. IN DWORD dwFlags,
  11794. IN DWORD dwCtrlType,
  11795. IN void const *pvCtrlPara)
  11796. {
  11797. BOOL fRet;
  11798. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  11799. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  11800. // Only support control for decoding
  11801. if (pcmi->fEncoding)
  11802. goto ControlForEncodingNotSupported;
  11803. switch (dwCtrlType) {
  11804. case CMSG_CTRL_VERIFY_SIGNATURE:
  11805. fRet = ICM_ControlVerifySignature(
  11806. pcmi,
  11807. dwFlags,
  11808. (PCERT_INFO)pvCtrlPara);
  11809. break;
  11810. #ifdef CMS_PKCS7
  11811. case CMSG_CTRL_VERIFY_SIGNATURE_EX:
  11812. fRet = ICM_ControlVerifySignatureEx(
  11813. pcmi,
  11814. dwFlags,
  11815. (PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA)pvCtrlPara);
  11816. break;
  11817. #endif // CMS_PKCS7
  11818. case CMSG_CTRL_DECRYPT:
  11819. #ifdef CMS_PKCS7
  11820. fRet = ICM_ControlPkcsDecrypt(
  11821. #else
  11822. fRet = ICM_ControlDecrypt(
  11823. #endif // CMS_PKCS7
  11824. pcmi,
  11825. dwFlags,
  11826. (PCMSG_CTRL_DECRYPT_PARA) pvCtrlPara);
  11827. break;
  11828. case CMSG_CTRL_VERIFY_HASH:
  11829. fRet = ICM_ControlVerifyDigest(
  11830. pcmi,
  11831. dwFlags);
  11832. break;
  11833. case CMSG_CTRL_ADD_SIGNER:
  11834. fRet = ICM_ControlAddSigner(
  11835. pcmi,
  11836. dwFlags,
  11837. (PCMSG_SIGNER_ENCODE_INFO)pvCtrlPara);
  11838. break;
  11839. case CMSG_CTRL_ADD_CMS_SIGNER_INFO:
  11840. fRet = ICM_ControlAddCmsSignerInfo(
  11841. pcmi,
  11842. dwFlags,
  11843. (PCMSG_CMS_SIGNER_INFO)pvCtrlPara);
  11844. break;
  11845. case CMSG_CTRL_DEL_SIGNER:
  11846. fRet = ICM_ControlDelSigner(
  11847. pcmi,
  11848. dwFlags,
  11849. *(PDWORD)pvCtrlPara);
  11850. break;
  11851. case CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR:
  11852. fRet = ICM_ControlAddUnauthAttr(
  11853. pcmi,
  11854. dwFlags,
  11855. (PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA)pvCtrlPara);
  11856. break;
  11857. case CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR:
  11858. fRet = ICM_ControlDelUnauthAttr(
  11859. pcmi,
  11860. dwFlags,
  11861. (PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA)pvCtrlPara);
  11862. break;
  11863. case CMSG_CTRL_ADD_CERT:
  11864. fRet = ICM_InsertTailBlob(
  11865. pcmi->psdi->pCertificateList,
  11866. (Any *)pvCtrlPara);
  11867. break;
  11868. case CMSG_CTRL_DEL_CERT:
  11869. {
  11870. DWORD dwIndex = *(PDWORD)pvCtrlPara;
  11871. #ifdef CMS_PKCS7
  11872. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  11873. // Advance index past attribute certs.
  11874. ICM_GetTaggedBlobAndAdvanceIndex(
  11875. pcmi->psdi->pCertificateList,
  11876. ICM_TAG_SEQ,
  11877. &dwIndex
  11878. );
  11879. #endif // CMS_PKCS7
  11880. fRet = ICM_DelBlobByIndex(
  11881. pcmi->psdi->pCertificateList,
  11882. dwIndex);
  11883. }
  11884. break;
  11885. #ifdef CMS_PKCS7
  11886. case CMSG_CTRL_ADD_ATTR_CERT:
  11887. {
  11888. Any *pAny = (Any *) pvCtrlPara;
  11889. Any AnyAttrCert;
  11890. BOOL fV3;
  11891. fV3 = (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION);
  11892. if (!(fV3 || 0 != strcmp(pszObjIdDataType,
  11893. pcmi->psdi->pci->pszContentType)))
  11894. goto InvalidMsgTypeToAddAttrCert;
  11895. AnyAttrCert.length = pAny->length;
  11896. if (0 == AnyAttrCert.length)
  11897. goto InvalidParamError;
  11898. if (NULL == (AnyAttrCert.value = (unsigned char*) ICM_Alloc(
  11899. AnyAttrCert.length)))
  11900. goto AllocError;
  11901. memcpy(AnyAttrCert.value, pAny->value, AnyAttrCert.length);
  11902. #ifdef OSS_CRYPT_ASN1
  11903. *AnyAttrCert.value = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  11904. #else
  11905. *((BYTE *) AnyAttrCert.value) = ICM_TAG_CONSTRUCTED_CONTEXT_1;
  11906. #endif // OSS_CRYPT_ASN1
  11907. fRet = ICM_InsertTailBlob(
  11908. pcmi->psdi->pCertificateList,
  11909. &AnyAttrCert);
  11910. if (fRet && !fV3)
  11911. pcmi->psdi->version = CMSG_SIGNED_DATA_CMS_VERSION;
  11912. ICM_Free(AnyAttrCert.value);
  11913. }
  11914. break;
  11915. case CMSG_CTRL_DEL_ATTR_CERT:
  11916. if (pcmi->psdi->version < CMSG_SIGNED_DATA_CMS_VERSION)
  11917. goto NoAttrCerts;
  11918. else {
  11919. DWORD dwIndex = *(PDWORD)pvCtrlPara;
  11920. // Advance index past certs.
  11921. ICM_GetTaggedBlobAndAdvanceIndex(
  11922. pcmi->psdi->pCertificateList,
  11923. ICM_TAG_CONSTRUCTED_CONTEXT_1,
  11924. &dwIndex
  11925. );
  11926. fRet = ICM_DelBlobByIndex(
  11927. pcmi->psdi->pCertificateList,
  11928. dwIndex);
  11929. }
  11930. break;
  11931. #endif // CMS_PKCS7
  11932. case CMSG_CTRL_ADD_CRL:
  11933. fRet = ICM_InsertTailBlob(
  11934. pcmi->psdi->pCrlList,
  11935. (Any *)pvCtrlPara);
  11936. break;
  11937. case CMSG_CTRL_DEL_CRL:
  11938. fRet = ICM_DelBlobByIndex(
  11939. pcmi->psdi->pCrlList,
  11940. *(PDWORD)pvCtrlPara);
  11941. break;
  11942. #ifdef CMS_PKCS7
  11943. case CMSG_CTRL_KEY_TRANS_DECRYPT:
  11944. {
  11945. PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pmcdp =
  11946. (PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA) pvCtrlPara;
  11947. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11948. if (pmcdp->cbSize < sizeof(*pmcdp))
  11949. goto InvalidArg;
  11950. fRet = ICM_ControlCmsDecrypt(
  11951. pcmi,
  11952. dwFlags,
  11953. pmcdp,
  11954. pmcdp->hCryptProv,
  11955. pmcdp->dwRecipientIndex,
  11956. hImportKeyTransFuncSet,
  11957. pmcdp->pKeyTrans->KeyEncryptionAlgorithm.pszObjId,
  11958. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyTrans
  11959. );
  11960. }
  11961. break;
  11962. case CMSG_CTRL_KEY_AGREE_DECRYPT:
  11963. {
  11964. PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA pmcdp =
  11965. (PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA) pvCtrlPara;
  11966. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11967. if (pmcdp->cbSize < sizeof(*pmcdp))
  11968. goto InvalidArg;
  11969. fRet = ICM_ControlCmsDecrypt(
  11970. pcmi,
  11971. dwFlags,
  11972. pmcdp,
  11973. pmcdp->hCryptProv,
  11974. pmcdp->dwRecipientIndex,
  11975. hImportKeyAgreeFuncSet,
  11976. pmcdp->pKeyAgree->KeyEncryptionAlgorithm.pszObjId,
  11977. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportKeyAgree
  11978. );
  11979. if (fRet)
  11980. pcmi->dwDecryptedRecipientEncryptedKeyIndex =
  11981. pmcdp->dwRecipientEncryptedKeyIndex;
  11982. }
  11983. break;
  11984. case CMSG_CTRL_MAIL_LIST_DECRYPT:
  11985. {
  11986. PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA pmcdp =
  11987. (PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA) pvCtrlPara;
  11988. assert(pmcdp->cbSize >= sizeof(*pmcdp));
  11989. if (pmcdp->cbSize < sizeof(*pmcdp))
  11990. goto InvalidArg;
  11991. fRet = ICM_ControlCmsDecrypt(
  11992. pcmi,
  11993. dwFlags,
  11994. pmcdp,
  11995. pmcdp->hCryptProv,
  11996. pmcdp->dwRecipientIndex,
  11997. hImportMailListFuncSet,
  11998. pmcdp->pMailList->KeyEncryptionAlgorithm.pszObjId,
  11999. (PFN_ICM_IMPORT_CONTENT_ENCRYPT_KEY) ICM_DefaultImportMailList
  12000. );
  12001. }
  12002. break;
  12003. #endif // CMS_PKCS7
  12004. default:
  12005. goto InvalidCtrlType;
  12006. }
  12007. CommonReturn:
  12008. ICM_Unlock( pcmi);
  12009. return fRet;
  12010. ErrorReturn:
  12011. fRet = FALSE;
  12012. goto CommonReturn;
  12013. SET_ERROR(ControlForEncodingNotSupported,E_INVALIDARG)
  12014. SET_ERROR(InvalidCtrlType,CRYPT_E_CONTROL_TYPE)
  12015. #ifdef CMS_PKCS7
  12016. SET_ERROR(InvalidMsgTypeToAddAttrCert,CRYPT_E_INVALID_MSG_TYPE)
  12017. SET_ERROR(InvalidParamError,E_INVALIDARG)
  12018. TRACE_ERROR(AllocError)
  12019. SET_ERROR(NoAttrCerts,CRYPT_E_INVALID_INDEX)
  12020. SET_ERROR(InvalidArg,E_INVALIDARG)
  12021. #endif // CMS_PKCS7
  12022. }
  12023. //+-------------------------------------------------------------------------
  12024. // Copy out a DWORD
  12025. //--------------------------------------------------------------------------
  12026. BOOL
  12027. WINAPI
  12028. ICM_GetDWORD(
  12029. IN DWORD dwValue,
  12030. OUT void *pvData,
  12031. IN OUT DWORD *pcbData)
  12032. {
  12033. return ICM_CopyOut(
  12034. (PBYTE)&dwValue,
  12035. sizeof(DWORD),
  12036. (PBYTE)pvData,
  12037. pcbData);
  12038. }
  12039. //+-------------------------------------------------------------------------
  12040. // Get Any
  12041. //--------------------------------------------------------------------------
  12042. BOOL
  12043. WINAPI
  12044. ICM_GetOssAny(
  12045. IN Any *pany,
  12046. OUT PCRYPT_DATA_BLOB pInfo,
  12047. IN OUT BYTE **ppbExtra,
  12048. IN OUT LONG *plRemainExtra)
  12049. {
  12050. BOOL fResult = TRUE;
  12051. LONG lRemainExtra = *plRemainExtra;
  12052. BYTE *pbExtra = *ppbExtra;
  12053. LONG lAlignExtra;
  12054. LONG lData;
  12055. BOOL fNULL = FALSE;
  12056. PBYTE pbValue;
  12057. pbValue = (PBYTE) pany->value;
  12058. if ((pany->length == 2) &&
  12059. (pbValue[0] == 0x05) &&
  12060. (pbValue[1] == 0x00)) {
  12061. // Detected NULL encoding. Map to NULL blob.
  12062. fNULL = TRUE;
  12063. }
  12064. lData = fNULL ? 0 : pany->length;
  12065. lAlignExtra = INFO_LEN_ALIGN(lData);
  12066. lRemainExtra -= lAlignExtra;
  12067. if (lRemainExtra >= 0) {
  12068. if ((lData > 0) && !fNULL) {
  12069. pInfo->pbData = pbExtra;
  12070. pInfo->cbData = (DWORD) lData;
  12071. memcpy( pbExtra, pany->value, lData);
  12072. } else {
  12073. memset(pInfo, 0, sizeof(*pInfo));
  12074. }
  12075. pbExtra += lAlignExtra;
  12076. }
  12077. *plRemainExtra = lRemainExtra;
  12078. *ppbExtra = pbExtra;
  12079. return fResult;
  12080. }
  12081. //+-------------------------------------------------------------------------
  12082. // Get the data for an Attributes
  12083. //--------------------------------------------------------------------------
  12084. BOOL
  12085. WINAPI
  12086. ICM_GetAnyData(
  12087. IN Any *pAny,
  12088. OUT void *pvData,
  12089. IN OUT DWORD *pcbData)
  12090. {
  12091. BOOL fRet;
  12092. LONG lData;
  12093. LONG lRemainExtra;
  12094. PBYTE pbExtra;
  12095. PCRYPT_DATA_BLOB pBlob = (PCRYPT_DATA_BLOB)pvData;
  12096. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12097. lData = INFO_LEN_ALIGN( sizeof(CRYPT_DATA_BLOB));
  12098. lRemainExtra = (LONG)*pcbData - lData;
  12099. if (0 > lRemainExtra) {
  12100. pBlob = NULL;
  12101. pbExtra = NULL;
  12102. } else {
  12103. pbExtra = (PBYTE)pBlob + lData;
  12104. }
  12105. if (!ICM_GetOssAny( pAny, pBlob, &pbExtra, &lRemainExtra))
  12106. goto GetOssAnyError;
  12107. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12108. CommonReturn:
  12109. return fRet;
  12110. ErrorReturn:
  12111. *pcbData = 0;
  12112. fRet = FALSE;
  12113. goto CommonReturn;
  12114. TRACE_ERROR(GetOssAnyError) // error already set
  12115. }
  12116. //+-------------------------------------------------------------------------
  12117. // Get Object Identifier string
  12118. //--------------------------------------------------------------------------
  12119. BOOL
  12120. WINAPI
  12121. ICM_GetOssObjId(
  12122. IN ObjectID *poi,
  12123. OUT LPSTR *ppszObjId,
  12124. IN OUT BYTE **ppbExtra,
  12125. IN OUT LONG *plRemainExtra)
  12126. {
  12127. BOOL fRet;
  12128. LONG lRemainExtra = *plRemainExtra;
  12129. BYTE *pbExtra = *ppbExtra;
  12130. LONG lAlignExtra;
  12131. LONG lObjId;
  12132. if (!PkiAsn1FromObjectIdentifier(
  12133. poi->count,
  12134. poi->value,
  12135. NULL,
  12136. (PDWORD)&lObjId))
  12137. goto PkiAsn1FromObjectIdentifierSizeError;
  12138. lAlignExtra = INFO_LEN_ALIGN(lObjId);
  12139. lRemainExtra -= lAlignExtra;
  12140. if (lRemainExtra >= 0) {
  12141. if(lObjId > 0) {
  12142. *ppszObjId = (LPSTR) pbExtra;
  12143. if (!PkiAsn1FromObjectIdentifier(
  12144. poi->count,
  12145. poi->value,
  12146. (LPSTR)pbExtra,
  12147. (PDWORD)&lObjId))
  12148. goto PkiAsn1FromObjectIdentifierError;
  12149. } else
  12150. *ppszObjId = NULL;
  12151. pbExtra += lAlignExtra;
  12152. }
  12153. fRet = TRUE;
  12154. CommonReturn:
  12155. *plRemainExtra = lRemainExtra;
  12156. *ppbExtra = pbExtra;
  12157. return fRet;
  12158. ErrorReturn:
  12159. *ppszObjId = NULL;
  12160. fRet = FALSE;
  12161. goto CommonReturn;
  12162. SET_ERROR(PkiAsn1FromObjectIdentifierSizeError,CRYPT_E_OID_FORMAT)
  12163. SET_ERROR(PkiAsn1FromObjectIdentifierError,CRYPT_E_OID_FORMAT)
  12164. }
  12165. //+-------------------------------------------------------------------------
  12166. // Get Oss HugeInteger
  12167. //--------------------------------------------------------------------------
  12168. void
  12169. inline
  12170. WINAPI
  12171. ICM_GetOssHugeInteger(
  12172. IN HugeIntegerType *pOssHugeInteger,
  12173. OUT PCRYPT_INTEGER_BLOB pHugeInteger,
  12174. IN OUT BYTE **ppbExtra,
  12175. IN OUT LONG *plRemainExtra
  12176. )
  12177. {
  12178. PkiAsn1GetHugeInteger(pOssHugeInteger->length, pOssHugeInteger->value, 0,
  12179. pHugeInteger, ppbExtra, plRemainExtra);
  12180. }
  12181. //+-------------------------------------------------------------------------
  12182. // Get an Attribute
  12183. //--------------------------------------------------------------------------
  12184. BOOL
  12185. WINAPI
  12186. ICM_GetOssAttribute(
  12187. IN Attribute *poatr,
  12188. OUT PCRYPT_ATTRIBUTE patr,
  12189. IN OUT BYTE **ppbExtra,
  12190. IN OUT LONG *plRemainExtra)
  12191. {
  12192. BOOL fRet;
  12193. LONG lData;
  12194. DWORD i;
  12195. Any *pAny;
  12196. PCRYPT_ATTR_BLOB patrbl = NULL;
  12197. if (!ICM_GetOssObjId(&poatr->attributeType, &patr->pszObjId,
  12198. ppbExtra, plRemainExtra))
  12199. goto GetOssObjIdError;
  12200. lData = INFO_LEN_ALIGN( poatr->attributeValue.count * sizeof(CRYPT_ATTR_BLOB));
  12201. *plRemainExtra -= lData;
  12202. if (0 < *plRemainExtra) {
  12203. patr->cValue = poatr->attributeValue.count;
  12204. patr->rgValue = patrbl = (PCRYPT_ATTR_BLOB)*ppbExtra;
  12205. *ppbExtra += lData;
  12206. }
  12207. for (i=poatr->attributeValue.count, pAny=poatr->attributeValue.value;
  12208. i>0;
  12209. i--, pAny++, patrbl++) {
  12210. if (!ICM_GetOssAny(pAny, patrbl, ppbExtra, plRemainExtra))
  12211. goto GetOssAnyError;
  12212. }
  12213. fRet = TRUE;
  12214. CommonReturn:
  12215. return fRet;
  12216. ErrorReturn:
  12217. fRet = FALSE;
  12218. goto CommonReturn;
  12219. TRACE_ERROR(GetOssObjIdError) // error already set
  12220. TRACE_ERROR(GetOssAnyError) // error already set
  12221. }
  12222. //+-------------------------------------------------------------------------
  12223. // Get an CRYPT_ATTRIBUTE
  12224. //--------------------------------------------------------------------------
  12225. BOOL
  12226. WINAPI
  12227. ICM_GetATTRIBUTE(
  12228. IN Attribute *poatr,
  12229. OUT void *pvData,
  12230. IN OUT DWORD *pcbData)
  12231. {
  12232. BOOL fRet;
  12233. LONG lData;
  12234. LONG lRemainExtra;
  12235. PBYTE pbExtra;
  12236. PCRYPT_ATTRIBUTE patr = (PCRYPT_ATTRIBUTE)pvData;
  12237. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12238. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ATTRIBUTE));
  12239. lRemainExtra = (LONG)*pcbData - lData;
  12240. if (0 > lRemainExtra) {
  12241. patr = NULL;
  12242. pbExtra = NULL;
  12243. } else {
  12244. pbExtra = (PBYTE)patr + lData;
  12245. }
  12246. if (!ICM_GetOssAttribute( poatr, patr, &pbExtra, &lRemainExtra))
  12247. goto GetOssAttributeError;
  12248. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12249. CommonReturn:
  12250. return fRet;
  12251. ErrorReturn:
  12252. *pcbData = 0;
  12253. fRet = FALSE;
  12254. goto CommonReturn;
  12255. TRACE_ERROR(GetOssAttributeError) // error already set
  12256. }
  12257. //+-------------------------------------------------------------------------
  12258. // Get an Attributes
  12259. //--------------------------------------------------------------------------
  12260. BOOL
  12261. WINAPI
  12262. ICM_GetOssAttributes(
  12263. IN Attributes *poatrs,
  12264. OUT PCRYPT_ATTRIBUTES patrs,
  12265. IN OUT BYTE **ppbExtra,
  12266. IN OUT LONG *plRemainExtra)
  12267. {
  12268. BOOL fRet;
  12269. LONG lData;
  12270. DWORD i;
  12271. Attribute *poatr;
  12272. PCRYPT_ATTRIBUTE patr;
  12273. lData = INFO_LEN_ALIGN( poatrs->count * sizeof(CRYPT_ATTRIBUTE));
  12274. *plRemainExtra -= lData;
  12275. if (0 < *plRemainExtra) {
  12276. patrs->cAttr = poatrs->count;
  12277. patrs->rgAttr = patr = (PCRYPT_ATTRIBUTE)*ppbExtra;
  12278. *ppbExtra += lData;
  12279. } else {
  12280. patr = NULL;
  12281. }
  12282. for (i=poatrs->count, poatr=poatrs->value;
  12283. i>0;
  12284. i--, poatr++, patr++) {
  12285. if (!ICM_GetOssAttribute( poatr, patr, ppbExtra, plRemainExtra))
  12286. goto GetOssAttributeError;
  12287. }
  12288. fRet = TRUE;
  12289. CommonReturn:
  12290. return fRet;
  12291. ErrorReturn:
  12292. fRet = FALSE;
  12293. goto CommonReturn;
  12294. TRACE_ERROR(GetOssAttributeError) // error already set
  12295. }
  12296. //+-------------------------------------------------------------------------
  12297. // Get from an Attributes in CList form
  12298. //--------------------------------------------------------------------------
  12299. BOOL
  12300. WINAPI
  12301. ICM_GetCListAttributes(
  12302. IN CBlobList *pBlobList,
  12303. OUT PCRYPT_ATTRIBUTES patrs,
  12304. IN OUT BYTE **ppbExtra,
  12305. IN OUT LONG *plRemainExtra)
  12306. {
  12307. DWORD dwError = ERROR_SUCCESS;
  12308. BOOL fRet;
  12309. LONG lData;
  12310. CBlobNode *pBlobNode;
  12311. AttributeNC2 *poatr = NULL;
  12312. PCRYPT_ATTRIBUTE patr;
  12313. ASN1error_e Asn1Err;
  12314. ASN1decoding_t pDec = ICM_GetDecoder();
  12315. PCRYPT_DATA_BLOB pDataBlob;
  12316. lData = INFO_LEN_ALIGN( pBlobList->Length() * sizeof(CRYPT_ATTRIBUTE));
  12317. *plRemainExtra -= lData;
  12318. if (0 < *plRemainExtra) {
  12319. patrs->cAttr = pBlobList->Length();
  12320. patrs->rgAttr = patr = (PCRYPT_ATTRIBUTE)*ppbExtra;
  12321. *ppbExtra += lData;
  12322. } else {
  12323. patr = NULL;
  12324. }
  12325. for (pBlobNode=pBlobList->Head();
  12326. pBlobNode;
  12327. pBlobNode=pBlobNode->Next(), patr++) {
  12328. poatr = NULL;
  12329. pDataBlob = pBlobNode->Data();
  12330. if (0 != (Asn1Err = PkiAsn1Decode(
  12331. pDec,
  12332. (void **)&poatr,
  12333. AttributeNC2_PDU,
  12334. pDataBlob->pbData,
  12335. pDataBlob->cbData)))
  12336. goto DecodeAttributeNC2Error;
  12337. if (!ICM_GetOssAttribute(
  12338. (Attribute *)poatr, // same, except for NOCOPY
  12339. patr,
  12340. ppbExtra,
  12341. plRemainExtra))
  12342. goto GetOssAttributeError;
  12343. PkiAsn1FreeDecoded(pDec, poatr, AttributeNC2_PDU);
  12344. poatr = NULL;
  12345. }
  12346. fRet = TRUE;
  12347. CommonReturn:
  12348. PkiAsn1FreeInfo(pDec, AttributeNC2_PDU, poatr);
  12349. ICM_SetLastError(dwError);
  12350. return fRet;
  12351. ErrorReturn:
  12352. dwError = GetLastError();
  12353. fRet = FALSE;
  12354. goto CommonReturn;
  12355. SET_ERROR_VAR(DecodeAttributeNC2Error, PkiAsn1ErrToHr(Asn1Err))
  12356. TRACE_ERROR(GetOssAttributeError) // error already set
  12357. }
  12358. //+-------------------------------------------------------------------------
  12359. // Get the data for an Attributes
  12360. //--------------------------------------------------------------------------
  12361. BOOL
  12362. WINAPI
  12363. ICM_GetAttributesData(
  12364. IN Attributes *poatrs,
  12365. OUT void *pvData,
  12366. IN OUT DWORD *pcbData)
  12367. {
  12368. BOOL fRet;
  12369. LONG lData;
  12370. LONG lRemainExtra;
  12371. PBYTE pbExtra;
  12372. PCRYPT_ATTRIBUTES patrs = (PCRYPT_ATTRIBUTES)pvData;
  12373. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12374. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ATTRIBUTES));
  12375. lRemainExtra = (LONG)*pcbData - lData;
  12376. if (0 > lRemainExtra) {
  12377. patrs = NULL;
  12378. pbExtra = NULL;
  12379. } else {
  12380. pbExtra = (PBYTE)patrs + lData;
  12381. }
  12382. if (!ICM_GetOssAttributes( poatrs, patrs, &pbExtra, &lRemainExtra))
  12383. goto GetOssAttributesError;
  12384. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12385. CommonReturn:
  12386. return fRet;
  12387. ErrorReturn:
  12388. *pcbData = 0;
  12389. fRet = FALSE;
  12390. goto CommonReturn;
  12391. TRACE_ERROR(GetOssAttributesError) // error already set
  12392. }
  12393. //+-------------------------------------------------------------------------
  12394. // Get an OSS Algorithm
  12395. //--------------------------------------------------------------------------
  12396. BOOL
  12397. WINAPI
  12398. ICM_GetOssAlgorithm(
  12399. IN AlgorithmIdentifier *pai,
  12400. OUT PCRYPT_ALGORITHM_IDENTIFIER pInfo,
  12401. IN OUT BYTE **ppbExtra,
  12402. IN OUT LONG *plRemainExtra)
  12403. {
  12404. if (!ICM_GetOssObjId(&pai->algorithm, &pInfo->pszObjId,
  12405. ppbExtra, plRemainExtra))
  12406. return FALSE;
  12407. if (pai->bit_mask & parameters_present) {
  12408. if (!ICM_GetOssAny(&pai->parameters, &pInfo->Parameters,
  12409. ppbExtra, plRemainExtra))
  12410. return FALSE;
  12411. } else if (*plRemainExtra >= 0) {
  12412. memset(&pInfo->Parameters, 0, sizeof(pInfo->Parameters));
  12413. }
  12414. return TRUE;
  12415. }
  12416. //+-------------------------------------------------------------------------
  12417. // Get a ContentInfo (internal)
  12418. //--------------------------------------------------------------------------
  12419. BOOL
  12420. WINAPI
  12421. ICM_GetOssContentInfo(
  12422. IN ContentInfo *poci,
  12423. OUT PCONTENT_INFO pInfo,
  12424. IN OUT BYTE **ppbExtra,
  12425. IN OUT LONG *plRemainExtra)
  12426. {
  12427. if (!ICM_GetOssObjId(&poci->contentType, &pInfo->pszContentType,
  12428. ppbExtra, plRemainExtra))
  12429. return FALSE;
  12430. if (poci->bit_mask & content_present) {
  12431. if (!ICM_GetOssAny(&poci->content, &pInfo->content,
  12432. ppbExtra, plRemainExtra))
  12433. return FALSE;
  12434. } else {
  12435. if (pInfo) {
  12436. pInfo->content.cbData = 0;
  12437. pInfo->content.pbData = 0;
  12438. }
  12439. }
  12440. return TRUE;
  12441. }
  12442. //+-------------------------------------------------------------------------
  12443. // Get a ContentInfo
  12444. //--------------------------------------------------------------------------
  12445. BOOL
  12446. WINAPI
  12447. ICM_GetOssContentInfoData(
  12448. IN ContentInfo *poci,
  12449. OUT void *pvData,
  12450. IN OUT DWORD *pcbData)
  12451. {
  12452. BOOL fRet;
  12453. LONG lData;
  12454. LONG lRemainExtra;
  12455. PBYTE pbExtra;
  12456. PCONTENT_INFO pci = (PCONTENT_INFO)pvData;
  12457. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12458. lData = INFO_LEN_ALIGN( sizeof(CONTENT_INFO));
  12459. lRemainExtra = (LONG)*pcbData - lData;
  12460. if (0 > lRemainExtra) {
  12461. pci = NULL;
  12462. pbExtra = NULL;
  12463. } else {
  12464. pbExtra = (PBYTE)pci + lData;
  12465. }
  12466. if (!ICM_GetOssContentInfo( poci, pci, &pbExtra, &lRemainExtra))
  12467. goto GetContentInfoError;
  12468. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12469. CommonReturn:
  12470. return fRet;
  12471. ErrorReturn:
  12472. *pcbData = 0;
  12473. fRet = FALSE;
  12474. goto CommonReturn;
  12475. TRACE_ERROR(GetContentInfoError) // error already set
  12476. }
  12477. BOOL
  12478. WINAPI
  12479. ICM_GetOssIssuerAndSerialNumberFromCertId(
  12480. IN CertIdentifier *pOssCertId,
  12481. OUT PCERT_NAME_BLOB pIssuer,
  12482. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12483. IN OUT BYTE **ppbExtra,
  12484. IN OUT LONG *plRemainExtra);
  12485. //+-------------------------------------------------------------------------
  12486. // Get an Special Issuer and SerialNumber from a KeyId.
  12487. //
  12488. // Converts the KeyId to a special encoded Issuer name having a RDN with
  12489. // the szOID_KEYID_RDN OID and a CERT_RDN_OCTET_STRING value containing
  12490. // the KeyId. The SerialNumber is set to 0.
  12491. //--------------------------------------------------------------------------
  12492. BOOL
  12493. WINAPI
  12494. ICM_GetOssIssuerAndSerialNumberFromKeyId(
  12495. IN SubjectKeyIdentifier *pOssKeyId,
  12496. OUT PCERT_NAME_BLOB pIssuer,
  12497. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12498. IN OUT BYTE **ppbExtra,
  12499. IN OUT LONG *plRemainExtra)
  12500. {
  12501. BOOL fRet;
  12502. CertIdentifier OssCertId;
  12503. ASN1octet_t SerialNumber;
  12504. CERT_RDN_ATTR KeyIdAttr;
  12505. CERT_RDN KeyIdRDN;
  12506. CERT_NAME_INFO IssuerInfo;
  12507. BYTE *pbEncodedIssuer = NULL;
  12508. DWORD cbEncodedIssuer;
  12509. KeyIdAttr.pszObjId = szOID_KEYID_RDN;
  12510. KeyIdAttr.dwValueType = CERT_RDN_OCTET_STRING;
  12511. KeyIdAttr.Value.pbData = pOssKeyId->value;
  12512. KeyIdAttr.Value.cbData = pOssKeyId->length;
  12513. KeyIdRDN.cRDNAttr = 1;
  12514. KeyIdRDN.rgRDNAttr = &KeyIdAttr;
  12515. IssuerInfo.cRDN = 1;
  12516. IssuerInfo.rgRDN = &KeyIdRDN;
  12517. // Encode the special Issuer Name containing the KeyId
  12518. if (!CryptEncodeObjectEx(
  12519. X509_ASN_ENCODING,
  12520. X509_NAME,
  12521. &IssuerInfo,
  12522. CRYPT_ENCODE_ALLOC_FLAG,
  12523. &PkiEncodePara,
  12524. (void *) &pbEncodedIssuer,
  12525. &cbEncodedIssuer
  12526. ))
  12527. goto EncodeError;
  12528. OssCertId.choice = issuerAndSerialNumber_chosen;
  12529. OssCertId.u.issuerAndSerialNumber.serialNumber.length = 1;
  12530. OssCertId.u.issuerAndSerialNumber.serialNumber.value = &SerialNumber;
  12531. SerialNumber = 0;
  12532. OssCertId.u.issuerAndSerialNumber.issuer.length = cbEncodedIssuer;
  12533. OssCertId.u.issuerAndSerialNumber.issuer.value = pbEncodedIssuer;
  12534. fRet = ICM_GetOssIssuerAndSerialNumberFromCertId(
  12535. &OssCertId,
  12536. pIssuer,
  12537. pSerialNumber,
  12538. ppbExtra,
  12539. plRemainExtra
  12540. );
  12541. CommonReturn:
  12542. PkiFree(pbEncodedIssuer);
  12543. return fRet;
  12544. ErrorReturn:
  12545. fRet = FALSE;
  12546. goto CommonReturn;
  12547. TRACE_ERROR(EncodeError)
  12548. }
  12549. //+-------------------------------------------------------------------------
  12550. // Get an Issuer and SerialNumber from a CertIdentifier.
  12551. //
  12552. // Converts a KEYID choice to a special encoded Issuer name having a RDN with
  12553. // the szOID_KEYID_RDN OID and a CERT_RDN_OCTET_STRING value containing
  12554. // the KeyId. The SerialNumber is set to 0.
  12555. //--------------------------------------------------------------------------
  12556. BOOL
  12557. WINAPI
  12558. ICM_GetOssIssuerAndSerialNumberFromCertId(
  12559. IN CertIdentifier *pOssCertId,
  12560. OUT PCERT_NAME_BLOB pIssuer,
  12561. OUT PCRYPT_INTEGER_BLOB pSerialNumber,
  12562. IN OUT BYTE **ppbExtra,
  12563. IN OUT LONG *plRemainExtra)
  12564. {
  12565. BOOL fRet;
  12566. switch (pOssCertId->choice) {
  12567. case issuerAndSerialNumber_chosen:
  12568. ICM_GetOssHugeInteger(
  12569. &pOssCertId->u.issuerAndSerialNumber.serialNumber,
  12570. pSerialNumber, ppbExtra, plRemainExtra);
  12571. if (!ICM_GetOssAny(&pOssCertId->u.issuerAndSerialNumber.issuer,
  12572. pIssuer, ppbExtra, plRemainExtra))
  12573. goto GetIssuerError;
  12574. break;
  12575. case subjectKeyIdentifier_chosen:
  12576. if (!ICM_GetOssIssuerAndSerialNumberFromKeyId(
  12577. &pOssCertId->u.subjectKeyIdentifier,
  12578. pIssuer, pSerialNumber, ppbExtra, plRemainExtra))
  12579. goto GetKeyIdError;
  12580. break;
  12581. default:
  12582. goto InvalidCertIdChoice;
  12583. }
  12584. fRet = TRUE;
  12585. CommonReturn:
  12586. return fRet;
  12587. ErrorReturn:
  12588. fRet = FALSE;
  12589. goto CommonReturn;
  12590. TRACE_ERROR(GetIssuerError)
  12591. TRACE_ERROR(GetKeyIdError)
  12592. SET_ERROR(InvalidCertIdChoice, CRYPT_E_BAD_ENCODE)
  12593. }
  12594. BOOL
  12595. WINAPI
  12596. ICM_GetOssIssuerAndSerialNumberForCertInfo(
  12597. IN CertIdentifier *pOssCertId,
  12598. OUT PCERT_INFO pCertInfo,
  12599. IN OUT BYTE **ppbExtra,
  12600. IN OUT LONG *plRemainExtra)
  12601. {
  12602. return ICM_GetOssIssuerAndSerialNumberFromCertId(
  12603. pOssCertId,
  12604. &pCertInfo->Issuer,
  12605. &pCertInfo->SerialNumber,
  12606. ppbExtra,
  12607. plRemainExtra
  12608. );
  12609. }
  12610. //+-------------------------------------------------------------------------
  12611. // Get an CertInfo with an updated IssuerAndSerialNumber
  12612. //--------------------------------------------------------------------------
  12613. BOOL
  12614. WINAPI
  12615. ICM_GetCertInfoIssuerAndSerialNumber(
  12616. IN CertIdentifier *pOssCertIdentifier,
  12617. OUT void *pvData,
  12618. IN OUT DWORD *pcbData)
  12619. {
  12620. BOOL fRet;
  12621. LONG lData;
  12622. PCERT_INFO pci = (PCERT_INFO)pvData;
  12623. PBYTE pbExtra;
  12624. LONG lRemainExtra;
  12625. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12626. lData = INFO_LEN_ALIGN( sizeof(CERT_INFO));
  12627. lRemainExtra = (LONG)*pcbData - lData;
  12628. if (0 > lRemainExtra) {
  12629. pci = NULL;
  12630. pbExtra = NULL;
  12631. } else {
  12632. pbExtra = (PBYTE)pci + lData;
  12633. }
  12634. if (!ICM_GetOssIssuerAndSerialNumberForCertInfo(pOssCertIdentifier,
  12635. pci, &pbExtra, &lRemainExtra))
  12636. goto GetOssIssuerAndSerialNumberError;
  12637. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12638. CommonReturn:
  12639. return fRet;
  12640. ErrorReturn:
  12641. *pcbData = 0;
  12642. fRet = FALSE;
  12643. goto CommonReturn;
  12644. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  12645. }
  12646. BOOL
  12647. WINAPI
  12648. ICM_GetOssCertIdentifier(
  12649. IN CertIdentifier *pOssCertId,
  12650. OUT PCERT_ID pCertId,
  12651. IN OUT BYTE **ppbExtra,
  12652. IN OUT LONG *plRemainExtra
  12653. );
  12654. BOOL
  12655. WINAPI
  12656. ICM_GetCertId(
  12657. IN CertIdentifier *pOssCertIdentifier,
  12658. OUT void *pvData,
  12659. IN OUT DWORD *pcbData)
  12660. {
  12661. BOOL fRet;
  12662. LONG lData;
  12663. PCERT_ID pid = (PCERT_ID)pvData;
  12664. PBYTE pbExtra;
  12665. LONG lRemainExtra;
  12666. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12667. lData = INFO_LEN_ALIGN( sizeof(CERT_ID));
  12668. lRemainExtra = (LONG)*pcbData - lData;
  12669. if (0 > lRemainExtra) {
  12670. pid = NULL;
  12671. pbExtra = NULL;
  12672. } else {
  12673. pbExtra = (PBYTE)pid + lData;
  12674. }
  12675. if (!ICM_GetOssCertIdentifier(pOssCertIdentifier,
  12676. pid, &pbExtra, &lRemainExtra))
  12677. goto GetOssCertIdentifierError;
  12678. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12679. CommonReturn:
  12680. return fRet;
  12681. ErrorReturn:
  12682. *pcbData = 0;
  12683. fRet = FALSE;
  12684. goto CommonReturn;
  12685. TRACE_ERROR(GetOssCertIdentifierError) // error already set
  12686. }
  12687. //+-------------------------------------------------------------------------
  12688. // Copy out an CRYPT_ALGORITHM_IDENTIFIER
  12689. //--------------------------------------------------------------------------
  12690. BOOL
  12691. WINAPI
  12692. ICM_GetALGORITHM_IDENTIFIER(
  12693. IN AlgorithmIdentifier *paiOss,
  12694. OUT void *pvData,
  12695. IN OUT DWORD *pcbData)
  12696. {
  12697. BOOL fRet;
  12698. LONG lData;
  12699. PCRYPT_ALGORITHM_IDENTIFIER pai = (PCRYPT_ALGORITHM_IDENTIFIER)pvData;
  12700. PBYTE pbExtra;
  12701. LONG lRemainExtra;
  12702. if (NULL == pvData)
  12703. *pcbData = 0;
  12704. // for lRemainExtra < 0, LENGTH_ONLY calculation
  12705. lData = INFO_LEN_ALIGN( sizeof(CRYPT_ALGORITHM_IDENTIFIER));
  12706. lRemainExtra = (LONG)*pcbData - lData;
  12707. if (0 > lRemainExtra) {
  12708. pai = NULL;
  12709. pbExtra = NULL;
  12710. } else {
  12711. pbExtra = (PBYTE)pai + lData;
  12712. }
  12713. if (!ICM_GetOssAlgorithm( paiOss, pai, &pbExtra, &lRemainExtra))
  12714. goto GetOssAlgorithmError;
  12715. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  12716. CommonReturn:
  12717. return fRet;
  12718. ErrorReturn:
  12719. *pcbData = 0;
  12720. fRet = FALSE;
  12721. goto CommonReturn;
  12722. TRACE_ERROR(GetOssAlgorithmError) // error already set
  12723. }
  12724. //+-------------------------------------------------------------------------
  12725. // Get the digest in a DIGESTED message.
  12726. //--------------------------------------------------------------------------
  12727. BOOL
  12728. WINAPI
  12729. ICM_GetDigestDataParam(
  12730. IN PCRYPT_MSG_INFO pcmi,
  12731. OUT void *pvData,
  12732. IN OUT DWORD *pcbData)
  12733. {
  12734. BOOL fRet;
  12735. DigestedData *pdd;
  12736. if (CMSG_HASHED != pcmi->dwMsgType)
  12737. goto InvalidMsgType;
  12738. pdd = (DigestedData *)pcmi->pvMsg;
  12739. fRet = ICM_CopyOut(
  12740. (PBYTE)pdd->digest.value,
  12741. (DWORD)pdd->digest.length,
  12742. (PBYTE)pvData,
  12743. pcbData);
  12744. CommonReturn:
  12745. return fRet;
  12746. ErrorReturn:
  12747. *pcbData = 0;
  12748. fRet = FALSE;
  12749. goto CommonReturn;
  12750. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  12751. }
  12752. #ifdef CMS_PKCS7
  12753. HCRYPTHASH
  12754. WINAPI
  12755. ICM_GetEncodedSignerHash(
  12756. IN PCRYPT_MSG_INFO pcmi,
  12757. IN DWORD dwSignerIndex
  12758. )
  12759. {
  12760. HCRYPTHASH hHash = NULL;
  12761. SignerInfo *psi;
  12762. PSIGNER_ENCODE_DATA_INFO pSignerEncodeDataInfo;
  12763. CHashNode *pnHash;
  12764. PICM_HASH_INFO pHashInfo;
  12765. if (dwSignerIndex >= ((SignedData *)pcmi->pvMsg)->signerInfos.count)
  12766. goto IndexTooBig;
  12767. psi = ((SignedData *)pcmi->pvMsg)->signerInfos.value + dwSignerIndex;
  12768. pSignerEncodeDataInfo = pcmi->rgSignerEncodeDataInfo + dwSignerIndex;
  12769. pnHash = pSignerEncodeDataInfo->pHashNode;
  12770. pHashInfo = pnHash->Data();
  12771. if (psi->bit_mask & authenticatedAttributes_present) {
  12772. if (!ICM_GetAttrsHash(
  12773. pHashInfo->dwAlgoCAPI,
  12774. pSignerEncodeDataInfo->hCryptProv,
  12775. &psi->authenticatedAttributes,
  12776. &hHash))
  12777. goto GetAuthAttrsHashError;
  12778. } else {
  12779. if (!ICM_DupListHash( pnHash, pSignerEncodeDataInfo->hCryptProv,
  12780. &hHash))
  12781. goto DupListHashError;
  12782. }
  12783. CommonReturn:
  12784. return hHash;
  12785. ErrorReturn:
  12786. hHash = NULL;
  12787. goto CommonReturn;
  12788. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  12789. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  12790. TRACE_ERROR(DupListHashError) // error already set
  12791. }
  12792. HCRYPTHASH
  12793. WINAPI
  12794. ICM_GetDecodedSignerHash(
  12795. IN PCRYPT_MSG_INFO pcmi,
  12796. IN DWORD dwSignerIndex
  12797. )
  12798. {
  12799. HCRYPTHASH hHash = NULL;
  12800. DWORD dwError = ERROR_SUCCESS;
  12801. SignerInfoWithBlobs *psib = NULL;
  12802. CSignerNode *pSignerNode = NULL;
  12803. HCRYPTPROV hCryptProv; // doen't need to be released
  12804. ASN1error_e Asn1Err;
  12805. ASN1decoding_t pDec = ICM_GetDecoder();
  12806. CRYPT_DATA_BLOB DataBlob;
  12807. CHashNode *pnHash;
  12808. PICM_HASH_INFO pHashInfo;
  12809. if (!ICM_FindSignerInfo(pcmi, dwSignerIndex, (PVOID *)&pSignerNode))
  12810. goto FindSignerInfoError;
  12811. DataBlob = pSignerNode->Data()->blob;
  12812. if (0 != (Asn1Err = PkiAsn1Decode(
  12813. pDec,
  12814. (void **)&psib,
  12815. SignerInfoWithBlobs_PDU,
  12816. DataBlob.pbData,
  12817. DataBlob.cbData)))
  12818. goto DecodeSignerInfoWithBlobsError;
  12819. if (!ICM_FindHashNodeFromEncodedAlgo(
  12820. pcmi->pHashList,
  12821. (PCRYPT_DATA_BLOB)&psib->digestAlgorithm,
  12822. &pnHash))
  12823. goto GetHashNodeFromEncodedAlgoError;
  12824. pHashInfo = pnHash->Data();
  12825. if (pcmi->fDefaultCryptProv)
  12826. hCryptProv = 0;
  12827. else
  12828. hCryptProv = pcmi->hCryptProv;
  12829. if (0 == hCryptProv) {
  12830. hCryptProv = I_CryptGetDefaultCryptProv(0);
  12831. if (0 == hCryptProv)
  12832. goto GetDefaultCryptProvError;
  12833. }
  12834. if (psib->bit_mask & authAttributes_present) {
  12835. if (!ICM_GetAttrsHash(
  12836. pHashInfo->dwAlgoCAPI,
  12837. hCryptProv,
  12838. (Attributes *)&psib->authAttributes, // same, except for NOCOPY
  12839. &hHash))
  12840. goto GetAuthAttrsHashError;
  12841. } else {
  12842. if (!ICM_DupListHash( pnHash, hCryptProv, &hHash))
  12843. goto DupListHashError;
  12844. }
  12845. CommonReturn:
  12846. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, psib);
  12847. ICM_SetLastError(dwError);
  12848. return hHash;
  12849. ErrorReturn:
  12850. dwError = GetLastError();
  12851. hHash = NULL;
  12852. goto CommonReturn;
  12853. TRACE_ERROR(FindSignerInfoError) // error already set
  12854. SET_ERROR_VAR(DecodeSignerInfoWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  12855. TRACE_ERROR(GetHashNodeFromEncodedAlgoError) // error already set
  12856. TRACE_ERROR(GetDefaultCryptProvError) // error already set
  12857. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  12858. TRACE_ERROR(DupListHashError) // error already set
  12859. }
  12860. #endif // CMS_PKCS7
  12861. //+-------------------------------------------------------------------------
  12862. // Get the digest of the content in a DIGESTED message or for one of
  12863. // the signers in a SIGNED message
  12864. //--------------------------------------------------------------------------
  12865. BOOL
  12866. WINAPI
  12867. ICM_GetComputedDigestParam(
  12868. IN PCRYPT_MSG_INFO pcmi,
  12869. IN DWORD dwIndex,
  12870. OUT void *pvData,
  12871. IN OUT DWORD *pcbData)
  12872. {
  12873. BOOL fRet;
  12874. DWORD dwError = ERROR_SUCCESS;
  12875. HCRYPTHASH hHash = NULL;
  12876. PBYTE pbAllocHash = NULL;
  12877. DWORD cbHash;
  12878. PBYTE pbHash;
  12879. switch (pcmi->dwMsgType) {
  12880. case CMSG_HASHED:
  12881. if (!ICM_GetListHashValue(
  12882. pcmi->pHashList->Head(),
  12883. &cbHash,
  12884. &pbHash))
  12885. goto GetHashValueError;
  12886. break;
  12887. #ifdef CMS_PKCS7
  12888. case CMSG_SIGNED:
  12889. if (pcmi->fEncoding)
  12890. hHash = ICM_GetEncodedSignerHash(pcmi, dwIndex);
  12891. else
  12892. hHash = ICM_GetDecodedSignerHash(pcmi, dwIndex);
  12893. if (NULL == hHash)
  12894. goto GetSignerHashError;
  12895. if (!CryptGetHashParam(
  12896. hHash,
  12897. HP_HASHVAL,
  12898. NULL,
  12899. &cbHash,
  12900. 0)) // dwFlags
  12901. goto GetHashParamSizeError;
  12902. if (NULL == (pbAllocHash = (PBYTE)ICM_AllocA(cbHash)))
  12903. goto AllocHashParamError;
  12904. pbHash = pbAllocHash;
  12905. if (!CryptGetHashParam(
  12906. hHash,
  12907. HP_HASHVAL,
  12908. pbHash,
  12909. &cbHash,
  12910. 0)) // dwFlags
  12911. goto GetHashParamError;
  12912. break;
  12913. #endif // CMS_PKCS7
  12914. default:
  12915. goto InvalidMsgType;
  12916. }
  12917. fRet = ICM_CopyOut(
  12918. pbHash,
  12919. cbHash,
  12920. (PBYTE)pvData,
  12921. pcbData);
  12922. if (!fRet)
  12923. dwError = GetLastError();
  12924. CommonReturn:
  12925. if (hHash)
  12926. CryptDestroyHash(hHash);
  12927. ICM_FreeA(pbAllocHash);
  12928. ICM_SetLastError(dwError);
  12929. return fRet;
  12930. ErrorReturn:
  12931. dwError = GetLastError();
  12932. *pcbData = 0;
  12933. fRet = FALSE;
  12934. goto CommonReturn;
  12935. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  12936. TRACE_ERROR(GetHashValueError)
  12937. TRACE_ERROR(GetSignerHashError)
  12938. TRACE_ERROR(GetHashParamSizeError)
  12939. TRACE_ERROR(AllocHashParamError)
  12940. TRACE_ERROR(GetHashParamError)
  12941. }
  12942. //+-------------------------------------------------------------------------
  12943. // Find the SignerInfo by index, if the message type permits and if the
  12944. // index value is in range.
  12945. //
  12946. // Returns: FALSE iff fails
  12947. //--------------------------------------------------------------------------
  12948. BOOL
  12949. WINAPI
  12950. ICM_FindSignerInfo(
  12951. IN PCRYPT_MSG_INFO pcmi,
  12952. IN DWORD dwIndex,
  12953. OUT PVOID *ppv)
  12954. {
  12955. BOOL fRet;
  12956. PVOID pv;
  12957. SignerInfo *psi = NULL;
  12958. CSignerNode *pSignerNode = NULL;
  12959. DWORD i;
  12960. if (pcmi->fEncoding) {
  12961. switch (pcmi->dwMsgType) {
  12962. case CMSG_SIGNED:
  12963. if (dwIndex >= ((SignedData *)pcmi->pvMsg)->signerInfos.count)
  12964. goto IndexTooBig;
  12965. psi = ((SignedData *)pcmi->pvMsg)->signerInfos.value + dwIndex;
  12966. break;
  12967. case CMSG_SIGNED_AND_ENVELOPED:
  12968. goto MessageTypeNotSupportedYet;
  12969. default:
  12970. goto InvalidMsgType;
  12971. }
  12972. pv = psi;
  12973. } else {
  12974. switch (pcmi->dwMsgType) {
  12975. case CMSG_SIGNED:
  12976. if (NULL == pcmi->psdi)
  12977. goto InvalidSignedMessageError;
  12978. for (i=dwIndex, pSignerNode=pcmi->psdi->pSignerList->Head();
  12979. (i>0) && pSignerNode;
  12980. i--, pSignerNode=pSignerNode->Next())
  12981. ;
  12982. if (NULL == pSignerNode)
  12983. goto IndexTooBig;
  12984. break;
  12985. case CMSG_SIGNED_AND_ENVELOPED:
  12986. goto MessageTypeNotSupportedYet;
  12987. default:
  12988. goto InvalidMsgType;
  12989. }
  12990. pv = pSignerNode;
  12991. }
  12992. fRet = TRUE;
  12993. CommonReturn:
  12994. *ppv = pv;
  12995. return fRet;
  12996. ErrorReturn:
  12997. pv = NULL;
  12998. fRet = FALSE;
  12999. goto CommonReturn;
  13000. SET_ERROR(InvalidSignedMessageError, ERROR_INVALID_DATA)
  13001. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  13002. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  13003. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  13004. }
  13005. //+-------------------------------------------------------------------------
  13006. // Countersign an already-existing signature, output an encoded attribute
  13007. //--------------------------------------------------------------------------
  13008. BOOL
  13009. WINAPI
  13010. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13011. ICMTest_NewCryptMsgCountersignEncoded(
  13012. #else
  13013. CryptMsgCountersignEncoded(
  13014. #endif
  13015. IN DWORD dwEncodingType,
  13016. IN PBYTE pbSignerInfo,
  13017. IN DWORD cbSignerInfo,
  13018. IN DWORD cCountersigners,
  13019. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  13020. OUT PBYTE pbCountersignatureAttribute,
  13021. IN OUT PDWORD pcbCountersignatureAttribute)
  13022. {
  13023. DWORD dwError = ERROR_SUCCESS;
  13024. BOOL fRet;
  13025. HCRYPTMSG hCryptMsgCountersign = NULL;
  13026. CMSG_SIGNED_ENCODE_INFO EncodeInfo; ZEROSTRUCT(EncodeInfo);
  13027. EncodeInfo.cbSize = sizeof(EncodeInfo);
  13028. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA UnauthAttrPara; ZEROSTRUCT(UnauthAttrPara);
  13029. UnauthAttrPara.cbSize = sizeof(UnauthAttrPara);
  13030. Attribute oatrCountersignature; ZEROSTRUCT(oatrCountersignature);
  13031. ASN1error_e Asn1Err;
  13032. ASN1decoding_t pDec = ICM_GetDecoder();
  13033. ASN1encoding_t pEnc = ICM_GetEncoder();
  13034. PBYTE pbEncoded = NULL;
  13035. DWORD cbEncoded;
  13036. SignerInfoWithBlobs *posib = NULL;
  13037. DWORD i;
  13038. Any *pAny;
  13039. DWORD dwFlags;
  13040. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13041. goto InvalidEncodingTypeError;
  13042. // crack the SignerInfo being countersigned
  13043. if (0 != (Asn1Err = PkiAsn1Decode(
  13044. pDec,
  13045. (void **)&posib,
  13046. SignerInfoWithBlobs_PDU,
  13047. pbSignerInfo,
  13048. cbSignerInfo)))
  13049. goto DecodeSignerInfoError;
  13050. // create a new message
  13051. EncodeInfo.cSigners = cCountersigners;
  13052. EncodeInfo.rgSigners = rgCountersigners;
  13053. dwFlags = CMSG_AUTHENTICATED_ATTRIBUTES_FLAG;
  13054. if (NULL == pbCountersignatureAttribute ||
  13055. 0 == *pcbCountersignatureAttribute)
  13056. dwFlags |= CMSG_MAX_LENGTH_FLAG;
  13057. if (NULL == (hCryptMsgCountersign = CryptMsgOpenToEncode(
  13058. PKCS_7_ASN_ENCODING,
  13059. dwFlags,
  13060. CMSG_SIGNED,
  13061. &EncodeInfo,
  13062. NULL, // pszInnerContentObjID
  13063. NULL))) // pStreamInfo
  13064. goto OpenToEncodeError;
  13065. // feed encrypted digest into the new message
  13066. if (!CryptMsgUpdate(
  13067. hCryptMsgCountersign,
  13068. posib->encryptedDigest.value,
  13069. posib->encryptedDigest.length,
  13070. TRUE)) // fFinal
  13071. goto UpdateError;
  13072. oatrCountersignature.attributeType.count = SIZE_OSS_OID;
  13073. if (!PkiAsn1ToObjectIdentifier(
  13074. szOID_RSA_counterSign,
  13075. &oatrCountersignature.attributeType.count,
  13076. oatrCountersignature.attributeType.value))
  13077. goto PkiAsn1ToObjectIdentifierError;
  13078. oatrCountersignature.attributeValue.count = cCountersigners;
  13079. if (NULL == (oatrCountersignature.attributeValue.value = (Any *)ICM_AllocA(
  13080. cCountersigners * sizeof(Any))))
  13081. goto AllocCountersignersError;
  13082. // extract encoded SignerInfo's, and store
  13083. for (i=0, pAny=oatrCountersignature.attributeValue.value;
  13084. i<cCountersigners;
  13085. i++, pAny++) {
  13086. cbSignerInfo = 0;
  13087. CryptMsgGetParam(
  13088. hCryptMsgCountersign,
  13089. CMSG_ENCODED_SIGNER,
  13090. i,
  13091. NULL,
  13092. &cbSignerInfo);
  13093. if (cbSignerInfo == 0)
  13094. goto GetSignerInfoSizeError;
  13095. if (NULL == (pbSignerInfo = (PBYTE)ICM_AllocA( cbSignerInfo)))
  13096. goto AllocSignerInfoError;
  13097. if (!CryptMsgGetParam(
  13098. hCryptMsgCountersign,
  13099. CMSG_ENCODED_SIGNER,
  13100. i,
  13101. pbSignerInfo,
  13102. &cbSignerInfo))
  13103. goto GetSignerInfoError;
  13104. pAny->length = cbSignerInfo;
  13105. pAny->value = pbSignerInfo;
  13106. }
  13107. // encode the Countersignature attribute
  13108. if (0 != (Asn1Err = PkiAsn1Encode(
  13109. pEnc,
  13110. &oatrCountersignature,
  13111. AttributeNC2_PDU,
  13112. &pbEncoded,
  13113. &cbEncoded)))
  13114. goto Asn1EncodeAttributeError;
  13115. // copy out the Countersignature attribute
  13116. fRet = ICM_CopyOut(
  13117. pbEncoded,
  13118. cbEncoded,
  13119. pbCountersignatureAttribute,
  13120. pcbCountersignatureAttribute);
  13121. if (!fRet)
  13122. dwError = GetLastError();
  13123. CommonReturn:
  13124. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13125. CryptMsgClose( hCryptMsgCountersign);
  13126. if (oatrCountersignature.attributeValue.value) {
  13127. for (i=cCountersigners, pAny=oatrCountersignature.attributeValue.value;
  13128. i>0;
  13129. i--, pAny++)
  13130. ICM_FreeA( pAny->value);
  13131. ICM_FreeA( oatrCountersignature.attributeValue.value);
  13132. }
  13133. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  13134. ICM_SetLastError(dwError);
  13135. return fRet;
  13136. ErrorReturn:
  13137. dwError = GetLastError();
  13138. fRet = FALSE;
  13139. goto CommonReturn;
  13140. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13141. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13142. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  13143. SET_ERROR_VAR(Asn1EncodeAttributeError, PkiAsn1ErrToHr(Asn1Err))
  13144. TRACE_ERROR(OpenToEncodeError) // error already set
  13145. TRACE_ERROR(UpdateError) // error already set
  13146. TRACE_ERROR(AllocCountersignersError) // error already set
  13147. TRACE_ERROR(GetSignerInfoSizeError) // error already set
  13148. TRACE_ERROR(AllocSignerInfoError) // error already set
  13149. TRACE_ERROR(GetSignerInfoError) // error already set
  13150. }
  13151. //+-------------------------------------------------------------------------
  13152. // Countersign an already-existing signature in a message
  13153. //--------------------------------------------------------------------------
  13154. BOOL
  13155. WINAPI
  13156. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13157. ICMTest_NewCryptMsgCountersign(
  13158. #else
  13159. CryptMsgCountersign(
  13160. #endif
  13161. IN OUT HCRYPTMSG hCryptMsg,
  13162. IN DWORD dwIndex,
  13163. IN DWORD cCountersigners,
  13164. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners)
  13165. {
  13166. DWORD dwError = ERROR_SUCCESS;
  13167. BOOL fRet;
  13168. PBYTE pbCountersignatureAttribute = NULL;
  13169. DWORD cbCountersignatureAttribute;
  13170. PBYTE pbSignerInfo = NULL;
  13171. DWORD cbSignerInfo;
  13172. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA UnauthAttrPara; ZEROSTRUCT(UnauthAttrPara);
  13173. UnauthAttrPara.cbSize = sizeof(UnauthAttrPara);
  13174. if (((PCRYPT_MSG_INFO)hCryptMsg)->fEncoding)
  13175. goto EncodingCountersignNotSupportedError;
  13176. // extract encoded SignerInfo being countersigned from the message
  13177. cbSignerInfo = 0;
  13178. CryptMsgGetParam(
  13179. hCryptMsg,
  13180. CMSG_ENCODED_SIGNER,
  13181. dwIndex,
  13182. NULL,
  13183. &cbSignerInfo);
  13184. if (cbSignerInfo == 0)
  13185. goto GetEncodedSignerSizeError;
  13186. if (NULL == (pbSignerInfo = (PBYTE)ICM_AllocA( cbSignerInfo)))
  13187. goto AllocEncodedSignerError;
  13188. if (!CryptMsgGetParam(
  13189. hCryptMsg,
  13190. CMSG_ENCODED_SIGNER,
  13191. dwIndex,
  13192. pbSignerInfo,
  13193. &cbSignerInfo))
  13194. goto GetEncodedSignerError;
  13195. // create the countersignature blob
  13196. cbCountersignatureAttribute = 0;
  13197. CryptMsgCountersignEncoded(
  13198. PKCS_7_ASN_ENCODING,
  13199. pbSignerInfo,
  13200. cbSignerInfo,
  13201. cCountersigners,
  13202. rgCountersigners,
  13203. NULL,
  13204. &cbCountersignatureAttribute);
  13205. if (cbCountersignatureAttribute == 0)
  13206. goto GetCountersignatureAttributeSizeError;
  13207. if (NULL == (pbCountersignatureAttribute = (PBYTE)ICM_AllocA( cbCountersignatureAttribute)))
  13208. goto AllocCountersignatureAttributeError;
  13209. if (!CryptMsgCountersignEncoded(
  13210. PKCS_7_ASN_ENCODING,
  13211. pbSignerInfo,
  13212. cbSignerInfo,
  13213. cCountersigners,
  13214. rgCountersigners,
  13215. pbCountersignatureAttribute,
  13216. &cbCountersignatureAttribute))
  13217. goto GetCountersignatureAttributeError;
  13218. // add encoded Countersignature attribute to unauth attrs
  13219. UnauthAttrPara.dwSignerIndex = dwIndex;
  13220. UnauthAttrPara.blob.cbData = cbCountersignatureAttribute;
  13221. UnauthAttrPara.blob.pbData = pbCountersignatureAttribute;
  13222. if (!CryptMsgControl(
  13223. hCryptMsg,
  13224. 0, // dwFlags
  13225. CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
  13226. &UnauthAttrPara))
  13227. goto AddUnauthAttrError;
  13228. fRet = TRUE;
  13229. CommonReturn:
  13230. ICM_FreeA( pbSignerInfo);
  13231. ICM_FreeA( pbCountersignatureAttribute);
  13232. ICM_SetLastError(dwError);
  13233. return fRet;
  13234. ErrorReturn:
  13235. dwError = GetLastError();
  13236. fRet = FALSE;
  13237. goto CommonReturn;
  13238. TRACE_ERROR(EncodingCountersignNotSupportedError) // error already set
  13239. TRACE_ERROR(GetEncodedSignerSizeError) // error already set
  13240. TRACE_ERROR(AllocEncodedSignerError) // error already set
  13241. TRACE_ERROR(GetEncodedSignerError) // error already set
  13242. TRACE_ERROR(GetCountersignatureAttributeSizeError) // error already set
  13243. TRACE_ERROR(AllocCountersignatureAttributeError) // error already set
  13244. TRACE_ERROR(GetCountersignatureAttributeError) // error already set
  13245. TRACE_ERROR(AddUnauthAttrError) // error already set
  13246. }
  13247. #ifdef CMS_PKCS7
  13248. //+-------------------------------------------------------------------------
  13249. // Verify a countersignature, at the SignerInfo level.
  13250. // ie. verify that pbSignerInfoCountersignature contains the encrypted
  13251. // hash of the encryptedDigest field of pbSignerInfo.
  13252. //
  13253. // hCryptProv is used to hash the encryptedDigest field of pbSignerInfo.
  13254. //
  13255. // The signer can be a CERT_PUBLIC_KEY_INFO, certificate context or a
  13256. // chain context.
  13257. //--------------------------------------------------------------------------
  13258. BOOL
  13259. WINAPI
  13260. #ifdef DEBUG_CRYPT_ASN1_MASTER
  13261. ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  13262. #else
  13263. CryptMsgVerifyCountersignatureEncodedEx(
  13264. #endif
  13265. IN HCRYPTPROV hCryptProv,
  13266. IN DWORD dwEncodingType,
  13267. IN PBYTE pbSignerInfo,
  13268. IN DWORD cbSignerInfo,
  13269. IN PBYTE pbSignerInfoCountersignature,
  13270. IN DWORD cbSignerInfoCountersignature,
  13271. IN DWORD dwSignerType,
  13272. IN void *pvSigner,
  13273. IN DWORD dwFlags,
  13274. IN OPTIONAL void *pvReserved
  13275. )
  13276. {
  13277. DWORD dwError = ERROR_SUCCESS;
  13278. BOOL fRet;
  13279. SignerInfoWithBlobs *posib = NULL;
  13280. SignerInfoWithBlobs *posibCS = NULL;
  13281. Any anyValue;
  13282. DWORD cbMessageDigest;
  13283. PBYTE pbMessageDigest;
  13284. DWORD dwDigestAlgoCAPI;
  13285. DWORD dwPubKeyAlgId;
  13286. DWORD dwPubKeyFlags;
  13287. ASN1error_e Asn1Err;
  13288. ASN1decoding_t pDec = ICM_GetDecoder();
  13289. HCRYPTKEY hPubKey = NULL;
  13290. HCRYPTHASH hHashRaw = NULL;
  13291. HCRYPTHASH hHashAttr = NULL;
  13292. PBYTE pbHash = NULL;
  13293. DWORD cbHash;
  13294. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13295. goto InvalidEncodingTypeError;
  13296. // crack the SignerInfo being countersigned
  13297. if (0 != (Asn1Err = PkiAsn1Decode(
  13298. pDec,
  13299. (void **)&posib,
  13300. SignerInfoWithBlobs_PDU,
  13301. pbSignerInfo,
  13302. cbSignerInfo)))
  13303. goto DecodeSignerInfoError;
  13304. // crack the SignerInfo doing the countersigning
  13305. if (0 != (Asn1Err = PkiAsn1Decode(
  13306. pDec,
  13307. (void **)&posibCS,
  13308. SignerInfoWithBlobs_PDU,
  13309. pbSignerInfoCountersignature,
  13310. cbSignerInfoCountersignature)))
  13311. goto DecodeSignerInfoCSError;
  13312. if (!ICM_GetVerifySignatureStuff(
  13313. dwSignerType,
  13314. pvSigner,
  13315. &hCryptProv,
  13316. &hPubKey,
  13317. &dwPubKeyAlgId,
  13318. &dwPubKeyFlags)) goto GetSignatureStuffError;
  13319. // hash the encrypted digest
  13320. if (!ICM_GetCapiFromAlgidBlob(
  13321. (PCRYPT_DATA_BLOB)&posibCS->digestAlgorithm,
  13322. &dwDigestAlgoCAPI))
  13323. goto GetCapiFromAlgidBlobError;
  13324. if (!CryptCreateHash(
  13325. hCryptProv,
  13326. dwDigestAlgoCAPI,
  13327. NULL, // hKey - optional for MAC
  13328. 0, // dwFlags
  13329. &hHashRaw))
  13330. goto CreateHashError;
  13331. if (!ICM_UpdateDigest(
  13332. hHashRaw,
  13333. posib->encryptedDigest.value,
  13334. posib->encryptedDigest.length))
  13335. goto HashDataError;
  13336. if (0 == (posibCS->bit_mask & authAttributes_present))
  13337. goto CountersignerAuthAttributesMissingError;
  13338. // check that the message digest attr matches the hashed encrypted digest
  13339. if (!CryptGetHashParam(
  13340. hHashRaw,
  13341. HP_HASHVAL,
  13342. NULL,
  13343. &cbHash,
  13344. 0)) // dwFlags
  13345. goto GetHashParamSizeError;
  13346. if (NULL == (pbHash = (PBYTE)ICM_AllocA( cbHash)))
  13347. goto AllocHashParamError;
  13348. if (!CryptGetHashParam(
  13349. hHashRaw,
  13350. HP_HASHVAL,
  13351. pbHash,
  13352. &cbHash,
  13353. 0)) // dwFlags
  13354. goto GetHashParamError;
  13355. // find the message digest attr value
  13356. if (!ICM_GetAttrValue(
  13357. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13358. &oidMessageDigest,
  13359. &anyValue))
  13360. goto FindAttrError;
  13361. // find the message digest octets
  13362. if (!Asn1UtilExtractContent(
  13363. #ifdef OSS_CRYPT_ASN1
  13364. anyValue.value,
  13365. #else
  13366. (const BYTE *) anyValue.value,
  13367. #endif // OSS_CRYPT_ASN1
  13368. anyValue.length,
  13369. &cbMessageDigest,
  13370. (const BYTE **)&pbMessageDigest))
  13371. goto ExtractContentError;
  13372. // hash sizes equal?
  13373. if (cbHash != cbMessageDigest)
  13374. goto HashCompareSizeError;
  13375. // hash octets equal?
  13376. if (memcmp( pbMessageDigest, pbHash, cbHash))
  13377. goto HashCompareValueError;
  13378. // Now that we have verified the message digest octets,
  13379. // get the hash of the authenticated attributes.
  13380. if (!ICM_GetAttrsHash(
  13381. dwDigestAlgoCAPI,
  13382. hCryptProv,
  13383. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13384. &hHashAttr))
  13385. goto GetAuthAttrsHashError;
  13386. // verify the hash, signature, and public key are consistent
  13387. if (!ICM_VerifySignature(
  13388. hHashAttr,
  13389. hPubKey,
  13390. dwPubKeyAlgId,
  13391. dwPubKeyFlags,
  13392. posibCS->encryptedDigest.value,
  13393. posibCS->encryptedDigest.length))
  13394. goto VerifySignatureError;
  13395. fRet = TRUE;
  13396. CommonReturn:
  13397. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13398. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posibCS);
  13399. if (hHashRaw)
  13400. CryptDestroyHash( hHashRaw);
  13401. if (hHashAttr)
  13402. CryptDestroyHash( hHashAttr);
  13403. if (hPubKey)
  13404. CryptDestroyKey( hPubKey);
  13405. ICM_FreeA( pbHash);
  13406. ICM_SetLastError(dwError);
  13407. return fRet;
  13408. ErrorReturn:
  13409. dwError = GetLastError();
  13410. fRet = FALSE;
  13411. goto CommonReturn;
  13412. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13413. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13414. SET_ERROR_VAR(DecodeSignerInfoCSError, PkiAsn1ErrToHr(Asn1Err))
  13415. SET_ERROR(CountersignerAuthAttributesMissingError,CRYPT_E_AUTH_ATTR_MISSING)
  13416. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  13417. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  13418. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  13419. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  13420. TRACE_ERROR(GetCapiFromAlgidBlobError) // error already set
  13421. TRACE_ERROR(CreateHashError) // error already set
  13422. TRACE_ERROR(HashDataError) // error already set
  13423. TRACE_ERROR(GetHashParamSizeError) // error already set
  13424. TRACE_ERROR(AllocHashParamError) // error already set
  13425. TRACE_ERROR(GetHashParamError) // error already set
  13426. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  13427. TRACE_ERROR(GetSignatureStuffError) // error already set
  13428. TRACE_ERROR(VerifySignatureError) // error already set
  13429. }
  13430. //+-------------------------------------------------------------------------
  13431. // Verify a countersignature, at the SignerInfo level
  13432. //--------------------------------------------------------------------------
  13433. BOOL
  13434. WINAPI
  13435. CryptMsgVerifyCountersignatureEncoded(
  13436. IN HCRYPTPROV hCryptProv,
  13437. IN DWORD dwEncodingType,
  13438. IN PBYTE pbSignerInfo,
  13439. IN DWORD cbSignerInfo,
  13440. IN PBYTE pbSignerInfoCountersignature,
  13441. IN DWORD cbSignerInfoCountersignature,
  13442. IN PCERT_INFO pciCountersigner)
  13443. {
  13444. return CryptMsgVerifyCountersignatureEncodedEx(
  13445. hCryptProv,
  13446. dwEncodingType,
  13447. pbSignerInfo,
  13448. cbSignerInfo,
  13449. pbSignerInfoCountersignature,
  13450. cbSignerInfoCountersignature,
  13451. CMSG_VERIFY_SIGNER_PUBKEY,
  13452. (void *) &pciCountersigner->SubjectPublicKeyInfo,
  13453. 0, // dwFlags
  13454. NULL // pvReserved
  13455. );
  13456. }
  13457. #else
  13458. //+-------------------------------------------------------------------------
  13459. // Verify a countersignature, at the SignerInfo level
  13460. //--------------------------------------------------------------------------
  13461. BOOL
  13462. WINAPI
  13463. CryptMsgVerifyCountersignatureEncoded(
  13464. IN HCRYPTPROV hCryptProv,
  13465. IN DWORD dwEncodingType,
  13466. IN PBYTE pbSignerInfo,
  13467. IN DWORD cbSignerInfo,
  13468. IN PBYTE pbSignerInfoCountersignature,
  13469. IN DWORD cbSignerInfoCountersignature,
  13470. IN PCERT_INFO pciCountersigner)
  13471. {
  13472. DWORD dwError = ERROR_SUCCESS;
  13473. BOOL fRet;
  13474. SignerInfoWithBlobs *posib = NULL;
  13475. SignerInfoWithBlobs *posibCS = NULL;
  13476. Any anyValue;
  13477. DWORD cbMessageDigest;
  13478. PBYTE pbMessageDigest;
  13479. DWORD dwDigestAlgoCAPI;
  13480. DWORD dwPubKeyAlgId;
  13481. DWORD dwPubKeyFlags;
  13482. ASN1error_e Asn1Err;
  13483. ASN1decoding_t pDec = ICM_GetDecoder();
  13484. IssuerAndSerialNumber *pisn = NULL;
  13485. HCRYPTKEY hPubKey = NULL;
  13486. HCRYPTHASH hHashRaw = NULL;
  13487. HCRYPTHASH hHashAttr = NULL;
  13488. PBYTE pbHash = NULL;
  13489. DWORD cbHash;
  13490. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13491. goto InvalidEncodingTypeError;
  13492. // crack the SignerInfo being countersigned
  13493. if (0 != (Asn1Err = PkiAsn1Decode(
  13494. pDec,
  13495. (void **)&posib,
  13496. SignerInfoWithBlobs_PDU,
  13497. pbSignerInfo,
  13498. cbSignerInfo)))
  13499. goto DecodeSignerInfoError;
  13500. // crack the SignerInfo doing the countersigning
  13501. if (0 != (Asn1Err = PkiAsn1Decode(
  13502. pDec,
  13503. (void **)&posibCS,
  13504. SignerInfoWithBlobs_PDU,
  13505. pbSignerInfoCountersignature,
  13506. cbSignerInfoCountersignature)))
  13507. goto DecodeSignerInfoCSError;
  13508. // verify that the countersignature SignerInfo and the cert info are consistent
  13509. if (0 != (Asn1Err = PkiAsn1Decode(
  13510. pDec,
  13511. (void **)&pisn,
  13512. IssuerAndSerialNumber_PDU,
  13513. (BYTE *) posibCS->issuerAndSerialNumber.value,
  13514. posibCS->issuerAndSerialNumber.length)))
  13515. goto DecodeIssuerAndSerialNumberError;
  13516. if (pisn->issuer.length != pciCountersigner->Issuer.cbData)
  13517. goto IssuerSizeMismatchError;
  13518. if (0 != memcmp(
  13519. pciCountersigner->Issuer.pbData,
  13520. pisn->issuer.value,
  13521. pciCountersigner->Issuer.cbData))
  13522. goto IssuerValueMismatchError;
  13523. if (pisn->serialNumber.length != pciCountersigner->SerialNumber.cbData)
  13524. goto SerialNumberSizeMismatchError;
  13525. if (ICM_ReverseCompare(
  13526. pisn->serialNumber.value,
  13527. pciCountersigner->SerialNumber.pbData,
  13528. pciCountersigner->SerialNumber.cbData))
  13529. goto SerialNumberValueMismatchError;
  13530. if (!ICM_GetVerifySignatureStuff(
  13531. pciCountersigner,
  13532. &hCryptProv,
  13533. &hPubKey,
  13534. &dwPubKeyAlgId,
  13535. &dwPubKeyFlags)) goto GetSignatureStuffError;
  13536. // hash the encrypted digest
  13537. if (!ICM_GetCapiFromAlgidBlob(
  13538. (PCRYPT_DATA_BLOB)&posibCS->digestAlgorithm,
  13539. &dwDigestAlgoCAPI))
  13540. goto GetCapiFromAlgidBlobError;
  13541. if (!CryptCreateHash(
  13542. hCryptProv,
  13543. dwDigestAlgoCAPI,
  13544. NULL, // hKey - optional for MAC
  13545. 0, // dwFlags
  13546. &hHashRaw))
  13547. goto CreateHashError;
  13548. if (!ICM_UpdateDigest(
  13549. hHashRaw,
  13550. posib->encryptedDigest.value,
  13551. posib->encryptedDigest.length))
  13552. goto HashDataError;
  13553. if (0 == (posibCS->bit_mask & authAttributes_present))
  13554. goto CountersignerAuthAttributesMissingError;
  13555. // check that the message digest attr matches the hashed encrypted digest
  13556. if (!CryptGetHashParam(
  13557. hHashRaw,
  13558. HP_HASHVAL,
  13559. NULL,
  13560. &cbHash,
  13561. 0)) // dwFlags
  13562. goto GetHashParamSizeError;
  13563. if (NULL == (pbHash = (PBYTE)ICM_AllocA( cbHash)))
  13564. goto AllocHashParamError;
  13565. if (!CryptGetHashParam(
  13566. hHashRaw,
  13567. HP_HASHVAL,
  13568. pbHash,
  13569. &cbHash,
  13570. 0)) // dwFlags
  13571. goto GetHashParamError;
  13572. // find the message digest attr value
  13573. if (!ICM_GetAttrValue(
  13574. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13575. &oidMessageDigest,
  13576. &anyValue))
  13577. goto FindAttrError;
  13578. // find the message digest octets
  13579. if (!Asn1UtilExtractContent(
  13580. (BYTE *) anyValue.value,
  13581. anyValue.length,
  13582. &cbMessageDigest,
  13583. (const BYTE **)&pbMessageDigest))
  13584. goto ExtractContentError;
  13585. // hash sizes equal?
  13586. if (cbHash != cbMessageDigest)
  13587. goto HashCompareSizeError;
  13588. // hash octets equal?
  13589. if (memcmp( pbMessageDigest, pbHash, cbHash))
  13590. goto HashCompareValueError;
  13591. // Now that we have verified the message digest octets,
  13592. // get the hash of the authenticated attributes.
  13593. if (!ICM_GetAttrsHash(
  13594. dwDigestAlgoCAPI,
  13595. hCryptProv,
  13596. (Attributes *)&posibCS->authAttributes, // same, except for NOCOPY
  13597. &hHashAttr))
  13598. goto GetAuthAttrsHashError;
  13599. // verify the hash, signature, and public key are consistent
  13600. if (!ICM_VerifySignature(
  13601. hHashAttr,
  13602. hPubKey,
  13603. dwPubKeyAlgId,
  13604. dwPubKeyFlags,
  13605. posibCS->encryptedDigest.value,
  13606. posibCS->encryptedDigest.length))
  13607. goto VerifySignatureError;
  13608. fRet = TRUE;
  13609. CommonReturn:
  13610. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  13611. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posibCS);
  13612. PkiAsn1FreeInfo(pDec, IssuerAndSerialNumber_PDU, pisn);
  13613. if (hHashRaw)
  13614. CryptDestroyHash( hHashRaw);
  13615. if (hHashAttr)
  13616. CryptDestroyHash( hHashAttr);
  13617. if (hPubKey)
  13618. CryptDestroyKey( hPubKey);
  13619. ICM_FreeA( pbHash);
  13620. ICM_SetLastError(dwError);
  13621. return fRet;
  13622. ErrorReturn:
  13623. dwError = GetLastError();
  13624. fRet = FALSE;
  13625. goto CommonReturn;
  13626. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13627. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  13628. SET_ERROR_VAR(DecodeSignerInfoCSError, PkiAsn1ErrToHr(Asn1Err))
  13629. SET_ERROR_VAR(DecodeIssuerAndSerialNumberError, PkiAsn1ErrToHr(Asn1Err))
  13630. SET_ERROR(IssuerSizeMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13631. SET_ERROR(IssuerValueMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13632. SET_ERROR(SerialNumberSizeMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13633. SET_ERROR(SerialNumberValueMismatchError,CRYPT_E_ISSUER_SERIALNUMBER)
  13634. SET_ERROR(CountersignerAuthAttributesMissingError,CRYPT_E_AUTH_ATTR_MISSING)
  13635. SET_ERROR(FindAttrError,CRYPT_E_AUTH_ATTR_MISSING)
  13636. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  13637. SET_ERROR(HashCompareSizeError,CRYPT_E_HASH_VALUE)
  13638. SET_ERROR(HashCompareValueError,CRYPT_E_HASH_VALUE)
  13639. TRACE_ERROR(GetCapiFromAlgidBlobError) // error already set
  13640. TRACE_ERROR(CreateHashError) // error already set
  13641. TRACE_ERROR(HashDataError) // error already set
  13642. TRACE_ERROR(GetHashParamSizeError) // error already set
  13643. TRACE_ERROR(AllocHashParamError) // error already set
  13644. TRACE_ERROR(GetHashParamError) // error already set
  13645. TRACE_ERROR(GetAuthAttrsHashError) // error already set
  13646. TRACE_ERROR(GetSignatureStuffError) // error already set
  13647. TRACE_ERROR(VerifySignatureError) // error already set
  13648. }
  13649. #endif // CMS_PKCS7
  13650. //+-------------------------------------------------------------------------
  13651. // Set an OSS Any
  13652. //--------------------------------------------------------------------------
  13653. void
  13654. WINAPI
  13655. ICM_SetOssAny(
  13656. IN PCRYPT_OBJID_BLOB pInfo,
  13657. OUT OpenType *pOss
  13658. )
  13659. {
  13660. memset(pOss, 0, sizeof(*pOss));
  13661. pOss->encoded = pInfo->pbData;
  13662. pOss->length = pInfo->cbData;
  13663. }
  13664. //+-------------------------------------------------------------------------
  13665. // Encode a CMS SignerInfo
  13666. //--------------------------------------------------------------------------
  13667. STATIC
  13668. BOOL
  13669. WINAPI
  13670. ICM_CmsSignerInfoEncode(
  13671. IN DWORD dwEncodingType,
  13672. IN LPCSTR lpszStructType,
  13673. IN PCMSG_CMS_SIGNER_INFO pInfo,
  13674. OUT PBYTE pbEncoded,
  13675. IN OUT PDWORD pcbEncoded)
  13676. {
  13677. DWORD dwError = ERROR_SUCCESS;
  13678. BOOL fRet;
  13679. SignerInfo osi; ZEROSTRUCT(osi);
  13680. PCMSG_CMS_SIGNER_INFO psi = pInfo;
  13681. DWORD i;
  13682. Attribute *poatrAuth = NULL;
  13683. Attribute *poatrUnauth = NULL;
  13684. Attribute *poatr;
  13685. PCRYPT_ATTRIBUTE patr;
  13686. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  13687. goto InvalidEncodingTypeError;
  13688. // version
  13689. osi.version = psi->dwVersion;
  13690. // sid
  13691. if (!ICM_SetOssCertIdentifier(
  13692. &psi->SignerId,
  13693. &osi.sid
  13694. ))
  13695. goto SetOssCertIdentifierError;
  13696. // digestAlgorithm
  13697. if (!ICM_Asn1ToAlgorithmIdentifier(
  13698. &psi->HashAlgorithm,
  13699. &osi.digestAlgorithm))
  13700. goto DigestAsn1ToAlgorithmIdentifierError;
  13701. // authenticatedAttributes
  13702. if (psi->AuthAttrs.cAttr) {
  13703. osi.bit_mask |= authenticatedAttributes_present;
  13704. osi.authenticatedAttributes.count = psi->AuthAttrs.cAttr;
  13705. if (NULL == (poatrAuth = (Attribute *)ICM_AllocA(
  13706. psi->AuthAttrs.cAttr * sizeof(Attribute))))
  13707. goto AllocAuthAttrsError;
  13708. osi.authenticatedAttributes.value = poatrAuth;
  13709. for (i=psi->AuthAttrs.cAttr, patr=psi->AuthAttrs.rgAttr, poatr=poatrAuth;
  13710. i>0;
  13711. i--, patr++, poatr++) {
  13712. if (!ICM_Asn1ToAttribute( patr, poatr))
  13713. goto Asn1AuthenticatedAttributeError;
  13714. }
  13715. }
  13716. // digestEncryptionAlgorithm
  13717. if (!ICM_FillAsnDigestEncryptionAlgorithm(
  13718. NULL, // pcmi
  13719. &psi->HashEncryptionAlgorithm,
  13720. &osi.digestEncryptionAlgorithm))
  13721. goto FillAsnDigestEncryptionAlgorithmError;
  13722. // encryptedDigest
  13723. osi.encryptedDigest.length = psi->EncryptedHash.cbData;
  13724. osi.encryptedDigest.value = psi->EncryptedHash.pbData;
  13725. // unauthenticatedAttributes
  13726. if (psi->UnauthAttrs.cAttr) {
  13727. osi.bit_mask |= unauthAttributes_present;
  13728. osi.unauthAttributes.count = psi->UnauthAttrs.cAttr;
  13729. if (NULL == (poatrUnauth = (Attribute *)ICM_AllocA(
  13730. psi->UnauthAttrs.cAttr * sizeof(Attribute))))
  13731. goto AllocUnauthAttrsError;
  13732. osi.unauthAttributes.value = poatrUnauth;
  13733. for (i=psi->UnauthAttrs.cAttr, patr=psi->UnauthAttrs.rgAttr, poatr=poatrUnauth;
  13734. i>0;
  13735. i--, patr++, poatr++) {
  13736. if (!ICM_Asn1ToAttribute( patr, poatr))
  13737. goto Asn1UnauthenticatedAttributeError;
  13738. }
  13739. }
  13740. fRet = PkiAsn1EncodeInfo(
  13741. ICM_GetEncoder(),
  13742. SignerInfo_PDU,
  13743. &osi,
  13744. pbEncoded,
  13745. pcbEncoded);
  13746. if (!fRet)
  13747. dwError = GetLastError();
  13748. CommonReturn:
  13749. ICM_FreeOssCertIdentifier(&osi.sid);
  13750. if (poatrAuth) {
  13751. for (i=psi->AuthAttrs.cAttr, poatr=poatrAuth;
  13752. i>0;
  13753. i--, poatr++)
  13754. ICM_Free( poatr->attributeValue.value);
  13755. }
  13756. if (poatrUnauth) {
  13757. for (i=psi->UnauthAttrs.cAttr, poatr=poatrUnauth;
  13758. i>0;
  13759. i--, poatr++)
  13760. ICM_Free( poatr->attributeValue.value);
  13761. }
  13762. ICM_FreeA( poatrAuth);
  13763. ICM_FreeA( poatrUnauth);
  13764. ICM_SetLastError(dwError);
  13765. return fRet;
  13766. ErrorReturn:
  13767. dwError = GetLastError();
  13768. fRet = FALSE;
  13769. *pcbEncoded = 0;
  13770. goto CommonReturn;
  13771. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  13772. TRACE_ERROR(SetOssCertIdentifierError) // error already set
  13773. TRACE_ERROR(DigestAsn1ToAlgorithmIdentifierError) // error already set
  13774. TRACE_ERROR(AllocAuthAttrsError) // error already set
  13775. TRACE_ERROR(Asn1AuthenticatedAttributeError) // error already set
  13776. TRACE_ERROR(FillAsnDigestEncryptionAlgorithmError) // error already set
  13777. TRACE_ERROR(AllocUnauthAttrsError) // error already set
  13778. TRACE_ERROR(Asn1UnauthenticatedAttributeError) // error already set
  13779. lpszStructType;
  13780. }
  13781. //+-------------------------------------------------------------------------
  13782. // Encode a Pkcs SignerInfo
  13783. //--------------------------------------------------------------------------
  13784. STATIC
  13785. BOOL
  13786. WINAPI
  13787. ICM_PkcsSignerInfoEncode(
  13788. IN DWORD dwEncodingType,
  13789. IN LPCSTR lpszStructType,
  13790. IN PCMSG_SIGNER_INFO pInfo,
  13791. OUT PBYTE pbEncoded,
  13792. IN OUT PDWORD pcbEncoded)
  13793. {
  13794. CMSG_CMS_SIGNER_INFO csi;
  13795. CERT_INFO CertInfo;
  13796. csi.dwVersion = pInfo->dwVersion;
  13797. CertInfo.Issuer = pInfo->Issuer;
  13798. CertInfo.SerialNumber = pInfo->SerialNumber;
  13799. ICM_GetCertIdFromCertInfo(&CertInfo, &csi.SignerId);
  13800. csi.HashAlgorithm = pInfo->HashAlgorithm;
  13801. csi.HashEncryptionAlgorithm = pInfo->HashEncryptionAlgorithm;
  13802. csi.EncryptedHash = pInfo->EncryptedHash;
  13803. csi.AuthAttrs = pInfo->AuthAttrs;
  13804. csi.UnauthAttrs = pInfo->UnauthAttrs;
  13805. return ICM_CmsSignerInfoEncode(
  13806. dwEncodingType,
  13807. lpszStructType,
  13808. &csi,
  13809. pbEncoded,
  13810. pcbEncoded
  13811. );
  13812. }
  13813. //+-------------------------------------------------------------------------
  13814. // Get fields shared by PKCS and CMS SignerInfos
  13815. //--------------------------------------------------------------------------
  13816. BOOL
  13817. WINAPI
  13818. ICM_GetOssSharedSignerInfo(
  13819. IN SignerInfo *posi,
  13820. IN CBlobList *pUnauthAttrList,
  13821. OUT PCRYPT_ALGORITHM_IDENTIFIER pHashAlgorithm,
  13822. OUT PCRYPT_ALGORITHM_IDENTIFIER pHashEncryptionAlgorithm,
  13823. OUT PCRYPT_DATA_BLOB pEncryptedHash,
  13824. OUT PCRYPT_ATTRIBUTES pAuthAttrs,
  13825. OUT PCRYPT_ATTRIBUTES pUnauthAttrs,
  13826. IN OUT PBYTE *ppbExtra,
  13827. IN OUT LONG *plRemainExtra)
  13828. {
  13829. BOOL fRet;
  13830. if (!ICM_GetOssAlgorithm( &posi->digestAlgorithm,
  13831. pHashAlgorithm, ppbExtra, plRemainExtra))
  13832. goto GetOssHashAlgorithmError;
  13833. if (!ICM_GetOssAlgorithm( &posi->digestEncryptionAlgorithm,
  13834. pHashEncryptionAlgorithm, ppbExtra, plRemainExtra))
  13835. goto GetOssHashEncryptionAlgorithmError;
  13836. if (!ICM_GetOssAny( (Any *)&posi->encryptedDigest,
  13837. pEncryptedHash, ppbExtra, plRemainExtra))
  13838. goto GetOssEncryptedHashError;
  13839. if (posi->bit_mask & authenticatedAttributes_present) {
  13840. if (!ICM_GetOssAttributes( &posi->authenticatedAttributes,
  13841. pAuthAttrs, ppbExtra, plRemainExtra))
  13842. goto GetOssAuthAttrsError;
  13843. } else if (0 <= *plRemainExtra)
  13844. pAuthAttrs->cAttr = 0;
  13845. if (posi->bit_mask & unauthAttributes_present || pUnauthAttrList) {
  13846. if (pUnauthAttrList) {
  13847. if (!ICM_GetCListAttributes( pUnauthAttrList,
  13848. pUnauthAttrs, ppbExtra, plRemainExtra))
  13849. goto GetCListUnauthAttrsError;
  13850. } else {
  13851. if (!ICM_GetOssAttributes( &posi->unauthAttributes,
  13852. pUnauthAttrs, ppbExtra, plRemainExtra))
  13853. goto GetOssUnauthAttrsError;
  13854. }
  13855. } else if (0 <= *plRemainExtra)
  13856. pUnauthAttrs->cAttr = 0;
  13857. fRet = TRUE;
  13858. CommonReturn:
  13859. return fRet;
  13860. ErrorReturn:
  13861. fRet = FALSE;
  13862. goto CommonReturn;
  13863. TRACE_ERROR(GetOssHashAlgorithmError) // error already set
  13864. TRACE_ERROR(GetOssHashEncryptionAlgorithmError) // error already set
  13865. TRACE_ERROR(GetOssEncryptedHashError) // error already set
  13866. TRACE_ERROR(GetOssAuthAttrsError) // error already set
  13867. TRACE_ERROR(GetCListUnauthAttrsError) // error already set
  13868. TRACE_ERROR(GetOssUnauthAttrsError) // error already set
  13869. }
  13870. //+-------------------------------------------------------------------------
  13871. // Get a CMS SignerInfo
  13872. //--------------------------------------------------------------------------
  13873. BOOL
  13874. WINAPI
  13875. ICM_GetOssCmsSignerInfo(
  13876. IN SignerInfo *posi,
  13877. IN CBlobList *pUnauthAttrList,
  13878. OUT PCMSG_CMS_SIGNER_INFO psi,
  13879. IN OUT PBYTE *ppbExtra,
  13880. IN OUT LONG *plRemainExtra)
  13881. {
  13882. BOOL fRet;
  13883. if (0 <= *plRemainExtra)
  13884. psi->dwVersion = posi->version;
  13885. if (!ICM_GetOssCertIdentifier(&posi->sid, &psi->SignerId,
  13886. ppbExtra, plRemainExtra))
  13887. goto GetOssCertIdentifierError;
  13888. if (!ICM_GetOssSharedSignerInfo(
  13889. posi,
  13890. pUnauthAttrList,
  13891. &psi->HashAlgorithm,
  13892. &psi->HashEncryptionAlgorithm,
  13893. &psi->EncryptedHash,
  13894. &psi->AuthAttrs,
  13895. &psi->UnauthAttrs,
  13896. ppbExtra,
  13897. plRemainExtra))
  13898. goto GetOssSharedSignerInfoError;
  13899. fRet = TRUE;
  13900. CommonReturn:
  13901. return fRet;
  13902. ErrorReturn:
  13903. fRet = FALSE;
  13904. goto CommonReturn;
  13905. TRACE_ERROR(GetOssCertIdentifierError) // error already set
  13906. TRACE_ERROR(GetOssSharedSignerInfoError) // error already set
  13907. }
  13908. //+-------------------------------------------------------------------------
  13909. // Get a PKCS SignerInfo
  13910. //--------------------------------------------------------------------------
  13911. BOOL
  13912. WINAPI
  13913. ICM_GetOssPkcsSignerInfo(
  13914. IN SignerInfo *posi,
  13915. IN CBlobList *pUnauthAttrList,
  13916. OUT PCMSG_SIGNER_INFO psi,
  13917. IN OUT PBYTE *ppbExtra,
  13918. IN OUT LONG *plRemainExtra)
  13919. {
  13920. BOOL fRet;
  13921. if (0 <= *plRemainExtra)
  13922. psi->dwVersion = posi->version;
  13923. if (!ICM_GetOssIssuerAndSerialNumberFromCertId(&posi->sid,
  13924. &psi->Issuer, &psi->SerialNumber, ppbExtra, plRemainExtra))
  13925. goto GetOssIssuerAndSerialNumberError;
  13926. if (!ICM_GetOssSharedSignerInfo(
  13927. posi,
  13928. pUnauthAttrList,
  13929. &psi->HashAlgorithm,
  13930. &psi->HashEncryptionAlgorithm,
  13931. &psi->EncryptedHash,
  13932. &psi->AuthAttrs,
  13933. &psi->UnauthAttrs,
  13934. ppbExtra,
  13935. plRemainExtra))
  13936. goto GetOssSharedSignerInfoError;
  13937. fRet = TRUE;
  13938. CommonReturn:
  13939. return fRet;
  13940. ErrorReturn:
  13941. fRet = FALSE;
  13942. goto CommonReturn;
  13943. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  13944. TRACE_ERROR(GetOssSharedSignerInfoError) // error already set
  13945. }
  13946. //+-------------------------------------------------------------------------
  13947. // Decode a PKCS SignerInfo blob.
  13948. //
  13949. // Returns: FALSE iff fails
  13950. //--------------------------------------------------------------------------
  13951. STATIC
  13952. BOOL
  13953. WINAPI
  13954. ICM_PkcsSignerInfoDecode(
  13955. IN DWORD dwEncodingType,
  13956. IN LPCSTR lpszStructType,
  13957. IN const BYTE *pbEncoded,
  13958. IN DWORD cbEncoded,
  13959. IN DWORD dwFlags,
  13960. OUT PCMSG_SIGNER_INFO pInfo,
  13961. IN OUT DWORD *pcbInfo)
  13962. {
  13963. DWORD dwError = ERROR_SUCCESS;
  13964. BOOL fRet;
  13965. LONG lData;
  13966. SignerInfo *posi = NULL;
  13967. ASN1error_e Asn1Err;
  13968. ASN1decoding_t pDec = ICM_GetDecoder();
  13969. PCMSG_SIGNER_INFO psi = pInfo;
  13970. LONG lRemainExtra;
  13971. PBYTE pbExtra;
  13972. if (pInfo == NULL)
  13973. *pcbInfo = 0;
  13974. if (0 != (Asn1Err = PkiAsn1Decode(
  13975. pDec,
  13976. (void **)&posi,
  13977. SignerInfo_PDU,
  13978. pbEncoded,
  13979. cbEncoded)))
  13980. goto Asn1DecodeSignerInfoError;
  13981. // for lRemainExtra < 0, LENGTH_ONLY calculation
  13982. lData = INFO_LEN_ALIGN( sizeof(CMSG_SIGNER_INFO));
  13983. lRemainExtra = (LONG)*pcbInfo - lData;
  13984. if (0 > lRemainExtra) {
  13985. psi = NULL;
  13986. pbExtra = NULL;
  13987. } else {
  13988. pbExtra = (PBYTE)psi + lData;
  13989. }
  13990. if (!ICM_GetOssPkcsSignerInfo(
  13991. posi,
  13992. NULL, // pUnauthAttrList
  13993. psi, &pbExtra, &lRemainExtra))
  13994. goto GetOssSignerInfoError;
  13995. fRet = ICM_GetSizeFromExtra( lRemainExtra, pInfo, pcbInfo);
  13996. if (!fRet)
  13997. dwError = GetLastError();
  13998. CommonReturn:
  13999. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14000. ICM_SetLastError(dwError);
  14001. return fRet;
  14002. ErrorReturn:
  14003. dwError = GetLastError();
  14004. *pcbInfo = 0;
  14005. fRet = FALSE;
  14006. goto CommonReturn;
  14007. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14008. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14009. dwFlags;
  14010. lpszStructType;
  14011. }
  14012. //+-------------------------------------------------------------------------
  14013. // Find the Pkcs SignerInfo by index, if the message type permits and if the
  14014. // index value is in range.
  14015. //
  14016. // Returns: FALSE iff fails
  14017. //--------------------------------------------------------------------------
  14018. BOOL
  14019. WINAPI
  14020. ICM_GetPkcsSignerInfo(
  14021. IN PCRYPT_MSG_INFO pcmi,
  14022. IN DWORD dwIndex,
  14023. OUT PVOID pvData,
  14024. IN OUT PDWORD pcbData)
  14025. {
  14026. DWORD dwError = ERROR_SUCCESS;
  14027. BOOL fRet;
  14028. LONG lData;
  14029. CSignerNode *pSignerNode;
  14030. SignerInfo *posi = NULL;
  14031. ASN1error_e Asn1Err;
  14032. ASN1decoding_t pDec = ICM_GetDecoder();
  14033. CRYPT_DATA_BLOB DataBlob;
  14034. PCMSG_SIGNER_INFO psi = (PCMSG_SIGNER_INFO)pvData;
  14035. LONG lRemainExtra;
  14036. PBYTE pbExtra;
  14037. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14038. goto FindSignerInfoError;
  14039. DataBlob = pSignerNode->Data()->blob;
  14040. if (0 != (Asn1Err = PkiAsn1Decode(
  14041. pDec,
  14042. (void **)&posi,
  14043. SignerInfo_PDU,
  14044. DataBlob.pbData,
  14045. DataBlob.cbData)))
  14046. goto Asn1DecodeSignerInfoError;
  14047. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14048. lData = INFO_LEN_ALIGN( sizeof(CMSG_SIGNER_INFO));
  14049. lRemainExtra = (LONG)*pcbData - lData;
  14050. if (0 > lRemainExtra) {
  14051. psi = NULL;
  14052. pbExtra = NULL;
  14053. } else {
  14054. pbExtra = (PBYTE)psi + lData;
  14055. }
  14056. if (!ICM_GetOssPkcsSignerInfo( posi, pSignerNode->Data()->pUnauthAttrList,
  14057. psi, &pbExtra, &lRemainExtra))
  14058. goto GetOssSignerInfoError;
  14059. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  14060. if (!fRet)
  14061. dwError = GetLastError();
  14062. CommonReturn:
  14063. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14064. ICM_SetLastError(dwError);
  14065. return fRet;
  14066. ErrorReturn:
  14067. dwError = GetLastError();
  14068. *pcbData = 0;
  14069. fRet = FALSE;
  14070. goto CommonReturn;
  14071. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14072. TRACE_ERROR(FindSignerInfoError) // error already set
  14073. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14074. }
  14075. //+-------------------------------------------------------------------------
  14076. // Decode a CMS SignerInfo blob.
  14077. //
  14078. // Returns: FALSE iff fails
  14079. //--------------------------------------------------------------------------
  14080. STATIC
  14081. BOOL
  14082. WINAPI
  14083. ICM_CmsSignerInfoDecode(
  14084. IN DWORD dwEncodingType,
  14085. IN LPCSTR lpszStructType,
  14086. IN const BYTE *pbEncoded,
  14087. IN DWORD cbEncoded,
  14088. IN DWORD dwFlags,
  14089. OUT PCMSG_CMS_SIGNER_INFO pInfo,
  14090. IN OUT DWORD *pcbInfo)
  14091. {
  14092. DWORD dwError = ERROR_SUCCESS;
  14093. BOOL fRet;
  14094. LONG lData;
  14095. SignerInfo *posi = NULL;
  14096. ASN1error_e Asn1Err;
  14097. ASN1decoding_t pDec = ICM_GetDecoder();
  14098. PCMSG_CMS_SIGNER_INFO psi = pInfo;
  14099. LONG lRemainExtra;
  14100. PBYTE pbExtra;
  14101. if (pInfo == NULL)
  14102. *pcbInfo = 0;
  14103. if (0 != (Asn1Err = PkiAsn1Decode(
  14104. pDec,
  14105. (void **)&posi,
  14106. SignerInfo_PDU,
  14107. pbEncoded,
  14108. cbEncoded)))
  14109. goto Asn1DecodeSignerInfoError;
  14110. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14111. lData = INFO_LEN_ALIGN( sizeof(CMSG_CMS_SIGNER_INFO));
  14112. lRemainExtra = (LONG)*pcbInfo - lData;
  14113. if (0 > lRemainExtra) {
  14114. psi = NULL;
  14115. pbExtra = NULL;
  14116. } else {
  14117. pbExtra = (PBYTE)psi + lData;
  14118. }
  14119. if (!ICM_GetOssCmsSignerInfo(
  14120. posi,
  14121. NULL, // pUnauthAttrList
  14122. psi, &pbExtra, &lRemainExtra))
  14123. goto GetOssSignerInfoError;
  14124. fRet = ICM_GetSizeFromExtra( lRemainExtra, pInfo, pcbInfo);
  14125. if (!fRet)
  14126. dwError = GetLastError();
  14127. CommonReturn:
  14128. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14129. ICM_SetLastError(dwError);
  14130. return fRet;
  14131. ErrorReturn:
  14132. dwError = GetLastError();
  14133. *pcbInfo = 0;
  14134. fRet = FALSE;
  14135. goto CommonReturn;
  14136. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14137. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14138. dwFlags;
  14139. lpszStructType;
  14140. }
  14141. //+-------------------------------------------------------------------------
  14142. // Find the CMS SignerInfo by index, if the message type permits and if the
  14143. // index value is in range.
  14144. //
  14145. // Returns: FALSE iff fails
  14146. //--------------------------------------------------------------------------
  14147. BOOL
  14148. WINAPI
  14149. ICM_GetCmsSignerInfo(
  14150. IN PCRYPT_MSG_INFO pcmi,
  14151. IN DWORD dwIndex,
  14152. OUT PVOID pvData,
  14153. IN OUT PDWORD pcbData)
  14154. {
  14155. DWORD dwError = ERROR_SUCCESS;
  14156. BOOL fRet;
  14157. LONG lData;
  14158. CSignerNode *pSignerNode;
  14159. SignerInfo *posi = NULL;
  14160. ASN1error_e Asn1Err;
  14161. ASN1decoding_t pDec = ICM_GetDecoder();
  14162. CRYPT_DATA_BLOB DataBlob;
  14163. PCMSG_CMS_SIGNER_INFO psi = (PCMSG_CMS_SIGNER_INFO)pvData;
  14164. LONG lRemainExtra;
  14165. PBYTE pbExtra;
  14166. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14167. goto FindSignerInfoError;
  14168. DataBlob = pSignerNode->Data()->blob;
  14169. if (0 != (Asn1Err = PkiAsn1Decode(
  14170. pDec,
  14171. (void **)&posi,
  14172. SignerInfo_PDU,
  14173. DataBlob.pbData,
  14174. DataBlob.cbData)))
  14175. goto Asn1DecodeSignerInfoError;
  14176. // for lRemainExtra < 0, LENGTH_ONLY calculation
  14177. lData = INFO_LEN_ALIGN( sizeof(CMSG_CMS_SIGNER_INFO));
  14178. lRemainExtra = (LONG)*pcbData - lData;
  14179. if (0 > lRemainExtra) {
  14180. psi = NULL;
  14181. pbExtra = NULL;
  14182. } else {
  14183. pbExtra = (PBYTE)psi + lData;
  14184. }
  14185. if (!ICM_GetOssCmsSignerInfo( posi, pSignerNode->Data()->pUnauthAttrList,
  14186. psi, &pbExtra, &lRemainExtra))
  14187. goto GetOssSignerInfoError;
  14188. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  14189. if (!fRet)
  14190. dwError = GetLastError();
  14191. CommonReturn:
  14192. PkiAsn1FreeInfo(pDec, SignerInfo_PDU, posi);
  14193. ICM_SetLastError(dwError);
  14194. return fRet;
  14195. ErrorReturn:
  14196. dwError = GetLastError();
  14197. *pcbData = 0;
  14198. fRet = FALSE;
  14199. goto CommonReturn;
  14200. SET_ERROR_VAR(Asn1DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14201. TRACE_ERROR(FindSignerInfoError) // error already set
  14202. TRACE_ERROR(GetOssSignerInfoError) // error already set
  14203. }
  14204. //+-------------------------------------------------------------------------
  14205. // Get the data for a field in a Signer, while encoding a message
  14206. //--------------------------------------------------------------------------
  14207. BOOL
  14208. WINAPI
  14209. ICM_GetSignerParamEncoding(
  14210. IN PCRYPT_MSG_INFO pcmi,
  14211. IN DWORD dwIndex,
  14212. IN DWORD dwParamType,
  14213. OUT PVOID pvData,
  14214. IN OUT PDWORD pcbData)
  14215. {
  14216. DWORD dwError = ERROR_SUCCESS;
  14217. BOOL fRet;
  14218. ASN1error_e Asn1Err;
  14219. ASN1encoding_t pEnc = ICM_GetEncoder();
  14220. PBYTE pbEncoded = NULL;
  14221. DWORD cbEncoded;
  14222. SignerInfo *posi = NULL;
  14223. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&posi))
  14224. goto FindSignerInfoError;
  14225. switch (dwParamType) {
  14226. case CMSG_ENCODED_SIGNER:
  14227. if (0 != (Asn1Err = PkiAsn1Encode(
  14228. pEnc,
  14229. posi,
  14230. SignerInfo_PDU,
  14231. &pbEncoded,
  14232. &cbEncoded)))
  14233. goto EncodeSignerInfoError;
  14234. break;
  14235. default:
  14236. goto InvalidParamError;
  14237. }
  14238. fRet = ICM_CopyOut(
  14239. pbEncoded,
  14240. cbEncoded,
  14241. (PBYTE)pvData,
  14242. pcbData);
  14243. if (!fRet)
  14244. dwError = GetLastError();
  14245. CommonReturn:
  14246. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  14247. ICM_SetLastError(dwError);
  14248. return fRet;
  14249. ErrorReturn:
  14250. dwError = GetLastError();
  14251. fRet = FALSE;
  14252. goto CommonReturn;
  14253. TRACE_ERROR(FindSignerInfoError) // error already set
  14254. SET_ERROR_VAR(EncodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14255. SET_ERROR(InvalidParamError,E_INVALIDARG)
  14256. }
  14257. //+-------------------------------------------------------------------------
  14258. // Get the data for a field in a Signer
  14259. //--------------------------------------------------------------------------
  14260. BOOL
  14261. WINAPI
  14262. ICM_GetSignerParam(
  14263. IN PCRYPT_MSG_INFO pcmi,
  14264. IN DWORD dwIndex,
  14265. IN DWORD dwParamType,
  14266. OUT PVOID pvData,
  14267. IN OUT PDWORD pcbData)
  14268. {
  14269. DWORD dwError = ERROR_SUCCESS;
  14270. BOOL fRet;
  14271. ASN1error_e Asn1Err;
  14272. ASN1decoding_t pDec = ICM_GetDecoder();
  14273. CRYPT_DATA_BLOB DataBlob;
  14274. ASN1uint32_t pdunumRef = 0; // invalid
  14275. SignerInfoWithBlobs *posib = NULL;
  14276. PVOID pv = NULL;
  14277. CSignerNode *pSignerNode;
  14278. if (!ICM_FindSignerInfo( pcmi, dwIndex, (PVOID *)&pSignerNode))
  14279. goto FindSignerInfoError;
  14280. DataBlob = pSignerNode->Data()->blob;
  14281. if (0 != (Asn1Err = PkiAsn1Decode(
  14282. pDec,
  14283. (void **)&posib,
  14284. SignerInfoWithBlobs_PDU,
  14285. DataBlob.pbData,
  14286. DataBlob.cbData)))
  14287. goto DecodeSignerInfoError;
  14288. switch (dwParamType) {
  14289. case CMSG_SIGNER_INFO_PARAM:
  14290. fRet = ICM_GetPkcsSignerInfo( pcmi, dwIndex, pvData, pcbData);
  14291. break;
  14292. case CMSG_CMS_SIGNER_INFO_PARAM:
  14293. fRet = ICM_GetCmsSignerInfo( pcmi, dwIndex, pvData, pcbData);
  14294. break;
  14295. case CMSG_ENCRYPTED_DIGEST:
  14296. fRet = ICM_CopyOut(
  14297. (PBYTE)posib->encryptedDigest.value,
  14298. (DWORD)posib->encryptedDigest.length,
  14299. (PBYTE)pvData,
  14300. pcbData);
  14301. break;
  14302. case CMSG_ENCODED_SIGNER:
  14303. if (pSignerNode->Data()->pUnauthAttrList) {
  14304. // Need to re-encode with new unauth attrs
  14305. goto ReEncodedSignerNotImplementedError;
  14306. } else {
  14307. fRet = ICM_CopyOut(
  14308. pSignerNode->Data()->blob.pbData,
  14309. pSignerNode->Data()->blob.cbData,
  14310. (PBYTE)pvData,
  14311. pcbData);
  14312. }
  14313. break;
  14314. case CMSG_SIGNER_CERT_INFO_PARAM:
  14315. case CMSG_SIGNER_CERT_ID_PARAM:
  14316. pdunumRef = CertIdentifier_PDU;
  14317. if (0 != (Asn1Err = PkiAsn1Decode(
  14318. pDec,
  14319. &pv,
  14320. pdunumRef,
  14321. (BYTE *) posib->sid.value,
  14322. posib->sid.length)))
  14323. goto DecodeCertIdentifierError;
  14324. if (CMSG_SIGNER_CERT_INFO_PARAM == dwParamType)
  14325. fRet = ICM_GetCertInfoIssuerAndSerialNumber(
  14326. (CertIdentifier *)pv,
  14327. pvData,
  14328. pcbData);
  14329. else
  14330. fRet = ICM_GetCertId(
  14331. (CertIdentifier *)pv,
  14332. pvData,
  14333. pcbData);
  14334. break;
  14335. case CMSG_SIGNER_HASH_ALGORITHM_PARAM:
  14336. pdunumRef = AlgorithmIdentifierNC2_PDU;
  14337. if (0 != (Asn1Err = PkiAsn1Decode(
  14338. pDec,
  14339. &pv,
  14340. pdunumRef,
  14341. (BYTE *) posib->digestAlgorithm.value,
  14342. posib->digestAlgorithm.length)))
  14343. goto DecodeAlgorithmIdentifierNC2Error;
  14344. fRet = ICM_GetALGORITHM_IDENTIFIER(
  14345. (AlgorithmIdentifier *)pv,
  14346. pvData,
  14347. pcbData);
  14348. break;
  14349. case CMSG_SIGNER_AUTH_ATTR_PARAM:
  14350. if (posib->bit_mask & authAttributes_present)
  14351. fRet = ICM_GetAttributesData(
  14352. (Attributes *)&posib->authAttributes,
  14353. pvData,
  14354. pcbData);
  14355. else
  14356. goto AuthAttrMissingError;
  14357. break;
  14358. case CMSG_SIGNER_UNAUTH_ATTR_PARAM:
  14359. if (posib->bit_mask & unauthAttributes_present)
  14360. fRet = ICM_GetAttributesData(
  14361. (Attributes *)&posib->unauthAttributes,
  14362. pvData,
  14363. pcbData);
  14364. else
  14365. goto UnauthAttrMissingError;
  14366. break;
  14367. default:
  14368. goto InvalidParamError;
  14369. }
  14370. if (!fRet)
  14371. dwError = GetLastError();
  14372. CommonReturn:
  14373. PkiAsn1FreeInfo(pDec, SignerInfoWithBlobs_PDU, posib);
  14374. PkiAsn1FreeInfo(pDec, pdunumRef, pv);
  14375. ICM_SetLastError(dwError);
  14376. return fRet;
  14377. ErrorReturn:
  14378. dwError = GetLastError();
  14379. *pcbData = 0;
  14380. fRet = FALSE;
  14381. goto CommonReturn;
  14382. SET_ERROR_VAR(DecodeSignerInfoError, PkiAsn1ErrToHr(Asn1Err))
  14383. SET_ERROR_VAR(DecodeCertIdentifierError, PkiAsn1ErrToHr(Asn1Err))
  14384. SET_ERROR_VAR(DecodeAlgorithmIdentifierNC2Error, PkiAsn1ErrToHr(Asn1Err))
  14385. SET_ERROR(AuthAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  14386. SET_ERROR(UnauthAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  14387. SET_ERROR(ReEncodedSignerNotImplementedError,E_INVALIDARG)
  14388. SET_ERROR(InvalidParamError,E_INVALIDARG)
  14389. TRACE_ERROR(FindSignerInfoError) // error already set
  14390. }
  14391. //+-------------------------------------------------------------------------
  14392. // Get the encoded blob for a SignerInfo
  14393. //--------------------------------------------------------------------------
  14394. BOOL
  14395. WINAPI
  14396. ICM_GetEncodedSignerInfo(
  14397. IN DWORD dwEncodingType,
  14398. IN PSIGNER_DATA_INFO pSignerInfo,
  14399. OUT PBYTE pbSignerInfo,
  14400. IN OUT PDWORD pcbSignerInfo)
  14401. {
  14402. DWORD dwError = ERROR_SUCCESS;
  14403. BOOL fRet;
  14404. SignerInfoWithAttrBlobs *posiab = NULL;
  14405. Any *pAnyAttr = NULL;
  14406. Any *pAny;
  14407. DWORD cAnyAttr;
  14408. AttributesNC unauthAttributesSave;
  14409. ZEROSTRUCT(unauthAttributesSave);
  14410. #ifdef OSS_CRYPT_ASN1
  14411. BYTE bit_maskSave = 0;
  14412. #else
  14413. ASN1uint16_t bit_maskSave = 0;
  14414. #endif // OSS_CRYPT_ASN1
  14415. ASN1error_e Asn1Err;
  14416. ASN1decoding_t pDec = ICM_GetDecoder();
  14417. ASN1encoding_t pEnc = ICM_GetEncoder();
  14418. PBYTE pbEncoded = NULL;
  14419. DWORD cbEncoded;
  14420. CBlobNode *pnBlob;
  14421. DWORD cbOut;
  14422. PBYTE pbOut;
  14423. if (GET_CMSG_ENCODING_TYPE(dwEncodingType) != PKCS_7_ASN_ENCODING)
  14424. goto InvalidEncodingTypeError;
  14425. if (pSignerInfo->pUnauthAttrList) {
  14426. if (0 != (Asn1Err = PkiAsn1Decode(
  14427. pDec,
  14428. (void **)&posiab,
  14429. SignerInfoWithAttrBlobs_PDU,
  14430. pSignerInfo->blob.pbData,
  14431. pSignerInfo->blob.cbData)))
  14432. goto DecodeSignerInfoWithAttrBlobsError;
  14433. // We have to take into account both the case where we have added
  14434. // unauth attrs, and the case where we have removed them. There might
  14435. // have been unauth attrs in the original message, and we removed
  14436. // them all. Or, there might have been none originally, and we added
  14437. // some.
  14438. bit_maskSave = posiab->bit_mask;
  14439. unauthAttributesSave = posiab->unauthAttributes;
  14440. cAnyAttr = pSignerInfo->pUnauthAttrList->Length();
  14441. posiab->bit_mask &= ~unauthAttributes_present;
  14442. posiab->bit_mask |= (cAnyAttr > 0) ? unauthAttributes_present : 0;
  14443. if (NULL == (pAnyAttr = (Any *)ICM_AllocA( cAnyAttr * sizeof(Any))))
  14444. goto AllocAnyAttrError;
  14445. posiab->unauthAttributes.count = cAnyAttr;
  14446. posiab->unauthAttributes.value = pAnyAttr;
  14447. for (pnBlob=pSignerInfo->pUnauthAttrList->Head(), pAny=pAnyAttr;
  14448. pnBlob;
  14449. pnBlob=pnBlob->Next(), pAny++)
  14450. *pAny = *(Any *)pnBlob->Data();
  14451. if (0 != (Asn1Err = PkiAsn1Encode(
  14452. pEnc,
  14453. posiab,
  14454. SignerInfoWithAttrBlobs_PDU,
  14455. &pbEncoded,
  14456. &cbEncoded)))
  14457. goto EncodeSignerInfoWithAttrBlobsError;
  14458. cbOut = cbEncoded;
  14459. pbOut = pbEncoded;
  14460. } else {
  14461. cbOut = pSignerInfo->blob.cbData;
  14462. pbOut = pSignerInfo->blob.pbData;
  14463. }
  14464. fRet = ICM_CopyOut(
  14465. pbOut,
  14466. cbOut,
  14467. pbSignerInfo,
  14468. pcbSignerInfo);
  14469. if (!fRet)
  14470. dwError = GetLastError();
  14471. CommonReturn:
  14472. ICM_FreeA( pAnyAttr);
  14473. if (posiab) {
  14474. posiab->bit_mask = bit_maskSave;
  14475. posiab->unauthAttributes = unauthAttributesSave;
  14476. PkiAsn1FreeDecoded(pDec, posiab, SignerInfoWithAttrBlobs_PDU);
  14477. }
  14478. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  14479. ICM_SetLastError(dwError);
  14480. return fRet;
  14481. ErrorReturn:
  14482. dwError = GetLastError();
  14483. fRet = FALSE;
  14484. goto CommonReturn;
  14485. SET_ERROR(InvalidEncodingTypeError,E_INVALIDARG)
  14486. SET_ERROR_VAR(DecodeSignerInfoWithAttrBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14487. SET_ERROR_VAR(EncodeSignerInfoWithAttrBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14488. TRACE_ERROR(AllocAnyAttrError) // error already set
  14489. }
  14490. //+-------------------------------------------------------------------------
  14491. // Get the data for a field in a Signer
  14492. //--------------------------------------------------------------------------
  14493. BOOL
  14494. WINAPI
  14495. ICM_GetEncodedMessageParam(
  14496. IN PCRYPT_MSG_INFO pcmi,
  14497. OUT PBYTE pbEncodedMessage,
  14498. IN OUT PDWORD pcbEncodedMessage)
  14499. {
  14500. DWORD dwError = ERROR_SUCCESS;
  14501. BOOL fRet;
  14502. SignedDataWithBlobs *posdb = NULL;
  14503. PSIGNED_DATA_INFO psdi = pcmi->psdi;
  14504. Any *pAny;
  14505. PSIGNER_DATA_INFO pSignerInfo;
  14506. ASN1error_e Asn1Err;
  14507. ASN1encoding_t pEnc = ICM_GetEncoder();
  14508. PBYTE pbEncodedSignedData = NULL;
  14509. DWORD cbEncodedSignedData;
  14510. PBYTE pbEncodedContentInfo = NULL;
  14511. DWORD cbEncodedContentInfo;
  14512. CSignerNode *pnSigner;
  14513. CBlobNode *pnBlob;
  14514. DWORD cb;
  14515. PBYTE pb;
  14516. DWORD i;
  14517. ContentInfo ci;
  14518. if (NULL == (posdb = (SignedDataWithBlobs *)ICM_AllocZeroA(
  14519. sizeof(SignedDataWithBlobs) +
  14520. sizeof(Any) *
  14521. (psdi->pAlgidList->Length() +
  14522. psdi->pCertificateList->Length() +
  14523. psdi->pCrlList->Length() +
  14524. psdi->pSignerList->Length()))))
  14525. goto AllocSignedDataWithBlobsError;
  14526. pAny = (Any *)(posdb + 1);
  14527. // version
  14528. posdb->version = psdi->version;
  14529. // digest algorithms
  14530. posdb->digestAlgorithms.count = psdi->pAlgidList->Length();
  14531. posdb->digestAlgorithms.value = pAny;
  14532. for (pnBlob=psdi->pAlgidList->Head();
  14533. pnBlob;
  14534. pnBlob=pnBlob->Next())
  14535. *pAny++ = *(Any *)pnBlob->Data();
  14536. // contentInfo
  14537. posdb->contentInfo.contentType.count = SIZE_OSS_OID;
  14538. if (!PkiAsn1ToObjectIdentifier(
  14539. psdi->pci->pszContentType,
  14540. &posdb->contentInfo.contentType.count,
  14541. posdb->contentInfo.contentType.value))
  14542. goto PkiAsn1ToObjectIdentifierError;
  14543. if (psdi->pci->content.cbData) {
  14544. posdb->contentInfo.bit_mask |= content_present;
  14545. posdb->contentInfo.content.length = psdi->pci->content.cbData;
  14546. posdb->contentInfo.content.value = psdi->pci->content.pbData;
  14547. }
  14548. // certificates
  14549. posdb->certificates.count = psdi->pCertificateList->Length();
  14550. #ifdef OSS_CRYPT_ASN1
  14551. posdb->certificates.certificates = pAny;
  14552. #else
  14553. posdb->certificates.value = pAny;
  14554. #endif // OSS_CRYPT_ASN1
  14555. for (pnBlob=psdi->pCertificateList->Head();
  14556. pnBlob;
  14557. pnBlob=pnBlob->Next()) {
  14558. posdb->bit_mask |= certificates_present;
  14559. *pAny++ = *(Any *)pnBlob->Data();
  14560. }
  14561. // crls
  14562. posdb->crls.count = psdi->pCrlList->Length();
  14563. #ifdef OSS_CRYPT_ASN1
  14564. posdb->crls.crls = pAny;
  14565. #else
  14566. posdb->crls.value = pAny;
  14567. #endif // OSS_CRYPT_ASN1
  14568. for (pnBlob=psdi->pCrlList->Head();
  14569. pnBlob;
  14570. pnBlob=pnBlob->Next()) {
  14571. posdb->bit_mask |= crls_present;
  14572. *pAny++ = *(Any *)pnBlob->Data();
  14573. }
  14574. // signerInfos
  14575. posdb->signerInfos.count = psdi->pSignerList->Length();
  14576. posdb->signerInfos.value = pAny;
  14577. for (pnSigner=psdi->pSignerList->Head();
  14578. pnSigner;
  14579. pnSigner=pnSigner->Next()) {
  14580. pSignerInfo = pnSigner->Data();
  14581. if (!ICM_GetEncodedSignerInfo(
  14582. PKCS_7_ASN_ENCODING,
  14583. pnSigner->Data(),
  14584. NULL,
  14585. &cb))
  14586. goto GetEncodedSignerInfoSizeError;
  14587. if (NULL == (pb = (PBYTE)ICM_AllocA( cb)))
  14588. goto AllocEncodedSignerInfoError;
  14589. if (!ICM_GetEncodedSignerInfo(
  14590. PKCS_7_ASN_ENCODING,
  14591. pnSigner->Data(),
  14592. pb,
  14593. &cb))
  14594. goto GetEncodedSignerInfoError;
  14595. pAny->length = cb;
  14596. pAny->value = pb;
  14597. pAny++;
  14598. }
  14599. if (0 != (Asn1Err = PkiAsn1Encode(
  14600. pEnc,
  14601. posdb,
  14602. SignedDataWithBlobs_PDU,
  14603. &pbEncodedSignedData,
  14604. &cbEncodedSignedData)))
  14605. goto EncodeSignedDataWithBlobsError;
  14606. ci.contentType.count = SIZE_OSS_OID;
  14607. if (!PkiAsn1ToObjectIdentifier(
  14608. szOID_RSA_signedData,
  14609. &ci.contentType.count,
  14610. ci.contentType.value))
  14611. goto ConvSignedDataToOidError;
  14612. ci.bit_mask = content_present;
  14613. ci.content.length = cbEncodedSignedData;
  14614. ci.content.value = pbEncodedSignedData;
  14615. if (0 != (Asn1Err = PkiAsn1Encode(
  14616. pEnc,
  14617. &ci,
  14618. ContentInfo_PDU,
  14619. &pbEncodedContentInfo,
  14620. &cbEncodedContentInfo)))
  14621. goto EncodeContentInfoError;
  14622. fRet = ICM_CopyOut(
  14623. pbEncodedContentInfo,
  14624. cbEncodedContentInfo,
  14625. pbEncodedMessage,
  14626. pcbEncodedMessage);
  14627. if (!fRet)
  14628. dwError = GetLastError();
  14629. CommonReturn:
  14630. PkiAsn1FreeEncoded(pEnc, pbEncodedSignedData);
  14631. PkiAsn1FreeEncoded(pEnc, pbEncodedContentInfo);
  14632. if (NULL != posdb) {
  14633. for (i=posdb->signerInfos.count, pAny=posdb->signerInfos.value;
  14634. i>0;
  14635. i--, pAny++)
  14636. ICM_FreeA( pAny->value);
  14637. ICM_FreeA(posdb);
  14638. }
  14639. ICM_SetLastError(dwError);
  14640. return fRet;
  14641. ErrorReturn:
  14642. dwError = GetLastError();
  14643. fRet = FALSE;
  14644. goto CommonReturn;
  14645. SET_ERROR(PkiAsn1ToObjectIdentifierError,CRYPT_E_OID_FORMAT)
  14646. SET_ERROR_VAR(EncodeSignedDataWithBlobsError, PkiAsn1ErrToHr(Asn1Err))
  14647. SET_ERROR(ConvSignedDataToOidError,CRYPT_E_OID_FORMAT)
  14648. SET_ERROR_VAR(EncodeContentInfoError, PkiAsn1ErrToHr(Asn1Err))
  14649. TRACE_ERROR(AllocSignedDataWithBlobsError) // error already set
  14650. TRACE_ERROR(GetEncodedSignerInfoSizeError) // error already set
  14651. TRACE_ERROR(AllocEncodedSignerInfoError) // error already set
  14652. TRACE_ERROR(GetEncodedSignerInfoError) // error already set
  14653. }
  14654. #ifdef CMS_PKCS7
  14655. //+-------------------------------------------------------------------------
  14656. // Get Oss OctetString
  14657. //--------------------------------------------------------------------------
  14658. void
  14659. inline
  14660. WINAPI
  14661. ICM_GetOssOctetString(
  14662. IN OctetStringType *pOssOctetString,
  14663. OUT PCRYPT_DATA_BLOB pOctetString,
  14664. IN OUT BYTE **ppbExtra,
  14665. IN OUT LONG *plRemainExtra
  14666. )
  14667. {
  14668. PkiAsn1GetOctetString(pOssOctetString->length, pOssOctetString->value, 0,
  14669. pOctetString, ppbExtra, plRemainExtra);
  14670. }
  14671. //+-------------------------------------------------------------------------
  14672. // Get Oss BitString
  14673. //--------------------------------------------------------------------------
  14674. void
  14675. inline
  14676. WINAPI
  14677. ICM_GetOssBitString(
  14678. IN BitStringType *pOssBitString,
  14679. OUT PCRYPT_BIT_BLOB pBitString,
  14680. IN OUT BYTE **ppbExtra,
  14681. IN OUT LONG *plRemainExtra
  14682. )
  14683. {
  14684. PkiAsn1GetBitString(pOssBitString->length, pOssBitString->value, 0,
  14685. pBitString, ppbExtra, plRemainExtra);
  14686. }
  14687. //+-------------------------------------------------------------------------
  14688. // Get an Oss IssuerAndSerialNumber
  14689. //--------------------------------------------------------------------------
  14690. BOOL
  14691. WINAPI
  14692. ICM_GetOssIssuerAndSerialNumber(
  14693. IN IssuerAndSerialNumber *pOssIssuerAndSerialNumber,
  14694. OUT PCERT_ISSUER_SERIAL_NUMBER pIssuerAndSerialNumber,
  14695. IN OUT BYTE **ppbExtra,
  14696. IN OUT LONG *plRemainExtra)
  14697. {
  14698. ICM_GetOssHugeInteger(&pOssIssuerAndSerialNumber->serialNumber,
  14699. &pIssuerAndSerialNumber->SerialNumber, ppbExtra, plRemainExtra);
  14700. return ICM_GetOssAny(&pOssIssuerAndSerialNumber->issuer,
  14701. &pIssuerAndSerialNumber->Issuer, ppbExtra, plRemainExtra);
  14702. }
  14703. //+-------------------------------------------------------------------------
  14704. // Get Oss CertIdentifier
  14705. //--------------------------------------------------------------------------
  14706. BOOL
  14707. WINAPI
  14708. ICM_GetOssCertIdentifier(
  14709. IN CertIdentifier *pOssCertId,
  14710. OUT PCERT_ID pCertId,
  14711. IN OUT BYTE **ppbExtra,
  14712. IN OUT LONG *plRemainExtra
  14713. )
  14714. {
  14715. BOOL fRet;
  14716. if (0 <= *plRemainExtra) {
  14717. assert(CERT_ID_ISSUER_SERIAL_NUMBER == issuerAndSerialNumber_chosen);
  14718. assert(CERT_ID_KEY_IDENTIFIER == subjectKeyIdentifier_chosen);
  14719. pCertId->dwIdChoice = pOssCertId->choice;
  14720. }
  14721. switch (pOssCertId->choice) {
  14722. case issuerAndSerialNumber_chosen:
  14723. if (!ICM_GetOssIssuerAndSerialNumber(
  14724. &pOssCertId->u.issuerAndSerialNumber,
  14725. &pCertId->IssuerSerialNumber, ppbExtra, plRemainExtra))
  14726. goto GetOssIssuerAndSerialNumberError;
  14727. break;
  14728. case subjectKeyIdentifier_chosen:
  14729. ICM_GetOssOctetString( &pOssCertId->u.subjectKeyIdentifier,
  14730. &pCertId->KeyId, ppbExtra, plRemainExtra);
  14731. break;
  14732. default:
  14733. goto InvalidCertIdChoice;
  14734. }
  14735. fRet = TRUE;
  14736. CommonReturn:
  14737. return fRet;
  14738. ErrorReturn:
  14739. fRet = FALSE;
  14740. goto CommonReturn;
  14741. TRACE_ERROR(GetOssIssuerAndSerialNumberError)
  14742. SET_ERROR(InvalidCertIdChoice, CRYPT_E_BAD_ENCODE)
  14743. }
  14744. //+-------------------------------------------------------------------------
  14745. // Get Oss OtherKeyAttribute
  14746. //--------------------------------------------------------------------------
  14747. BOOL
  14748. WINAPI
  14749. ICM_GetOssOtherKeyAttribute(
  14750. IN OtherKeyAttribute *pOssOtherAttr,
  14751. OUT PCRYPT_ATTRIBUTE_TYPE_VALUE *ppOtherAttr,
  14752. IN OUT BYTE **ppbExtra,
  14753. IN OUT LONG *plRemainExtra
  14754. )
  14755. {
  14756. BOOL fRet;
  14757. LONG lData;
  14758. PCRYPT_ATTRIBUTE_TYPE_VALUE pOtherAttr;
  14759. lData = INFO_LEN_ALIGN(sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE));
  14760. *plRemainExtra -= lData;
  14761. if (0 <= *plRemainExtra) {
  14762. pOtherAttr = (PCRYPT_ATTRIBUTE_TYPE_VALUE) *ppbExtra;
  14763. memset(pOtherAttr, 0, sizeof(*pOtherAttr));
  14764. *ppOtherAttr = pOtherAttr;
  14765. *ppbExtra += lData;
  14766. } else
  14767. pOtherAttr = NULL;
  14768. if (!ICM_GetOssObjId(&pOssOtherAttr->keyAttrId, &pOtherAttr->pszObjId,
  14769. ppbExtra, plRemainExtra))
  14770. goto GetOssObjIdError;
  14771. if (pOssOtherAttr->bit_mask & keyAttr_present) {
  14772. if (!ICM_GetOssAny(&pOssOtherAttr->keyAttr,
  14773. &pOtherAttr->Value, ppbExtra, plRemainExtra))
  14774. goto GetOssAnyError;
  14775. }
  14776. fRet = TRUE;
  14777. CommonReturn:
  14778. return fRet;
  14779. ErrorReturn:
  14780. fRet = FALSE;
  14781. goto CommonReturn;
  14782. TRACE_ERROR(GetOssObjIdError)
  14783. TRACE_ERROR(GetOssAnyError)
  14784. }
  14785. //+-------------------------------------------------------------------------
  14786. // Get Oss KeyTransRecipientInfo
  14787. //--------------------------------------------------------------------------
  14788. BOOL
  14789. WINAPI
  14790. ICM_GetOssKeyTransRecipientInfo(
  14791. IN KeyTransRecipientInfo *pori,
  14792. OUT PCMSG_KEY_TRANS_RECIPIENT_INFO *ppri,
  14793. IN OUT BYTE **ppbExtra,
  14794. IN OUT LONG *plRemainExtra
  14795. )
  14796. {
  14797. BOOL fRet;
  14798. LONG lData;
  14799. PCMSG_KEY_TRANS_RECIPIENT_INFO pri;
  14800. lData = INFO_LEN_ALIGN(sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO));
  14801. *plRemainExtra -= lData;
  14802. if (0 <= *plRemainExtra) {
  14803. pri = (PCMSG_KEY_TRANS_RECIPIENT_INFO) *ppbExtra;
  14804. *ppri = pri;
  14805. *ppbExtra += lData;
  14806. pri->dwVersion = pori->version;
  14807. } else {
  14808. pri = NULL;
  14809. }
  14810. if (!ICM_GetOssCertIdentifier(&pori->rid, &pri->RecipientId,
  14811. ppbExtra, plRemainExtra))
  14812. goto GetOssCertIdentifierError;
  14813. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  14814. &pri->KeyEncryptionAlgorithm,
  14815. ppbExtra, plRemainExtra))
  14816. goto GetOssKeyEncryptionAlgorithmError;
  14817. ICM_GetOssOctetString(&pori->encryptedKey, &pri->EncryptedKey,
  14818. ppbExtra, plRemainExtra);
  14819. fRet = TRUE;
  14820. CommonReturn:
  14821. return fRet;
  14822. ErrorReturn:
  14823. fRet = FALSE;
  14824. goto CommonReturn;
  14825. TRACE_ERROR(GetOssCertIdentifierError)
  14826. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  14827. }
  14828. //+-------------------------------------------------------------------------
  14829. // Get Oss KeyAgreeRecipientInfo
  14830. //--------------------------------------------------------------------------
  14831. BOOL
  14832. WINAPI
  14833. ICM_GetOssKeyAgreeRecipientInfo(
  14834. IN KeyAgreeRecipientInfo *pori,
  14835. OUT PCMSG_KEY_AGREE_RECIPIENT_INFO *ppri,
  14836. IN OUT BYTE **ppbExtra,
  14837. IN OUT LONG *plRemainExtra
  14838. )
  14839. {
  14840. BOOL fRet;
  14841. LONG lData;
  14842. PCMSG_KEY_AGREE_RECIPIENT_INFO pri;
  14843. DWORD count;
  14844. OriginatorIdentifierOrKey *pooriginator;
  14845. OriginatorPublicKey *pooriginatorKey;
  14846. lData = INFO_LEN_ALIGN(sizeof(CMSG_KEY_AGREE_RECIPIENT_INFO));
  14847. *plRemainExtra -= lData;
  14848. if (0 <= *plRemainExtra) {
  14849. pri = (PCMSG_KEY_AGREE_RECIPIENT_INFO) *ppbExtra;
  14850. memset(pri, 0, sizeof(*pri));
  14851. *ppri = pri;
  14852. *ppbExtra += lData;
  14853. pri->dwVersion = pori->version;
  14854. } else {
  14855. pri = NULL;
  14856. }
  14857. pooriginator = &pori->originator;
  14858. switch (pooriginator->choice) {
  14859. case issuerAndSerialNumber_chosen:
  14860. if (!ICM_GetOssIssuerAndSerialNumber(
  14861. &pooriginator->u.issuerAndSerialNumber,
  14862. &pri->OriginatorCertId.IssuerSerialNumber,
  14863. ppbExtra, plRemainExtra))
  14864. goto GetOssOriginatorIssuerAndSerialNumberError;
  14865. if (0 <= *plRemainExtra) {
  14866. pri->OriginatorCertId.dwIdChoice =
  14867. CERT_ID_ISSUER_SERIAL_NUMBER;
  14868. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_CERT;
  14869. }
  14870. break;
  14871. case subjectKeyIdentifier_chosen:
  14872. ICM_GetOssOctetString(
  14873. &pooriginator->u.subjectKeyIdentifier,
  14874. &pri->OriginatorCertId.KeyId,
  14875. ppbExtra, plRemainExtra);
  14876. if (0 <= *plRemainExtra) {
  14877. pri->OriginatorCertId.dwIdChoice =
  14878. CERT_ID_KEY_IDENTIFIER;
  14879. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_CERT;
  14880. }
  14881. break;
  14882. case originatorKey_chosen:
  14883. pooriginatorKey = &pooriginator->u.originatorKey;
  14884. if (!ICM_GetOssAlgorithm(&pooriginatorKey->algorithm,
  14885. &pri->OriginatorPublicKeyInfo.Algorithm,
  14886. ppbExtra, plRemainExtra
  14887. ))
  14888. goto GetOssOriginatorPublicKeyAlgorithmError;
  14889. ICM_GetOssBitString(&pooriginatorKey->publicKey,
  14890. &pri->OriginatorPublicKeyInfo.PublicKey,
  14891. ppbExtra, plRemainExtra);
  14892. if (0 <= *plRemainExtra)
  14893. pri->dwOriginatorChoice = CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY;
  14894. break;
  14895. default:
  14896. goto InvalidOriginatorChoice;
  14897. }
  14898. if (pori->bit_mask & ukm_present)
  14899. ICM_GetOssOctetString(&pori->ukm, &pri->UserKeyingMaterial,
  14900. ppbExtra, plRemainExtra);
  14901. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  14902. &pri->KeyEncryptionAlgorithm,
  14903. ppbExtra, plRemainExtra))
  14904. goto GetOssKeyEncryptionAlgorithmError;
  14905. count = pori->recipientEncryptedKeys.count;
  14906. if (0 < count) {
  14907. RecipientEncryptedKey *porek;
  14908. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO prek;
  14909. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *pprek;
  14910. lData = INFO_LEN_ALIGN(
  14911. count * sizeof(PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO) +
  14912. count * sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_INFO));
  14913. *plRemainExtra -= lData;
  14914. if (0 <= *plRemainExtra) {
  14915. pprek = (PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *) *ppbExtra;
  14916. prek = (PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO) (((PBYTE) pprek) +
  14917. (count * sizeof(PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO)));
  14918. *ppbExtra += lData;
  14919. pri->cRecipientEncryptedKeys = count;
  14920. pri->rgpRecipientEncryptedKeys = pprek;
  14921. } else {
  14922. pprek = NULL;
  14923. prek = NULL;
  14924. }
  14925. porek = pori->recipientEncryptedKeys.value;
  14926. for ( ; 0 < count; count--, porek++, prek++, pprek++) {
  14927. RecipientIdentifier *porid = &porek->rid;
  14928. if (0 <= *plRemainExtra) {
  14929. memset(prek, 0, sizeof(*prek));
  14930. *pprek = prek;
  14931. assert(issuerAndSerialNumber_chosen ==
  14932. CERT_ID_ISSUER_SERIAL_NUMBER);
  14933. assert(rKeyId_chosen ==
  14934. CERT_ID_KEY_IDENTIFIER);
  14935. prek->RecipientId.dwIdChoice = porid->choice;
  14936. }
  14937. ICM_GetOssOctetString(&porek->encryptedKey, &prek->EncryptedKey,
  14938. ppbExtra, plRemainExtra);
  14939. switch (porid->choice) {
  14940. case issuerAndSerialNumber_chosen:
  14941. if (!ICM_GetOssIssuerAndSerialNumber(
  14942. &porid->u.issuerAndSerialNumber,
  14943. &prek->RecipientId.IssuerSerialNumber,
  14944. ppbExtra, plRemainExtra))
  14945. goto GetOssIssuerAndSerialNumberError;
  14946. break;
  14947. case rKeyId_chosen:
  14948. ICM_GetOssOctetString(
  14949. &porid->u.rKeyId.subjectKeyIdentifier,
  14950. &prek->RecipientId.KeyId, ppbExtra, plRemainExtra);
  14951. if (porid->u.rKeyId.bit_mask & date_present) {
  14952. if (0 <= *plRemainExtra) {
  14953. if (!PkiAsn1FromGeneralizedTime(
  14954. &porid->u.rKeyId.date, &prek->Date))
  14955. goto ConvFromGeneralizedTimeError;
  14956. }
  14957. }
  14958. if (porid->u.rKeyId.bit_mask & other_present) {
  14959. if (!ICM_GetOssOtherKeyAttribute(
  14960. &porid->u.rKeyId.other,
  14961. &prek->pOtherAttr,
  14962. ppbExtra, plRemainExtra))
  14963. goto GetOssOtherKeyAttributeError;
  14964. }
  14965. break;
  14966. default:
  14967. goto InvalidRecipientChoice;
  14968. }
  14969. }
  14970. }
  14971. fRet = TRUE;
  14972. CommonReturn:
  14973. return fRet;
  14974. ErrorReturn:
  14975. fRet = FALSE;
  14976. goto CommonReturn;
  14977. TRACE_ERROR(GetOssOriginatorIssuerAndSerialNumberError)
  14978. TRACE_ERROR(GetOssOriginatorPublicKeyAlgorithmError)
  14979. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  14980. TRACE_ERROR(GetOssIssuerAndSerialNumberError)
  14981. TRACE_ERROR(ConvFromGeneralizedTimeError)
  14982. TRACE_ERROR(GetOssOtherKeyAttributeError)
  14983. SET_ERROR(InvalidOriginatorChoice, CRYPT_E_BAD_ENCODE)
  14984. SET_ERROR(InvalidRecipientChoice, CRYPT_E_BAD_ENCODE)
  14985. }
  14986. //+-------------------------------------------------------------------------
  14987. // Get Oss MailListRecipientInfo
  14988. //--------------------------------------------------------------------------
  14989. BOOL
  14990. WINAPI
  14991. ICM_GetOssMailListRecipientInfo(
  14992. IN MailListRecipientInfo *pori,
  14993. OUT PCMSG_MAIL_LIST_RECIPIENT_INFO *ppri,
  14994. IN OUT BYTE **ppbExtra,
  14995. IN OUT LONG *plRemainExtra
  14996. )
  14997. {
  14998. BOOL fRet;
  14999. LONG lData;
  15000. PCMSG_MAIL_LIST_RECIPIENT_INFO pri;
  15001. MailListKeyIdentifier *pomlid;
  15002. lData = INFO_LEN_ALIGN(sizeof(CMSG_MAIL_LIST_RECIPIENT_INFO));
  15003. *plRemainExtra -= lData;
  15004. if (0 <= *plRemainExtra) {
  15005. pri = (PCMSG_MAIL_LIST_RECIPIENT_INFO) *ppbExtra;
  15006. memset(pri, 0, sizeof(*pri));
  15007. *ppri = pri;
  15008. *ppbExtra += lData;
  15009. pri->dwVersion = pori->version;
  15010. } else {
  15011. pri = NULL;
  15012. }
  15013. pomlid = &pori->mlid;
  15014. ICM_GetOssOctetString(&pomlid->kekIdentifier, &pri->KeyId,
  15015. ppbExtra, plRemainExtra);
  15016. if (!ICM_GetOssAlgorithm(&pori->keyEncryptionAlgorithm,
  15017. &pri->KeyEncryptionAlgorithm,
  15018. ppbExtra, plRemainExtra))
  15019. goto GetOssKeyEncryptionAlgorithmError;
  15020. ICM_GetOssOctetString(&pori->encryptedKey, &pri->EncryptedKey,
  15021. ppbExtra, plRemainExtra);
  15022. if (pomlid->bit_mask & date_present) {
  15023. if (0 <= *plRemainExtra) {
  15024. if (!PkiAsn1FromGeneralizedTime(
  15025. &pomlid->date, &pri->Date))
  15026. goto ConvFromGeneralizedTimeError;
  15027. }
  15028. }
  15029. if (pomlid->bit_mask & other_present) {
  15030. if (!ICM_GetOssOtherKeyAttribute(
  15031. &pomlid->other,
  15032. &pri->pOtherAttr,
  15033. ppbExtra, plRemainExtra))
  15034. goto GetOssOtherKeyAttributeError;
  15035. }
  15036. fRet = TRUE;
  15037. CommonReturn:
  15038. return fRet;
  15039. ErrorReturn:
  15040. fRet = FALSE;
  15041. goto CommonReturn;
  15042. TRACE_ERROR(GetOssKeyEncryptionAlgorithmError)
  15043. TRACE_ERROR(ConvFromGeneralizedTimeError)
  15044. TRACE_ERROR(GetOssOtherKeyAttributeError)
  15045. }
  15046. //+-------------------------------------------------------------------------
  15047. // Copy out a CMSG_CMS_RECIPIENT_INFO
  15048. //--------------------------------------------------------------------------
  15049. BOOL
  15050. WINAPI
  15051. ICM_GetCmsRecipientInfo(
  15052. IN CmsRecipientInfo *pori,
  15053. OUT void *pvData,
  15054. IN OUT DWORD *pcbData
  15055. )
  15056. {
  15057. BOOL fRet;
  15058. LONG lData;
  15059. PCMSG_CMS_RECIPIENT_INFO pri = (PCMSG_CMS_RECIPIENT_INFO) pvData;
  15060. PBYTE pbExtra;
  15061. LONG lRemainExtra;
  15062. if (NULL == pvData)
  15063. *pcbData = 0;
  15064. // for lRemainExtra < 0, LENGTH_ONLY calculation
  15065. lData = INFO_LEN_ALIGN(sizeof(CMSG_CMS_RECIPIENT_INFO));
  15066. lRemainExtra = (LONG)*pcbData - lData;
  15067. if (0 > lRemainExtra) {
  15068. pri = NULL;
  15069. pbExtra = NULL;
  15070. } else {
  15071. assert(CMSG_KEY_TRANS_RECIPIENT == keyTransRecipientInfo_chosen);
  15072. assert(CMSG_KEY_AGREE_RECIPIENT == keyAgreeRecipientInfo_chosen);
  15073. assert(CMSG_MAIL_LIST_RECIPIENT == mailListRecipientInfo_chosen);
  15074. pri->dwRecipientChoice = pori->choice;
  15075. pbExtra = (PBYTE) pri + lData;
  15076. }
  15077. switch (pori->choice) {
  15078. case keyTransRecipientInfo_chosen:
  15079. if (!ICM_GetOssKeyTransRecipientInfo(
  15080. &pori->u.keyTransRecipientInfo,
  15081. &pri->pKeyTrans,
  15082. &pbExtra, &lRemainExtra
  15083. ))
  15084. goto GetOssKeyTransRecipientInfoError;
  15085. break;
  15086. case keyAgreeRecipientInfo_chosen:
  15087. if (!ICM_GetOssKeyAgreeRecipientInfo(
  15088. &pori->u.keyAgreeRecipientInfo,
  15089. &pri->pKeyAgree,
  15090. &pbExtra, &lRemainExtra
  15091. ))
  15092. goto GetOssKeyAgreeRecipientInfoError;
  15093. break;
  15094. case mailListRecipientInfo_chosen:
  15095. if (!ICM_GetOssMailListRecipientInfo(
  15096. &pori->u.mailListRecipientInfo,
  15097. &pri->pMailList,
  15098. &pbExtra, &lRemainExtra
  15099. ))
  15100. goto GetOssMailListRecipientInfoError;
  15101. break;
  15102. default:
  15103. goto InvalidRecipientChoice;
  15104. }
  15105. fRet = ICM_GetSizeFromExtra(lRemainExtra, pvData, pcbData);
  15106. CommonReturn:
  15107. return fRet;
  15108. ErrorReturn:
  15109. *pcbData = 0;
  15110. fRet = FALSE;
  15111. goto CommonReturn;
  15112. TRACE_ERROR(GetOssKeyTransRecipientInfoError)
  15113. TRACE_ERROR(GetOssKeyAgreeRecipientInfoError)
  15114. TRACE_ERROR(GetOssMailListRecipientInfoError)
  15115. SET_ERROR(InvalidRecipientChoice, CRYPT_E_BAD_ENCODE)
  15116. }
  15117. #endif // CMS_PKCS7
  15118. //+-------------------------------------------------------------------------
  15119. // Get a parameter after encoding/decoding a cryptographic message. Called
  15120. // after the final CryptMsgUpdate. Only the CMSG_CONTENT_PARAM and
  15121. // CMSG_COMPUTED_HASH_PARAM are valid for an encoded message.
  15122. //
  15123. // For an encoded HASHED message, the CMSG_COMPUTED_HASH_PARAM can be got
  15124. // before any CryptMsgUpdates to get its length.
  15125. //
  15126. // The pvData type definition depends on the dwParamType value.
  15127. //
  15128. // Elements pointed to by fields in the pvData structure follow the
  15129. // structure. Therefore, *pcbData may exceed the size of the structure.
  15130. //
  15131. // Upon input, if *pcbData == 0, then, *pcbData is updated with the length
  15132. // of the data and the pvData parameter is ignored.
  15133. //
  15134. // Upon return, *pcbData is updated with the length of the data.
  15135. //
  15136. // The OBJID BLOBs returned in the pvData structures point to
  15137. // their still encoded representation. The appropriate functions
  15138. // must be called to decode the information.
  15139. //
  15140. // See wincrypt.h for a list of the parameters to get.
  15141. //--------------------------------------------------------------------------
  15142. BOOL
  15143. WINAPI
  15144. #ifdef DEBUG_CRYPT_ASN1_MASTER
  15145. ICMTest_NewCryptMsgGetParam(
  15146. #else
  15147. CryptMsgGetParam(
  15148. #endif
  15149. IN HCRYPTMSG hCryptMsg,
  15150. IN DWORD dwParamType,
  15151. IN DWORD dwIndex,
  15152. OUT void *pvData,
  15153. IN OUT DWORD *pcbData)
  15154. {
  15155. DWORD dwError = ERROR_SUCCESS;
  15156. BOOL fRet;
  15157. PCRYPT_MSG_INFO pcmi = (PCRYPT_MSG_INFO)hCryptMsg;
  15158. ASN1error_e Asn1Err;
  15159. PCMSG_STREAM_INFO pcsi = pcmi->pStreamInfo;
  15160. BOOL fBER = FALSE;
  15161. DWORD dwExceptionCode;
  15162. ICM_Lock( pcmi); // Single thread access to HCRYPTMSG
  15163. // Handle MappedFile Exceptions
  15164. __try {
  15165. if (NULL == pvData)
  15166. *pcbData = 0;
  15167. #ifdef CMS_PKCS7
  15168. if (CMSG_VERSION_PARAM == dwParamType) {
  15169. int version = 0;
  15170. switch (pcmi->dwMsgType) {
  15171. case CMSG_SIGNED:
  15172. if (pcmi->fEncoding) {
  15173. if (NULL == pcmi->pvMsg)
  15174. goto InvalidMessageDataError;
  15175. version = ((SignedData *)pcmi->pvMsg)->version;
  15176. } else {
  15177. if (NULL == pcmi->psdi)
  15178. goto MessageNotDecodedError;
  15179. version = pcmi->psdi->version;
  15180. }
  15181. break;
  15182. case CMSG_ENVELOPED:
  15183. if (NULL == pcmi->pvMsg)
  15184. goto MessageNotDecodedError;
  15185. version = ((CmsEnvelopedData *)pcmi->pvMsg)->version;
  15186. break;
  15187. case CMSG_HASHED:
  15188. if (NULL == pcmi->pvMsg)
  15189. goto MessageNotDecodedError;
  15190. version = ((DigestedData *)pcmi->pvMsg)->version;
  15191. break;
  15192. case CMSG_SIGNED_AND_ENVELOPED:
  15193. goto MessageTypeNotSupportedYet;
  15194. case CMSG_ENCRYPTED:
  15195. case CMSG_DATA:
  15196. default:
  15197. goto InvalidMsgType;
  15198. }
  15199. fRet = ICM_GetDWORD(version, pvData, pcbData);
  15200. goto PreserveLengthReturn;
  15201. }
  15202. #endif // CMS_PKCS7
  15203. if (pcmi->fEncoding) {
  15204. switch (dwParamType) {
  15205. case CMSG_CONTENT_PARAM:
  15206. case CMSG_BARE_CONTENT_PARAM:
  15207. {
  15208. ContentInfo ci;
  15209. ASN1encoding_t pEnc = ICM_GetEncoder();
  15210. PBYTE pbEncoded = NULL;
  15211. DWORD cbEncoded;
  15212. PBYTE pbContent = NULL;
  15213. if (pcsi)
  15214. goto GetContentParamNotValidForStreaming;
  15215. switch (pcmi->dwMsgType) {
  15216. case CMSG_SIGNED:
  15217. if (0 == ((SignedData *) pcmi->pvMsg)->signerInfos.count)
  15218. // For a bag of certs, don't DER order
  15219. fBER = TRUE;
  15220. break;
  15221. case CMSG_DATA:
  15222. case CMSG_ENVELOPED:
  15223. case CMSG_HASHED:
  15224. break;
  15225. case CMSG_SIGNED_AND_ENVELOPED:
  15226. case CMSG_ENCRYPTED:
  15227. goto MessageTypeNotSupportedYet;
  15228. default:
  15229. goto InvalidMsgType;
  15230. }
  15231. if (fBER)
  15232. PkiAsn1SetEncodingRule(ICM_GetEncoder(), ASN1_BER_RULE_BER);
  15233. if (0 != (Asn1Err = PkiAsn1Encode(
  15234. pEnc,
  15235. pcmi->pvMsg,
  15236. aiPduNum[ pcmi->dwMsgType - 1],
  15237. &pbEncoded,
  15238. &cbEncoded))) {
  15239. goto CONTENT_PARAMAsn1EncodeError;
  15240. }
  15241. if (CMSG_CONTENT_PARAM == dwParamType) {
  15242. if (!ICM_CopyOssObjectIdentifier(
  15243. &ci.contentType,
  15244. &aoidMessages[ pcmi->dwMsgType - 1]))
  15245. goto CopyOssObjectIdentifierContentTypeError;
  15246. ci.bit_mask = content_present;
  15247. ci.content.length = cbEncoded;
  15248. ci.content.value = pbEncoded;
  15249. pbContent = pbEncoded;
  15250. if (0 != (Asn1Err = PkiAsn1Encode(
  15251. pEnc,
  15252. &ci,
  15253. ContentInfo_PDU,
  15254. &pbEncoded,
  15255. &cbEncoded))) {
  15256. PkiAsn1FreeEncoded(pEnc, pbContent);
  15257. goto Asn1EncodeSignedDataError;
  15258. }
  15259. }
  15260. fRet = ICM_CopyOut(
  15261. pbEncoded,
  15262. cbEncoded,
  15263. (PBYTE)pvData,
  15264. pcbData);
  15265. if (!fRet)
  15266. dwError = GetLastError();
  15267. if (pbContent)
  15268. PkiAsn1FreeEncoded(pEnc, pbContent);
  15269. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  15270. if (!fRet)
  15271. SetLastError(dwError);
  15272. break;
  15273. }
  15274. case CMSG_COMPUTED_HASH_PARAM:
  15275. fRet = ICM_GetComputedDigestParam( pcmi, dwIndex, pvData, pcbData);
  15276. break;
  15277. case CMSG_ENCODED_SIGNER:
  15278. switch (pcmi->dwMsgType) {
  15279. case CMSG_SIGNED:
  15280. break;
  15281. case CMSG_SIGNED_AND_ENVELOPED:
  15282. goto MessageTypeNotSupportedYet;
  15283. default:
  15284. goto InvalidMsgType;
  15285. }
  15286. fRet = ICM_GetSignerParamEncoding(
  15287. pcmi,
  15288. dwIndex,
  15289. dwParamType,
  15290. pvData,
  15291. pcbData);
  15292. break;
  15293. default:
  15294. goto InvalidMsgType;
  15295. }
  15296. } else {
  15297. //
  15298. // Decode
  15299. //
  15300. switch (dwParamType) {
  15301. case CMSG_TYPE_PARAM:
  15302. if (pcsi && (0 == pcmi->dwMsgType))
  15303. goto StreamMsgNotReadyError;
  15304. fRet = ICM_GetDWORD( pcmi->dwMsgType, pvData, pcbData);
  15305. break;
  15306. case CMSG_CONTENT_PARAM:
  15307. {
  15308. ContentInfo *pci;
  15309. PCONTENT_INFO pci2;
  15310. PBYTE pbDER = NULL;
  15311. DWORD cbDER;
  15312. PBYTE pb;
  15313. DWORD cb;
  15314. if (pcsi)
  15315. goto GetContentParamNotValidForStreaming;
  15316. switch (pcmi->dwMsgType) {
  15317. case CMSG_DATA:
  15318. {
  15319. OctetStringType *poos = (OctetStringType *)pcmi->pvMsg;
  15320. pb = (PBYTE)poos->value;
  15321. cb = poos->length;
  15322. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15323. break;
  15324. }
  15325. case CMSG_SIGNED:
  15326. if (NULL == pcmi->psdi)
  15327. goto InvalidSignedMessageError;
  15328. pci2 = pcmi->psdi->pci;
  15329. if (pci2->content.cbData) {
  15330. cb = pci2->content.cbData;
  15331. pb = pci2->content.pbData;
  15332. if (0 == strcmp(pszObjIdDataType,
  15333. pci2->pszContentType)
  15334. #ifdef CMS_PKCS7
  15335. || pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION
  15336. #endif // CMS_PKCS7
  15337. ) {
  15338. if (!ICM_ReEncodeAsOctetDER(
  15339. pb,
  15340. cb,
  15341. &pbDER,
  15342. &cbDER
  15343. ))
  15344. goto ReEncodeAsOctetDERError;
  15345. if (pbDER) {
  15346. if (0 > Asn1UtilExtractContent( pbDER, cbDER,
  15347. &cb, (const BYTE **)&pb)) {
  15348. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15349. goto ExtractContentError;
  15350. }
  15351. }
  15352. }
  15353. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15354. if (!fRet)
  15355. dwError = GetLastError();
  15356. if (pbDER)
  15357. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15358. if (!fRet)
  15359. SetLastError(dwError);
  15360. } else {
  15361. *pcbData = 0;
  15362. fRet = TRUE;
  15363. }
  15364. break;
  15365. case CMSG_ENVELOPED:
  15366. if (NULL == pcmi->Plaintext.pbData) {
  15367. // Hasn't been decrypted yet
  15368. EncryptedContentInfo *peci;
  15369. PBYTE pbCiphertext;
  15370. DWORD cbCiphertext;
  15371. #ifdef CMS_PKCS7
  15372. peci = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  15373. #else
  15374. peci = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo;
  15375. #endif // CMS_PKCS7
  15376. if (peci->bit_mask & encryptedContent_present) {
  15377. pbCiphertext = peci->encryptedContent.value;
  15378. cbCiphertext = peci->encryptedContent.length;
  15379. } else {
  15380. pbCiphertext = NULL;
  15381. cbCiphertext = 0;
  15382. }
  15383. if (NULL == pvData) {
  15384. // Assume (sizeof plaintext) <=
  15385. // (sizeof ciphertext)
  15386. //
  15387. // not decrypted yet; return ciphertext size
  15388. fRet = TRUE;
  15389. // + 6 => to allow for identifier and length octets
  15390. *pcbData = cbCiphertext + 6;
  15391. } else
  15392. // Return ciphertext
  15393. fRet = ICM_CopyOut(
  15394. pbCiphertext,
  15395. cbCiphertext,
  15396. (PBYTE)pvData,
  15397. pcbData);
  15398. goto ContentCopiedOut;
  15399. }
  15400. if (!ICM_EqualObjectIDs(
  15401. #ifdef CMS_PKCS7
  15402. &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType,
  15403. &aoidMessages[ CMSG_DATA - 1])
  15404. &&
  15405. CMSG_ENVELOPED_DATA_CMS_VERSION >
  15406. ((CmsEnvelopedData *)pcmi->pvMsg)->version) {
  15407. #else
  15408. &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType,
  15409. &aoidMessages[ CMSG_DATA - 1])) {
  15410. #endif // CMS_PKCS7
  15411. // Not DATA or encapsulated, so must prepend
  15412. // identifier and length octets
  15413. fRet = ICM_CopyOutAddDERPrefix(
  15414. pcmi->Plaintext.pbData,
  15415. pcmi->Plaintext.cbData,
  15416. ICM_TAG_SEQ,
  15417. (PBYTE)pvData,
  15418. pcbData);
  15419. } else {
  15420. fRet = ICM_CopyOut(
  15421. pcmi->Plaintext.pbData,
  15422. pcmi->Plaintext.cbData,
  15423. (PBYTE)pvData,
  15424. pcbData);
  15425. }
  15426. goto ContentCopiedOut;
  15427. case CMSG_HASHED:
  15428. pci = &((DigestedData *)pcmi->pvMsg)->contentInfo;
  15429. if (pci->bit_mask & content_present) {
  15430. cb = (DWORD)pci->content.length;
  15431. pb = (PBYTE)pci->content.value;
  15432. if (ICM_EqualObjectIDs(
  15433. &pci->contentType,
  15434. &aoidMessages[ CMSG_DATA - 1])
  15435. #ifdef CMS_PKCS7
  15436. || ((DigestedData *)pcmi->pvMsg)->version >=
  15437. CMSG_HASHED_DATA_V2
  15438. #endif // CMS_PKCS7
  15439. ) {
  15440. if (!ICM_ReEncodeAsOctetDER(
  15441. pb,
  15442. cb,
  15443. &pbDER,
  15444. &cbDER
  15445. ))
  15446. goto ReEncodeAsOctetDERError;
  15447. if (pbDER) {
  15448. if (0 > Asn1UtilExtractContent( pbDER, cbDER,
  15449. &cb, (const BYTE **)&pb)) {
  15450. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15451. goto ExtractContentError;
  15452. }
  15453. }
  15454. }
  15455. fRet = ICM_CopyOut( pb, cb, (PBYTE)pvData, pcbData);
  15456. if (!fRet)
  15457. dwError = GetLastError();
  15458. if (pbDER)
  15459. PkiAsn1FreeEncoded( ICM_GetEncoder(), pbDER);
  15460. if (!fRet)
  15461. SetLastError(dwError);
  15462. } else {
  15463. *pcbData = 0;
  15464. fRet = TRUE;
  15465. }
  15466. break;
  15467. case CMSG_SIGNED_AND_ENVELOPED:
  15468. case CMSG_ENCRYPTED:
  15469. goto MessageTypeNotSupportedYet;
  15470. default:
  15471. goto InvalidMsgType;
  15472. }
  15473. ContentCopiedOut:
  15474. break;
  15475. }
  15476. case CMSG_INNER_CONTENT_TYPE_PARAM:
  15477. {
  15478. ContentType *pct;
  15479. switch (pcmi->dwMsgType) {
  15480. case CMSG_SIGNED:
  15481. if (NULL == pcmi->psdi)
  15482. goto InvalidSignedMessageError;
  15483. fRet = ICM_CopyOut(
  15484. (PBYTE)pcmi->psdi->pci->pszContentType,
  15485. strlen( pcmi->psdi->pci->pszContentType) + 1,
  15486. (PBYTE)pvData,
  15487. pcbData);
  15488. goto ContentTypeCopiedOut;
  15489. break;
  15490. case CMSG_ENVELOPED:
  15491. #ifdef CMS_PKCS7
  15492. pct = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType;
  15493. #else
  15494. pct = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentType;
  15495. #endif // CMS_PKCS7
  15496. break;
  15497. case CMSG_HASHED:
  15498. pct = &((DigestedData *)pcmi->pvMsg)->contentInfo.contentType;
  15499. break;
  15500. case CMSG_SIGNED_AND_ENVELOPED:
  15501. case CMSG_ENCRYPTED:
  15502. goto MessageTypeNotSupportedYet;
  15503. default:
  15504. goto InvalidMsgType;
  15505. }
  15506. fRet = PkiAsn1FromObjectIdentifier(
  15507. pct->count,
  15508. pct->value,
  15509. (LPSTR)pvData,
  15510. pcbData);
  15511. ContentTypeCopiedOut:
  15512. break;
  15513. }
  15514. case CMSG_ENCODED_MESSAGE:
  15515. fRet = ICM_GetEncodedMessageParam(
  15516. pcmi,
  15517. (PBYTE)pvData,
  15518. pcbData);
  15519. break;
  15520. case CMSG_SIGNER_COUNT_PARAM:
  15521. {
  15522. DWORD cSigner;
  15523. switch (pcmi->dwMsgType) {
  15524. case CMSG_SIGNED:
  15525. if (NULL == pcmi->psdi)
  15526. goto InvalidSignedMessageError;
  15527. cSigner = pcmi->psdi->pSignerList->Length();
  15528. break;
  15529. case CMSG_SIGNED_AND_ENVELOPED:
  15530. goto MessageTypeNotSupportedYet;
  15531. default:
  15532. goto InvalidMsgType;
  15533. }
  15534. fRet = ICM_GetDWORD( cSigner, pvData, pcbData);
  15535. break;
  15536. }
  15537. case CMSG_ENCRYPTED_DIGEST:
  15538. case CMSG_ENCODED_SIGNER:
  15539. case CMSG_SIGNER_INFO_PARAM:
  15540. case CMSG_SIGNER_CERT_INFO_PARAM:
  15541. case CMSG_SIGNER_HASH_ALGORITHM_PARAM:
  15542. case CMSG_SIGNER_AUTH_ATTR_PARAM:
  15543. case CMSG_SIGNER_UNAUTH_ATTR_PARAM:
  15544. case CMSG_CMS_SIGNER_INFO_PARAM:
  15545. case CMSG_SIGNER_CERT_ID_PARAM:
  15546. switch (pcmi->dwMsgType) {
  15547. case CMSG_SIGNED:
  15548. break;
  15549. case CMSG_SIGNED_AND_ENVELOPED:
  15550. goto MessageTypeNotSupportedYet;
  15551. default:
  15552. goto InvalidMsgType;
  15553. }
  15554. fRet = ICM_GetSignerParam(
  15555. pcmi,
  15556. dwIndex,
  15557. dwParamType,
  15558. pvData,
  15559. pcbData);
  15560. break;
  15561. case CMSG_CERT_COUNT_PARAM:
  15562. {
  15563. CBlobList *pBlobList;
  15564. DWORD dwCount;
  15565. #ifdef CMS_PKCS7
  15566. BOOL fPossibleAttrCert = FALSE;
  15567. #endif // CMS_PKCS7
  15568. switch (pcmi->dwMsgType) {
  15569. case CMSG_SIGNED:
  15570. if (NULL == pcmi->psdi)
  15571. goto InvalidSignedMessageError;
  15572. pBlobList = pcmi->psdi->pCertificateList;
  15573. #ifdef CMS_PKCS7
  15574. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15575. fPossibleAttrCert = TRUE;
  15576. #endif // CMS_PKCS7
  15577. break;
  15578. #ifdef CMS_PKCS7
  15579. case CMSG_ENVELOPED:
  15580. pBlobList = pcmi->pCertificateList;
  15581. fPossibleAttrCert = TRUE;
  15582. break;
  15583. #endif // CMS_PKCS7
  15584. case CMSG_SIGNED_AND_ENVELOPED:
  15585. goto MessageTypeNotSupportedYet;
  15586. default:
  15587. goto InvalidMsgType;
  15588. }
  15589. dwCount = pBlobList->Length();
  15590. #ifdef CMS_PKCS7
  15591. if (dwCount && fPossibleAttrCert)
  15592. dwCount = ICM_GetTaggedBlobCount(
  15593. pBlobList,
  15594. ICM_TAG_SEQ
  15595. );
  15596. #endif // CMS_PKCS7
  15597. fRet = ICM_GetDWORD( dwCount, pvData, pcbData);
  15598. break;
  15599. }
  15600. case CMSG_CERT_PARAM:
  15601. {
  15602. CBlobList *pBlobList;
  15603. CBlobNode *pBlobNode;
  15604. #ifdef CMS_PKCS7
  15605. BOOL fPossibleAttrCert = FALSE;
  15606. #endif // CMS_PKCS7
  15607. switch (pcmi->dwMsgType) {
  15608. case CMSG_SIGNED:
  15609. if (NULL == pcmi->psdi)
  15610. goto InvalidSignedMessageError;
  15611. pBlobList = pcmi->psdi->pCertificateList;
  15612. #ifdef CMS_PKCS7
  15613. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15614. fPossibleAttrCert = TRUE;
  15615. #endif // CMS_PKCS7
  15616. break;
  15617. #ifdef CMS_PKCS7
  15618. case CMSG_ENVELOPED:
  15619. pBlobList = pcmi->pCertificateList;
  15620. fPossibleAttrCert = TRUE;
  15621. break;
  15622. #endif // CMS_PKCS7
  15623. case CMSG_SIGNED_AND_ENVELOPED:
  15624. goto MessageTypeNotSupportedYet;
  15625. default:
  15626. goto InvalidMsgType;
  15627. }
  15628. // Get blob at specified cert index. Index
  15629. // is advanced to the appropriate blob.
  15630. pBlobNode = ICM_GetTaggedBlobAndAdvanceIndex(
  15631. pBlobList,
  15632. #ifdef CMS_PKCS7
  15633. (BYTE)( fPossibleAttrCert ? ICM_TAG_SEQ : 0),
  15634. #else
  15635. 0, // bTag
  15636. #endif // CMS_PKCS7
  15637. &dwIndex
  15638. );
  15639. if (pBlobNode)
  15640. fRet = ICM_CopyOut(
  15641. pBlobNode->Data()->pbData,
  15642. pBlobNode->Data()->cbData,
  15643. (PBYTE)pvData,
  15644. pcbData);
  15645. else
  15646. fRet = FALSE;
  15647. break;
  15648. }
  15649. #ifdef CMS_PKCS7
  15650. case CMSG_ATTR_CERT_COUNT_PARAM:
  15651. {
  15652. CBlobList *pBlobList;
  15653. BOOL fPossibleAttrCert = FALSE;
  15654. DWORD dwCount;
  15655. switch (pcmi->dwMsgType) {
  15656. case CMSG_SIGNED:
  15657. if (NULL == pcmi->psdi)
  15658. goto InvalidSignedMessageError;
  15659. pBlobList = pcmi->psdi->pCertificateList;
  15660. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15661. fPossibleAttrCert = TRUE;
  15662. break;
  15663. case CMSG_ENVELOPED:
  15664. pBlobList = pcmi->pCertificateList;
  15665. fPossibleAttrCert = TRUE;
  15666. break;
  15667. default:
  15668. goto InvalidMsgType;
  15669. }
  15670. if (fPossibleAttrCert)
  15671. dwCount = ICM_GetTaggedBlobCount(
  15672. pBlobList,
  15673. ICM_TAG_CONSTRUCTED_CONTEXT_1
  15674. );
  15675. else
  15676. dwCount = 0;
  15677. fRet = ICM_GetDWORD( dwCount, pvData, pcbData);
  15678. break;
  15679. }
  15680. case CMSG_ATTR_CERT_PARAM:
  15681. {
  15682. CBlobList *pBlobList;
  15683. CBlobNode *pBlobNode;
  15684. BOOL fPossibleAttrCert = FALSE;
  15685. switch (pcmi->dwMsgType) {
  15686. case CMSG_SIGNED:
  15687. if (NULL == pcmi->psdi)
  15688. goto InvalidSignedMessageError;
  15689. pBlobList = pcmi->psdi->pCertificateList;
  15690. if (pcmi->psdi->version >= CMSG_SIGNED_DATA_CMS_VERSION)
  15691. fPossibleAttrCert = TRUE;
  15692. break;
  15693. case CMSG_ENVELOPED:
  15694. pBlobList = pcmi->pCertificateList;
  15695. fPossibleAttrCert = TRUE;
  15696. break;
  15697. default:
  15698. goto InvalidMsgType;
  15699. }
  15700. if (!fPossibleAttrCert)
  15701. pBlobNode = NULL;
  15702. else
  15703. // Get blob at specified attribute cert index. Index
  15704. // is advanced to the appropriate blob
  15705. pBlobNode = ICM_GetTaggedBlobAndAdvanceIndex(
  15706. pBlobList,
  15707. ICM_TAG_CONSTRUCTED_CONTEXT_1,
  15708. &dwIndex
  15709. );
  15710. if (pBlobNode) {
  15711. fRet = ICM_CopyOut(
  15712. pBlobNode->Data()->pbData,
  15713. pBlobNode->Data()->cbData,
  15714. (PBYTE)pvData,
  15715. pcbData);
  15716. if (fRet && pvData)
  15717. *((PBYTE)pvData) = ICM_TAG_SEQ;
  15718. } else
  15719. fRet = FALSE;
  15720. break;
  15721. }
  15722. #endif // CMS_PKCS7
  15723. case CMSG_CRL_COUNT_PARAM:
  15724. {
  15725. CBlobList *pBlobList;
  15726. switch (pcmi->dwMsgType) {
  15727. case CMSG_SIGNED:
  15728. if (NULL == pcmi->psdi)
  15729. goto InvalidSignedMessageError;
  15730. pBlobList = pcmi->psdi->pCrlList;
  15731. break;
  15732. #ifdef CMS_PKCS7
  15733. case CMSG_ENVELOPED:
  15734. pBlobList = pcmi->pCrlList;
  15735. break;
  15736. #endif // CMS_PKCS7
  15737. case CMSG_SIGNED_AND_ENVELOPED:
  15738. goto MessageTypeNotSupportedYet;
  15739. default:
  15740. goto InvalidMsgType;
  15741. }
  15742. fRet = ICM_GetDWORD( pBlobList->Length(), pvData, pcbData);
  15743. break;
  15744. }
  15745. case CMSG_CRL_PARAM:
  15746. {
  15747. CBlobList *pBlobList;
  15748. CBlobNode *pBlobNode;
  15749. DWORD i;
  15750. switch (pcmi->dwMsgType) {
  15751. case CMSG_SIGNED:
  15752. if (NULL == pcmi->psdi)
  15753. goto InvalidSignedMessageError;
  15754. pBlobList = pcmi->psdi->pCrlList;
  15755. break;
  15756. #ifdef CMS_PKCS7
  15757. case CMSG_ENVELOPED:
  15758. pBlobList = pcmi->pCrlList;
  15759. break;
  15760. #endif // CMS_PKCS7
  15761. case CMSG_SIGNED_AND_ENVELOPED:
  15762. goto MessageTypeNotSupportedYet;
  15763. default:
  15764. goto InvalidMsgType;
  15765. }
  15766. // This list-walking should be a class method
  15767. for (i=dwIndex, pBlobNode=pBlobList->Head();
  15768. (i>0) && pBlobNode;
  15769. i--, pBlobNode=pBlobNode->Next())
  15770. ;
  15771. if (pBlobNode)
  15772. fRet = ICM_CopyOut(
  15773. pBlobNode->Data()->pbData,
  15774. pBlobNode->Data()->cbData,
  15775. (PBYTE)pvData,
  15776. pcbData);
  15777. else
  15778. fRet = FALSE;
  15779. break;
  15780. }
  15781. case CMSG_ENVELOPE_ALGORITHM_PARAM:
  15782. {
  15783. ContentEncryptionAlgId *pceai;
  15784. if (pcsi &&
  15785. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_ECIALGID)))
  15786. goto StreamMsgNotReadyError;
  15787. switch (pcmi->dwMsgType) {
  15788. case CMSG_ENVELOPED:
  15789. #ifdef CMS_PKCS7
  15790. pceai = &((CmsEnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentEncryptionAlgorithm;
  15791. #else
  15792. pceai = &((EnvelopedData *)pcmi->pvMsg)->encryptedContentInfo.contentEncryptionAlgorithm;
  15793. #endif // CMS_PKCS7
  15794. break;
  15795. case CMSG_SIGNED_AND_ENVELOPED:
  15796. goto MessageTypeNotSupportedYet;
  15797. default:
  15798. goto InvalidMsgType;
  15799. }
  15800. fRet = ICM_GetALGORITHM_IDENTIFIER( pceai, pvData, pcbData);
  15801. break;
  15802. }
  15803. #ifdef CMS_PKCS7
  15804. case CMSG_UNPROTECTED_ATTR_PARAM:
  15805. {
  15806. CmsEnvelopedData *ped;
  15807. ped = (CmsEnvelopedData *)pcmi->pvMsg;
  15808. if (ped && (ped->bit_mask & unprotectedAttrs_present))
  15809. fRet = ICM_GetAttributesData(
  15810. &ped->unprotectedAttrs,
  15811. pvData,
  15812. pcbData);
  15813. else
  15814. goto UnprotectedAttrMissingError;
  15815. }
  15816. break;
  15817. case CMSG_RECIPIENT_COUNT_PARAM:
  15818. {
  15819. DWORD dwPkcsCount;
  15820. if (!ICM_GetPkcsRecipientCount(pcmi, &dwPkcsCount))
  15821. goto GetPkcsRecipientCountError;
  15822. fRet = ICM_GetDWORD(dwPkcsCount, pvData, pcbData);
  15823. }
  15824. break;
  15825. case CMSG_RECIPIENT_INDEX_PARAM:
  15826. {
  15827. DWORD dwPkcsIndex;
  15828. DWORD dwCmsIndex;
  15829. DWORD cbData = sizeof(dwCmsIndex);
  15830. if (!CryptMsgGetParam(
  15831. hCryptMsg,
  15832. CMSG_CMS_RECIPIENT_INDEX_PARAM,
  15833. 0, // dwIndex
  15834. &dwCmsIndex,
  15835. &cbData))
  15836. goto GetCmsRecipientIndexError;
  15837. if (!ICM_ConvertCmsToPkcsRecipientIndex(
  15838. pcmi, dwCmsIndex, &dwPkcsIndex))
  15839. goto ConvertCmsToPkcsRecipientIndexError;
  15840. fRet = ICM_GetDWORD(
  15841. dwPkcsIndex,
  15842. pvData,
  15843. pcbData);
  15844. }
  15845. break;
  15846. case CMSG_RECIPIENT_INFO_PARAM:
  15847. {
  15848. CmsRecipientInfos *pris;
  15849. KeyTransRecipientInfo *pri;
  15850. DWORD dwCmsIndex;
  15851. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15852. goto GetDecodedCmsRecipientsError;
  15853. if (!ICM_ConvertPkcsToCmsRecipientIndex(
  15854. pcmi, dwIndex, &dwCmsIndex))
  15855. goto ConvertPkcsToCmsRecipientIndexError;
  15856. pri = &pris->value[dwCmsIndex].u.keyTransRecipientInfo;
  15857. fRet = ICM_GetCertInfoIssuerAndSerialNumber(
  15858. &pri->rid, pvData, pcbData);
  15859. break;
  15860. }
  15861. case CMSG_CMS_RECIPIENT_COUNT_PARAM:
  15862. {
  15863. CmsRecipientInfos *pris;
  15864. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15865. goto GetDecodedCmsRecipientsError;
  15866. fRet = ICM_GetDWORD(pris->count, pvData, pcbData);
  15867. }
  15868. break;
  15869. case CMSG_CMS_RECIPIENT_INDEX_PARAM:
  15870. {
  15871. CmsRecipientInfos *pris;
  15872. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15873. goto GetDecodedCmsRecipientsError;
  15874. fRet = ICM_GetDWORD(
  15875. pcmi->dwDecryptedRecipientIndex,
  15876. pvData,
  15877. pcbData);
  15878. }
  15879. break;
  15880. case CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM:
  15881. {
  15882. CmsRecipientInfos *pris;
  15883. CmsRecipientInfo *pri;
  15884. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15885. goto GetDecodedCmsRecipientsError;
  15886. pri = pris->value + pcmi->dwDecryptedRecipientIndex;
  15887. if (keyAgreeRecipientInfo_chosen != pri->choice)
  15888. goto NotKeyAgreeRecipientIndex;
  15889. fRet = ICM_GetDWORD(
  15890. pcmi->dwDecryptedRecipientEncryptedKeyIndex,
  15891. pvData,
  15892. pcbData);
  15893. }
  15894. break;
  15895. case CMSG_CMS_RECIPIENT_INFO_PARAM:
  15896. {
  15897. CmsRecipientInfos *pris;
  15898. if (NULL == (pris = ICM_GetDecodedCmsRecipientInfos(pcmi)))
  15899. goto GetDecodedCmsRecipientsError;
  15900. if (dwIndex >= pris->count)
  15901. goto IndexTooBig;
  15902. fRet = ICM_GetCmsRecipientInfo(pris->value + dwIndex,
  15903. pvData, pcbData);
  15904. }
  15905. break;
  15906. #else
  15907. case CMSG_RECIPIENT_COUNT_PARAM:
  15908. {
  15909. RecipientInfos *pris;
  15910. if (pcsi &&
  15911. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15912. goto StreamMsgNotReadyError;
  15913. switch (pcmi->dwMsgType) {
  15914. case CMSG_ENVELOPED:
  15915. pris = &((EnvelopedData *)pcmi->pvMsg)->recipientInfos;
  15916. break;
  15917. case CMSG_SIGNED_AND_ENVELOPED:
  15918. goto MessageTypeNotSupportedYet;
  15919. default:
  15920. goto InvalidMsgType;
  15921. }
  15922. fRet = ICM_GetDWORD( pris->count, pvData, pcbData);
  15923. break;
  15924. }
  15925. case CMSG_RECIPIENT_INDEX_PARAM:
  15926. {
  15927. if (pcsi &&
  15928. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15929. goto StreamMsgNotReadyError;
  15930. switch (pcmi->dwMsgType) {
  15931. case CMSG_ENVELOPED:
  15932. case CMSG_SIGNED_AND_ENVELOPED:
  15933. break;
  15934. default:
  15935. goto InvalidMsgType;
  15936. }
  15937. fRet = ICM_GetDWORD(
  15938. pcmi->dwDecryptedRecipientIndex,
  15939. pvData,
  15940. pcbData);
  15941. break;
  15942. }
  15943. case CMSG_RECIPIENT_INFO_PARAM:
  15944. {
  15945. RecipientInfos *pris;
  15946. RecipientInfo *pri;
  15947. PCERT_INFO pci = (PCERT_INFO)pvData;
  15948. if (pcsi &&
  15949. (0 == (pcmi->aflDecode & ICMS_DECODED_ENVELOPED_RECIPINFOS)))
  15950. goto StreamMsgNotReadyError;
  15951. switch (pcmi->dwMsgType) {
  15952. case CMSG_ENVELOPED:
  15953. pris = &((EnvelopedData *)pcmi->pvMsg)->recipientInfos;
  15954. if (dwIndex >= pris->count)
  15955. goto IndexTooBig;
  15956. pri = pris->value + dwIndex;
  15957. break;
  15958. case CMSG_SIGNED_AND_ENVELOPED:
  15959. goto MessageTypeNotSupportedYet;
  15960. default:
  15961. goto InvalidMsgType;
  15962. }
  15963. // for lRemainExtra < 0, LENGTH_ONLY calculation
  15964. lData = INFO_LEN_ALIGN( sizeof(CERT_INFO));
  15965. lRemainExtra = (LONG)*pcbData - lData;
  15966. if (0 > lRemainExtra) {
  15967. pci = NULL;
  15968. pbExtra = NULL;
  15969. } else {
  15970. pbExtra = (PBYTE)pci + lData;
  15971. }
  15972. if (!ICM_GetOssIssuerAndSerialNumber(
  15973. &pri->issuerAndSerialNumber,
  15974. pci, &pbExtra, &lRemainExtra))
  15975. goto GetOssIssuerAndSerialNumberError;
  15976. fRet = ICM_GetSizeFromExtra( lRemainExtra, pvData, pcbData);
  15977. break;
  15978. }
  15979. #endif // CMS_PKCS7
  15980. case CMSG_HASH_ALGORITHM_PARAM:
  15981. fRet = ICM_GetALGORITHM_IDENTIFIER(
  15982. &((DigestedData *)pcmi->pvMsg)->digestAlgorithm,
  15983. pvData,
  15984. pcbData);
  15985. break;
  15986. case CMSG_HASH_DATA_PARAM:
  15987. fRet = ICM_GetDigestDataParam( pcmi, pvData, pcbData);
  15988. break;
  15989. case CMSG_COMPUTED_HASH_PARAM:
  15990. fRet = ICM_GetComputedDigestParam( pcmi, dwIndex, pvData, pcbData);
  15991. break;
  15992. case CMSG_ENCRYPT_PARAM:
  15993. #if 0
  15994. {
  15995. goto ParamTypeNotSupportedYet;
  15996. }
  15997. #endif
  15998. default:
  15999. goto InvalidMsgType;
  16000. }
  16001. }
  16002. #ifdef CMS_PKCS7
  16003. PreserveLengthReturn:
  16004. #endif // CMS_PKCS7
  16005. if (!fRet)
  16006. dwError = GetLastError();
  16007. } __except(EXCEPTION_EXECUTE_HANDLER) {
  16008. dwExceptionCode = GetExceptionCode();
  16009. goto ExceptionError;
  16010. }
  16011. CommonReturn:
  16012. if (fBER)
  16013. PkiAsn1SetEncodingRule(ICM_GetEncoder(), ASN1_BER_RULE_DER);
  16014. ICM_Unlock( pcmi);
  16015. ICM_SetLastError(dwError);
  16016. return fRet;
  16017. ErrorReturn:
  16018. *pcbData = 0;
  16019. fRet = FALSE;
  16020. goto CommonReturn;
  16021. StreamMsgNotReadyError:
  16022. dwError = (DWORD)CRYPT_E_STREAM_MSG_NOT_READY;
  16023. goto ErrorReturn;
  16024. SET_ERROR(GetContentParamNotValidForStreaming, E_INVALIDARG)
  16025. SET_ERROR(IndexTooBig,CRYPT_E_INVALID_INDEX)
  16026. SET_ERROR(MessageTypeNotSupportedYet,CRYPT_E_INVALID_MSG_TYPE)
  16027. SET_ERROR(InvalidMsgType,CRYPT_E_INVALID_MSG_TYPE)
  16028. SET_ERROR(ExtractContentError,CRYPT_E_UNEXPECTED_ENCODING)
  16029. SET_ERROR_VAR(CONTENT_PARAMAsn1EncodeError, PkiAsn1ErrToHr(Asn1Err))
  16030. SET_ERROR_VAR(Asn1EncodeSignedDataError, PkiAsn1ErrToHr(Asn1Err))
  16031. TRACE_ERROR(CopyOssObjectIdentifierContentTypeError) // error already set
  16032. TRACE_ERROR(ReEncodeAsOctetDERError) // error already set
  16033. SET_ERROR(InvalidSignedMessageError, ERROR_INVALID_DATA)
  16034. #ifdef CMS_PKCS7
  16035. SET_ERROR(MessageNotDecodedError, ERROR_INVALID_DATA)
  16036. SET_ERROR(InvalidMessageDataError, ERROR_INVALID_DATA)
  16037. TRACE_ERROR(GetDecodedCmsRecipientsError)
  16038. TRACE_ERROR(GetPkcsRecipientCountError)
  16039. TRACE_ERROR(ConvertCmsToPkcsRecipientIndexError)
  16040. TRACE_ERROR(ConvertPkcsToCmsRecipientIndexError)
  16041. TRACE_ERROR(GetCmsRecipientIndexError)
  16042. SET_ERROR(NotKeyAgreeRecipientIndex, CRYPT_E_INVALID_INDEX)
  16043. SET_ERROR(UnprotectedAttrMissingError,CRYPT_E_ATTRIBUTES_MISSING)
  16044. #else
  16045. TRACE_ERROR(GetOssIssuerAndSerialNumberError) // error already set
  16046. #endif // CMS_PKCS7
  16047. SET_ERROR_VAR(ExceptionError, dwExceptionCode)
  16048. }
  16049. //+=========================================================================
  16050. // Data structures and functions to test and compare the NEW Net Meeting
  16051. // ASN1 compiler and RTS with the OSS compiler and RTS.
  16052. //-=========================================================================
  16053. #ifdef DEBUG_CRYPT_ASN1
  16054. //#define DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG 0x010
  16055. //#define DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG 0x020
  16056. //#define DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG 0x100
  16057. //static BOOL fGotDebugCryptAsn1Flags = FALSE;
  16058. //static int iDebugCryptAsn1Flags = 0;
  16059. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16060. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_OPEN_TO_ENCODE)(
  16061. IN DWORD dwMsgEncodingType,
  16062. IN DWORD dwFlags,
  16063. IN DWORD dwMsgType,
  16064. IN void const *pvMsgEncodeInfo,
  16065. IN OPTIONAL LPSTR pszInnerContentObjID,
  16066. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16067. );
  16068. static PFN_CRYPT_MSG_OPEN_TO_ENCODE pfnOssCryptMsgOpenToEncode = NULL;
  16069. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_OPEN_TO_DECODE)(
  16070. IN DWORD dwMsgEncodingType,
  16071. IN DWORD dwFlags,
  16072. IN DWORD dwMsgType,
  16073. IN HCRYPTPROV hCryptProv,
  16074. IN OPTIONAL PCERT_INFO pRecipientInfo,
  16075. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16076. );
  16077. static PFN_CRYPT_MSG_OPEN_TO_DECODE pfnOssCryptMsgOpenToDecode = NULL;
  16078. typedef HCRYPTMSG (WINAPI *PFN_CRYPT_MSG_DUPLICATE)(
  16079. IN HCRYPTMSG hCryptMsg
  16080. );
  16081. static PFN_CRYPT_MSG_DUPLICATE pfnOssCryptMsgDuplicate = NULL;
  16082. typedef BOOL (WINAPI *PFN_CRYPT_MSG_CLOSE)(
  16083. IN HCRYPTMSG hCryptMsg
  16084. );
  16085. static PFN_CRYPT_MSG_CLOSE pfnOssCryptMsgClose = NULL;
  16086. typedef BOOL (WINAPI *PFN_CRYPT_MSG_UPDATE)(
  16087. IN HCRYPTMSG hCryptMsg,
  16088. IN const BYTE *pbData,
  16089. IN DWORD cbData,
  16090. IN BOOL fFinal
  16091. );
  16092. static PFN_CRYPT_MSG_UPDATE pfnOssCryptMsgUpdate = NULL;
  16093. typedef BOOL (WINAPI *PFN_CRYPT_MSG_GET_PARAM)(
  16094. IN HCRYPTMSG hCryptMsg,
  16095. IN DWORD dwParamType,
  16096. IN DWORD dwIndex,
  16097. OUT void *pvData,
  16098. IN OUT DWORD *pcbData
  16099. );
  16100. static PFN_CRYPT_MSG_GET_PARAM pfnOssCryptMsgGetParam = NULL;
  16101. typedef BOOL (WINAPI *PFN_CRYPT_MSG_CONTROL)(
  16102. IN HCRYPTMSG hCryptMsg,
  16103. IN DWORD dwFlags,
  16104. IN DWORD dwCtrlType,
  16105. IN void const *pvCtrlPara
  16106. );
  16107. static PFN_CRYPT_MSG_CONTROL pfnOssCryptMsgControl = NULL;
  16108. #ifdef CMS_PKCS7
  16109. typedef BOOL (WINAPI *PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX)(
  16110. IN HCRYPTPROV hCryptProv,
  16111. IN DWORD dwEncodingType,
  16112. IN PBYTE pbSignerInfo,
  16113. IN DWORD cbSignerInfo,
  16114. IN PBYTE pbSignerInfoCountersignature,
  16115. IN DWORD cbSignerInfoCountersignature,
  16116. IN DWORD dwSignerType,
  16117. IN void *pvSigner,
  16118. IN DWORD dwFlags,
  16119. IN OPTIONAL void *pvReserved
  16120. );
  16121. static PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX
  16122. pfnOssCryptMsgVerifyCountersignatureEncodedEx = NULL;
  16123. #endif // CMS_PKCS7
  16124. typedef BOOL (WINAPI *PFN_CRYPT_MSG_COUNTERSIGN)(
  16125. IN OUT HCRYPTMSG hCryptMsg,
  16126. IN DWORD dwIndex,
  16127. IN DWORD cCountersigners,
  16128. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners
  16129. );
  16130. static PFN_CRYPT_MSG_COUNTERSIGN pfnOssCryptMsgCountersign = NULL;
  16131. typedef BOOL (WINAPI *PFN_CRYPT_MSG_COUNTERSIGN_ENCODED)(
  16132. IN DWORD dwEncodingType,
  16133. IN PBYTE pbSignerInfo,
  16134. IN DWORD cbSignerInfo,
  16135. IN DWORD cCountersigners,
  16136. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  16137. OUT PBYTE pbCountersignature,
  16138. IN OUT PDWORD pcbCountersignature
  16139. );
  16140. static PFN_CRYPT_MSG_COUNTERSIGN_ENCODED
  16141. pfnOssCryptMsgCountersignEncoded = NULL;
  16142. #endif // DEBUG_CRYPT_ASN1_MASTER
  16143. int
  16144. WINAPI
  16145. ICMTest_GetDebugCryptAsn1Flags()
  16146. {
  16147. if (!fGotDebugCryptAsn1Flags) {
  16148. char *pszEnvVar;
  16149. char *p;
  16150. int iFlags;
  16151. if (pszEnvVar = getenv("DEBUG_CRYPT_ASN1_FLAGS")) {
  16152. iFlags = strtol(pszEnvVar, &p, 16);
  16153. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16154. if (iFlags) {
  16155. if (NULL == (hOssCryptDll = LoadLibraryA("osscrypt.dll"))) {
  16156. iFlags = 0;
  16157. MessageBoxA(
  16158. NULL, // hwndOwner
  16159. "LoadLibrary(osscrypt.dll) failed",
  16160. "CheckCryptMessageAsn1",
  16161. MB_TOPMOST | MB_OK | MB_ICONWARNING |
  16162. MB_SERVICE_NOTIFICATION
  16163. );
  16164. } else if (NULL == (pfnOssCryptMsgOpenToEncode =
  16165. (PFN_CRYPT_MSG_OPEN_TO_ENCODE)
  16166. GetProcAddress(hOssCryptDll,
  16167. "CryptMsgOpenToEncode")) ||
  16168. NULL == (pfnOssCryptMsgOpenToDecode =
  16169. (PFN_CRYPT_MSG_OPEN_TO_DECODE)
  16170. GetProcAddress(hOssCryptDll,
  16171. "CryptMsgOpenToDecode")) ||
  16172. NULL == (pfnOssCryptMsgDuplicate =
  16173. (PFN_CRYPT_MSG_DUPLICATE)
  16174. GetProcAddress(hOssCryptDll,
  16175. "CryptMsgDuplicate")) ||
  16176. NULL == (pfnOssCryptMsgClose =
  16177. (PFN_CRYPT_MSG_CLOSE)
  16178. GetProcAddress(hOssCryptDll,
  16179. "CryptMsgClose")) ||
  16180. NULL == (pfnOssCryptMsgUpdate =
  16181. (PFN_CRYPT_MSG_UPDATE)
  16182. GetProcAddress(hOssCryptDll,
  16183. "CryptMsgUpdate")) ||
  16184. NULL == (pfnOssCryptMsgControl =
  16185. (PFN_CRYPT_MSG_CONTROL)
  16186. GetProcAddress(hOssCryptDll,
  16187. "CryptMsgControl")) ||
  16188. NULL == (pfnOssCryptMsgGetParam =
  16189. (PFN_CRYPT_MSG_GET_PARAM)
  16190. GetProcAddress(hOssCryptDll,
  16191. "CryptMsgGetParam")) ||
  16192. #ifdef CMS_PKCS7
  16193. NULL == (pfnOssCryptMsgVerifyCountersignatureEncodedEx =
  16194. (PFN_CRYPT_MSG_VERIFY_COUNTERSIGNATURE_ENCODED_EX)
  16195. GetProcAddress(hOssCryptDll,
  16196. "CryptMsgVerifyCountersignatureEncodedEx"))
  16197. ||
  16198. #endif // CMS_PKCS7
  16199. NULL == (pfnOssCryptMsgCountersign =
  16200. (PFN_CRYPT_MSG_COUNTERSIGN)
  16201. GetProcAddress(hOssCryptDll,
  16202. "CryptMsgCountersign")) ||
  16203. NULL == (pfnOssCryptMsgCountersignEncoded =
  16204. (PFN_CRYPT_MSG_COUNTERSIGN_ENCODED)
  16205. GetProcAddress(hOssCryptDll,
  16206. "CryptMsgCountersignEncoded"))) {
  16207. iFlags = 0;
  16208. MessageBoxA(
  16209. NULL, // hwndOwner
  16210. "GetProcAddress(osscrypt.dll) failed",
  16211. "CheckCryptMessageAsn1",
  16212. MB_TOPMOST | MB_OK | MB_ICONWARNING |
  16213. MB_SERVICE_NOTIFICATION
  16214. );
  16215. }
  16216. }
  16217. #endif // DEBUG_CRYPT_ASN1_MASTER
  16218. } else
  16219. iFlags = 0;
  16220. if (iFlags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG)
  16221. iFlags &= ~DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG;
  16222. iDebugCryptAsn1Flags = iFlags;
  16223. fGotDebugCryptAsn1Flags = TRUE;
  16224. }
  16225. return iDebugCryptAsn1Flags;
  16226. }
  16227. HCRYPTKEY
  16228. ICMTest_GetSameEncryptKey()
  16229. {
  16230. DWORD dwError = 0;
  16231. HCRYPTPROV hCryptProv; // doesn't need to be freed
  16232. HCRYPTHASH hHash = 0;
  16233. HCRYPTKEY hDeriveKey = 0;
  16234. BYTE rgbBaseData[] = {1,2,3,4,5,6,7,8};
  16235. hCryptProv = I_CryptGetDefaultCryptProvForEncrypt(
  16236. 0, // aiPubKey
  16237. CALG_RC2,
  16238. 0 // dwBitLen
  16239. );
  16240. if (0 == hCryptProv)
  16241. goto GetDefaultCryptProvError;
  16242. if (!CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
  16243. goto CreateHashError;
  16244. if (!CryptHashData(hHash, rgbBaseData, sizeof(rgbBaseData), 0))
  16245. goto HashDataError;
  16246. if (!CryptDeriveKey(hCryptProv, CALG_RC2, hHash, 0, &hDeriveKey))
  16247. goto DeriveKeyError;
  16248. CommonReturn:
  16249. if (hHash)
  16250. CryptDestroyHash(hHash);
  16251. ICM_SetLastError(dwError);
  16252. return hDeriveKey;
  16253. ErrorReturn:
  16254. dwError = GetLastError();
  16255. if (hDeriveKey) {
  16256. CryptDestroyKey(hDeriveKey);
  16257. hDeriveKey = 0;
  16258. }
  16259. goto CommonReturn;
  16260. TRACE_ERROR(GetDefaultCryptProvError)
  16261. TRACE_ERROR(CreateHashError)
  16262. TRACE_ERROR(HashDataError)
  16263. TRACE_ERROR(DeriveKeyError)
  16264. }
  16265. #ifdef CMS_PKCS7
  16266. BOOL
  16267. WINAPI
  16268. ICM_DefaultGenContentEncryptKey(
  16269. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  16270. IN DWORD dwFlags,
  16271. IN OPTIONAL void *pvReserved
  16272. )
  16273. {
  16274. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16275. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16276. return ICMTest_DefaultGenContentEncryptKey(
  16277. pContentEncryptInfo,
  16278. dwFlags,
  16279. pvReserved
  16280. );
  16281. pContentEncryptInfo->hContentEncryptKey = ICMTest_GetSameEncryptKey();
  16282. if (pContentEncryptInfo->hContentEncryptKey)
  16283. return TRUE;
  16284. else
  16285. return FALSE;
  16286. }
  16287. BOOL
  16288. WINAPI
  16289. ICM_DefaultExportKeyTrans(
  16290. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  16291. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  16292. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
  16293. IN DWORD dwFlags,
  16294. IN OPTIONAL void *pvReserved
  16295. )
  16296. {
  16297. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16298. PCRYPT_DATA_BLOB pEncryptedKey;
  16299. BYTE rgbEncryptedKey[] = {1,1,2,2,3,3,4,4,5,5};
  16300. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16301. return ICMTest_DefaultExportKeyTrans(
  16302. pContentEncryptInfo,
  16303. pKeyTransEncodeInfo,
  16304. pKeyTransEncryptInfo,
  16305. dwFlags,
  16306. pvReserved
  16307. );
  16308. pEncryptedKey = &pKeyTransEncryptInfo->EncryptedKey;
  16309. if (NULL == (pEncryptedKey->pbData = (PBYTE) ICM_Alloc(
  16310. sizeof(rgbEncryptedKey))))
  16311. return FALSE;
  16312. pEncryptedKey->cbData = sizeof(rgbEncryptedKey);
  16313. memcpy(pEncryptedKey->pbData, rgbEncryptedKey, sizeof(rgbEncryptedKey));
  16314. return TRUE;
  16315. }
  16316. BOOL
  16317. WINAPI
  16318. ICM_DefaultImportKeyTrans(
  16319. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  16320. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  16321. IN DWORD dwFlags,
  16322. IN OPTIONAL void *pvReserved,
  16323. OUT HCRYPTKEY *phContentEncryptKey
  16324. )
  16325. {
  16326. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16327. if (0 == (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_SAME_ENCRYPT_FLAG))
  16328. return ICMTest_DefaultImportKeyTrans(
  16329. pContentEncryptionAlgorithm,
  16330. pKeyTransDecryptPara,
  16331. dwFlags,
  16332. pvReserved,
  16333. phContentEncryptKey
  16334. );
  16335. *phContentEncryptKey = ICMTest_GetSameEncryptKey();
  16336. if (*phContentEncryptKey)
  16337. return TRUE;
  16338. else
  16339. return FALSE;
  16340. }
  16341. #endif // CMS_PKCS7
  16342. #ifdef DEBUG_CRYPT_ASN1_MASTER
  16343. void
  16344. ICMTest_MessageBox(
  16345. IN LPSTR pszText
  16346. )
  16347. {
  16348. int id;
  16349. LPSTR pszAlloc = NULL;
  16350. DWORD cchAlloc;
  16351. static LPCSTR pszSelect =
  16352. " Select Cancel to stop future OssCryptAsn1 Cryptographic Messages.";
  16353. cchAlloc = strlen(pszText) + strlen(pszSelect) + 1;
  16354. if (pszAlloc = (LPSTR) ICM_Alloc(cchAlloc)) {
  16355. strcpy(pszAlloc, pszText);
  16356. strcat(pszAlloc, pszSelect);
  16357. pszText = pszAlloc;
  16358. }
  16359. id = MessageBoxA(
  16360. NULL, // hwndOwner
  16361. pszText,
  16362. "CheckCryptMessageAsn1",
  16363. MB_TOPMOST | MB_OKCANCEL | MB_ICONQUESTION |
  16364. MB_SERVICE_NOTIFICATION
  16365. );
  16366. if (IDCANCEL == id)
  16367. iDebugCryptAsn1Flags = 0;
  16368. ICM_Free(pszAlloc);
  16369. }
  16370. void
  16371. ICMTest_MessageBoxLastError(
  16372. IN LPSTR pszText,
  16373. IN DWORD dwOssErr,
  16374. IN DWORD dwNewErr
  16375. )
  16376. {
  16377. char szText[512];
  16378. if (dwNewErr == (DWORD) PkiAsn1ErrToHr(ASN1_ERR_BADTAG) &&
  16379. (OSS_DATA_ERROR == dwOssErr || OSS_PDU_MISMATCH == dwOssErr))
  16380. return;
  16381. if (dwNewErr == (DWORD) PkiAsn1ErrToHr(ASN1_ERR_EOD) &&
  16382. OSS_MORE_INPUT == dwOssErr)
  16383. return;
  16384. wsprintfA(szText,
  16385. "%s:: failed with different LastError Oss: %d 0x%x New: %d 0x%x.",
  16386. pszText, dwOssErr, dwOssErr, dwNewErr, dwNewErr
  16387. );
  16388. ICMTest_MessageBox(szText);
  16389. }
  16390. //+-------------------------------------------------------------------------
  16391. // Write an encoded DER blob to a file
  16392. //--------------------------------------------------------------------------
  16393. BOOL
  16394. ICMTest_WriteDERToFile(
  16395. LPCSTR pszFileName,
  16396. PBYTE pbDER,
  16397. DWORD cbDER
  16398. )
  16399. {
  16400. BOOL fResult;
  16401. // Write the Encoded Blob to the file
  16402. HANDLE hFile;
  16403. hFile = CreateFile(pszFileName,
  16404. GENERIC_WRITE,
  16405. 0, // fdwShareMode
  16406. NULL, // lpsa
  16407. CREATE_ALWAYS,
  16408. 0, // fdwAttrsAndFlags
  16409. 0); // TemplateFile
  16410. if (INVALID_HANDLE_VALUE == hFile) {
  16411. fResult = FALSE;
  16412. } else {
  16413. DWORD dwBytesWritten;
  16414. fResult = WriteFile(
  16415. hFile,
  16416. pbDER,
  16417. cbDER,
  16418. &dwBytesWritten,
  16419. NULL // lpOverlapped
  16420. );
  16421. CloseHandle(hFile);
  16422. }
  16423. return fResult;
  16424. }
  16425. #define TEST_MAGIC -12348765
  16426. // Note, in the following data structure lMagic is at the same offest as
  16427. // lRefCnt in CRYPT_MSG_INFO. lRefCnt should never be negative.
  16428. typedef struct _OSS_CRYPT_ASN1_MSG_INFO {
  16429. // The following must be ordered the same as CRYPT_MSG_INFO through
  16430. // dwEncodingType. msghlpr.cpp does a (PCRYPT_MSG_INFO) cast to
  16431. // access dwEncodingType.
  16432. CRITICAL_SECTION CriticalSection;
  16433. LONG lMagic; // lRefCnt in CRYPT_MSG_INFO
  16434. HCRYPTPROV hCryptProv; // decode
  16435. BOOL fDefaultCryptProv; // decode
  16436. DWORD dwKeySpec; // key to use in CryptSignHash
  16437. DWORD dwEncodingType; // encode
  16438. LONG lRefCnt;
  16439. union {
  16440. HCRYPTMSG hNewCryptMsg;
  16441. PCRYPT_MSG_INFO pNewcmi;
  16442. };
  16443. union {
  16444. HCRYPTMSG hOssCryptMsg;
  16445. PCRYPT_MSG_INFO pOsscmi;
  16446. };
  16447. PFN_CMSG_STREAM_OUTPUT pfnStreamOutput;
  16448. void *pvArg;
  16449. BYTE *pbOssOutput;
  16450. DWORD cbOssOutput;
  16451. BOOL fOssFinal;
  16452. BYTE *pbNewOutput;
  16453. DWORD cbNewOutput;
  16454. BOOL fNewFinal;
  16455. BOOL fDidCompare;
  16456. } OSS_CRYPT_ASN1_MSG_INFO, *POSS_CRYPT_ASN1_MSG_INFO;
  16457. BOOL
  16458. WINAPI
  16459. ICMTest_OssStreamOutput(
  16460. IN const void *pvArg,
  16461. IN BYTE *pbData,
  16462. IN DWORD cbData,
  16463. IN BOOL fFinal
  16464. )
  16465. {
  16466. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) pvArg;
  16467. assert(TEST_MAGIC == pInfo->lMagic);
  16468. assert(!pInfo->fOssFinal);
  16469. pInfo->fOssFinal = fFinal;
  16470. if (cbData) {
  16471. BYTE *pbOssOutput;
  16472. if (pbOssOutput = (BYTE *) ICM_ReAlloc(pInfo->pbOssOutput,
  16473. pInfo->cbOssOutput + cbData)) {
  16474. memcpy(pbOssOutput + pInfo->cbOssOutput, pbData, cbData);
  16475. pInfo->pbOssOutput = pbOssOutput;
  16476. pInfo->cbOssOutput += cbData;
  16477. }
  16478. }
  16479. return TRUE;
  16480. }
  16481. BOOL
  16482. WINAPI
  16483. ICMTest_NewStreamOutput(
  16484. IN const void *pvArg,
  16485. IN BYTE *pbData,
  16486. IN DWORD cbData,
  16487. IN BOOL fFinal
  16488. )
  16489. {
  16490. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) pvArg;
  16491. assert(TEST_MAGIC == pInfo->lMagic);
  16492. assert(!pInfo->fNewFinal);
  16493. pInfo->fNewFinal = fFinal;
  16494. if (cbData) {
  16495. BYTE *pbNewOutput;
  16496. if (pbNewOutput = (BYTE *) ICM_ReAlloc(pInfo->pbNewOutput,
  16497. pInfo->cbNewOutput + cbData)) {
  16498. memcpy(pbNewOutput + pInfo->cbNewOutput, pbData, cbData);
  16499. pInfo->pbNewOutput = pbNewOutput;
  16500. pInfo->cbNewOutput += cbData;
  16501. }
  16502. }
  16503. return pInfo->pfnStreamOutput(
  16504. pInfo->pvArg,
  16505. pbData,
  16506. cbData,
  16507. fFinal
  16508. );
  16509. }
  16510. void
  16511. ICMTest_CompareMessageBox(
  16512. IN LPSTR pszText,
  16513. IN BYTE *pbOss,
  16514. IN DWORD cbOss,
  16515. IN BYTE *pbNew,
  16516. IN DWORD cbNew
  16517. )
  16518. {
  16519. if (NULL == pbOss || NULL == pbNew)
  16520. return;
  16521. if (cbOss != cbNew || 0 != memcmp(pbOss, pbNew, cbNew)) {
  16522. ICMTest_WriteDERToFile("ossasn1.der", pbOss, cbOss);
  16523. ICMTest_WriteDERToFile("newasn1.der", pbNew, cbNew);
  16524. ICMTest_MessageBox(pszText);
  16525. }
  16526. }
  16527. void
  16528. ICMTest_CompareStreamOutput(
  16529. IN POSS_CRYPT_ASN1_MSG_INFO pInfo,
  16530. IN BOOL fForceCompare = FALSE
  16531. )
  16532. {
  16533. BOOL fDoCompare;
  16534. if (NULL == pInfo->pfnStreamOutput || pInfo->fDidCompare)
  16535. return;
  16536. fDoCompare = fForceCompare;
  16537. if (pInfo->fOssFinal || pInfo->fNewFinal)
  16538. fDoCompare = TRUE;
  16539. if (fDoCompare) {
  16540. if (pInfo->fOssFinal != pInfo->fNewFinal) {
  16541. if (pInfo->fOssFinal)
  16542. ICMTest_MessageBox("No fFinal on NewStreamOutput.");
  16543. else
  16544. ICMTest_MessageBox("No fFinal on OssStreamOutput.");
  16545. }
  16546. ICMTest_CompareMessageBox(
  16547. "StreamOutput compare failed. Check ossasn1.der and newasn1.der.",
  16548. pInfo->pbOssOutput,
  16549. pInfo->cbOssOutput,
  16550. pInfo->pbNewOutput,
  16551. pInfo->cbNewOutput
  16552. );
  16553. pInfo->fDidCompare = TRUE;
  16554. }
  16555. }
  16556. void
  16557. ICMTest_CompareGetParam(
  16558. IN POSS_CRYPT_ASN1_MSG_INFO pInfo,
  16559. IN DWORD dwParamType,
  16560. IN DWORD dwIndex,
  16561. IN void *pvOssData,
  16562. IN DWORD cbOssData,
  16563. IN void *pvNewData,
  16564. IN DWORD cbNewData
  16565. )
  16566. {
  16567. char szText[512];
  16568. switch (dwParamType) {
  16569. case CMSG_TYPE_PARAM:
  16570. case CMSG_CONTENT_PARAM:
  16571. case CMSG_BARE_CONTENT_PARAM:
  16572. case CMSG_INNER_CONTENT_TYPE_PARAM:
  16573. case CMSG_SIGNER_COUNT_PARAM:
  16574. case CMSG_CERT_COUNT_PARAM:
  16575. case CMSG_CERT_PARAM:
  16576. case CMSG_CRL_COUNT_PARAM:
  16577. case CMSG_CRL_PARAM:
  16578. case CMSG_RECIPIENT_COUNT_PARAM:
  16579. case CMSG_HASH_DATA_PARAM:
  16580. case CMSG_COMPUTED_HASH_PARAM:
  16581. case CMSG_ENCRYPTED_DIGEST:
  16582. case CMSG_ENCODED_SIGNER:
  16583. case CMSG_ENCODED_MESSAGE:
  16584. #ifdef CMS_PKCS7
  16585. case CMSG_VERSION_PARAM:
  16586. case CMSG_ATTR_CERT_COUNT_PARAM:
  16587. case CMSG_ATTR_CERT_PARAM:
  16588. case CMSG_CMS_RECIPIENT_COUNT_PARAM:
  16589. #endif // CMS_PKCS7
  16590. break;
  16591. default:
  16592. return;
  16593. }
  16594. if (NULL == pvOssData || NULL == pvNewData)
  16595. return;
  16596. wsprintfA(szText,
  16597. "ParamType: %d compare failed. Check ossasn1.der and newasn1.der.",
  16598. dwParamType
  16599. );
  16600. ICMTest_CompareMessageBox(
  16601. szText,
  16602. (BYTE *) pvOssData,
  16603. cbOssData,
  16604. (BYTE *) pvNewData,
  16605. cbNewData
  16606. );
  16607. }
  16608. inline
  16609. void
  16610. ICMTest_Lock(
  16611. IN POSS_CRYPT_ASN1_MSG_INFO pInfo
  16612. )
  16613. {
  16614. EnterCriticalSection( &pInfo->CriticalSection);
  16615. }
  16616. inline
  16617. void
  16618. ICMTest_Unlock(
  16619. IN POSS_CRYPT_ASN1_MSG_INFO pInfo
  16620. )
  16621. {
  16622. LeaveCriticalSection( &pInfo->CriticalSection);
  16623. }
  16624. HCRYPTMSG
  16625. WINAPI
  16626. CryptMsgOpenToEncode(
  16627. IN DWORD dwMsgEncodingType,
  16628. IN DWORD dwFlags,
  16629. IN DWORD dwMsgType,
  16630. IN void const *pvMsgEncodeInfo,
  16631. IN OPTIONAL LPSTR pszInnerContentObjID,
  16632. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16633. )
  16634. {
  16635. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16636. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  16637. POSS_CRYPT_ASN1_MSG_INFO pInfo;
  16638. CMSG_STREAM_INFO StreamInfo;
  16639. DWORD dwOssErr;
  16640. DWORD dwNewErr;
  16641. if (NULL == (pInfo = (POSS_CRYPT_ASN1_MSG_INFO) ICM_AllocZero(
  16642. sizeof(OSS_CRYPT_ASN1_MSG_INFO))))
  16643. return NULL;
  16644. pInfo->lMagic = TEST_MAGIC;
  16645. if (pStreamInfo) {
  16646. pInfo->pfnStreamOutput = pStreamInfo->pfnStreamOutput;
  16647. pInfo->pvArg = pStreamInfo->pvArg;
  16648. StreamInfo.cbContent = pStreamInfo->cbContent;
  16649. // StreamInfo.pfnStreamOutput =
  16650. StreamInfo.pvArg = pInfo;
  16651. pStreamInfo = &StreamInfo;
  16652. }
  16653. StreamInfo.pfnStreamOutput = ICMTest_NewStreamOutput;
  16654. pInfo->hNewCryptMsg = ICMTest_NewCryptMsgOpenToEncode(
  16655. dwMsgEncodingType,
  16656. dwFlags,
  16657. dwMsgType,
  16658. pvMsgEncodeInfo,
  16659. pszInnerContentObjID,
  16660. pStreamInfo
  16661. );
  16662. dwNewErr = GetLastError();
  16663. StreamInfo.pfnStreamOutput = ICMTest_OssStreamOutput;
  16664. pInfo->hOssCryptMsg = pfnOssCryptMsgOpenToEncode(
  16665. dwMsgEncodingType,
  16666. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  16667. dwMsgType,
  16668. pvMsgEncodeInfo,
  16669. pszInnerContentObjID,
  16670. pStreamInfo
  16671. );
  16672. dwOssErr = GetLastError();
  16673. if (pInfo->hNewCryptMsg) {
  16674. if (pInfo->hOssCryptMsg) {
  16675. pInfo->dwEncodingType = pInfo->pNewcmi->dwEncodingType;
  16676. InitializeCriticalSection(&pInfo->CriticalSection);
  16677. pInfo->lRefCnt = 1;
  16678. return (HCRYPTMSG) pInfo;
  16679. } else {
  16680. HCRYPTMSG hRet;
  16681. ICMTest_MessageBox("OssCryptMsgOpenToEncode failed.");
  16682. hRet = pInfo->hNewCryptMsg;
  16683. ICM_Free(pInfo);
  16684. return hRet;
  16685. }
  16686. } else {
  16687. if (pInfo->hOssCryptMsg) {
  16688. ICMTest_MessageBox("OssCryptMsgOpenToEncode succeeded while NewCryptMsgOpenToEncoded failed.");
  16689. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16690. } else if (dwOssErr != dwNewErr)
  16691. ICMTest_MessageBoxLastError("CryptMsgOpenToEncode",
  16692. dwOssErr, dwNewErr);
  16693. ICM_Free(pInfo);
  16694. SetLastError(dwNewErr);
  16695. return NULL;
  16696. }
  16697. } else if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16698. return pfnOssCryptMsgOpenToEncode(
  16699. dwMsgEncodingType,
  16700. dwFlags,
  16701. dwMsgType,
  16702. pvMsgEncodeInfo,
  16703. pszInnerContentObjID,
  16704. pStreamInfo
  16705. );
  16706. else
  16707. return ICMTest_NewCryptMsgOpenToEncode(
  16708. dwMsgEncodingType,
  16709. dwFlags,
  16710. dwMsgType,
  16711. pvMsgEncodeInfo,
  16712. pszInnerContentObjID,
  16713. pStreamInfo
  16714. );
  16715. }
  16716. HCRYPTMSG
  16717. WINAPI
  16718. CryptMsgOpenToDecode(
  16719. IN DWORD dwMsgEncodingType,
  16720. IN DWORD dwFlags,
  16721. IN DWORD dwMsgType,
  16722. IN HCRYPTPROV hCryptProv,
  16723. IN OPTIONAL PCERT_INFO pRecipientInfo,
  16724. IN OPTIONAL PCMSG_STREAM_INFO pStreamInfo
  16725. )
  16726. {
  16727. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  16728. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  16729. POSS_CRYPT_ASN1_MSG_INFO pInfo;
  16730. CMSG_STREAM_INFO StreamInfo;
  16731. DWORD dwOssErr;
  16732. DWORD dwNewErr;
  16733. if (NULL == (pInfo = (POSS_CRYPT_ASN1_MSG_INFO) ICM_AllocZero(
  16734. sizeof(OSS_CRYPT_ASN1_MSG_INFO))))
  16735. return NULL;
  16736. pInfo->lMagic = TEST_MAGIC;
  16737. if (pStreamInfo) {
  16738. pInfo->pfnStreamOutput = pStreamInfo->pfnStreamOutput;
  16739. pInfo->pvArg = pStreamInfo->pvArg;
  16740. StreamInfo.cbContent = pStreamInfo->cbContent;
  16741. // StreamInfo.pfnStreamOutput =
  16742. StreamInfo.pvArg = pInfo;
  16743. pStreamInfo = &StreamInfo;
  16744. }
  16745. StreamInfo.pfnStreamOutput = ICMTest_NewStreamOutput;
  16746. pInfo->hNewCryptMsg = ICMTest_NewCryptMsgOpenToDecode(
  16747. dwMsgEncodingType,
  16748. dwFlags,
  16749. dwMsgType,
  16750. hCryptProv,
  16751. pRecipientInfo,
  16752. pStreamInfo
  16753. );
  16754. dwNewErr = GetLastError();
  16755. StreamInfo.pfnStreamOutput = ICMTest_OssStreamOutput;
  16756. pInfo->hOssCryptMsg = pfnOssCryptMsgOpenToDecode(
  16757. dwMsgEncodingType,
  16758. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  16759. dwMsgType,
  16760. hCryptProv,
  16761. pRecipientInfo,
  16762. pStreamInfo
  16763. );
  16764. dwOssErr = GetLastError();
  16765. if (pInfo->hNewCryptMsg) {
  16766. if (pInfo->hOssCryptMsg) {
  16767. pInfo->dwEncodingType = pInfo->pNewcmi->dwEncodingType;
  16768. InitializeCriticalSection(&pInfo->CriticalSection);
  16769. pInfo->lRefCnt = 1;
  16770. return (HCRYPTMSG) pInfo;
  16771. } else {
  16772. HCRYPTMSG hRet;
  16773. ICMTest_MessageBox("OssCryptMsgOpenToDecode failed.");
  16774. hRet = pInfo->hNewCryptMsg;
  16775. ICM_Free(pInfo);
  16776. return hRet;
  16777. }
  16778. } else {
  16779. if (pInfo->hOssCryptMsg) {
  16780. ICMTest_MessageBox("OssCryptMsgOpenToDecode succeeded while NewCryptMsgOpenToDecode failed.");
  16781. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16782. } else if (dwOssErr != dwNewErr)
  16783. ICMTest_MessageBoxLastError("CryptMsgOpenToDecode",
  16784. dwOssErr, dwNewErr);
  16785. ICM_Free(pInfo);
  16786. SetLastError(dwNewErr);
  16787. return NULL;
  16788. }
  16789. } else if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16790. return pfnOssCryptMsgOpenToDecode(
  16791. dwMsgEncodingType,
  16792. dwFlags,
  16793. dwMsgType,
  16794. hCryptProv,
  16795. pRecipientInfo,
  16796. pStreamInfo
  16797. );
  16798. else
  16799. return ICMTest_NewCryptMsgOpenToDecode(
  16800. dwMsgEncodingType,
  16801. dwFlags,
  16802. dwMsgType,
  16803. hCryptProv,
  16804. pRecipientInfo,
  16805. pStreamInfo
  16806. );
  16807. }
  16808. HCRYPTMSG
  16809. WINAPI
  16810. CryptMsgDuplicate(
  16811. IN HCRYPTMSG hCryptMsg
  16812. )
  16813. {
  16814. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16815. if (pInfo && TEST_MAGIC == pInfo->lMagic) {
  16816. InterlockedIncrement(&pInfo->lRefCnt);
  16817. return hCryptMsg;
  16818. } else if (ICMTest_GetDebugCryptAsn1Flags() &
  16819. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16820. return pfnOssCryptMsgDuplicate(hCryptMsg);
  16821. else
  16822. return ICMTest_NewCryptMsgDuplicate(hCryptMsg);
  16823. }
  16824. BOOL
  16825. WINAPI
  16826. CryptMsgClose(
  16827. IN HCRYPTMSG hCryptMsg
  16828. )
  16829. {
  16830. BOOL fRet;
  16831. DWORD dwError;
  16832. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16833. if (NULL == pInfo)
  16834. return TRUE;
  16835. if (TEST_MAGIC != pInfo->lMagic) {
  16836. if (iDebugCryptAsn1Flags &
  16837. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16838. return pfnOssCryptMsgClose(hCryptMsg);
  16839. else
  16840. return ICMTest_NewCryptMsgClose(hCryptMsg);
  16841. }
  16842. if (0 != InterlockedDecrement(&pInfo->lRefCnt))
  16843. return TRUE;
  16844. // Preserve LastError
  16845. dwError = GetLastError();
  16846. assert(pInfo->hOssCryptMsg);
  16847. assert(1 == ((PCRYPT_MSG_INFO) pInfo->hOssCryptMsg)->lRefCnt);
  16848. assert(pInfo->hNewCryptMsg);
  16849. assert(1 == ((PCRYPT_MSG_INFO) pInfo->hNewCryptMsg)->lRefCnt);
  16850. ICMTest_CompareStreamOutput(pInfo, TRUE);
  16851. pfnOssCryptMsgClose(pInfo->hOssCryptMsg);
  16852. fRet = ICMTest_NewCryptMsgClose(pInfo->hNewCryptMsg);
  16853. ICM_Free(pInfo->pbOssOutput);
  16854. ICM_Free(pInfo->pbNewOutput);
  16855. DeleteCriticalSection(&pInfo->CriticalSection);
  16856. ICM_Free(pInfo);
  16857. SetLastError(dwError); // Preserve LastError
  16858. return fRet;
  16859. }
  16860. BOOL
  16861. WINAPI
  16862. CryptMsgUpdate(
  16863. IN HCRYPTMSG hCryptMsg,
  16864. IN const BYTE *pbData,
  16865. IN DWORD cbData,
  16866. IN BOOL fFinal
  16867. )
  16868. {
  16869. BOOL fNew;
  16870. DWORD dwNewErr;
  16871. BOOL fOss;
  16872. DWORD dwOssErr;
  16873. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16874. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  16875. if (ICMTest_GetDebugCryptAsn1Flags() &
  16876. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16877. return pfnOssCryptMsgUpdate(
  16878. hCryptMsg,
  16879. pbData,
  16880. cbData,
  16881. fFinal
  16882. );
  16883. else
  16884. return ICMTest_NewCryptMsgUpdate(
  16885. hCryptMsg,
  16886. pbData,
  16887. cbData,
  16888. fFinal
  16889. );
  16890. }
  16891. ICMTest_Lock(pInfo);
  16892. fOss = pfnOssCryptMsgUpdate(
  16893. pInfo->hOssCryptMsg,
  16894. pbData,
  16895. cbData,
  16896. fFinal
  16897. );
  16898. dwOssErr = GetLastError();
  16899. fNew = ICMTest_NewCryptMsgUpdate(
  16900. pInfo->hNewCryptMsg,
  16901. pbData,
  16902. cbData,
  16903. fFinal
  16904. );
  16905. dwNewErr = GetLastError();
  16906. if (fNew) {
  16907. if (fOss)
  16908. ICMTest_CompareStreamOutput(pInfo);
  16909. else
  16910. ICMTest_MessageBox("OssCryptMsgUpdate failed.");
  16911. } else {
  16912. if (fOss)
  16913. ICMTest_MessageBox("OssCryptMsgUpdate succeeded while NewCryptMsgUpdate failed.");
  16914. else if (dwOssErr != dwNewErr)
  16915. ICMTest_MessageBoxLastError("CryptMsgUpdate",
  16916. dwOssErr, dwNewErr);
  16917. }
  16918. ICMTest_Unlock(pInfo);
  16919. SetLastError(dwNewErr);
  16920. return fNew;
  16921. }
  16922. BOOL
  16923. WINAPI
  16924. CryptMsgGetParam(
  16925. IN HCRYPTMSG hCryptMsg,
  16926. IN DWORD dwParamType,
  16927. IN DWORD dwIndex,
  16928. OUT void *pvData,
  16929. IN OUT DWORD *pcbData
  16930. )
  16931. {
  16932. BOOL fOss;
  16933. DWORD dwOssErr;
  16934. void *pvOssData = NULL;
  16935. DWORD cbOssData;
  16936. BOOL fNew;
  16937. DWORD dwNewErr;
  16938. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  16939. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  16940. if (ICMTest_GetDebugCryptAsn1Flags() &
  16941. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  16942. return pfnOssCryptMsgGetParam(
  16943. hCryptMsg,
  16944. dwParamType,
  16945. dwIndex,
  16946. pvData,
  16947. pcbData
  16948. );
  16949. else
  16950. return ICMTest_NewCryptMsgGetParam(
  16951. hCryptMsg,
  16952. dwParamType,
  16953. dwIndex,
  16954. pvData,
  16955. pcbData
  16956. );
  16957. }
  16958. ICMTest_Lock(pInfo);
  16959. cbOssData = *pcbData;
  16960. if (pvData)
  16961. pvOssData = ICM_Alloc(cbOssData);
  16962. fOss = pfnOssCryptMsgGetParam(
  16963. pInfo->hOssCryptMsg,
  16964. dwParamType,
  16965. dwIndex,
  16966. pvOssData,
  16967. &cbOssData
  16968. );
  16969. dwOssErr = GetLastError();
  16970. fNew = ICMTest_NewCryptMsgGetParam(
  16971. pInfo->hNewCryptMsg,
  16972. dwParamType,
  16973. dwIndex,
  16974. pvData,
  16975. pcbData
  16976. );
  16977. dwNewErr = GetLastError();
  16978. if (fNew) {
  16979. if (fOss)
  16980. ICMTest_CompareGetParam(
  16981. pInfo,
  16982. dwParamType,
  16983. dwIndex,
  16984. pvOssData,
  16985. cbOssData,
  16986. pvData,
  16987. *pcbData
  16988. );
  16989. else
  16990. ICMTest_MessageBox("OssCryptMsgGetParam failed.");
  16991. } else {
  16992. if (fOss)
  16993. ICMTest_MessageBox("OssCryptMsgGetParam succeeded while NewCryptMsgGetParam failed.");
  16994. else if (dwOssErr != dwNewErr)
  16995. ICMTest_MessageBoxLastError("CryptMsgGetParam",
  16996. dwOssErr, dwNewErr);
  16997. }
  16998. ICMTest_Unlock(pInfo);
  16999. ICM_Free(pvOssData);
  17000. SetLastError(dwNewErr);
  17001. return fNew;
  17002. }
  17003. BOOL
  17004. WINAPI
  17005. CryptMsgControl(
  17006. IN HCRYPTMSG hCryptMsg,
  17007. IN DWORD dwFlags,
  17008. IN DWORD dwCtrlType,
  17009. IN void const *pvCtrlPara
  17010. )
  17011. {
  17012. BOOL fNew;
  17013. DWORD dwNewErr;
  17014. BOOL fOss;
  17015. DWORD dwOssErr;
  17016. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  17017. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  17018. if (ICMTest_GetDebugCryptAsn1Flags() &
  17019. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  17020. return pfnOssCryptMsgControl(
  17021. hCryptMsg,
  17022. dwFlags,
  17023. dwCtrlType,
  17024. pvCtrlPara
  17025. );
  17026. else
  17027. return ICMTest_NewCryptMsgControl(
  17028. hCryptMsg,
  17029. dwFlags,
  17030. dwCtrlType,
  17031. pvCtrlPara
  17032. );
  17033. }
  17034. ICMTest_Lock(pInfo);
  17035. fOss = pfnOssCryptMsgControl(
  17036. pInfo->hOssCryptMsg,
  17037. dwFlags & ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG,
  17038. dwCtrlType,
  17039. pvCtrlPara
  17040. );
  17041. dwOssErr = GetLastError();
  17042. fNew = ICMTest_NewCryptMsgControl(
  17043. pInfo->hNewCryptMsg,
  17044. dwFlags,
  17045. dwCtrlType,
  17046. pvCtrlPara
  17047. );
  17048. dwNewErr = GetLastError();
  17049. if (fNew) {
  17050. if (fOss)
  17051. ICMTest_CompareStreamOutput(pInfo);
  17052. else
  17053. ICMTest_MessageBox("OssCryptMsgControl failed.");
  17054. } else {
  17055. if (fOss)
  17056. ICMTest_MessageBox("OssCryptMsgControl succeeded while NewCryptMsgControl failed.");
  17057. else if (dwOssErr != dwNewErr)
  17058. ICMTest_MessageBoxLastError("CryptMsgControl",
  17059. dwOssErr, dwNewErr);
  17060. }
  17061. ICMTest_Unlock(pInfo);
  17062. SetLastError(dwNewErr);
  17063. return fNew;
  17064. }
  17065. #ifdef CMS_PKCS7
  17066. BOOL
  17067. WINAPI
  17068. CryptMsgVerifyCountersignatureEncodedEx(
  17069. IN HCRYPTPROV hCryptProv,
  17070. IN DWORD dwEncodingType,
  17071. IN PBYTE pbSignerInfo,
  17072. IN DWORD cbSignerInfo,
  17073. IN PBYTE pbSignerInfoCountersignature,
  17074. IN DWORD cbSignerInfoCountersignature,
  17075. IN DWORD dwSignerType,
  17076. IN void *pvSigner,
  17077. IN DWORD dwFlags,
  17078. IN OPTIONAL void *pvReserved
  17079. )
  17080. {
  17081. BOOL fOss;
  17082. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  17083. if (0 == (iOssAsn1Flags &
  17084. (DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG |
  17085. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)))
  17086. return ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  17087. hCryptProv,
  17088. dwEncodingType,
  17089. pbSignerInfo,
  17090. cbSignerInfo,
  17091. pbSignerInfoCountersignature,
  17092. cbSignerInfoCountersignature,
  17093. dwSignerType,
  17094. pvSigner,
  17095. dwFlags,
  17096. pvReserved
  17097. );
  17098. fOss = pfnOssCryptMsgVerifyCountersignatureEncodedEx(
  17099. hCryptProv,
  17100. dwEncodingType,
  17101. pbSignerInfo,
  17102. cbSignerInfo,
  17103. pbSignerInfoCountersignature,
  17104. cbSignerInfoCountersignature,
  17105. dwSignerType,
  17106. pvSigner,
  17107. dwFlags,
  17108. pvReserved
  17109. );
  17110. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17111. DWORD dwOssErr = GetLastError();
  17112. BOOL fNew;
  17113. DWORD dwNewErr;
  17114. fNew = ICMTest_NewCryptMsgVerifyCountersignatureEncodedEx(
  17115. hCryptProv,
  17116. dwEncodingType,
  17117. pbSignerInfo,
  17118. cbSignerInfo,
  17119. pbSignerInfoCountersignature,
  17120. cbSignerInfoCountersignature,
  17121. dwSignerType,
  17122. pvSigner,
  17123. dwFlags,
  17124. pvReserved
  17125. );
  17126. dwNewErr = GetLastError();
  17127. if (fNew) {
  17128. if (!fOss)
  17129. ICMTest_MessageBox("OssCryptMsgVerifyCountersignatureEncodedEx failed.");
  17130. } else {
  17131. if (fOss)
  17132. ICMTest_MessageBox("OssCryptMsgVerifyCountersignatureEncodedEx succeeded while NewCryptMsgVerifyCountersignatureEncodedEx failed.");
  17133. else if (dwOssErr != dwNewErr)
  17134. ICMTest_MessageBoxLastError("CryptMsgVerifyCountersignatureEncodedEx",
  17135. dwOssErr, dwNewErr);
  17136. }
  17137. SetLastError(dwOssErr);
  17138. }
  17139. return fOss;
  17140. }
  17141. #endif // CMS_PKCS7
  17142. BOOL
  17143. WINAPI
  17144. CryptMsgCountersign(
  17145. IN OUT HCRYPTMSG hCryptMsg,
  17146. IN DWORD dwIndex,
  17147. IN DWORD cCountersigners,
  17148. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners
  17149. )
  17150. {
  17151. BOOL fNew;
  17152. DWORD dwNewErr;
  17153. BOOL fOss;
  17154. DWORD dwOssErr;
  17155. POSS_CRYPT_ASN1_MSG_INFO pInfo = (POSS_CRYPT_ASN1_MSG_INFO) hCryptMsg;
  17156. if (NULL == pInfo || TEST_MAGIC != pInfo->lMagic) {
  17157. if (ICMTest_GetDebugCryptAsn1Flags() &
  17158. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)
  17159. return pfnOssCryptMsgCountersign(
  17160. hCryptMsg,
  17161. dwIndex,
  17162. cCountersigners,
  17163. rgCountersigners
  17164. );
  17165. else
  17166. return ICMTest_NewCryptMsgCountersign(
  17167. hCryptMsg,
  17168. dwIndex,
  17169. cCountersigners,
  17170. rgCountersigners
  17171. );
  17172. }
  17173. ICMTest_Lock(pInfo);
  17174. fOss = pfnOssCryptMsgCountersign(
  17175. pInfo->hOssCryptMsg,
  17176. dwIndex,
  17177. cCountersigners,
  17178. rgCountersigners
  17179. );
  17180. dwOssErr = GetLastError();
  17181. fNew = ICMTest_NewCryptMsgCountersign(
  17182. pInfo->hNewCryptMsg,
  17183. dwIndex,
  17184. cCountersigners,
  17185. rgCountersigners
  17186. );
  17187. dwNewErr = GetLastError();
  17188. if (fNew) {
  17189. if (!fOss)
  17190. ICMTest_MessageBox("OssCryptMsgCountersign failed.");
  17191. } else {
  17192. if (fOss)
  17193. ICMTest_MessageBox("OssCryptMsgCountersign succeeded while NewCryptMsgCountersign failed.");
  17194. else if (dwOssErr != dwNewErr)
  17195. ICMTest_MessageBoxLastError("CryptMsgCountersign",
  17196. dwOssErr, dwNewErr);
  17197. }
  17198. ICMTest_Unlock(pInfo);
  17199. SetLastError(dwNewErr);
  17200. return fNew;
  17201. }
  17202. BOOL
  17203. WINAPI
  17204. CryptMsgCountersignEncoded(
  17205. IN DWORD dwEncodingType,
  17206. IN PBYTE pbSignerInfo,
  17207. IN DWORD cbSignerInfo,
  17208. IN DWORD cCountersigners,
  17209. IN PCMSG_SIGNER_ENCODE_INFO rgCountersigners,
  17210. OUT PBYTE pbCountersignature,
  17211. IN OUT PDWORD pcbCountersignature
  17212. )
  17213. {
  17214. BOOL fOss;
  17215. int iOssAsn1Flags = ICMTest_GetDebugCryptAsn1Flags();
  17216. BYTE *pbNew = NULL;
  17217. DWORD cbNew;
  17218. if (0 == (iOssAsn1Flags &
  17219. (DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG |
  17220. DEBUG_OSS_CRYPT_ASN1_CMSG_FLAG)))
  17221. return ICMTest_NewCryptMsgCountersignEncoded(
  17222. dwEncodingType,
  17223. pbSignerInfo,
  17224. cbSignerInfo,
  17225. cCountersigners,
  17226. rgCountersigners,
  17227. pbCountersignature,
  17228. pcbCountersignature
  17229. );
  17230. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17231. cbNew = *pcbCountersignature;
  17232. if (pbCountersignature)
  17233. pbNew = (BYTE *) ICM_Alloc(cbNew);
  17234. }
  17235. fOss = pfnOssCryptMsgCountersignEncoded(
  17236. dwEncodingType,
  17237. pbSignerInfo,
  17238. cbSignerInfo,
  17239. cCountersigners,
  17240. rgCountersigners,
  17241. pbCountersignature,
  17242. pcbCountersignature
  17243. );
  17244. if (iOssAsn1Flags & DEBUG_OSS_CRYPT_ASN1_CMSG_COMPARE_FLAG) {
  17245. DWORD dwOssErr = GetLastError();
  17246. BOOL fNew;
  17247. DWORD dwNewErr;
  17248. fNew = ICMTest_NewCryptMsgCountersignEncoded(
  17249. dwEncodingType,
  17250. pbSignerInfo,
  17251. cbSignerInfo,
  17252. cCountersigners,
  17253. rgCountersigners,
  17254. pbNew,
  17255. &cbNew
  17256. );
  17257. dwNewErr = GetLastError();
  17258. if (fNew) {
  17259. if (fOss)
  17260. ICMTest_CompareMessageBox(
  17261. "CountersignEncoded compare failed. Check ossasn1.der and newasn1.der.",
  17262. pbCountersignature,
  17263. *pcbCountersignature,
  17264. pbNew,
  17265. cbNew
  17266. );
  17267. else
  17268. ICMTest_MessageBox("NewCryptMsgCountersignEncoded failed.");
  17269. } else {
  17270. if (fOss)
  17271. ICMTest_MessageBox("OssCryptMsgCountersignEncoded succeeded while NewCryptMsgCountersignEncoded failed.");
  17272. else if (dwOssErr != dwNewErr)
  17273. ICMTest_MessageBoxLastError("CryptMsgCountersignEncoded",
  17274. dwOssErr, dwNewErr);
  17275. }
  17276. SetLastError(dwOssErr);
  17277. }
  17278. ICM_Free(pbNew);
  17279. return fOss;
  17280. }
  17281. #endif // DEBUG_CRYPT_ASN1_MASTER
  17282. #endif // DEBUG_CRYPT_ASN1