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.

937 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 2001 - 2001
  5. //
  6. // File: asn1parse.cpp
  7. //
  8. // Contents: Minimal ASN.1 parse functions.
  9. //
  10. // Functions: MinAsn1ParseCertificate
  11. // MinAsn1ParseAlgorithmIdentifier
  12. // MinAsn1ParsePublicKeyInfo
  13. // MinAsn1ParseRSAPublicKey
  14. // MinAsn1ParseExtensions
  15. // MinAsn1ParseSignedData
  16. // MinAsn1ParseSignedDataCertificates
  17. // MinAsn1ParseAttributes
  18. // MinAsn1ParseCTL
  19. // MinAsn1ParseCTLSubject
  20. // MinAsn1ParseIndirectData
  21. //
  22. // History: 15-Jan-01 philh created
  23. //--------------------------------------------------------------------------
  24. #include "global.hxx"
  25. const BYTE rgbSeqTag[] = {MINASN1_TAG_SEQ, 0};
  26. const BYTE rgbSetTag[] = {MINASN1_TAG_SET, 0};
  27. const BYTE rgbOIDTag[] = {MINASN1_TAG_OID, 0};
  28. const BYTE rgbIntegerTag[] = {MINASN1_TAG_INTEGER, 0};
  29. const BYTE rgbBooleanTag[] = {MINASN1_TAG_BOOLEAN, 0};
  30. const BYTE rgbBitStringTag[] = {MINASN1_TAG_BITSTRING, 0};
  31. const BYTE rgbOctetStringTag[] = {MINASN1_TAG_OCTETSTRING, 0};
  32. const BYTE rgbConstructedContext0Tag[] =
  33. {MINASN1_TAG_CONSTRUCTED_CONTEXT_0, 0};
  34. const BYTE rgbConstructedContext1Tag[] =
  35. {MINASN1_TAG_CONSTRUCTED_CONTEXT_1, 0};
  36. const BYTE rgbConstructedContext3Tag[] =
  37. {MINASN1_TAG_CONSTRUCTED_CONTEXT_3, 0};
  38. const BYTE rgbContext1Tag[] = {MINASN1_TAG_CONTEXT_1, 0};
  39. const BYTE rgbContext2Tag[] = {MINASN1_TAG_CONTEXT_2, 0};
  40. const BYTE rgbChoiceOfTimeTag[] =
  41. {MINASN1_TAG_UTC_TIME, MINASN1_TAG_GENERALIZED_TIME, 0};
  42. const MINASN1_EXTRACT_VALUE_PARA rgParseCertPara[] = {
  43. // 0 - SignedContent ::= SEQUENCE {
  44. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  45. MINASN1_CERT_ENCODED_IDX, rgbSeqTag,
  46. // 0.1 - toBeSigned ::== SEQUENCE {
  47. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  48. MINASN1_CERT_TO_BE_SIGNED_IDX, rgbSeqTag,
  49. // 0.1.0 - version [0] EXPLICIT CertificateVersion DEFAULT v1,
  50. MINASN1_OPTIONAL_STEP_INTO_VALUE_OP, 0, rgbConstructedContext0Tag,
  51. // 0.1.0.0 - version number (INTEGER)
  52. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  53. MINASN1_CERT_VERSION_IDX, rgbIntegerTag,
  54. // 0.1.0.1
  55. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  56. // 0.1.1 - serialNumber CertificateSerialNumber,
  57. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  58. MINASN1_CERT_SERIAL_NUMBER_IDX, rgbIntegerTag,
  59. // 0.1.2 - signature AlgorithmIdentifier,
  60. MINASN1_STEP_OVER_VALUE_OP, 0, rgbSeqTag,
  61. // 0.1.3 - issuer NOCOPYANY, -- really Name
  62. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  63. MINASN1_CERT_ISSUER_IDX, rgbSeqTag,
  64. // 0.1.4 - validity Validity,
  65. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  66. // 0.1.4.0 - notBefore ChoiceOfTime,
  67. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  68. MINASN1_CERT_NOT_BEFORE_IDX, rgbChoiceOfTimeTag,
  69. // 0.1.4.1 - notAfter ChoiceOfTime,
  70. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  71. MINASN1_CERT_NOT_AFTER_IDX, rgbChoiceOfTimeTag,
  72. // 0.1.4.2
  73. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  74. // 0.1.5 - subject NOCOPYANY, -- really Name
  75. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  76. MINASN1_CERT_SUBJECT_IDX, rgbSeqTag,
  77. // 0.1.6 - subjectPublicKeyInfo SubjectPublicKeyInfo,
  78. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  79. MINASN1_CERT_PUBKEY_INFO_IDX, rgbSeqTag,
  80. // 0.1.7 - issuerUniqueIdentifier [1] IMPLICIT BITSTRING OPTIONAL,
  81. // Note, advanced past the unused bits octet
  82. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  83. MINASN1_CERT_ISSUER_UNIQUE_ID_IDX, rgbContext1Tag,
  84. // 0.1.8 - subjectUniqueIdentifier [2] IMPLICIT BITSTRING OPTIONAL,
  85. // Note, advanced past the unused bits octet
  86. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  87. MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX, rgbContext2Tag,
  88. // 0.1.9 - extensions [3] EXPLICIT Extensions OPTIONAL
  89. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  90. MINASN1_CERT_EXTS_IDX, rgbConstructedContext3Tag,
  91. // 0.1.10
  92. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  93. // 0.2 - signatureAlgorithm AlgorithmIdentifier,
  94. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  95. MINASN1_CERT_SIGN_ALGID_IDX, rgbSeqTag,
  96. // 0.3 - signature BITSTRING
  97. // Note, advanced past the unused bits octet
  98. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  99. MINASN1_CERT_SIGNATURE_IDX, rgbBitStringTag,
  100. };
  101. #define PARSE_CERT_PARA_CNT \
  102. (sizeof(rgParseCertPara) / sizeof(rgParseCertPara[0]))
  103. //+-------------------------------------------------------------------------
  104. // Function: MinAsn1ParseCertificate
  105. //
  106. // Parses an ASN.1 encoded X.509 certificate.
  107. //
  108. // Returns:
  109. // success - > 0 => bytes skipped, length of the encoded certificate
  110. // failure - < 0 => negative (offset + 1) of first bad tagged value
  111. //
  112. // All BITSTRING fields have been advanced past the unused count octet.
  113. //--------------------------------------------------------------------------
  114. LONG
  115. WINAPI
  116. MinAsn1ParseCertificate(
  117. IN const BYTE *pbEncoded,
  118. IN DWORD cbEncoded,
  119. OUT CRYPT_DER_BLOB rgCertBlob[MINASN1_CERT_BLOB_CNT]
  120. )
  121. {
  122. LONG lSkipped;
  123. DWORD cValuePara = PARSE_CERT_PARA_CNT;
  124. lSkipped = MinAsn1ExtractValues(
  125. pbEncoded,
  126. cbEncoded,
  127. &cValuePara,
  128. rgParseCertPara,
  129. MINASN1_CERT_BLOB_CNT,
  130. rgCertBlob
  131. );
  132. if (0 < lSkipped) {
  133. lSkipped = rgCertBlob[MINASN1_CERT_ENCODED_IDX].cbData;
  134. // If present, fixup the ISSUER_UNIQUE_ID and SUBJECT_UNIQUE_ID bit
  135. // fields to advance past the first contents octet containing the
  136. // number of unused bits
  137. if (0 != rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].cbData) {
  138. rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].pbData += 1;
  139. rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].cbData -= 1;
  140. }
  141. if (0 != rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].cbData) {
  142. rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].pbData += 1;
  143. rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].cbData -= 1;
  144. }
  145. }
  146. return lSkipped;
  147. }
  148. const MINASN1_EXTRACT_VALUE_PARA rgParseAlgIdPara[] = {
  149. // 0 - AlgorithmIdentifier ::= SEQUENCE {
  150. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  151. MINASN1_ALGID_ENCODED_IDX, rgbSeqTag,
  152. // 0.0 - algorithm ObjectID,
  153. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  154. MINASN1_ALGID_OID_IDX, rgbOIDTag,
  155. // 0.1 parameters ANY OPTIONAL
  156. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  157. MINASN1_ALGID_PARA_IDX, NULL,
  158. };
  159. #define PARSE_ALGID_PARA_CNT \
  160. (sizeof(rgParseAlgIdPara) / sizeof(rgParseAlgIdPara[0]))
  161. //+-------------------------------------------------------------------------
  162. // Function: MinAsn1ParseAlgorithmIdentifier
  163. //
  164. // Parses an ASN.1 encoded Algorithm Identifier contained in numerous
  165. // other ASN.1 structures, such as, X.509 certificate and PKCS #7 Signed Data
  166. // message.
  167. //
  168. // Returns:
  169. // success - > 0 => bytes skipped, length of the encoded algorithm
  170. // identifier
  171. // failure - < 0 => negative (offset + 1) of first bad tagged value
  172. //--------------------------------------------------------------------------
  173. LONG
  174. WINAPI
  175. MinAsn1ParseAlgorithmIdentifier(
  176. IN PCRYPT_DER_BLOB pAlgIdValueBlob,
  177. OUT CRYPT_DER_BLOB rgAlgIdBlob[MINASN1_ALGID_BLOB_CNT]
  178. )
  179. {
  180. LONG lSkipped;
  181. DWORD cValuePara = PARSE_ALGID_PARA_CNT;
  182. lSkipped = MinAsn1ExtractValues(
  183. pAlgIdValueBlob->pbData,
  184. pAlgIdValueBlob->cbData,
  185. &cValuePara,
  186. rgParseAlgIdPara,
  187. MINASN1_ALGID_BLOB_CNT,
  188. rgAlgIdBlob
  189. );
  190. if (0 < lSkipped)
  191. lSkipped = rgAlgIdBlob[MINASN1_ALGID_ENCODED_IDX].cbData;
  192. return lSkipped;
  193. }
  194. const MINASN1_EXTRACT_VALUE_PARA rgParsePubKeyInfoPara[] = {
  195. // 0 - PublicKeyInfo ::= SEQUENCE {
  196. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  197. MINASN1_PUBKEY_INFO_ENCODED_IDX, rgbSeqTag,
  198. // 0.0 - algorithm AlgorithmIdentifier,
  199. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  200. MINASN1_PUBKEY_INFO_ALGID_IDX, rgbSeqTag,
  201. // 0.1 - PublicKey BITSTRING
  202. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  203. MINASN1_PUBKEY_INFO_PUBKEY_IDX, rgbBitStringTag,
  204. };
  205. #define PARSE_PUBKEY_INFO_PARA_CNT \
  206. (sizeof(rgParsePubKeyInfoPara) / sizeof(rgParsePubKeyInfoPara[0]))
  207. //+-------------------------------------------------------------------------
  208. // Function: MinAsn1ParsePublicKeyInfo
  209. //
  210. // Parses an ASN.1 encoded Public Key Info structure contained in an
  211. // X.509 certificate
  212. //
  213. // Returns:
  214. // success - > 0 => bytes skipped, length of the encoded public key
  215. // info
  216. // failure - < 0 => negative (offset + 1) of first bad tagged value
  217. //
  218. // All BITSTRING fields have been advanced past the unused count octet.
  219. //--------------------------------------------------------------------------
  220. LONG
  221. WINAPI
  222. MinAsn1ParsePublicKeyInfo(
  223. IN PCRYPT_DER_BLOB pPubKeyInfoValueBlob,
  224. CRYPT_DER_BLOB rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_BLOB_CNT]
  225. )
  226. {
  227. LONG lSkipped;
  228. DWORD cValuePara = PARSE_PUBKEY_INFO_PARA_CNT;
  229. lSkipped = MinAsn1ExtractValues(
  230. pPubKeyInfoValueBlob->pbData,
  231. pPubKeyInfoValueBlob->cbData,
  232. &cValuePara,
  233. rgParsePubKeyInfoPara,
  234. MINASN1_PUBKEY_INFO_BLOB_CNT,
  235. rgPubKeyInfoBlob
  236. );
  237. if (0 < lSkipped)
  238. lSkipped = rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_ENCODED_IDX].cbData;
  239. return lSkipped;
  240. }
  241. const MINASN1_EXTRACT_VALUE_PARA rgParseRSAPubKeyPara[] = {
  242. // 0 - RSAPublicKey ::= SEQUENCE {
  243. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  244. MINASN1_RSA_PUBKEY_ENCODED_IDX, rgbSeqTag,
  245. // 0.0 - modulus HUGEINTEGER, -- n
  246. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  247. MINASN1_RSA_PUBKEY_MODULUS_IDX, rgbIntegerTag,
  248. // 0.1 - publicExponent INTEGER (0..4294967295) -- e
  249. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  250. MINASN1_RSA_PUBKEY_EXPONENT_IDX, rgbIntegerTag,
  251. };
  252. #define PARSE_RSA_PUBKEY_PARA_CNT \
  253. (sizeof(rgParseRSAPubKeyPara) / sizeof(rgParseRSAPubKeyPara[0]))
  254. //+-------------------------------------------------------------------------
  255. // Function: MinAsn1ParseRSAPublicKey
  256. //
  257. // Parses an ASN.1 encoded RSA PKCS #1 Public Key contained in the contents of
  258. // Public Key BITSTRING in a X.509 certificate.
  259. //
  260. // Returns:
  261. // success - > 0 => bytes skipped, length of the encoded RSA public key
  262. // failure - < 0 => negative (offset + 1) of first bad tagged value
  263. //--------------------------------------------------------------------------
  264. LONG
  265. WINAPI
  266. MinAsn1ParseRSAPublicKey(
  267. IN PCRYPT_DER_BLOB pPubKeyContentBlob,
  268. CRYPT_DER_BLOB rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_BLOB_CNT]
  269. )
  270. {
  271. LONG lSkipped;
  272. DWORD cValuePara = PARSE_RSA_PUBKEY_PARA_CNT;
  273. lSkipped = MinAsn1ExtractValues(
  274. pPubKeyContentBlob->pbData,
  275. pPubKeyContentBlob->cbData,
  276. &cValuePara,
  277. rgParseRSAPubKeyPara,
  278. MINASN1_RSA_PUBKEY_BLOB_CNT,
  279. rgRSAPubKeyBlob
  280. );
  281. if (0 < lSkipped)
  282. lSkipped = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_ENCODED_IDX].cbData;
  283. return lSkipped;
  284. }
  285. const MINASN1_EXTRACT_VALUE_PARA rgParseExtPara[] = {
  286. // 0 - Extension ::= SEQUENCE {
  287. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  288. MINASN1_EXT_ENCODED_IDX, rgbSeqTag,
  289. // 0.0 - extnId EncodedObjectID,
  290. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  291. MINASN1_EXT_OID_IDX, rgbOIDTag,
  292. // 0.1 - critical BOOLEAN DEFAULT FALSE,
  293. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  294. MINASN1_EXT_CRITICAL_IDX, rgbBooleanTag,
  295. // 0.2 - extnValue OCTETSTRING
  296. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  297. MINASN1_EXT_VALUE_IDX, rgbOctetStringTag,
  298. };
  299. #define PARSE_EXT_PARA_CNT \
  300. (sizeof(rgParseExtPara) / sizeof(rgParseExtPara[0]))
  301. //+-------------------------------------------------------------------------
  302. // Function: MinAsn1ParseExtensions
  303. //
  304. // Parses an ASN.1 encoded sequence of extensions contained in
  305. // other ASN.1 structures, such as, X.509 certificate and CTL.
  306. //
  307. // Upon input, *pcExt contains the maximum number of parsed extensions
  308. // that can be returned. Updated with the number of extensions processed.
  309. //
  310. // Returns:
  311. // success - >= 0 => bytes skipped, length of the encoded extensions
  312. // processed. If all extensions were processed,
  313. // bytes skipped = pExtsValueBlob->cbData.
  314. // failure - < 0 => negative (offset + 1) of first bad tagged value
  315. //--------------------------------------------------------------------------
  316. LONG
  317. WINAPI
  318. MinAsn1ParseExtensions(
  319. IN PCRYPT_DER_BLOB pExtsValueBlob, // Extensions ::= SEQUENCE OF Extension
  320. IN OUT DWORD *pcExt,
  321. OUT CRYPT_DER_BLOB rgrgExtBlob[][MINASN1_EXT_BLOB_CNT]
  322. )
  323. {
  324. const BYTE *pbEncoded = (const BYTE *) pExtsValueBlob->pbData;
  325. DWORD cbEncoded = pExtsValueBlob->cbData;
  326. DWORD cExt = *pcExt;
  327. DWORD iExt = 0;
  328. LONG lAllExts = 0;
  329. const BYTE *pb;
  330. DWORD cb;
  331. if (0 == cbEncoded)
  332. // No extensions
  333. goto CommonReturn;
  334. // Step into the SEQUENCE
  335. if (0 >= MinAsn1ExtractContent(
  336. pbEncoded,
  337. cbEncoded,
  338. &cb,
  339. &pb
  340. )) {
  341. lAllExts = -1;
  342. goto CommonReturn;
  343. }
  344. for (iExt = 0; 0 < cb && iExt < cExt; iExt++) {
  345. LONG lExt;
  346. DWORD cbExt;
  347. DWORD cValuePara = PARSE_EXT_PARA_CNT;
  348. lExt = MinAsn1ExtractValues(
  349. pb,
  350. cb,
  351. &cValuePara,
  352. rgParseExtPara,
  353. MINASN1_EXT_BLOB_CNT,
  354. rgrgExtBlob[iExt]
  355. );
  356. if (0 >= lExt) {
  357. if (0 == lExt)
  358. lExt = -1;
  359. lAllExts = -((LONG)(pb - pbEncoded)) + lExt;
  360. goto CommonReturn;
  361. }
  362. cbExt = rgrgExtBlob[iExt][MINASN1_EXT_ENCODED_IDX].cbData;
  363. pb += cbExt;
  364. cb -= cbExt;
  365. }
  366. lAllExts = (LONG)(pb - pbEncoded);
  367. assert((DWORD) lAllExts <= cbEncoded);
  368. CommonReturn:
  369. *pcExt = iExt;
  370. return lAllExts;
  371. }
  372. const MINASN1_EXTRACT_VALUE_PARA rgParseSignedDataPara[] = {
  373. // 0 - ContentInfo ::= SEQUENCE {
  374. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  375. MINASN1_SIGNED_DATA_ENCODED_IDX, rgbSeqTag,
  376. // 0.0 - contentType ContentType,
  377. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  378. MINASN1_SIGNED_DATA_OUTER_OID_IDX, rgbOIDTag,
  379. // 0.1 - content [0] EXPLICIT ANY -- OPTIONAL
  380. MINASN1_STEP_INTO_VALUE_OP, 0, rgbConstructedContext0Tag,
  381. // 0.1.0 - SignedData ::= SEQUENCE {
  382. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  383. // 0.1.0.0 - version INTEGER,
  384. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  385. MINASN1_SIGNED_DATA_VERSION_IDX, rgbIntegerTag,
  386. // 0.1.0.1 - digestAlgorithms DigestAlgorithmIdentifiers,
  387. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  388. MINASN1_SIGNED_DATA_DIGEST_ALGIDS_IDX, rgbSetTag,
  389. // 0.1.0.2 - ContentInfo ::= SEQUENCE {
  390. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  391. // 0.1.0.2.0 - contentType ContentType,
  392. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  393. MINASN1_SIGNED_DATA_CONTENT_OID_IDX, rgbOIDTag,
  394. // 0.1.0.2.1 - content [0] EXPLICIT ANY -- OPTIONAL
  395. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  396. MINASN1_SIGNED_DATA_CONTENT_DATA_IDX, rgbConstructedContext0Tag,
  397. // 0.1.0.2.2
  398. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  399. // 0.1.0.3 - certificates [0] IMPLICIT Certificates OPTIONAL,
  400. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  401. MINASN1_SIGNED_DATA_CERTS_IDX, rgbConstructedContext0Tag,
  402. // 0.1.0.4 - crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  403. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  404. MINASN1_SIGNED_DATA_CRLS_IDX, rgbConstructedContext1Tag,
  405. // 0.1.0.5 - signerInfos :: = SET OF
  406. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  407. MINASN1_SIGNED_DATA_SIGNER_INFOS_IDX, rgbSetTag,
  408. // 0.1.0.5.0 - SignerInfo ::= SEQUENCE {
  409. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_INTO_VALUE_OP,
  410. MINASN1_SIGNED_DATA_SIGNER_INFO_ENCODED_IDX, rgbSeqTag,
  411. // 0.1.0.5.0.0 - version INTEGER,
  412. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  413. MINASN1_SIGNED_DATA_SIGNER_INFO_VERSION_IDX, rgbIntegerTag,
  414. // 0.1.0.5.0.1 - issuerAndSerialNumber IssuerAndSerialNumber
  415. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  416. // 0.1.0.5.0.1.0 - issuer ANY,
  417. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  418. MINASN1_SIGNED_DATA_SIGNER_INFO_ISSUER_IDX, rgbSeqTag,
  419. // 0.1.0.5.0.1.1 - serialNumber INTEGER
  420. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  421. MINASN1_SIGNED_DATA_SIGNER_INFO_SERIAL_NUMBER_IDX, rgbIntegerTag,
  422. // 0.1.0.5.0.1.2
  423. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  424. // 0.1.0.5.0.2 - digestAlgorithm DigestAlgorithmIdentifier,
  425. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  426. MINASN1_SIGNED_DATA_SIGNER_INFO_DIGEST_ALGID_IDX, rgbSeqTag,
  427. // 0.1.0.5.0.3 - authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
  428. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  429. MINASN1_SIGNED_DATA_SIGNER_INFO_AUTH_ATTRS_IDX, rgbConstructedContext0Tag,
  430. // 0.1.0.5.0.4 - digestEncryptionAlgorithm DigestEncryptionAlgId,
  431. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  432. MINASN1_SIGNED_DATA_SIGNER_INFO_ENCRYPT_DIGEST_ALGID_IDX, rgbSeqTag,
  433. // 0.1.0.5.0.5 - encryptedDigest EncryptedDigest,
  434. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  435. MINASN1_SIGNED_DATA_SIGNER_INFO_ENCYRPT_DIGEST_IDX, rgbOctetStringTag,
  436. // 0.1.0.5.0.6 - unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
  437. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  438. MINASN1_SIGNED_DATA_SIGNER_INFO_UNAUTH_ATTRS_IDX, rgbConstructedContext1Tag,
  439. };
  440. #define PARSE_SIGNED_DATA_PARA_CNT \
  441. (sizeof(rgParseSignedDataPara) / sizeof(rgParseSignedDataPara[0]))
  442. //+-------------------------------------------------------------------------
  443. // Function: MinAsn1ParseSignedData
  444. //
  445. // Parses an ASN.1 encoded PKCS #7 Signed Data Message. Assumes the
  446. // PKCS #7 message is definite length encoded. Assumes PKCS #7 version
  447. // 1.5, ie, not the newer CMS version.
  448. //
  449. // Returns:
  450. // success - > 0 => bytes skipped, length of the encoded message
  451. // failure - < 0 => negative (offset + 1) of first bad tagged value
  452. //--------------------------------------------------------------------------
  453. LONG
  454. WINAPI
  455. MinAsn1ParseSignedData(
  456. IN const BYTE *pbEncoded,
  457. IN DWORD cbEncoded,
  458. OUT CRYPT_DER_BLOB rgSignedDataBlob[MINASN1_SIGNED_DATA_BLOB_CNT]
  459. )
  460. {
  461. LONG lSkipped;
  462. DWORD cValuePara = PARSE_SIGNED_DATA_PARA_CNT;
  463. lSkipped = MinAsn1ExtractValues(
  464. pbEncoded,
  465. cbEncoded,
  466. &cValuePara,
  467. rgParseSignedDataPara,
  468. MINASN1_SIGNED_DATA_BLOB_CNT,
  469. rgSignedDataBlob
  470. );
  471. if (0 < lSkipped)
  472. lSkipped = rgSignedDataBlob[MINASN1_SIGNED_DATA_ENCODED_IDX].cbData;
  473. return lSkipped;
  474. }
  475. //+-------------------------------------------------------------------------
  476. // Function: MinAsn1ParseSignedDataCertificates
  477. //
  478. // Parses an ASN.1 encoded set of certificates contained in
  479. // a Signed Data message.
  480. //
  481. // Upon input, *pcCert contains the maximum number of parsed certificates
  482. // that can be returned. Updated with the number of certificates processed.
  483. //
  484. // Returns:
  485. // success - >= 0 => bytes skipped, length of the encoded certificates
  486. // processed. If all certificates were processed,
  487. // bytes skipped = pCertsValueBlob->cbData.
  488. // failure - < 0 => negative (offset + 1) of first bad tagged value
  489. //
  490. // The rgrgCertBlob[][] is updated with pointer to and length of the
  491. // fields in the encoded certificate. See MinAsn1ParseCertificate for the
  492. // field definitions.
  493. //--------------------------------------------------------------------------
  494. LONG
  495. WINAPI
  496. MinAsn1ParseSignedDataCertificates(
  497. IN PCRYPT_DER_BLOB pCertsValueBlob,
  498. IN OUT DWORD *pcCert,
  499. OUT CRYPT_DER_BLOB rgrgCertBlob[][MINASN1_CERT_BLOB_CNT]
  500. )
  501. {
  502. const BYTE *pbEncoded = (const BYTE *) pCertsValueBlob->pbData;
  503. DWORD cbEncoded = pCertsValueBlob->cbData;
  504. DWORD cCert = *pcCert;
  505. DWORD iCert = 0;
  506. LONG lAllCerts = 0;
  507. const BYTE *pb;
  508. DWORD cb;
  509. if (0 == cbEncoded)
  510. // No certificates
  511. goto CommonReturn;
  512. // Skip outer tag and length
  513. if (0 >= MinAsn1ExtractContent(
  514. pbEncoded,
  515. cbEncoded,
  516. &cb,
  517. &pb
  518. )) {
  519. lAllCerts = -1;
  520. goto CommonReturn;
  521. }
  522. for (iCert = 0; 0 < cb && iCert < cCert; iCert++) {
  523. LONG lCert;
  524. lCert = MinAsn1ParseCertificate(
  525. pb,
  526. cb,
  527. rgrgCertBlob[iCert]
  528. );
  529. if (0 >= lCert) {
  530. if (0 == lCert)
  531. lCert = -1;
  532. lAllCerts = -((LONG)(pb - pbEncoded)) + lCert;
  533. goto CommonReturn;
  534. }
  535. pb += lCert;
  536. cb -= lCert;
  537. }
  538. lAllCerts = (LONG)(pb - pbEncoded);
  539. assert((DWORD) lAllCerts <= cbEncoded);
  540. CommonReturn:
  541. *pcCert = iCert;
  542. return lAllCerts;
  543. }
  544. const MINASN1_EXTRACT_VALUE_PARA rgParseAttrPara[] = {
  545. // 0 - Attribute ::= SEQUENCE {
  546. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  547. MINASN1_ATTR_ENCODED_IDX, rgbSeqTag,
  548. // 0.0 - attributeType ObjectID,
  549. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  550. MINASN1_ATTR_OID_IDX, rgbOIDTag,
  551. // 0.1 - attributeValue SET OF
  552. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  553. MINASN1_ATTR_VALUES_IDX, rgbSetTag,
  554. // 0.1.0 - Value ANY -- OPTIONAL
  555. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  556. MINASN1_ATTR_VALUE_IDX, NULL,
  557. };
  558. #define PARSE_ATTR_PARA_CNT \
  559. (sizeof(rgParseAttrPara) / sizeof(rgParseAttrPara[0]))
  560. //+-------------------------------------------------------------------------
  561. // Function: MinAsn1ParseAttributes
  562. //
  563. // Parses an ASN.1 encoded sequence of attributes contained in
  564. // other ASN.1 structures, such as, Signer Info authenticated or
  565. // unauthenticated attributes.
  566. //
  567. // The outer tag is ignored. It can be a SET, [0] IMPLICIT, or [1] IMPLICIT.
  568. //
  569. // Upon input, *pcAttr contains the maximum number of parsed attributes
  570. // that can be returned. Updated with the number of attributes processed.
  571. //
  572. // Returns:
  573. // success - >= 0 => bytes skipped, length of the encoded attributes
  574. // processed. If all attributes were processed,
  575. // bytes skipped = pAttrsValueBlob->cbData.
  576. // failure - < 0 => negative (offset + 1) of first bad tagged value
  577. //--------------------------------------------------------------------------
  578. LONG
  579. WINAPI
  580. MinAsn1ParseAttributes(
  581. IN PCRYPT_DER_BLOB pAttrsValueBlob,
  582. IN OUT DWORD *pcAttr,
  583. OUT CRYPT_DER_BLOB rgrgAttrBlob[][MINASN1_ATTR_BLOB_CNT]
  584. )
  585. {
  586. const BYTE *pbEncoded = (const BYTE *) pAttrsValueBlob->pbData;
  587. DWORD cbEncoded = pAttrsValueBlob->cbData;
  588. DWORD cAttr = *pcAttr;
  589. DWORD iAttr = 0;
  590. LONG lAllAttrs = 0;
  591. const BYTE *pb;
  592. DWORD cb;
  593. if (0 == cbEncoded)
  594. // No attributes
  595. goto CommonReturn;
  596. // Skip the outer tag and length
  597. if (0 >= MinAsn1ExtractContent(
  598. pbEncoded,
  599. cbEncoded,
  600. &cb,
  601. &pb
  602. )) {
  603. lAllAttrs = -1;
  604. goto CommonReturn;
  605. }
  606. for (iAttr = 0; 0 < cb && iAttr < cAttr; iAttr++) {
  607. LONG lAttr;
  608. DWORD cbAttr;
  609. DWORD cValuePara = PARSE_ATTR_PARA_CNT;
  610. lAttr = MinAsn1ExtractValues(
  611. pb,
  612. cb,
  613. &cValuePara,
  614. rgParseAttrPara,
  615. MINASN1_ATTR_BLOB_CNT,
  616. rgrgAttrBlob[iAttr]
  617. );
  618. if (0 >= lAttr) {
  619. if (0 == lAttr)
  620. lAttr = -1;
  621. lAllAttrs = -((LONG)(pb - pbEncoded)) + lAttr;
  622. goto CommonReturn;
  623. }
  624. cbAttr = rgrgAttrBlob[iAttr][MINASN1_ATTR_ENCODED_IDX].cbData;
  625. pb += cbAttr;
  626. cb -= cbAttr;
  627. }
  628. lAllAttrs = (LONG)(pb - pbEncoded);
  629. assert((DWORD) lAllAttrs <= cbEncoded);
  630. CommonReturn:
  631. *pcAttr = iAttr;
  632. return lAllAttrs;
  633. }
  634. const MINASN1_EXTRACT_VALUE_PARA rgParseCTLPara[] = {
  635. // 0 - CertificateTrustList ::= SEQUENCE {
  636. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  637. MINASN1_CTL_ENCODED_IDX, rgbSeqTag,
  638. // 0.0 - version CTLVersion DEFAULT v1,
  639. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  640. MINASN1_CTL_VERSION_IDX, rgbIntegerTag,
  641. // 0.1 - subjectUsage SubjectUsage,
  642. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  643. MINASN1_CTL_SUBJECT_USAGE_IDX, rgbSeqTag,
  644. // 0.2 - listIdentifier ListIdentifier OPTIONAL,
  645. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  646. MINASN1_CTL_LIST_ID_IDX, rgbOctetStringTag,
  647. // 0.3 - sequenceNumber HUGEINTEGER OPTIONAL,
  648. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  649. MINASN1_CTL_SEQUENCE_NUMBER_IDX, rgbIntegerTag,
  650. // 0.4 - ctlThisUpdate ChoiceOfTime,
  651. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  652. MINASN1_CTL_THIS_UPDATE_IDX, rgbChoiceOfTimeTag,
  653. // 0.5 - ctlNextUpdate ChoiceOfTime OPTIONAL,
  654. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  655. MINASN1_CTL_NEXT_UPDATE_IDX, rgbChoiceOfTimeTag,
  656. // 0.6 - subjectAlgorithm AlgorithmIdentifier,
  657. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  658. MINASN1_CTL_SUBJECT_ALGID_IDX, rgbSeqTag,
  659. // 0.7 - trustedSubjects TrustedSubjects OPTIONAL,
  660. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  661. MINASN1_CTL_SUBJECTS_IDX, rgbSeqTag,
  662. // 0.8 - ctlExtensions [0] EXPLICIT Extensions OPTIONAL
  663. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  664. MINASN1_CTL_EXTS_IDX, rgbConstructedContext0Tag,
  665. };
  666. #define PARSE_CTL_PARA_CNT \
  667. (sizeof(rgParseCTLPara) / sizeof(rgParseCTLPara[0]))
  668. //+-------------------------------------------------------------------------
  669. // Function: MinAsn1ParseCTL
  670. //
  671. // Parses an ASN.1 encoded Certificate Trust List (CTL). A CTL is always
  672. // contained as the inner content data in a PKCS #7 Signed Data. A CTL has
  673. // the following OID: "1.3.6.1.4.1.311.10.1".
  674. //
  675. // A catalog file is formatted as a PKCS #7 Signed CTL.
  676. //
  677. // Returns:
  678. // success - > 0 => bytes skipped, length of the encoded CTL
  679. // failure - < 0 => negative (offset + 1) of first bad tagged value
  680. //--------------------------------------------------------------------------
  681. LONG
  682. WINAPI
  683. MinAsn1ParseCTL(
  684. IN PCRYPT_DER_BLOB pEncodedContentBlob,
  685. OUT CRYPT_DER_BLOB rgCTLBlob[MINASN1_CTL_BLOB_CNT]
  686. )
  687. {
  688. LONG lSkipped;
  689. DWORD cValuePara = PARSE_CTL_PARA_CNT;
  690. lSkipped = MinAsn1ExtractValues(
  691. pEncodedContentBlob->pbData,
  692. pEncodedContentBlob->cbData,
  693. &cValuePara,
  694. rgParseCTLPara,
  695. MINASN1_CTL_BLOB_CNT,
  696. rgCTLBlob
  697. );
  698. if (0 < lSkipped)
  699. lSkipped = rgCTLBlob[MINASN1_CTL_ENCODED_IDX].cbData;
  700. return lSkipped;
  701. }
  702. const MINASN1_EXTRACT_VALUE_PARA rgParseCTLSubjectPara[] = {
  703. // 0 - TrustedSubject ::= SEQUENCE {
  704. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  705. MINASN1_CTL_SUBJECT_ENCODED_IDX, rgbSeqTag,
  706. // 0.0 - subjectIdentifier SubjectIdentifier,
  707. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  708. MINASN1_CTL_SUBJECT_ID_IDX, rgbOctetStringTag,
  709. // 0.1 - subjectAttributes Attributes OPTIONAL
  710. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  711. MINASN1_CTL_SUBJECT_ATTRS_IDX, rgbSetTag,
  712. };
  713. #define PARSE_CTL_SUBJECT_PARA_CNT \
  714. (sizeof(rgParseCTLSubjectPara) / sizeof(rgParseCTLSubjectPara[0]))
  715. //+-------------------------------------------------------------------------
  716. // Function: MinAsn1ParseCTLSubject
  717. //
  718. // Parses an ASN.1 encoded CTL Subject contained within a CTL's SEQUENCE OF
  719. // Subjects.
  720. //
  721. // Returns:
  722. // success - > 0 => bytes skipped, length of the encoded subject.
  723. // failure - < 0 => negative (offset + 1) of first bad tagged value
  724. //--------------------------------------------------------------------------
  725. LONG
  726. WINAPI
  727. MinAsn1ParseCTLSubject(
  728. IN const BYTE *pbEncoded,
  729. IN DWORD cbEncoded,
  730. OUT CRYPT_DER_BLOB rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_BLOB_CNT]
  731. )
  732. {
  733. LONG lSkipped;
  734. DWORD cValuePara = PARSE_CTL_SUBJECT_PARA_CNT;
  735. lSkipped = MinAsn1ExtractValues(
  736. pbEncoded,
  737. cbEncoded,
  738. &cValuePara,
  739. rgParseCTLSubjectPara,
  740. MINASN1_CTL_SUBJECT_BLOB_CNT,
  741. rgCTLSubjectBlob
  742. );
  743. if (0 < lSkipped)
  744. lSkipped = rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_ENCODED_IDX].cbData;
  745. return lSkipped;
  746. }
  747. const MINASN1_EXTRACT_VALUE_PARA rgParseIndirectDataPara[] = {
  748. // 0 - SpcIndirectDataContent ::= SEQUENCE {
  749. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
  750. MINASN1_INDIRECT_DATA_ENCODED_IDX, rgbSeqTag,
  751. // 0.0 - data SpcAttributeTypeAndOptionalValue,
  752. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  753. // 0.0.0 - type ObjectID,
  754. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  755. MINASN1_INDIRECT_DATA_ATTR_OID_IDX, rgbOIDTag,
  756. // 0.0.1 - value NOCOPYANY OPTIONAL
  757. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
  758. MINASN1_INDIRECT_DATA_ATTR_VALUE_IDX, NULL,
  759. // 0.0.2
  760. MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
  761. // 0.1 - messageDigest DigestInfo
  762. MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
  763. // 0.1.0 - digestAlgorithm AlgorithmIdentifier,
  764. MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  765. MINASN1_INDIRECT_DATA_DIGEST_ALGID_IDX, rgbSeqTag,
  766. // 0.1.1 - digest OCTETSTRING
  767. MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
  768. MINASN1_INDIRECT_DATA_DIGEST_IDX, rgbOctetStringTag,
  769. };
  770. #define PARSE_INDIRECT_DATA_PARA_CNT \
  771. (sizeof(rgParseIndirectDataPara) / sizeof(rgParseIndirectDataPara[0]))
  772. //+-------------------------------------------------------------------------
  773. // Function: MinAsn1ParseIndirectData
  774. //
  775. // Parses an ASN.1 encoded Indirect Data. Indirect Data is always
  776. // contained as the inner content data in a PKCS #7 Signed Data. It has
  777. // the following OID: "1.3.6.1.4.1.311.2.1.4"
  778. //
  779. // An Authenticode signed file contains a PKCS #7 Signed Indirect Data.
  780. //
  781. // Returns:
  782. // success - > 0 => bytes skipped, length of the encoded Indirect Data
  783. // failure - < 0 => negative (offset + 1) of first bad tagged value
  784. //--------------------------------------------------------------------------
  785. LONG
  786. WINAPI
  787. MinAsn1ParseIndirectData(
  788. IN PCRYPT_DER_BLOB pEncodedContentBlob,
  789. OUT CRYPT_DER_BLOB rgIndirectDataBlob[MINASN1_INDIRECT_DATA_BLOB_CNT]
  790. )
  791. {
  792. LONG lSkipped;
  793. DWORD cValuePara = PARSE_INDIRECT_DATA_PARA_CNT;
  794. lSkipped = MinAsn1ExtractValues(
  795. pEncodedContentBlob->pbData,
  796. pEncodedContentBlob->cbData,
  797. &cValuePara,
  798. rgParseIndirectDataPara,
  799. MINASN1_INDIRECT_DATA_BLOB_CNT,
  800. rgIndirectDataBlob
  801. );
  802. if (0 < lSkipped)
  803. lSkipped = rgIndirectDataBlob[MINASN1_INDIRECT_DATA_ENCODED_IDX].cbData;
  804. return lSkipped;
  805. }