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.

2416 lines
70 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: xmsasnx.cpp
  8. //
  9. // Contents:
  10. // Encode/Decode APIs
  11. //
  12. // Implementation using the MS ASN1 compiler / RTS.
  13. //
  14. // Functions: CryptEncodeObject
  15. // CryptDecodeObject
  16. //
  17. // History: 02-Nov-98 philh created
  18. //
  19. //--------------------------------------------------------------------------
  20. //
  21. // ASN1C needs to be defined so that the compiler does not pickup the ASN1 routines from
  22. // the import table
  23. //
  24. #ifdef _X86_
  25. #define ASN1C
  26. #endif
  27. #include "stdafx.h"
  28. #include <windows.h>
  29. #include <wincrypt.h>
  30. #include <malloc.h>
  31. #include "xenroll.h"
  32. #include "cenroll.h"
  33. #pragma warning(disable:4100) // 'var' : unreferenced formal parameter
  34. #include "pkiasn1.h"
  35. #pragma warning(default:4100) // re-enable 4100
  36. #include "pkialloc.h"
  37. #include "crypttls.h"
  38. extern "C"
  39. {
  40. #include "xmsasn.h"
  41. }
  42. #define NO_OSS_DEBUG
  43. #include <dbgdef.h>
  44. // All the *pvInfo extra stuff needs to be aligned
  45. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  46. HCRYPTASN1MODULE hAsn1Module = NULL;
  47. HMODULE hCrypt32Dll = NULL;
  48. typedef HCRYPTASN1MODULE (WINAPI *PFN_CRYPT_INSTALL_ASN1_MODULE) (
  49. IN ASN1module_t pMod,
  50. IN DWORD dwFlags,
  51. IN void *pvReserved
  52. );
  53. typedef BOOL (WINAPI *PFN_CRYPT_UNINSTALL_ASN1_MODULE) (
  54. IN HCRYPTASN1MODULE hAsn1Module
  55. );
  56. typedef ASN1encoding_t (WINAPI *PFN_CRYPT_GET_ASN1_ENCODER)(
  57. IN HCRYPTASN1MODULE hAsn1Module
  58. );
  59. typedef ASN1decoding_t (WINAPI *PFN_CRYPT_GET_ASN1_DECODER)(
  60. IN HCRYPTASN1MODULE hAsn1Module
  61. );
  62. PFN_CRYPT_INSTALL_ASN1_MODULE pfnCryptInstallAsn1Module = NULL;
  63. PFN_CRYPT_UNINSTALL_ASN1_MODULE pfnCryptUninstallAsn1Module = NULL;
  64. PFN_CRYPT_GET_ASN1_ENCODER pfnCryptGetAsn1Encoder = NULL;
  65. PFN_CRYPT_GET_ASN1_DECODER pfnCryptGetAsn1Decoder = NULL;
  66. //+-------------------------------------------------------------------------
  67. // Function: GetEncoder/GetDecoder
  68. //
  69. // Synopsis: Initialize thread local storage for the asn libs
  70. //
  71. // Returns: pointer to an initialized Asn1 encoder/decoder data
  72. // structures
  73. //--------------------------------------------------------------------------
  74. static ASN1encoding_t GetEncoder(void)
  75. {
  76. if (hAsn1Module)
  77. return pfnCryptGetAsn1Encoder(hAsn1Module);
  78. else
  79. return NULL;
  80. }
  81. static ASN1decoding_t GetDecoder(void)
  82. {
  83. if (hAsn1Module)
  84. return pfnCryptGetAsn1Decoder(hAsn1Module);
  85. else
  86. return NULL;
  87. }
  88. //+-------------------------------------------------------------------------
  89. // Cert allocation and free functions
  90. //--------------------------------------------------------------------------
  91. static void *CertAlloc(
  92. IN size_t cbBytes
  93. )
  94. {
  95. void *pv;
  96. pv = malloc(cbBytes);
  97. if (pv == NULL)
  98. SetLastError((DWORD) E_OUTOFMEMORY);
  99. return pv;
  100. }
  101. static void CertFree(
  102. IN void *pv
  103. )
  104. {
  105. free(pv);
  106. }
  107. //+-------------------------------------------------------------------------
  108. // Encode an ASN1 formatted info structure
  109. //
  110. // Called by the Asn1X509*Encode() functions.
  111. //--------------------------------------------------------------------------
  112. static BOOL Asn1InfoEncode(
  113. IN int pdunum,
  114. IN void *pAsn1Info,
  115. OUT BYTE *pbEncoded,
  116. IN OUT DWORD *pcbEncoded
  117. )
  118. {
  119. ASN1encoding_t ge = GetEncoder();
  120. if (NULL == ge)
  121. return FALSE;
  122. return PkiAsn1EncodeInfo(
  123. ge,
  124. pdunum,
  125. pAsn1Info,
  126. pbEncoded,
  127. pcbEncoded);
  128. }
  129. //+-------------------------------------------------------------------------
  130. // Decode into an allocated, ASN1 formatted info structure
  131. //
  132. // Called by the Asn1X509*Decode() functions.
  133. //--------------------------------------------------------------------------
  134. static BOOL Asn1InfoDecodeAndAlloc(
  135. IN int pdunum,
  136. IN const BYTE *pbEncoded,
  137. IN DWORD cbEncoded,
  138. OUT void **ppAsn1Info
  139. )
  140. {
  141. return PkiAsn1DecodeAndAllocInfo(
  142. GetDecoder(),
  143. pdunum,
  144. pbEncoded,
  145. cbEncoded,
  146. ppAsn1Info);
  147. }
  148. //+-------------------------------------------------------------------------
  149. // Free an allocated, ASN1 formatted info structure
  150. //
  151. // Called by the Asn1X509*Decode() functions.
  152. //--------------------------------------------------------------------------
  153. static void Asn1InfoFree(
  154. IN int pdunum,
  155. IN void *pAsn1Info
  156. )
  157. {
  158. if (pAsn1Info) {
  159. DWORD dwErr = GetLastError();
  160. // TlsGetValue globbers LastError
  161. PkiAsn1FreeInfo(GetDecoder(), pdunum, pAsn1Info);
  162. SetLastError(dwErr);
  163. }
  164. }
  165. //+-------------------------------------------------------------------------
  166. // ASN1 X509 v3 ASN.1 Set / Get functions
  167. //
  168. // Called by the ASN1 X509 encode/decode functions.
  169. //
  170. // Assumption: all types are UNBOUNDED.
  171. //
  172. // The Get functions decrement *plRemainExtra and advance
  173. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  174. // with the length calculation but stop doing any copies.
  175. // The functions don't return an error for a negative *plRemainExtra.
  176. //--------------------------------------------------------------------------
  177. //+-------------------------------------------------------------------------
  178. // Set/Get Object Identifier string
  179. //--------------------------------------------------------------------------
  180. static BOOL Asn1X509SetObjId(
  181. IN LPSTR pszObjId,
  182. OUT ObjectID *pAsn1
  183. )
  184. {
  185. pAsn1->count = sizeof(pAsn1->value) / sizeof(pAsn1->value[0]);
  186. if (PkiAsn1ToObjectIdentifier(pszObjId, &pAsn1->count, pAsn1->value))
  187. return TRUE;
  188. else {
  189. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  190. return FALSE;
  191. }
  192. }
  193. static void Asn1X509GetObjId(
  194. IN ObjectID *pAsn1,
  195. IN DWORD /*dwFlags*/,
  196. OUT LPSTR *ppszObjId,
  197. IN OUT BYTE **ppbExtra,
  198. IN OUT LONG *plRemainExtra
  199. )
  200. {
  201. LONG lRemainExtra = *plRemainExtra;
  202. BYTE *pbExtra = *ppbExtra;
  203. LONG lAlignExtra;
  204. DWORD cbObjId;
  205. cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
  206. PkiAsn1FromObjectIdentifier(
  207. pAsn1->count,
  208. pAsn1->value,
  209. (LPSTR) pbExtra,
  210. &cbObjId
  211. );
  212. lAlignExtra = INFO_LEN_ALIGN(cbObjId);
  213. lRemainExtra -= lAlignExtra;
  214. if (lRemainExtra >= 0) {
  215. if(cbObjId) {
  216. *ppszObjId = (LPSTR) pbExtra;
  217. } else
  218. *ppszObjId = NULL;
  219. pbExtra += lAlignExtra;
  220. }
  221. *plRemainExtra = lRemainExtra;
  222. *ppbExtra = pbExtra;
  223. }
  224. static BOOL WINAPI Asn1X509CtlUsageEncode(
  225. IN DWORD dwCertEncodingType,
  226. IN LPCSTR lpszStructType,
  227. IN PCTL_USAGE pInfo,
  228. OUT BYTE *pbEncoded,
  229. IN OUT DWORD *pcbEncoded
  230. );
  231. static BOOL WINAPI Asn1X509CtlUsageDecode(
  232. IN DWORD dwCertEncodingType,
  233. IN LPCSTR lpszStructType,
  234. IN const BYTE *pbEncoded,
  235. IN DWORD cbEncoded,
  236. IN DWORD dwFlags,
  237. OUT PCTL_USAGE pInfo,
  238. IN OUT DWORD *pcbInfo
  239. );
  240. static BOOL WINAPI Asn1RequestInfoDecode(
  241. IN DWORD dwCertEncodingType,
  242. IN LPCSTR lpszStructType,
  243. IN const BYTE *pbEncoded,
  244. IN DWORD cbEncoded,
  245. IN DWORD dwFlags,
  246. OUT RequestFlags * pInfo,
  247. IN OUT DWORD *pcbInfo
  248. );
  249. static BOOL WINAPI Asn1RequestInfoEncode(
  250. IN DWORD dwCertEncodingType,
  251. IN LPCSTR lpszStructType,
  252. IN RequestFlags * pInfo,
  253. OUT BYTE *pbEncoded,
  254. IN OUT DWORD *pcbEncoded
  255. );
  256. static BOOL WINAPI Asn1CSPProviderEncode(
  257. IN DWORD dwCertEncodingType,
  258. IN LPCSTR lpszStructType,
  259. IN PCRYPT_CSP_PROVIDER pCSPProvider,
  260. OUT BYTE *pbEncoded,
  261. IN OUT DWORD *pcbEncoded
  262. );
  263. static BOOL WINAPI Asn1NameValueEncode(
  264. IN DWORD dwCertEncodingType,
  265. IN LPCSTR lpszStructType,
  266. IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
  267. OUT BYTE *pbEncoded,
  268. IN OUT DWORD *pcbEncoded
  269. );
  270. static const CRYPT_OID_FUNC_ENTRY X509EncodeFuncTable[] = {
  271. X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageEncode,
  272. XENROLL_REQUEST_INFO, Asn1RequestInfoEncode,
  273. szOID_ENROLLMENT_CSP_PROVIDER, Asn1CSPProviderEncode,
  274. szOID_ENROLLMENT_NAME_VALUE_PAIR, Asn1NameValueEncode,
  275. };
  276. #define X509_ENCODE_FUNC_COUNT (sizeof(X509EncodeFuncTable) / \
  277. sizeof(X509EncodeFuncTable[0]))
  278. static const CRYPT_OID_FUNC_ENTRY X509DecodeFuncTable[] = {
  279. X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageDecode,
  280. XENROLL_REQUEST_INFO, Asn1RequestInfoDecode
  281. };
  282. #define X509_DECODE_FUNC_COUNT (sizeof(X509DecodeFuncTable) / \
  283. sizeof(X509DecodeFuncTable[0]))
  284. //+=========================================================================
  285. // Certificate Management Messages over CMS (CMC) Encode/Decode Functions
  286. //==========================================================================
  287. BOOL WINAPI Asn1CmcDataEncodeEx(
  288. IN DWORD dwCertEncodingType,
  289. IN LPCSTR lpszStructType,
  290. IN PCMC_DATA_INFO pInfo,
  291. IN DWORD dwFlags,
  292. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  293. OUT OPTIONAL void *pvEncoded,
  294. IN OUT DWORD *pcbEncoded
  295. );
  296. BOOL WINAPI Asn1CmcDataDecodeEx(
  297. IN DWORD dwCertEncodingType,
  298. IN LPCSTR lpszStructType,
  299. IN const BYTE *pbEncoded,
  300. IN DWORD cbEncoded,
  301. IN DWORD dwFlags,
  302. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  303. OUT OPTIONAL void *pvStructInfo,
  304. IN OUT DWORD *pcbStructInfo
  305. );
  306. BOOL WINAPI Asn1CmcResponseEncodeEx(
  307. IN DWORD dwCertEncodingType,
  308. IN LPCSTR lpszStructType,
  309. IN PCMC_RESPONSE_INFO pInfo,
  310. IN DWORD dwFlags,
  311. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  312. OUT OPTIONAL void *pvEncoded,
  313. IN OUT DWORD *pcbEncoded
  314. );
  315. BOOL WINAPI Asn1CmcResponseDecodeEx(
  316. IN DWORD dwCertEncodingType,
  317. IN LPCSTR lpszStructType,
  318. IN const BYTE *pbEncoded,
  319. IN DWORD cbEncoded,
  320. IN DWORD dwFlags,
  321. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  322. OUT OPTIONAL void *pvStructInfo,
  323. IN OUT DWORD *pcbStructInfo
  324. );
  325. BOOL WINAPI Asn1CmcStatusEncodeEx(
  326. IN DWORD dwCertEncodingType,
  327. IN LPCSTR lpszStructType,
  328. IN PCMC_STATUS_INFO pInfo,
  329. IN DWORD dwFlags,
  330. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  331. OUT OPTIONAL void *pvEncoded,
  332. IN OUT DWORD *pcbEncoded
  333. );
  334. BOOL WINAPI Asn1CmcStatusDecodeEx(
  335. IN DWORD dwCertEncodingType,
  336. IN LPCSTR lpszStructType,
  337. IN const BYTE *pbEncoded,
  338. IN DWORD cbEncoded,
  339. IN DWORD dwFlags,
  340. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  341. OUT OPTIONAL void *pvStructInfo,
  342. IN OUT DWORD *pcbStructInfo
  343. );
  344. BOOL WINAPI Asn1CmcAddExtensionsEncodeEx(
  345. IN DWORD dwCertEncodingType,
  346. IN LPCSTR lpszStructType,
  347. IN PCMC_ADD_EXTENSIONS_INFO pInfo,
  348. IN DWORD dwFlags,
  349. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  350. OUT OPTIONAL void *pvEncoded,
  351. IN OUT DWORD *pcbEncoded
  352. );
  353. BOOL WINAPI Asn1CmcAddExtensionsDecodeEx(
  354. IN DWORD dwCertEncodingType,
  355. IN LPCSTR lpszStructType,
  356. IN const BYTE *pbEncoded,
  357. IN DWORD cbEncoded,
  358. IN DWORD dwFlags,
  359. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  360. OUT OPTIONAL void *pvStructInfo,
  361. IN OUT DWORD *pcbStructInfo
  362. );
  363. BOOL WINAPI Asn1CmcAddAttributesEncodeEx(
  364. IN DWORD dwCertEncodingType,
  365. IN LPCSTR lpszStructType,
  366. IN PCMC_ADD_ATTRIBUTES_INFO pInfo,
  367. IN DWORD dwFlags,
  368. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  369. OUT OPTIONAL void *pvEncoded,
  370. IN OUT DWORD *pcbEncoded
  371. );
  372. BOOL WINAPI Asn1CmcAddAttributesDecodeEx(
  373. IN DWORD dwCertEncodingType,
  374. IN LPCSTR lpszStructType,
  375. IN const BYTE *pbEncoded,
  376. IN DWORD cbEncoded,
  377. IN DWORD dwFlags,
  378. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  379. OUT OPTIONAL void *pvStructInfo,
  380. IN OUT DWORD *pcbStructInfo
  381. );
  382. static const CRYPT_OID_FUNC_ENTRY CmcEncodeExFuncTable[] = {
  383. CMC_DATA, Asn1CmcDataEncodeEx,
  384. CMC_RESPONSE, Asn1CmcResponseEncodeEx,
  385. CMC_STATUS, Asn1CmcStatusEncodeEx,
  386. CMC_ADD_EXTENSIONS, Asn1CmcAddExtensionsEncodeEx,
  387. CMC_ADD_ATTRIBUTES, Asn1CmcAddAttributesEncodeEx,
  388. };
  389. #define CMC_ENCODE_EX_FUNC_COUNT (sizeof(CmcEncodeExFuncTable) / \
  390. sizeof(CmcEncodeExFuncTable[0]))
  391. static const CRYPT_OID_FUNC_ENTRY CmcDecodeExFuncTable[] = {
  392. CMC_DATA, Asn1CmcDataDecodeEx,
  393. CMC_RESPONSE, Asn1CmcResponseDecodeEx,
  394. CMC_STATUS, Asn1CmcStatusDecodeEx,
  395. CMC_ADD_EXTENSIONS, Asn1CmcAddExtensionsDecodeEx,
  396. CMC_ADD_ATTRIBUTES, Asn1CmcAddAttributesDecodeEx,
  397. };
  398. #define CMC_DECODE_EX_FUNC_COUNT (sizeof(CmcDecodeExFuncTable) / \
  399. sizeof(CmcDecodeExFuncTable[0]))
  400. //+-------------------------------------------------------------------------
  401. // Dll initialization
  402. //--------------------------------------------------------------------------
  403. BOOL MSAsnInit(
  404. HMODULE hInst)
  405. {
  406. BOOL fRet;
  407. DWORD dwExceptionCode;
  408. if (NULL == (hCrypt32Dll = LoadLibraryA("crypt32.dll")))
  409. goto LoadCrypt32DllError;
  410. if (NULL == (pfnCryptInstallAsn1Module =
  411. (PFN_CRYPT_INSTALL_ASN1_MODULE) GetProcAddress(
  412. hCrypt32Dll, "I_CryptInstallAsn1Module")))
  413. goto I_CryptInstallAsn1ModuleProcAddressError;
  414. if (NULL == (pfnCryptUninstallAsn1Module =
  415. (PFN_CRYPT_UNINSTALL_ASN1_MODULE) GetProcAddress(
  416. hCrypt32Dll, "I_CryptUninstallAsn1Module")))
  417. goto I_CryptUninstallAsn1ModuleProcAddressError;
  418. if (NULL == (pfnCryptGetAsn1Encoder =
  419. (PFN_CRYPT_GET_ASN1_ENCODER) GetProcAddress(
  420. hCrypt32Dll, "I_CryptGetAsn1Encoder")))
  421. goto I_CryptGetAsn1EncoderProcAddressError;
  422. if (NULL == (pfnCryptGetAsn1Decoder =
  423. (PFN_CRYPT_GET_ASN1_DECODER) GetProcAddress(
  424. hCrypt32Dll, "I_CryptGetAsn1Decoder")))
  425. goto I_CryptGetAsn1DecoderProcAddressError;
  426. __try {
  427. XMSASN_Module_Startup();
  428. } __except(EXCEPTION_EXECUTE_HANDLER) {
  429. dwExceptionCode = GetExceptionCode();
  430. goto MSAsn1DllException;
  431. }
  432. if (0 == (hAsn1Module = pfnCryptInstallAsn1Module(XMSASN_Module, 0, NULL)))
  433. goto InstallAsn1ModuleError;
  434. if (!CryptInstallOIDFunctionAddress(
  435. hInst,
  436. X509_ASN_ENCODING,
  437. CRYPT_OID_ENCODE_OBJECT_FUNC,
  438. X509_ENCODE_FUNC_COUNT,
  439. X509EncodeFuncTable,
  440. 0)) // dwFlags
  441. goto InstallOidFuncError;
  442. if (!CryptInstallOIDFunctionAddress(
  443. hInst,
  444. X509_ASN_ENCODING,
  445. CRYPT_OID_DECODE_OBJECT_FUNC,
  446. X509_DECODE_FUNC_COUNT,
  447. X509DecodeFuncTable,
  448. 0)) // dwFlags
  449. goto InstallOidFuncError;
  450. if (!CryptInstallOIDFunctionAddress(
  451. hInst,
  452. X509_ASN_ENCODING,
  453. CRYPT_OID_ENCODE_OBJECT_EX_FUNC,
  454. CMC_ENCODE_EX_FUNC_COUNT,
  455. CmcEncodeExFuncTable,
  456. 0)) // dwFlags
  457. goto InstallOidFuncError;
  458. if (!CryptInstallOIDFunctionAddress(
  459. hInst,
  460. X509_ASN_ENCODING,
  461. CRYPT_OID_DECODE_OBJECT_EX_FUNC,
  462. CMC_DECODE_EX_FUNC_COUNT,
  463. CmcDecodeExFuncTable,
  464. 0)) // dwFlags
  465. goto InstallOidFuncError;
  466. fRet = TRUE;
  467. CommonReturn:
  468. return fRet;
  469. InstallOidFuncError:
  470. fRet = FALSE;
  471. goto CommonReturn;
  472. ErrorReturn:
  473. fRet = FALSE;
  474. if (hCrypt32Dll) {
  475. FreeLibrary(hCrypt32Dll);
  476. hCrypt32Dll = NULL;
  477. }
  478. pfnCryptInstallAsn1Module = NULL;
  479. pfnCryptUninstallAsn1Module = NULL;
  480. pfnCryptGetAsn1Encoder = NULL;
  481. pfnCryptGetAsn1Decoder = NULL;
  482. hAsn1Module = NULL;
  483. goto CommonReturn;
  484. TRACE_ERROR(LoadCrypt32DllError)
  485. TRACE_ERROR(I_CryptInstallAsn1ModuleProcAddressError)
  486. TRACE_ERROR(I_CryptUninstallAsn1ModuleProcAddressError)
  487. TRACE_ERROR(I_CryptGetAsn1EncoderProcAddressError)
  488. TRACE_ERROR(I_CryptGetAsn1DecoderProcAddressError)
  489. SET_ERROR_VAR(MSAsn1DllException, dwExceptionCode)
  490. TRACE_ERROR(InstallAsn1ModuleError)
  491. }
  492. void MSAsnTerm()
  493. {
  494. if (hAsn1Module) {
  495. pfnCryptUninstallAsn1Module(hAsn1Module);
  496. __try {
  497. XMSASN_Module_Cleanup();
  498. } __except(EXCEPTION_EXECUTE_HANDLER) {
  499. }
  500. hAsn1Module = NULL;
  501. }
  502. if (hCrypt32Dll) {
  503. FreeLibrary(hCrypt32Dll);
  504. hCrypt32Dll = NULL;
  505. }
  506. }
  507. //+-------------------------------------------------------------------------
  508. // ASN1 X509 v3 ASN.1 Set / Get functions
  509. //
  510. // Called by the ASN1 X509 encode/decode functions.
  511. //
  512. // Assumption: all types are UNBOUNDED.
  513. //
  514. // The Get functions decrement *plRemainExtra and advance
  515. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  516. // with the length calculation but stop doing any copies.
  517. // The functions don't return an error for a negative *plRemainExtra.
  518. //--------------------------------------------------------------------------
  519. //+-------------------------------------------------------------------------
  520. // Set/Free/Get CTL Usage object identifiers
  521. //--------------------------------------------------------------------------
  522. static BOOL Asn1X509SetCtlUsage(
  523. IN PCTL_USAGE pUsage,
  524. OUT EnhancedKeyUsage *pAsn1
  525. )
  526. {
  527. DWORD cId;
  528. LPSTR *ppszId;
  529. UsageIdentifier *pAsn1Id;
  530. pAsn1->count = 0;
  531. pAsn1->value = NULL;
  532. cId = pUsage->cUsageIdentifier;
  533. if (0 == cId)
  534. return TRUE;
  535. pAsn1Id = (UsageIdentifier *) CertAlloc(cId * sizeof(UsageIdentifier));
  536. if (pAsn1Id == NULL)
  537. return FALSE;
  538. pAsn1->count = cId;
  539. pAsn1->value = pAsn1Id;
  540. ppszId = pUsage->rgpszUsageIdentifier;
  541. for ( ; cId > 0; cId--, ppszId++, pAsn1Id++) {
  542. if (!Asn1X509SetObjId(*ppszId, pAsn1Id))
  543. return FALSE;
  544. }
  545. return TRUE;
  546. }
  547. static void Asn1X509FreeCtlUsage(
  548. IN EnhancedKeyUsage *pAsn1)
  549. {
  550. if (pAsn1->value) {
  551. CertFree(pAsn1->value);
  552. pAsn1->value = NULL;
  553. }
  554. }
  555. static void Asn1X509GetCtlUsage(
  556. IN EnhancedKeyUsage *pAsn1,
  557. IN DWORD dwFlags,
  558. OUT PCTL_USAGE pUsage,
  559. IN OUT BYTE **ppbExtra,
  560. IN OUT LONG *plRemainExtra
  561. )
  562. {
  563. LONG lRemainExtra = *plRemainExtra;
  564. BYTE *pbExtra = *ppbExtra;
  565. LONG lAlignExtra;
  566. DWORD cId;
  567. UsageIdentifier *pAsn1Id;
  568. LPSTR *ppszId;
  569. cId = pAsn1->count;
  570. lAlignExtra = INFO_LEN_ALIGN(cId * sizeof(LPSTR));
  571. lRemainExtra -= lAlignExtra;
  572. if (lRemainExtra >= 0) {
  573. pUsage->cUsageIdentifier = cId;
  574. ppszId = (LPSTR *) pbExtra;
  575. pUsage->rgpszUsageIdentifier = ppszId;
  576. pbExtra += lAlignExtra;
  577. } else
  578. ppszId = NULL;
  579. pAsn1Id = pAsn1->value;
  580. for ( ; cId > 0; cId--, pAsn1Id++, ppszId++)
  581. Asn1X509GetObjId(pAsn1Id, dwFlags, ppszId, &pbExtra, &lRemainExtra);
  582. *plRemainExtra = lRemainExtra;
  583. *ppbExtra = pbExtra;
  584. }
  585. //+-------------------------------------------------------------------------
  586. // CTL Usage (Enhanced Key Usage) Encode (ASN1 X509)
  587. //--------------------------------------------------------------------------
  588. static BOOL WINAPI Asn1X509CtlUsageEncode(
  589. IN DWORD /*dwCertEncodingType*/,
  590. IN LPCSTR /*lpszStructType*/,
  591. IN PCTL_USAGE pInfo,
  592. OUT BYTE *pbEncoded,
  593. IN OUT DWORD *pcbEncoded
  594. )
  595. {
  596. BOOL fResult;
  597. EnhancedKeyUsage Asn1Info;
  598. if (!Asn1X509SetCtlUsage(pInfo, &Asn1Info)) {
  599. *pcbEncoded = 0;
  600. fResult = FALSE;
  601. } else
  602. fResult = Asn1InfoEncode(
  603. EnhancedKeyUsage_PDU,
  604. &Asn1Info,
  605. pbEncoded,
  606. pcbEncoded
  607. );
  608. Asn1X509FreeCtlUsage(&Asn1Info);
  609. return fResult;
  610. }
  611. //+-------------------------------------------------------------------------
  612. // CTL Usage (Enhanced Key Usage) Decode (ASN1 X509)
  613. //--------------------------------------------------------------------------
  614. static BOOL WINAPI Asn1X509CtlUsageDecode(
  615. IN DWORD /*dwCertEncodingType*/,
  616. IN LPCSTR /*lpszStructType*/,
  617. IN const BYTE *pbEncoded,
  618. IN DWORD cbEncoded,
  619. IN DWORD dwFlags,
  620. OUT PCTL_USAGE pInfo,
  621. IN OUT DWORD *pcbInfo
  622. )
  623. {
  624. BOOL fResult;
  625. EnhancedKeyUsage *pAsn1Info = NULL;
  626. BYTE *pbExtra;
  627. LONG lRemainExtra;
  628. if (pInfo == NULL)
  629. *pcbInfo = 0;
  630. if (!Asn1InfoDecodeAndAlloc(
  631. EnhancedKeyUsage_PDU,
  632. pbEncoded,
  633. cbEncoded,
  634. (void **) &pAsn1Info))
  635. goto ErrorReturn;
  636. // for lRemainExtra < 0, LENGTH_ONLY calculation
  637. lRemainExtra = (LONG) *pcbInfo - sizeof(CTL_USAGE);
  638. if (lRemainExtra < 0) {
  639. pbExtra = NULL;
  640. } else
  641. pbExtra = (BYTE *) pInfo + sizeof(CTL_USAGE);
  642. Asn1X509GetCtlUsage(pAsn1Info, dwFlags, pInfo, &pbExtra, &lRemainExtra);
  643. if (lRemainExtra >= 0)
  644. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  645. else {
  646. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  647. if (pInfo) goto LengthError;
  648. }
  649. fResult = TRUE;
  650. goto CommonReturn;
  651. LengthError:
  652. SetLastError((DWORD) ERROR_MORE_DATA);
  653. fResult = FALSE;
  654. goto CommonReturn;
  655. ErrorReturn:
  656. *pcbInfo = 0;
  657. fResult = FALSE;
  658. CommonReturn:
  659. Asn1InfoFree(EnhancedKeyUsage_PDU, pAsn1Info);
  660. return fResult;
  661. }
  662. //+-------------------------------------------------------------------------
  663. // Request Info Encode
  664. //--------------------------------------------------------------------------
  665. static BOOL WINAPI Asn1RequestInfoEncode(
  666. IN DWORD /*dwCertEncodingType*/,
  667. IN LPCSTR /*lpszStructType*/,
  668. IN RequestFlags * pInfo,
  669. OUT BYTE *pbEncoded,
  670. IN OUT DWORD *pcbEncoded
  671. )
  672. {
  673. BOOL fResult;
  674. fResult = Asn1InfoEncode(
  675. RequestFlags_PDU,
  676. pInfo,
  677. pbEncoded,
  678. pcbEncoded
  679. );
  680. return fResult;
  681. }
  682. //+-------------------------------------------------------------------------
  683. // Request Info Decode
  684. //--------------------------------------------------------------------------
  685. static BOOL WINAPI Asn1RequestInfoDecode(
  686. IN DWORD /*dwCertEncodingType*/,
  687. IN LPCSTR /*lpszStructType*/,
  688. IN const BYTE *pbEncoded,
  689. IN DWORD cbEncoded,
  690. IN DWORD /*dwFlags*/,
  691. OUT RequestFlags * pInfo,
  692. IN OUT DWORD *pcbInfo
  693. )
  694. {
  695. BOOL fResult;
  696. RequestFlags * pAsn1 = NULL;
  697. if (NULL == pInfo || NULL == pcbInfo)
  698. goto ParamError;
  699. if( *pcbInfo < sizeof(RequestFlags) )
  700. goto LengthError;
  701. else if (!Asn1InfoDecodeAndAlloc(
  702. RequestFlags_PDU,
  703. pbEncoded,
  704. cbEncoded,
  705. (void **) &pAsn1) || NULL == pAsn1)
  706. goto ErrorReturn;
  707. memcpy(pInfo, pAsn1, sizeof(RequestFlags));
  708. fResult = TRUE;
  709. goto CommonReturn;
  710. ParamError:
  711. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  712. fResult = FALSE;
  713. goto CommonReturn;
  714. LengthError:
  715. SetLastError((DWORD) ERROR_MORE_DATA);
  716. fResult = FALSE;
  717. goto CommonReturn;
  718. ErrorReturn:
  719. *pcbInfo = 0;
  720. fResult = FALSE;
  721. CommonReturn:
  722. if (NULL != pAsn1)
  723. {
  724. Asn1InfoFree(RequestFlags_PDU, pAsn1);
  725. }
  726. return fResult;
  727. }
  728. static BOOL WINAPI Asn1CSPProviderEncode(
  729. IN DWORD /*dwCertEncodingType*/,
  730. IN LPCSTR /*lpszStructType*/,
  731. IN PCRYPT_CSP_PROVIDER pCSPProvider,
  732. OUT BYTE *pbEncoded,
  733. IN OUT DWORD *pcbEncoded
  734. )
  735. {
  736. BOOL fResult;
  737. CSPProvider CspProvider;
  738. CspProvider.keySpec = (int) pCSPProvider->dwKeySpec;
  739. CspProvider.cspName.length = (DWORD)wcslen(pCSPProvider->pwszProviderName);
  740. CspProvider.cspName.value = pCSPProvider->pwszProviderName;
  741. PkiAsn1SetBitString(&pCSPProvider->Signature, &CspProvider.signature.length, &CspProvider.signature.value);
  742. fResult = Asn1InfoEncode(
  743. CSPProvider_PDU,
  744. &CspProvider,
  745. pbEncoded,
  746. pcbEncoded
  747. );
  748. return fResult;
  749. }
  750. static BOOL WINAPI Asn1NameValueEncode(
  751. IN DWORD /*dwCertEncodingType*/,
  752. IN LPCSTR /*lpszStructType*/,
  753. IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValue,
  754. OUT BYTE *pbEncoded,
  755. IN OUT DWORD *pcbEncoded
  756. )
  757. {
  758. BOOL fResult;
  759. EnrollmentNameValuePair NameValue;
  760. NameValue.name.length = (DWORD)wcslen(pNameValue->pwszName);
  761. NameValue.name.value = pNameValue->pwszName;
  762. NameValue.value.length = (DWORD)wcslen(pNameValue->pwszValue);
  763. NameValue.value.value = pNameValue->pwszValue;
  764. fResult = Asn1InfoEncode(
  765. EnrollmentNameValuePair_PDU,
  766. &NameValue,
  767. pbEncoded,
  768. pcbEncoded
  769. );
  770. return fResult;
  771. }
  772. //+=========================================================================
  773. // Certificate Management Messages over CMS (CMC) Encode/Decode Functions
  774. //==========================================================================
  775. //+-------------------------------------------------------------------------
  776. // Encode an ASN1 formatted info structure
  777. //
  778. // Called by the Asn1X509*Encode() functions.
  779. //--------------------------------------------------------------------------
  780. static BOOL Asn1InfoEncodeEx(
  781. IN int pdunum,
  782. IN void *pvAsn1Info,
  783. IN DWORD dwFlags,
  784. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  785. OUT OPTIONAL void *pvEncoded,
  786. IN OUT DWORD *pcbEncoded
  787. )
  788. {
  789. return PkiAsn1EncodeInfoEx(
  790. GetEncoder(),
  791. pdunum,
  792. pvAsn1Info,
  793. dwFlags,
  794. pEncodePara,
  795. pvEncoded,
  796. pcbEncoded);
  797. }
  798. //+-------------------------------------------------------------------------
  799. // Decode into an ASN1 formatted info structure. Call the callback
  800. // function to convert into the 'C' data structure. If
  801. // CRYPT_DECODE_ALLOC_FLAG is set, call the callback twice. First,
  802. // to get the length of the 'C' data structure. Then after allocating,
  803. // call again to update the 'C' data structure.
  804. //
  805. // Called by the Asn1X509*Decode() functions.
  806. //--------------------------------------------------------------------------
  807. static BOOL Asn1InfoDecodeAndAllocEx(
  808. IN int pdunum,
  809. IN const BYTE *pbEncoded,
  810. IN DWORD cbEncoded,
  811. IN DWORD dwFlags,
  812. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  813. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  814. OUT OPTIONAL void *pvStructInfo,
  815. IN OUT DWORD *pcbStructInfo
  816. )
  817. {
  818. return PkiAsn1DecodeAndAllocInfoEx(
  819. GetDecoder(),
  820. pdunum,
  821. pbEncoded,
  822. cbEncoded,
  823. dwFlags,
  824. pDecodePara,
  825. pfnDecodeExCallback,
  826. pvStructInfo,
  827. pcbStructInfo
  828. );
  829. }
  830. //+-------------------------------------------------------------------------
  831. // Set/Get CRYPT_DATA_BLOB (Octet String)
  832. //--------------------------------------------------------------------------
  833. inline void Asn1X509SetOctetString(
  834. IN PCRYPT_DATA_BLOB pInfo,
  835. OUT OCTETSTRING *pAsn1
  836. )
  837. {
  838. pAsn1->value = pInfo->pbData;
  839. pAsn1->length = pInfo->cbData;
  840. }
  841. inline void Asn1X509GetOctetString(
  842. IN OCTETSTRING *pAsn1,
  843. IN DWORD dwFlags,
  844. OUT PCRYPT_DATA_BLOB pInfo,
  845. IN OUT BYTE **ppbExtra,
  846. IN OUT LONG *plRemainExtra
  847. )
  848. {
  849. PkiAsn1GetOctetString(pAsn1->length, pAsn1->value, dwFlags,
  850. pInfo, ppbExtra, plRemainExtra);
  851. }
  852. //+-------------------------------------------------------------------------
  853. // Set/Get "Any" DER BLOB
  854. //--------------------------------------------------------------------------
  855. inline void Asn1X509SetAny(
  856. IN PCRYPT_OBJID_BLOB pInfo,
  857. OUT NOCOPYANY *pAsn1
  858. )
  859. {
  860. PkiAsn1SetAny(pInfo, pAsn1);
  861. }
  862. inline void Asn1X509GetAny(
  863. IN NOCOPYANY *pAsn1,
  864. IN DWORD dwFlags,
  865. OUT PCRYPT_OBJID_BLOB pInfo,
  866. IN OUT BYTE **ppbExtra,
  867. IN OUT LONG *plRemainExtra
  868. )
  869. {
  870. PkiAsn1GetAny(pAsn1, dwFlags, pInfo, ppbExtra, plRemainExtra);
  871. }
  872. //+-------------------------------------------------------------------------
  873. // Set/Free/Get SeqOfAny
  874. //--------------------------------------------------------------------------
  875. BOOL WINAPI Asn1X509SetSeqOfAny(
  876. IN DWORD cValue,
  877. IN PCRYPT_DER_BLOB pValue,
  878. OUT ASN1uint32_t *pAsn1Count,
  879. OUT NOCOPYANY **ppAsn1Value
  880. )
  881. {
  882. *pAsn1Count = 0;
  883. *ppAsn1Value = NULL;
  884. if (cValue > 0) {
  885. NOCOPYANY *pAsn1Value;
  886. pAsn1Value = (NOCOPYANY *) PkiZeroAlloc(cValue * sizeof(NOCOPYANY));
  887. if (pAsn1Value == NULL)
  888. return FALSE;
  889. *pAsn1Count = cValue;
  890. *ppAsn1Value = pAsn1Value;
  891. for ( ; cValue > 0; cValue--, pValue++, pAsn1Value++)
  892. Asn1X509SetAny(pValue, pAsn1Value);
  893. }
  894. return TRUE;
  895. }
  896. void Asn1X509FreeSeqOfAny(
  897. IN NOCOPYANY *pAsn1Value
  898. )
  899. {
  900. if (pAsn1Value)
  901. PkiFree(pAsn1Value);
  902. }
  903. void Asn1X509GetSeqOfAny(
  904. IN unsigned int Asn1Count,
  905. IN NOCOPYANY *pAsn1Value,
  906. IN DWORD dwFlags,
  907. OUT DWORD *pcValue,
  908. OUT PCRYPT_DER_BLOB *ppValue,
  909. IN OUT BYTE **ppbExtra,
  910. IN OUT LONG *plRemainExtra
  911. )
  912. {
  913. LONG lAlignExtra;
  914. PCRYPT_ATTR_BLOB pValue;
  915. lAlignExtra = INFO_LEN_ALIGN(Asn1Count * sizeof(CRYPT_DER_BLOB));
  916. *plRemainExtra -= lAlignExtra;
  917. if (*plRemainExtra >= 0) {
  918. *pcValue = Asn1Count;
  919. pValue = (PCRYPT_DER_BLOB) *ppbExtra;
  920. *ppValue = pValue;
  921. *ppbExtra += lAlignExtra;
  922. } else
  923. pValue = NULL;
  924. for (; Asn1Count > 0; Asn1Count--, pAsn1Value++, pValue++)
  925. Asn1X509GetAny(pAsn1Value, dwFlags, pValue, ppbExtra, plRemainExtra);
  926. }
  927. //+-------------------------------------------------------------------------
  928. // Set/Free/Get Extensions
  929. //--------------------------------------------------------------------------
  930. BOOL Asn1X509SetExtensions(
  931. IN DWORD cExtension,
  932. IN PCERT_EXTENSION pExtension,
  933. OUT Extensions *pAsn1
  934. )
  935. {
  936. Extension *pAsn1Ext;
  937. pAsn1->value = NULL;
  938. pAsn1->count = 0;
  939. if (cExtension == 0)
  940. return TRUE;
  941. pAsn1Ext = (Extension *) PkiZeroAlloc(cExtension * sizeof(Extension));
  942. if (pAsn1Ext == NULL)
  943. return FALSE;
  944. pAsn1->value = pAsn1Ext;
  945. pAsn1->count = cExtension;
  946. for ( ; cExtension > 0; cExtension--, pExtension++, pAsn1Ext++) {
  947. if (!Asn1X509SetObjId(pExtension->pszObjId, &pAsn1Ext->extnId))
  948. return FALSE;
  949. if (pExtension->fCritical) {
  950. pAsn1Ext->critical = TRUE;
  951. pAsn1Ext->bit_mask |= critical_present;
  952. }
  953. Asn1X509SetOctetString(&pExtension->Value, &pAsn1Ext->extnValue);
  954. }
  955. return TRUE;
  956. }
  957. void Asn1X509FreeExtensions(
  958. IN Extensions *pAsn1)
  959. {
  960. if (pAsn1->value) {
  961. PkiFree(pAsn1->value);
  962. pAsn1->value = NULL;
  963. }
  964. pAsn1->count = 0;
  965. }
  966. void Asn1X509GetExtensions(
  967. IN Extensions *pAsn1,
  968. IN DWORD dwFlags,
  969. OUT DWORD *pcExtension,
  970. OUT PCERT_EXTENSION *ppExtension,
  971. IN OUT BYTE **ppbExtra,
  972. IN OUT LONG *plRemainExtra
  973. )
  974. {
  975. LONG lRemainExtra = *plRemainExtra;
  976. BYTE *pbExtra = *ppbExtra;
  977. LONG lAlignExtra;
  978. DWORD cExt;
  979. Extension *pAsn1Ext;
  980. PCERT_EXTENSION pGetExt;
  981. cExt = pAsn1->count;
  982. lAlignExtra = INFO_LEN_ALIGN(cExt * sizeof(CERT_EXTENSION));
  983. lRemainExtra -= lAlignExtra;
  984. if (lRemainExtra >= 0) {
  985. *pcExtension = cExt;
  986. pGetExt = (PCERT_EXTENSION) pbExtra;
  987. *ppExtension = pGetExt;
  988. pbExtra += lAlignExtra;
  989. } else
  990. pGetExt = NULL;
  991. pAsn1Ext = pAsn1->value;
  992. for ( ; cExt > 0; cExt--, pAsn1Ext++, pGetExt++) {
  993. Asn1X509GetObjId(&pAsn1Ext->extnId, dwFlags, &pGetExt->pszObjId,
  994. &pbExtra, &lRemainExtra);
  995. if (lRemainExtra >= 0) {
  996. pGetExt->fCritical = FALSE;
  997. if (pAsn1Ext->bit_mask & critical_present)
  998. pGetExt->fCritical = (BOOLEAN) pAsn1Ext->critical;
  999. }
  1000. Asn1X509GetOctetString(&pAsn1Ext->extnValue, dwFlags, &pGetExt->Value,
  1001. &pbExtra, &lRemainExtra);
  1002. }
  1003. *plRemainExtra = lRemainExtra;
  1004. *ppbExtra = pbExtra;
  1005. }
  1006. //+-------------------------------------------------------------------------
  1007. // Set/Free/Get CRYPT_ATTRIBUTE
  1008. //--------------------------------------------------------------------------
  1009. BOOL WINAPI Asn1X509SetAttribute(
  1010. IN PCRYPT_ATTRIBUTE pInfo,
  1011. OUT Attribute *pAsn1
  1012. )
  1013. {
  1014. memset(pAsn1, 0, sizeof(*pAsn1));
  1015. if (!Asn1X509SetObjId(pInfo->pszObjId, &pAsn1->type))
  1016. return FALSE;
  1017. return Asn1X509SetSeqOfAny(
  1018. pInfo->cValue,
  1019. pInfo->rgValue,
  1020. &pAsn1->values.count,
  1021. &pAsn1->values.value);
  1022. }
  1023. void Asn1X509FreeAttribute(
  1024. IN OUT Attribute *pAsn1
  1025. )
  1026. {
  1027. Asn1X509FreeSeqOfAny(pAsn1->values.value);
  1028. }
  1029. void Asn1X509GetAttribute(
  1030. IN Attribute *pAsn1,
  1031. IN DWORD dwFlags,
  1032. OUT PCRYPT_ATTRIBUTE pInfo,
  1033. IN OUT BYTE **ppbExtra,
  1034. IN OUT LONG *plRemainExtra
  1035. )
  1036. {
  1037. Asn1X509GetObjId(&pAsn1->type, dwFlags,
  1038. &pInfo->pszObjId, ppbExtra, plRemainExtra);
  1039. Asn1X509GetSeqOfAny(pAsn1->values.count, pAsn1->values.value, dwFlags,
  1040. &pInfo->cValue, &pInfo->rgValue, ppbExtra, plRemainExtra);
  1041. }
  1042. //+-------------------------------------------------------------------------
  1043. // Set/Free/Get Attributes
  1044. //--------------------------------------------------------------------------
  1045. BOOL Asn1X509SetAttributes(
  1046. IN DWORD cAttribute,
  1047. IN PCRYPT_ATTRIBUTE pAttribute,
  1048. OUT Attributes *pAsn1
  1049. )
  1050. {
  1051. Attribute *pAsn1Attr;
  1052. pAsn1->value = NULL;
  1053. pAsn1->count = 0;
  1054. if (cAttribute == 0)
  1055. return TRUE;
  1056. pAsn1Attr = (Attribute *) PkiZeroAlloc(cAttribute * sizeof(Attribute));
  1057. if (pAsn1Attr == NULL)
  1058. return FALSE;
  1059. pAsn1->value = pAsn1Attr;
  1060. pAsn1->count = cAttribute;
  1061. for ( ; cAttribute > 0; cAttribute--, pAttribute++, pAsn1Attr++) {
  1062. if (!Asn1X509SetAttribute(pAttribute, pAsn1Attr))
  1063. return FALSE;
  1064. }
  1065. return TRUE;
  1066. }
  1067. void Asn1X509FreeAttributes(
  1068. IN Attributes *pAsn1
  1069. )
  1070. {
  1071. if (pAsn1->value) {
  1072. DWORD cAttr = pAsn1->count;
  1073. Attribute *pAsn1Attr = pAsn1->value;
  1074. for ( ; cAttr > 0; cAttr--, pAsn1Attr++)
  1075. Asn1X509FreeAttribute(pAsn1Attr);
  1076. PkiFree(pAsn1->value);
  1077. pAsn1->value = NULL;
  1078. }
  1079. pAsn1->count = 0;
  1080. }
  1081. void Asn1X509GetAttributes(
  1082. IN Attributes *pAsn1,
  1083. IN DWORD dwFlags,
  1084. OUT DWORD *pcAttribute,
  1085. OUT PCRYPT_ATTRIBUTE *ppAttribute,
  1086. IN OUT BYTE **ppbExtra,
  1087. IN OUT LONG *plRemainExtra
  1088. )
  1089. {
  1090. LONG lRemainExtra = *plRemainExtra;
  1091. BYTE *pbExtra = *ppbExtra;
  1092. LONG lAlignExtra;
  1093. DWORD cAttr;
  1094. Attribute *pAsn1Attr;
  1095. PCRYPT_ATTRIBUTE pGetAttr;
  1096. cAttr = pAsn1->count;
  1097. lAlignExtra = INFO_LEN_ALIGN(cAttr * sizeof(CRYPT_ATTRIBUTE));
  1098. lRemainExtra -= lAlignExtra;
  1099. if (lRemainExtra >= 0) {
  1100. *pcAttribute = cAttr;
  1101. pGetAttr = (PCRYPT_ATTRIBUTE) pbExtra;
  1102. *ppAttribute = pGetAttr;
  1103. pbExtra += lAlignExtra;
  1104. } else
  1105. pGetAttr = NULL;
  1106. pAsn1Attr = pAsn1->value;
  1107. for ( ; cAttr > 0; cAttr--, pAsn1Attr++, pGetAttr++) {
  1108. Asn1X509GetAttribute(pAsn1Attr, dwFlags, pGetAttr,
  1109. &pbExtra, &lRemainExtra);
  1110. }
  1111. *plRemainExtra = lRemainExtra;
  1112. *ppbExtra = pbExtra;
  1113. }
  1114. //+-------------------------------------------------------------------------
  1115. // Set/Free/Get CMC Tagged Attributes
  1116. //--------------------------------------------------------------------------
  1117. BOOL Asn1CmcSetTaggedAttributes(
  1118. IN DWORD cTaggedAttr,
  1119. IN PCMC_TAGGED_ATTRIBUTE pTaggedAttr,
  1120. OUT ControlSequence *pAsn1
  1121. )
  1122. {
  1123. TaggedAttribute *pAsn1Attr;
  1124. pAsn1->value = NULL;
  1125. pAsn1->count = 0;
  1126. if (cTaggedAttr == 0)
  1127. return TRUE;
  1128. pAsn1Attr = (TaggedAttribute *) PkiZeroAlloc(
  1129. cTaggedAttr * sizeof(TaggedAttribute));
  1130. if (pAsn1Attr == NULL)
  1131. return FALSE;
  1132. pAsn1->value = pAsn1Attr;
  1133. pAsn1->count = cTaggedAttr;
  1134. for ( ; cTaggedAttr > 0; cTaggedAttr--, pTaggedAttr++, pAsn1Attr++) {
  1135. pAsn1Attr->bodyPartID = pTaggedAttr->dwBodyPartID;
  1136. if (!Asn1X509SetObjId(pTaggedAttr->Attribute.pszObjId,
  1137. &pAsn1Attr->type))
  1138. return FALSE;
  1139. if (!Asn1X509SetSeqOfAny(
  1140. pTaggedAttr->Attribute.cValue,
  1141. pTaggedAttr->Attribute.rgValue,
  1142. &pAsn1Attr->values.count,
  1143. &pAsn1Attr->values.value))
  1144. return FALSE;
  1145. }
  1146. return TRUE;
  1147. }
  1148. void Asn1CmcFreeTaggedAttributes(
  1149. IN OUT ControlSequence *pAsn1
  1150. )
  1151. {
  1152. if (pAsn1->value) {
  1153. TaggedAttribute *pAsn1Attr = pAsn1->value;
  1154. DWORD cTaggedAttr = pAsn1->count;
  1155. for ( ; cTaggedAttr > 0; cTaggedAttr--, pAsn1Attr++) {
  1156. Asn1X509FreeSeqOfAny(pAsn1Attr->values.value);
  1157. }
  1158. PkiFree(pAsn1->value);
  1159. pAsn1->value = NULL;
  1160. }
  1161. pAsn1->count = 0;
  1162. }
  1163. void Asn1CmcGetTaggedAttributes(
  1164. IN ControlSequence *pAsn1,
  1165. IN DWORD dwFlags,
  1166. OUT DWORD *pcTaggedAttr,
  1167. OUT PCMC_TAGGED_ATTRIBUTE *ppTaggedAttr,
  1168. IN OUT BYTE **ppbExtra,
  1169. IN OUT LONG *plRemainExtra
  1170. )
  1171. {
  1172. LONG lRemainExtra = *plRemainExtra;
  1173. BYTE *pbExtra = *ppbExtra;
  1174. LONG lAlignExtra;
  1175. DWORD cTaggedAttr;
  1176. TaggedAttribute *pAsn1Attr;
  1177. PCMC_TAGGED_ATTRIBUTE pTaggedAttr;
  1178. cTaggedAttr = pAsn1->count;
  1179. lAlignExtra = INFO_LEN_ALIGN(cTaggedAttr * sizeof(CMC_TAGGED_ATTRIBUTE));
  1180. lRemainExtra -= lAlignExtra;
  1181. if (lRemainExtra >= 0) {
  1182. *pcTaggedAttr = cTaggedAttr;
  1183. pTaggedAttr = (PCMC_TAGGED_ATTRIBUTE) pbExtra;
  1184. *ppTaggedAttr = pTaggedAttr;
  1185. pbExtra += lAlignExtra;
  1186. } else
  1187. pTaggedAttr = NULL;
  1188. pAsn1Attr = pAsn1->value;
  1189. for ( ; cTaggedAttr > 0; cTaggedAttr--, pAsn1Attr++, pTaggedAttr++) {
  1190. if (lRemainExtra >= 0) {
  1191. pTaggedAttr->dwBodyPartID = pAsn1Attr->bodyPartID;
  1192. }
  1193. Asn1X509GetObjId(&pAsn1Attr->type, dwFlags,
  1194. &pTaggedAttr->Attribute.pszObjId, &pbExtra, &lRemainExtra);
  1195. Asn1X509GetSeqOfAny(
  1196. pAsn1Attr->values.count, pAsn1Attr->values.value, dwFlags,
  1197. &pTaggedAttr->Attribute.cValue, &pTaggedAttr->Attribute.rgValue,
  1198. &pbExtra, &lRemainExtra);
  1199. }
  1200. *plRemainExtra = lRemainExtra;
  1201. *ppbExtra = pbExtra;
  1202. }
  1203. //+-------------------------------------------------------------------------
  1204. // Set/Free/Get CMC Tagged Requests
  1205. //--------------------------------------------------------------------------
  1206. BOOL Asn1CmcSetTaggedRequests(
  1207. IN DWORD cTaggedReq,
  1208. IN PCMC_TAGGED_REQUEST pTaggedReq,
  1209. OUT ReqSequence *pAsn1
  1210. )
  1211. {
  1212. TaggedRequest *pAsn1Req;
  1213. pAsn1->value = NULL;
  1214. pAsn1->count = 0;
  1215. if (cTaggedReq == 0)
  1216. return TRUE;
  1217. pAsn1Req = (TaggedRequest *) PkiZeroAlloc(
  1218. cTaggedReq * sizeof(TaggedRequest));
  1219. if (pAsn1Req == NULL)
  1220. return FALSE;
  1221. pAsn1->value = pAsn1Req;
  1222. pAsn1->count = cTaggedReq;
  1223. for ( ; cTaggedReq > 0; cTaggedReq--, pTaggedReq++, pAsn1Req++) {
  1224. PCMC_TAGGED_CERT_REQUEST pTaggedCertReq;
  1225. TaggedCertificationRequest *ptcr;
  1226. if (CMC_TAGGED_CERT_REQUEST_CHOICE !=
  1227. pTaggedReq->dwTaggedRequestChoice) {
  1228. SetLastError((DWORD) E_INVALIDARG);
  1229. return FALSE;
  1230. }
  1231. pAsn1Req->choice = tcr_chosen;
  1232. ptcr = &pAsn1Req->u.tcr;
  1233. pTaggedCertReq = pTaggedReq->pTaggedCertRequest;
  1234. ptcr->bodyPartID = pTaggedCertReq->dwBodyPartID;
  1235. Asn1X509SetAny(&pTaggedCertReq->SignedCertRequest,
  1236. &ptcr->certificationRequest);
  1237. }
  1238. return TRUE;
  1239. }
  1240. void Asn1CmcFreeTaggedRequests(
  1241. IN OUT ReqSequence *pAsn1
  1242. )
  1243. {
  1244. if (pAsn1->value) {
  1245. PkiFree(pAsn1->value);
  1246. pAsn1->value = NULL;
  1247. }
  1248. pAsn1->count = 0;
  1249. }
  1250. BOOL Asn1CmcGetTaggedRequests(
  1251. IN ReqSequence *pAsn1,
  1252. IN DWORD dwFlags,
  1253. OUT DWORD *pcTaggedReq,
  1254. OUT PCMC_TAGGED_REQUEST *ppTaggedReq,
  1255. IN OUT BYTE **ppbExtra,
  1256. IN OUT LONG *plRemainExtra
  1257. )
  1258. {
  1259. BOOL fResult;
  1260. LONG lRemainExtra = *plRemainExtra;
  1261. BYTE *pbExtra = *ppbExtra;
  1262. LONG lAlignExtra;
  1263. DWORD cTaggedReq;
  1264. TaggedRequest *pAsn1Req;
  1265. PCMC_TAGGED_REQUEST pTaggedReq;
  1266. cTaggedReq = pAsn1->count;
  1267. lAlignExtra = INFO_LEN_ALIGN(cTaggedReq * sizeof(CMC_TAGGED_REQUEST));
  1268. lRemainExtra -= lAlignExtra;
  1269. if (lRemainExtra >= 0) {
  1270. *pcTaggedReq = cTaggedReq;
  1271. pTaggedReq = (PCMC_TAGGED_REQUEST) pbExtra;
  1272. *ppTaggedReq = pTaggedReq;
  1273. pbExtra += lAlignExtra;
  1274. } else
  1275. pTaggedReq = NULL;
  1276. pAsn1Req = pAsn1->value;
  1277. for ( ; cTaggedReq > 0; cTaggedReq--, pAsn1Req++, pTaggedReq++) {
  1278. PCMC_TAGGED_CERT_REQUEST pTaggedCertReq;
  1279. TaggedCertificationRequest *ptcr;
  1280. if (tcr_chosen != pAsn1Req->choice) {
  1281. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  1282. goto ErrorReturn;
  1283. }
  1284. ptcr = &pAsn1Req->u.tcr;
  1285. lAlignExtra = INFO_LEN_ALIGN(sizeof(CMC_TAGGED_CERT_REQUEST));
  1286. lRemainExtra -= lAlignExtra;
  1287. if (lRemainExtra >= 0) {
  1288. pTaggedReq->dwTaggedRequestChoice =
  1289. CMC_TAGGED_CERT_REQUEST_CHOICE;
  1290. pTaggedCertReq = (PCMC_TAGGED_CERT_REQUEST) pbExtra;
  1291. pbExtra += lAlignExtra;
  1292. pTaggedReq->pTaggedCertRequest = pTaggedCertReq;
  1293. pTaggedCertReq->dwBodyPartID = ptcr->bodyPartID;
  1294. } else
  1295. pTaggedCertReq = NULL;
  1296. Asn1X509GetAny(&ptcr->certificationRequest, dwFlags,
  1297. &pTaggedCertReq->SignedCertRequest, &pbExtra, &lRemainExtra);
  1298. }
  1299. *plRemainExtra = lRemainExtra;
  1300. *ppbExtra = pbExtra;
  1301. fResult = TRUE;
  1302. CommonReturn:
  1303. return fResult;
  1304. ErrorReturn:
  1305. fResult = FALSE;
  1306. goto CommonReturn;
  1307. }
  1308. //+-------------------------------------------------------------------------
  1309. // Set/Free/Get CMC Tagged ContentInfo
  1310. //--------------------------------------------------------------------------
  1311. BOOL Asn1CmcSetTaggedContentInfos(
  1312. IN DWORD cTaggedCI,
  1313. IN PCMC_TAGGED_CONTENT_INFO pTaggedCI,
  1314. OUT CmsSequence *pAsn1
  1315. )
  1316. {
  1317. TaggedContentInfo *pAsn1CI;
  1318. pAsn1->value = NULL;
  1319. pAsn1->count = 0;
  1320. if (cTaggedCI == 0)
  1321. return TRUE;
  1322. pAsn1CI = (TaggedContentInfo *) PkiZeroAlloc(
  1323. cTaggedCI * sizeof(TaggedContentInfo));
  1324. if (pAsn1CI == NULL)
  1325. return FALSE;
  1326. pAsn1->value = pAsn1CI;
  1327. pAsn1->count = cTaggedCI;
  1328. for ( ; cTaggedCI > 0; cTaggedCI--, pTaggedCI++, pAsn1CI++) {
  1329. pAsn1CI->bodyPartID = pTaggedCI->dwBodyPartID;
  1330. Asn1X509SetAny(&pTaggedCI->EncodedContentInfo, &pAsn1CI->contentInfo);
  1331. }
  1332. return TRUE;
  1333. }
  1334. void Asn1CmcFreeTaggedContentInfos(
  1335. IN OUT CmsSequence *pAsn1
  1336. )
  1337. {
  1338. if (pAsn1->value) {
  1339. PkiFree(pAsn1->value);
  1340. pAsn1->value = NULL;
  1341. }
  1342. pAsn1->count = 0;
  1343. }
  1344. void Asn1CmcGetTaggedContentInfos(
  1345. IN CmsSequence *pAsn1,
  1346. IN DWORD dwFlags,
  1347. OUT DWORD *pcTaggedCI,
  1348. OUT PCMC_TAGGED_CONTENT_INFO *ppTaggedCI,
  1349. IN OUT BYTE **ppbExtra,
  1350. IN OUT LONG *plRemainExtra
  1351. )
  1352. {
  1353. LONG lRemainExtra = *plRemainExtra;
  1354. BYTE *pbExtra = *ppbExtra;
  1355. LONG lAlignExtra;
  1356. DWORD cTaggedCI;
  1357. TaggedContentInfo *pAsn1CI;
  1358. PCMC_TAGGED_CONTENT_INFO pTaggedCI;
  1359. cTaggedCI = pAsn1->count;
  1360. lAlignExtra = INFO_LEN_ALIGN(cTaggedCI * sizeof(CMC_TAGGED_CONTENT_INFO));
  1361. lRemainExtra -= lAlignExtra;
  1362. if (lRemainExtra >= 0) {
  1363. *pcTaggedCI = cTaggedCI;
  1364. pTaggedCI = (PCMC_TAGGED_CONTENT_INFO) pbExtra;
  1365. *ppTaggedCI = pTaggedCI;
  1366. pbExtra += lAlignExtra;
  1367. } else
  1368. pTaggedCI = NULL;
  1369. pAsn1CI = pAsn1->value;
  1370. for ( ; cTaggedCI > 0; cTaggedCI--, pAsn1CI++, pTaggedCI++) {
  1371. if (lRemainExtra >= 0) {
  1372. pTaggedCI->dwBodyPartID = pAsn1CI->bodyPartID;
  1373. }
  1374. Asn1X509GetAny(&pAsn1CI->contentInfo, dwFlags,
  1375. &pTaggedCI->EncodedContentInfo, &pbExtra, &lRemainExtra);
  1376. }
  1377. *plRemainExtra = lRemainExtra;
  1378. *ppbExtra = pbExtra;
  1379. }
  1380. //+-------------------------------------------------------------------------
  1381. // Set/Free/Get CMC Tagged OtherMsg
  1382. //--------------------------------------------------------------------------
  1383. BOOL Asn1CmcSetTaggedOtherMsgs(
  1384. IN DWORD cTaggedOM,
  1385. IN PCMC_TAGGED_OTHER_MSG pTaggedOM,
  1386. OUT OtherMsgSequence *pAsn1
  1387. )
  1388. {
  1389. TaggedOtherMsg *pAsn1OM;
  1390. pAsn1->value = NULL;
  1391. pAsn1->count = 0;
  1392. if (cTaggedOM == 0)
  1393. return TRUE;
  1394. pAsn1OM = (TaggedOtherMsg *) PkiZeroAlloc(
  1395. cTaggedOM * sizeof(TaggedOtherMsg));
  1396. if (pAsn1OM == NULL)
  1397. return FALSE;
  1398. pAsn1->value = pAsn1OM;
  1399. pAsn1->count = cTaggedOM;
  1400. for ( ; cTaggedOM > 0; cTaggedOM--, pTaggedOM++, pAsn1OM++) {
  1401. pAsn1OM->bodyPartID = pTaggedOM->dwBodyPartID;
  1402. if (!Asn1X509SetObjId(pTaggedOM->pszObjId,
  1403. &pAsn1OM->otherMsgType))
  1404. return FALSE;
  1405. Asn1X509SetAny(&pTaggedOM->Value, &pAsn1OM->otherMsgValue);
  1406. }
  1407. return TRUE;
  1408. }
  1409. void Asn1CmcFreeTaggedOtherMsgs(
  1410. IN OUT OtherMsgSequence *pAsn1
  1411. )
  1412. {
  1413. if (pAsn1->value) {
  1414. PkiFree(pAsn1->value);
  1415. pAsn1->value = NULL;
  1416. }
  1417. pAsn1->count = 0;
  1418. }
  1419. void Asn1CmcGetTaggedOtherMsgs(
  1420. IN OtherMsgSequence *pAsn1,
  1421. IN DWORD dwFlags,
  1422. OUT DWORD *pcTaggedOM,
  1423. OUT PCMC_TAGGED_OTHER_MSG *ppTaggedOM,
  1424. IN OUT BYTE **ppbExtra,
  1425. IN OUT LONG *plRemainExtra
  1426. )
  1427. {
  1428. LONG lRemainExtra = *plRemainExtra;
  1429. BYTE *pbExtra = *ppbExtra;
  1430. LONG lAlignExtra;
  1431. DWORD cTaggedOM;
  1432. TaggedOtherMsg *pAsn1OM;
  1433. PCMC_TAGGED_OTHER_MSG pTaggedOM;
  1434. cTaggedOM = pAsn1->count;
  1435. lAlignExtra = INFO_LEN_ALIGN(cTaggedOM * sizeof(CMC_TAGGED_OTHER_MSG));
  1436. lRemainExtra -= lAlignExtra;
  1437. if (lRemainExtra >= 0) {
  1438. *pcTaggedOM = cTaggedOM;
  1439. pTaggedOM = (PCMC_TAGGED_OTHER_MSG) pbExtra;
  1440. *ppTaggedOM = pTaggedOM;
  1441. pbExtra += lAlignExtra;
  1442. } else
  1443. pTaggedOM = NULL;
  1444. pAsn1OM = pAsn1->value;
  1445. for ( ; cTaggedOM > 0; cTaggedOM--, pAsn1OM++, pTaggedOM++) {
  1446. if (lRemainExtra >= 0) {
  1447. pTaggedOM->dwBodyPartID = pAsn1OM->bodyPartID;
  1448. }
  1449. Asn1X509GetObjId(&pAsn1OM->otherMsgType, dwFlags,
  1450. &pTaggedOM->pszObjId, &pbExtra, &lRemainExtra);
  1451. Asn1X509GetAny(&pAsn1OM->otherMsgValue, dwFlags,
  1452. &pTaggedOM->Value, &pbExtra, &lRemainExtra);
  1453. }
  1454. *plRemainExtra = lRemainExtra;
  1455. *ppbExtra = pbExtra;
  1456. }
  1457. //+-------------------------------------------------------------------------
  1458. // CMC Data Encode (ASN1)
  1459. //--------------------------------------------------------------------------
  1460. BOOL WINAPI Asn1CmcDataEncodeEx(
  1461. IN DWORD /*dwCertEncodingType*/,
  1462. IN LPCSTR /*lpszStructType*/,
  1463. IN PCMC_DATA_INFO pInfo,
  1464. IN DWORD dwFlags,
  1465. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1466. OUT OPTIONAL void *pvEncoded,
  1467. IN OUT DWORD *pcbEncoded
  1468. )
  1469. {
  1470. BOOL fResult;
  1471. CmcData Asn1Info;
  1472. memset(&Asn1Info, 0, sizeof(Asn1Info));
  1473. if (!Asn1CmcSetTaggedAttributes(pInfo->cTaggedAttribute,
  1474. pInfo->rgTaggedAttribute, &Asn1Info.controlSequence))
  1475. goto ErrorReturn;
  1476. if (!Asn1CmcSetTaggedRequests(pInfo->cTaggedRequest,
  1477. pInfo->rgTaggedRequest, &Asn1Info.reqSequence))
  1478. goto ErrorReturn;
  1479. if (!Asn1CmcSetTaggedContentInfos(pInfo->cTaggedContentInfo,
  1480. pInfo->rgTaggedContentInfo, &Asn1Info.cmsSequence))
  1481. goto ErrorReturn;
  1482. if (!Asn1CmcSetTaggedOtherMsgs(pInfo->cTaggedOtherMsg,
  1483. pInfo->rgTaggedOtherMsg, &Asn1Info.otherMsgSequence))
  1484. goto ErrorReturn;
  1485. fResult = Asn1InfoEncodeEx(
  1486. CmcData_PDU,
  1487. &Asn1Info,
  1488. dwFlags,
  1489. pEncodePara,
  1490. pvEncoded,
  1491. pcbEncoded
  1492. );
  1493. CommonReturn:
  1494. Asn1CmcFreeTaggedAttributes(&Asn1Info.controlSequence);
  1495. Asn1CmcFreeTaggedRequests(&Asn1Info.reqSequence);
  1496. Asn1CmcFreeTaggedContentInfos(&Asn1Info.cmsSequence);
  1497. Asn1CmcFreeTaggedOtherMsgs(&Asn1Info.otherMsgSequence);
  1498. return fResult;
  1499. ErrorReturn:
  1500. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
  1501. *((void **) pvEncoded) = NULL;
  1502. *pcbEncoded = 0;
  1503. fResult = FALSE;
  1504. goto CommonReturn;
  1505. }
  1506. //+-------------------------------------------------------------------------
  1507. // CMC Data Decode (ASN1)
  1508. //--------------------------------------------------------------------------
  1509. BOOL WINAPI Asn1CmcDataDecodeExCallback(
  1510. IN void *pvAsn1Info,
  1511. IN DWORD dwFlags,
  1512. IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
  1513. OUT OPTIONAL void *pvStructInfo,
  1514. IN OUT LONG *plRemainExtra
  1515. )
  1516. {
  1517. BOOL fResult;
  1518. CmcData *pAsn1 = (CmcData *) pvAsn1Info;
  1519. PCMC_DATA_INFO pInfo = (PCMC_DATA_INFO) pvStructInfo;
  1520. LONG lRemainExtra = *plRemainExtra;
  1521. BYTE *pbExtra;
  1522. lRemainExtra -= sizeof(CMC_DATA_INFO);
  1523. if (lRemainExtra < 0) {
  1524. pbExtra = NULL;
  1525. } else {
  1526. memset(pInfo, 0, sizeof(CMC_DATA_INFO));
  1527. pbExtra = (BYTE *) pInfo + sizeof(CMC_DATA_INFO);
  1528. }
  1529. Asn1CmcGetTaggedAttributes(&pAsn1->controlSequence,
  1530. dwFlags,
  1531. &pInfo->cTaggedAttribute,
  1532. &pInfo->rgTaggedAttribute,
  1533. &pbExtra,
  1534. &lRemainExtra
  1535. );
  1536. if (!Asn1CmcGetTaggedRequests(&pAsn1->reqSequence,
  1537. dwFlags,
  1538. &pInfo->cTaggedRequest,
  1539. &pInfo->rgTaggedRequest,
  1540. &pbExtra,
  1541. &lRemainExtra
  1542. ))
  1543. goto ErrorReturn;
  1544. Asn1CmcGetTaggedContentInfos(&pAsn1->cmsSequence,
  1545. dwFlags,
  1546. &pInfo->cTaggedContentInfo,
  1547. &pInfo->rgTaggedContentInfo,
  1548. &pbExtra,
  1549. &lRemainExtra
  1550. );
  1551. Asn1CmcGetTaggedOtherMsgs(&pAsn1->otherMsgSequence,
  1552. dwFlags,
  1553. &pInfo->cTaggedOtherMsg,
  1554. &pInfo->rgTaggedOtherMsg,
  1555. &pbExtra,
  1556. &lRemainExtra
  1557. );
  1558. fResult = TRUE;
  1559. CommonReturn:
  1560. *plRemainExtra = lRemainExtra;
  1561. return fResult;
  1562. ErrorReturn:
  1563. fResult = FALSE;
  1564. goto CommonReturn;
  1565. }
  1566. BOOL WINAPI Asn1CmcDataDecodeEx(
  1567. IN DWORD /*dwCertEncodingType*/,
  1568. IN LPCSTR /*lpszStructType*/,
  1569. IN const BYTE *pbEncoded,
  1570. IN DWORD cbEncoded,
  1571. IN DWORD dwFlags,
  1572. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1573. OUT OPTIONAL void *pvStructInfo,
  1574. IN OUT DWORD *pcbStructInfo
  1575. )
  1576. {
  1577. return Asn1InfoDecodeAndAllocEx(
  1578. CmcData_PDU,
  1579. pbEncoded,
  1580. cbEncoded,
  1581. dwFlags,
  1582. pDecodePara,
  1583. Asn1CmcDataDecodeExCallback,
  1584. pvStructInfo,
  1585. pcbStructInfo
  1586. );
  1587. }
  1588. //+-------------------------------------------------------------------------
  1589. // CMC Response Encode (ASN1)
  1590. //--------------------------------------------------------------------------
  1591. BOOL WINAPI Asn1CmcResponseEncodeEx(
  1592. IN DWORD /*dwCertEncodingType*/,
  1593. IN LPCSTR /*lpszStructType*/,
  1594. IN PCMC_RESPONSE_INFO pInfo,
  1595. IN DWORD dwFlags,
  1596. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1597. OUT OPTIONAL void *pvEncoded,
  1598. IN OUT DWORD *pcbEncoded
  1599. )
  1600. {
  1601. BOOL fResult;
  1602. CmcResponseBody Asn1Info;
  1603. memset(&Asn1Info, 0, sizeof(Asn1Info));
  1604. if (!Asn1CmcSetTaggedAttributes(pInfo->cTaggedAttribute,
  1605. pInfo->rgTaggedAttribute, &Asn1Info.controlSequence))
  1606. goto ErrorReturn;
  1607. if (!Asn1CmcSetTaggedContentInfos(pInfo->cTaggedContentInfo,
  1608. pInfo->rgTaggedContentInfo, &Asn1Info.cmsSequence))
  1609. goto ErrorReturn;
  1610. if (!Asn1CmcSetTaggedOtherMsgs(pInfo->cTaggedOtherMsg,
  1611. pInfo->rgTaggedOtherMsg, &Asn1Info.otherMsgSequence))
  1612. goto ErrorReturn;
  1613. fResult = Asn1InfoEncodeEx(
  1614. CmcResponseBody_PDU,
  1615. &Asn1Info,
  1616. dwFlags,
  1617. pEncodePara,
  1618. pvEncoded,
  1619. pcbEncoded
  1620. );
  1621. CommonReturn:
  1622. Asn1CmcFreeTaggedAttributes(&Asn1Info.controlSequence);
  1623. Asn1CmcFreeTaggedContentInfos(&Asn1Info.cmsSequence);
  1624. Asn1CmcFreeTaggedOtherMsgs(&Asn1Info.otherMsgSequence);
  1625. return fResult;
  1626. ErrorReturn:
  1627. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
  1628. *((void **) pvEncoded) = NULL;
  1629. *pcbEncoded = 0;
  1630. fResult = FALSE;
  1631. goto CommonReturn;
  1632. }
  1633. //+-------------------------------------------------------------------------
  1634. // CMC Response Decode (ASN1)
  1635. //--------------------------------------------------------------------------
  1636. BOOL WINAPI Asn1CmcResponseDecodeExCallback(
  1637. IN void *pvAsn1Info,
  1638. IN DWORD dwFlags,
  1639. IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
  1640. OUT OPTIONAL void *pvStructInfo,
  1641. IN OUT LONG *plRemainExtra
  1642. )
  1643. {
  1644. BOOL fResult;
  1645. CmcResponseBody *pAsn1 = (CmcResponseBody *) pvAsn1Info;
  1646. PCMC_RESPONSE_INFO pInfo = (PCMC_RESPONSE_INFO) pvStructInfo;
  1647. LONG lRemainExtra = *plRemainExtra;
  1648. BYTE *pbExtra;
  1649. lRemainExtra -= sizeof(CMC_RESPONSE_INFO);
  1650. if (lRemainExtra < 0) {
  1651. pbExtra = NULL;
  1652. } else {
  1653. memset(pInfo, 0, sizeof(CMC_RESPONSE_INFO));
  1654. pbExtra = (BYTE *) pInfo + sizeof(CMC_RESPONSE_INFO);
  1655. }
  1656. Asn1CmcGetTaggedAttributes(&pAsn1->controlSequence,
  1657. dwFlags,
  1658. &pInfo->cTaggedAttribute,
  1659. &pInfo->rgTaggedAttribute,
  1660. &pbExtra,
  1661. &lRemainExtra
  1662. );
  1663. Asn1CmcGetTaggedContentInfos(&pAsn1->cmsSequence,
  1664. dwFlags,
  1665. &pInfo->cTaggedContentInfo,
  1666. &pInfo->rgTaggedContentInfo,
  1667. &pbExtra,
  1668. &lRemainExtra
  1669. );
  1670. Asn1CmcGetTaggedOtherMsgs(&pAsn1->otherMsgSequence,
  1671. dwFlags,
  1672. &pInfo->cTaggedOtherMsg,
  1673. &pInfo->rgTaggedOtherMsg,
  1674. &pbExtra,
  1675. &lRemainExtra
  1676. );
  1677. fResult = TRUE;
  1678. *plRemainExtra = lRemainExtra;
  1679. return fResult;
  1680. }
  1681. BOOL WINAPI Asn1CmcResponseDecodeEx(
  1682. IN DWORD /*dwCertEncodingType*/,
  1683. IN LPCSTR /*lpszStructType*/,
  1684. IN const BYTE *pbEncoded,
  1685. IN DWORD cbEncoded,
  1686. IN DWORD dwFlags,
  1687. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1688. OUT OPTIONAL void *pvStructInfo,
  1689. IN OUT DWORD *pcbStructInfo
  1690. )
  1691. {
  1692. return Asn1InfoDecodeAndAllocEx(
  1693. CmcResponseBody_PDU,
  1694. pbEncoded,
  1695. cbEncoded,
  1696. dwFlags,
  1697. pDecodePara,
  1698. Asn1CmcResponseDecodeExCallback,
  1699. pvStructInfo,
  1700. pcbStructInfo
  1701. );
  1702. }
  1703. //+-------------------------------------------------------------------------
  1704. // CMC Status Encode (ASN1)
  1705. //--------------------------------------------------------------------------
  1706. BOOL WINAPI Asn1CmcStatusEncodeEx(
  1707. IN DWORD /*dwCertEncodingType*/,
  1708. IN LPCSTR /*lpszStructType*/,
  1709. IN PCMC_STATUS_INFO pInfo,
  1710. IN DWORD dwFlags,
  1711. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1712. OUT OPTIONAL void *pvEncoded,
  1713. IN OUT DWORD *pcbEncoded
  1714. )
  1715. {
  1716. BOOL fResult;
  1717. CmcStatusInfo Asn1Info;
  1718. memset(&Asn1Info, 0, sizeof(Asn1Info));
  1719. Asn1Info.cmcStatus = pInfo->dwStatus;
  1720. if (pInfo->cBodyList) {
  1721. Asn1Info.bodyList.count = pInfo->cBodyList;
  1722. Asn1Info.bodyList.value = pInfo->rgdwBodyList;
  1723. }
  1724. if (pInfo->pwszStatusString && L'\0' != *pInfo->pwszStatusString) {
  1725. Asn1Info.bit_mask |= statusString_present;
  1726. Asn1Info.statusString.length = (DWORD)wcslen(pInfo->pwszStatusString);
  1727. Asn1Info.statusString.value = pInfo->pwszStatusString;
  1728. }
  1729. if (CMC_OTHER_INFO_NO_CHOICE != pInfo->dwOtherInfoChoice) {
  1730. Asn1Info.bit_mask |= otherInfo_present;
  1731. switch (pInfo->dwOtherInfoChoice) {
  1732. case CMC_OTHER_INFO_FAIL_CHOICE:
  1733. Asn1Info.otherInfo.choice = failInfo_chosen;
  1734. Asn1Info.otherInfo.u.failInfo = pInfo->dwFailInfo;
  1735. break;
  1736. case CMC_OTHER_INFO_PEND_CHOICE:
  1737. Asn1Info.otherInfo.choice = pendInfo_chosen;
  1738. Asn1X509SetOctetString(&pInfo->pPendInfo->PendToken,
  1739. &Asn1Info.otherInfo.u.pendInfo.pendToken);
  1740. if (!PkiAsn1ToGeneralizedTime(
  1741. &pInfo->pPendInfo->PendTime,
  1742. &Asn1Info.otherInfo.u.pendInfo.pendTime))
  1743. goto GeneralizedTimeError;
  1744. break;
  1745. default:
  1746. goto InvalidOtherInfoChoiceError;
  1747. }
  1748. }
  1749. fResult = Asn1InfoEncodeEx(
  1750. CmcStatusInfo_PDU,
  1751. &Asn1Info,
  1752. dwFlags,
  1753. pEncodePara,
  1754. pvEncoded,
  1755. pcbEncoded
  1756. );
  1757. CommonReturn:
  1758. return fResult;
  1759. ErrorReturn:
  1760. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
  1761. *((void **) pvEncoded) = NULL;
  1762. *pcbEncoded = 0;
  1763. fResult = FALSE;
  1764. goto CommonReturn;
  1765. SET_ERROR(InvalidOtherInfoChoiceError, E_INVALIDARG)
  1766. SET_ERROR(GeneralizedTimeError, CRYPT_E_BAD_ENCODE)
  1767. }
  1768. //+-------------------------------------------------------------------------
  1769. // CMC Status Decode (ASN1)
  1770. //--------------------------------------------------------------------------
  1771. BOOL WINAPI Asn1CmcStatusDecodeExCallback(
  1772. IN void *pvAsn1Info,
  1773. IN DWORD dwFlags,
  1774. IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
  1775. OUT OPTIONAL void *pvStructInfo,
  1776. IN OUT LONG *plRemainExtra
  1777. )
  1778. {
  1779. BOOL fResult;
  1780. CmcStatusInfo *pAsn1 = (CmcStatusInfo *) pvAsn1Info;
  1781. PCMC_STATUS_INFO pInfo = (PCMC_STATUS_INFO) pvStructInfo;
  1782. LONG lRemainExtra = *plRemainExtra;
  1783. LONG lAlignExtra;
  1784. BYTE *pbExtra;
  1785. lRemainExtra -= sizeof(CMC_STATUS_INFO);
  1786. if (lRemainExtra < 0) {
  1787. pbExtra = NULL;
  1788. } else {
  1789. memset(pInfo, 0, sizeof(CMC_STATUS_INFO));
  1790. pbExtra = (BYTE *) pInfo + sizeof(CMC_STATUS_INFO);
  1791. pInfo->dwStatus = pAsn1->cmcStatus;
  1792. }
  1793. if (pAsn1->bodyList.count > 0) {
  1794. ASN1uint32_t count = pAsn1->bodyList.count;
  1795. lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
  1796. lRemainExtra -= lAlignExtra;
  1797. if (lRemainExtra >= 0) {
  1798. BodyPartID *value;
  1799. DWORD *pdwBodyList;
  1800. value = pAsn1->bodyList.value;
  1801. pdwBodyList = (DWORD *) pbExtra;
  1802. pbExtra += lAlignExtra;
  1803. pInfo->cBodyList = count;
  1804. pInfo->rgdwBodyList = pdwBodyList;
  1805. for ( ; count > 0; count--, value++, pdwBodyList++)
  1806. *pdwBodyList = *value;
  1807. }
  1808. }
  1809. if (pAsn1->bit_mask & statusString_present) {
  1810. ASN1uint32_t length = pAsn1->statusString.length;
  1811. lAlignExtra = INFO_LEN_ALIGN((length + 1) * sizeof(WCHAR));
  1812. lRemainExtra -= lAlignExtra;
  1813. if (lRemainExtra >= 0) {
  1814. memcpy(pbExtra, pAsn1->statusString.value, length * sizeof(WCHAR));
  1815. memset(pbExtra + (length * sizeof(WCHAR)), 0, sizeof(WCHAR));
  1816. pInfo->pwszStatusString = (LPWSTR) pbExtra;
  1817. pbExtra += lAlignExtra;
  1818. }
  1819. }
  1820. if (pAsn1->bit_mask & otherInfo_present) {
  1821. switch (pAsn1->otherInfo.choice) {
  1822. case failInfo_chosen:
  1823. if (lRemainExtra >= 0) {
  1824. pInfo->dwOtherInfoChoice = CMC_OTHER_INFO_FAIL_CHOICE;
  1825. pInfo->dwFailInfo = pAsn1->otherInfo.u.failInfo;
  1826. }
  1827. break;
  1828. case pendInfo_chosen:
  1829. {
  1830. PCMC_PEND_INFO pPendInfo;
  1831. lAlignExtra = INFO_LEN_ALIGN(sizeof(CMC_PEND_INFO));
  1832. lRemainExtra -= lAlignExtra;
  1833. if (lRemainExtra >= 0) {
  1834. pInfo->dwOtherInfoChoice = CMC_OTHER_INFO_PEND_CHOICE;
  1835. pPendInfo = (PCMC_PEND_INFO) pbExtra;
  1836. pInfo->pPendInfo = pPendInfo;
  1837. pbExtra += lAlignExtra;
  1838. if (!PkiAsn1FromGeneralizedTime(
  1839. &pAsn1->otherInfo.u.pendInfo.pendTime,
  1840. &pPendInfo->PendTime))
  1841. goto GeneralizedTimeDecodeError;
  1842. } else
  1843. pPendInfo = NULL;
  1844. Asn1X509GetOctetString(
  1845. &pAsn1->otherInfo.u.pendInfo.pendToken, dwFlags,
  1846. &pPendInfo->PendToken, &pbExtra, &lRemainExtra);
  1847. }
  1848. break;
  1849. default:
  1850. goto InvalidOtherInfoChoiceError;
  1851. }
  1852. }
  1853. fResult = TRUE;
  1854. CommonReturn:
  1855. *plRemainExtra = lRemainExtra;
  1856. return fResult;
  1857. ErrorReturn:
  1858. fResult = FALSE;
  1859. goto CommonReturn;
  1860. SET_ERROR(InvalidOtherInfoChoiceError, CRYPT_E_BAD_ENCODE)
  1861. SET_ERROR(GeneralizedTimeDecodeError, CRYPT_E_BAD_ENCODE)
  1862. }
  1863. BOOL WINAPI Asn1CmcStatusDecodeEx(
  1864. IN DWORD /*dwCertEncodingType*/,
  1865. IN LPCSTR /*lpszStructType*/,
  1866. IN const BYTE *pbEncoded,
  1867. IN DWORD cbEncoded,
  1868. IN DWORD dwFlags,
  1869. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1870. OUT OPTIONAL void *pvStructInfo,
  1871. IN OUT DWORD *pcbStructInfo
  1872. )
  1873. {
  1874. return Asn1InfoDecodeAndAllocEx(
  1875. CmcStatusInfo_PDU,
  1876. pbEncoded,
  1877. cbEncoded,
  1878. dwFlags,
  1879. pDecodePara,
  1880. Asn1CmcStatusDecodeExCallback,
  1881. pvStructInfo,
  1882. pcbStructInfo
  1883. );
  1884. }
  1885. //+-------------------------------------------------------------------------
  1886. // CMC Add Extensions Encode (ASN1)
  1887. //--------------------------------------------------------------------------
  1888. BOOL WINAPI Asn1CmcAddExtensionsEncodeEx(
  1889. IN DWORD /*dwCertEncodingType*/,
  1890. IN LPCSTR /*lpszStructType*/,
  1891. IN PCMC_ADD_EXTENSIONS_INFO pInfo,
  1892. IN DWORD dwFlags,
  1893. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1894. OUT OPTIONAL void *pvEncoded,
  1895. IN OUT DWORD *pcbEncoded
  1896. )
  1897. {
  1898. BOOL fResult;
  1899. CmcAddExtensions Asn1Info;
  1900. memset(&Asn1Info, 0, sizeof(Asn1Info));
  1901. Asn1Info.pkiDataReference = pInfo->dwCmcDataReference;
  1902. if (pInfo->cCertReference) {
  1903. Asn1Info.certReferences.count = pInfo->cCertReference;
  1904. Asn1Info.certReferences.value = pInfo->rgdwCertReference;
  1905. }
  1906. if (!Asn1X509SetExtensions(pInfo->cExtension, pInfo->rgExtension,
  1907. &Asn1Info.extensions))
  1908. goto ErrorReturn;
  1909. fResult = Asn1InfoEncodeEx(
  1910. CmcAddExtensions_PDU,
  1911. &Asn1Info,
  1912. dwFlags,
  1913. pEncodePara,
  1914. pvEncoded,
  1915. pcbEncoded
  1916. );
  1917. CommonReturn:
  1918. Asn1X509FreeExtensions(&Asn1Info.extensions);
  1919. return fResult;
  1920. ErrorReturn:
  1921. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
  1922. *((void **) pvEncoded) = NULL;
  1923. *pcbEncoded = 0;
  1924. fResult = FALSE;
  1925. goto CommonReturn;
  1926. }
  1927. //+-------------------------------------------------------------------------
  1928. // CMC Add Extensions Decode (ASN1)
  1929. //--------------------------------------------------------------------------
  1930. BOOL WINAPI Asn1CmcAddExtensionsDecodeExCallback(
  1931. IN void *pvAsn1Info,
  1932. IN DWORD dwFlags,
  1933. IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
  1934. OUT OPTIONAL void *pvStructInfo,
  1935. IN OUT LONG *plRemainExtra
  1936. )
  1937. {
  1938. BOOL fResult;
  1939. CmcAddExtensions *pAsn1 = (CmcAddExtensions *) pvAsn1Info;
  1940. PCMC_ADD_EXTENSIONS_INFO pInfo = (PCMC_ADD_EXTENSIONS_INFO) pvStructInfo;
  1941. LONG lRemainExtra = *plRemainExtra;
  1942. LONG lAlignExtra;
  1943. BYTE *pbExtra;
  1944. lRemainExtra -= sizeof(CMC_ADD_EXTENSIONS_INFO);
  1945. if (lRemainExtra < 0) {
  1946. pbExtra = NULL;
  1947. } else {
  1948. memset(pInfo, 0, sizeof(CMC_ADD_EXTENSIONS_INFO));
  1949. pbExtra = (BYTE *) pInfo + sizeof(CMC_ADD_EXTENSIONS_INFO);
  1950. pInfo->dwCmcDataReference = pAsn1->pkiDataReference;
  1951. }
  1952. if (pAsn1->certReferences.count > 0) {
  1953. ASN1uint32_t count = pAsn1->certReferences.count;
  1954. lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
  1955. lRemainExtra -= lAlignExtra;
  1956. if (lRemainExtra >= 0) {
  1957. BodyPartID *value;
  1958. DWORD *pdwCertReference;
  1959. value = pAsn1->certReferences.value;
  1960. pdwCertReference = (DWORD *) pbExtra;
  1961. pbExtra += lAlignExtra;
  1962. pInfo->cCertReference = count;
  1963. pInfo->rgdwCertReference = pdwCertReference;
  1964. for ( ; count > 0; count--, value++, pdwCertReference++)
  1965. *pdwCertReference = *value;
  1966. }
  1967. }
  1968. Asn1X509GetExtensions(&pAsn1->extensions, dwFlags,
  1969. &pInfo->cExtension, &pInfo->rgExtension, &pbExtra, &lRemainExtra);
  1970. fResult = TRUE;
  1971. *plRemainExtra = lRemainExtra;
  1972. return fResult;
  1973. }
  1974. BOOL WINAPI Asn1CmcAddExtensionsDecodeEx(
  1975. IN DWORD /*dwCertEncodingType*/,
  1976. IN LPCSTR /*lpszStructType*/,
  1977. IN const BYTE *pbEncoded,
  1978. IN DWORD cbEncoded,
  1979. IN DWORD dwFlags,
  1980. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1981. OUT OPTIONAL void *pvStructInfo,
  1982. IN OUT DWORD *pcbStructInfo
  1983. )
  1984. {
  1985. return Asn1InfoDecodeAndAllocEx(
  1986. CmcAddExtensions_PDU,
  1987. pbEncoded,
  1988. cbEncoded,
  1989. dwFlags,
  1990. pDecodePara,
  1991. Asn1CmcAddExtensionsDecodeExCallback,
  1992. pvStructInfo,
  1993. pcbStructInfo
  1994. );
  1995. }
  1996. //+-------------------------------------------------------------------------
  1997. // CMC Add Attributes Encode (ASN1)
  1998. //--------------------------------------------------------------------------
  1999. BOOL WINAPI Asn1CmcAddAttributesEncodeEx(
  2000. IN DWORD /*dwCertEncodingType*/,
  2001. IN LPCSTR /*lpszStructType*/,
  2002. IN PCMC_ADD_ATTRIBUTES_INFO pInfo,
  2003. IN DWORD dwFlags,
  2004. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  2005. OUT OPTIONAL void *pvEncoded,
  2006. IN OUT DWORD *pcbEncoded
  2007. )
  2008. {
  2009. BOOL fResult;
  2010. CmcAddAttributes Asn1Info;
  2011. memset(&Asn1Info, 0, sizeof(Asn1Info));
  2012. Asn1Info.pkiDataReference = pInfo->dwCmcDataReference;
  2013. if (pInfo->cCertReference) {
  2014. Asn1Info.certReferences.count = pInfo->cCertReference;
  2015. Asn1Info.certReferences.value = pInfo->rgdwCertReference;
  2016. }
  2017. if (!Asn1X509SetAttributes(pInfo->cAttribute, pInfo->rgAttribute,
  2018. &Asn1Info.attributes))
  2019. goto ErrorReturn;
  2020. fResult = Asn1InfoEncodeEx(
  2021. CmcAddAttributes_PDU,
  2022. &Asn1Info,
  2023. dwFlags,
  2024. pEncodePara,
  2025. pvEncoded,
  2026. pcbEncoded
  2027. );
  2028. CommonReturn:
  2029. Asn1X509FreeAttributes(&Asn1Info.attributes);
  2030. return fResult;
  2031. ErrorReturn:
  2032. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
  2033. *((void **) pvEncoded) = NULL;
  2034. *pcbEncoded = 0;
  2035. fResult = FALSE;
  2036. goto CommonReturn;
  2037. }
  2038. //+-------------------------------------------------------------------------
  2039. // CMC Add Attributes Decode (ASN1)
  2040. //--------------------------------------------------------------------------
  2041. BOOL WINAPI Asn1CmcAddAttributesDecodeExCallback(
  2042. IN void *pvAsn1Info,
  2043. IN DWORD dwFlags,
  2044. IN OPTIONAL PCRYPT_DECODE_PARA /*pDecodePara*/,
  2045. OUT OPTIONAL void *pvStructInfo,
  2046. IN OUT LONG *plRemainExtra
  2047. )
  2048. {
  2049. BOOL fResult;
  2050. CmcAddAttributes *pAsn1 = (CmcAddAttributes *) pvAsn1Info;
  2051. PCMC_ADD_ATTRIBUTES_INFO pInfo = (PCMC_ADD_ATTRIBUTES_INFO) pvStructInfo;
  2052. LONG lRemainExtra = *plRemainExtra;
  2053. LONG lAlignExtra;
  2054. BYTE *pbExtra;
  2055. lRemainExtra -= sizeof(CMC_ADD_ATTRIBUTES_INFO);
  2056. if (lRemainExtra < 0) {
  2057. pbExtra = NULL;
  2058. } else {
  2059. memset(pInfo, 0, sizeof(CMC_ADD_ATTRIBUTES_INFO));
  2060. pbExtra = (BYTE *) pInfo + sizeof(CMC_ADD_ATTRIBUTES_INFO);
  2061. pInfo->dwCmcDataReference = pAsn1->pkiDataReference;
  2062. }
  2063. if (pAsn1->certReferences.count > 0) {
  2064. ASN1uint32_t count = pAsn1->certReferences.count;
  2065. lAlignExtra = INFO_LEN_ALIGN(count * sizeof(DWORD));
  2066. lRemainExtra -= lAlignExtra;
  2067. if (lRemainExtra >= 0) {
  2068. BodyPartID *value;
  2069. DWORD *pdwCertReference;
  2070. value = pAsn1->certReferences.value;
  2071. pdwCertReference = (DWORD *) pbExtra;
  2072. pbExtra += lAlignExtra;
  2073. pInfo->cCertReference = count;
  2074. pInfo->rgdwCertReference = pdwCertReference;
  2075. for ( ; count > 0; count--, value++, pdwCertReference++)
  2076. *pdwCertReference = *value;
  2077. }
  2078. }
  2079. Asn1X509GetAttributes(&pAsn1->attributes, dwFlags,
  2080. &pInfo->cAttribute, &pInfo->rgAttribute, &pbExtra, &lRemainExtra);
  2081. fResult = TRUE;
  2082. *plRemainExtra = lRemainExtra;
  2083. return fResult;
  2084. }
  2085. BOOL WINAPI Asn1CmcAddAttributesDecodeEx(
  2086. IN DWORD /*dwCertEncodingType*/,
  2087. IN LPCSTR /*lpszStructType*/,
  2088. IN const BYTE *pbEncoded,
  2089. IN DWORD cbEncoded,
  2090. IN DWORD dwFlags,
  2091. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  2092. OUT OPTIONAL void *pvStructInfo,
  2093. IN OUT DWORD *pcbStructInfo
  2094. )
  2095. {
  2096. return Asn1InfoDecodeAndAllocEx(
  2097. CmcAddAttributes_PDU,
  2098. pbEncoded,
  2099. cbEncoded,
  2100. dwFlags,
  2101. pDecodePara,
  2102. Asn1CmcAddAttributesDecodeExCallback,
  2103. pvStructInfo,
  2104. pcbStructInfo
  2105. );
  2106. }