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

691 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995 - 1998
  5. //
  6. // File: pkiasn1.cpp
  7. //
  8. // Contents: PKI ASN.1 support functions.
  9. //
  10. // Functions: PkiAsn1Encode
  11. // PkiAsn1Decode
  12. // PkiAsn1SetEncodingRule
  13. // PkiAsn1GetEncodingRule
  14. //
  15. // PkiAsn1ReverseBytes
  16. // PkiAsn1EncodeInfoEx
  17. // PkiAsn1EncodeInfo
  18. // PkiAsn1DecodeAndAllocInfo
  19. // PkiAsn1AllocStructInfoEx
  20. // PkiAsn1DecodeAndAllocInfoEx
  21. //
  22. // PkiAsn1ToObjectIdentifier
  23. // PkiAsn1FromObjectIdentifier
  24. //
  25. //
  26. // History: 23-Oct-98 philh created
  27. //--------------------------------------------------------------------------
  28. #include "global.hxx"
  29. #include <dbgdef.h>
  30. // All the *pvInfo extra stuff needs to be aligned
  31. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  32. inline BOOL my_isdigit( char ch)
  33. {
  34. return (ch >= '0') && (ch <= '9');
  35. }
  36. //+-------------------------------------------------------------------------
  37. // Asn1 Encode function. The encoded output is allocated and must be freed
  38. // by calling PkiAsn1FreeEncoded().
  39. //--------------------------------------------------------------------------
  40. ASN1error_e
  41. WINAPI
  42. PkiAsn1Encode(
  43. IN ASN1encoding_t pEnc,
  44. IN void *pvAsn1Info,
  45. IN ASN1uint32_t id,
  46. OUT BYTE **ppbEncoded,
  47. OUT DWORD *pcbEncoded
  48. )
  49. {
  50. ASN1error_e Asn1Err;
  51. Asn1Err = ASN1_Encode(
  52. pEnc,
  53. pvAsn1Info,
  54. id,
  55. ASN1ENCODE_ALLOCATEBUFFER,
  56. NULL, // pbBuf
  57. 0 // cbBufSize
  58. );
  59. if (ASN1_SUCCEEDED(Asn1Err)) {
  60. Asn1Err = ASN1_SUCCESS;
  61. *ppbEncoded = pEnc->buf;
  62. *pcbEncoded = pEnc->len;
  63. } else {
  64. *ppbEncoded = NULL;
  65. *pcbEncoded = 0;
  66. }
  67. return Asn1Err;
  68. }
  69. //+-------------------------------------------------------------------------
  70. // Asn1 Encode function. The encoded output isn't allocated.
  71. //
  72. // If pbEncoded is NULL, does a length only calculation.
  73. //--------------------------------------------------------------------------
  74. ASN1error_e
  75. WINAPI
  76. PkiAsn1Encode2(
  77. IN ASN1encoding_t pEnc,
  78. IN void *pvAsn1Info,
  79. IN ASN1uint32_t id,
  80. OUT OPTIONAL BYTE *pbEncoded,
  81. IN OUT DWORD *pcbEncoded
  82. )
  83. {
  84. ASN1error_e Asn1Err;
  85. DWORD cbEncoded;
  86. if (NULL == pbEncoded)
  87. cbEncoded = 0;
  88. else
  89. cbEncoded = *pcbEncoded;
  90. if (0 == cbEncoded) {
  91. // Length only calculation
  92. Asn1Err = ASN1_Encode(
  93. pEnc,
  94. pvAsn1Info,
  95. id,
  96. ASN1ENCODE_ALLOCATEBUFFER,
  97. NULL, // pbBuf
  98. 0 // cbBufSize
  99. );
  100. if (ASN1_SUCCEEDED(Asn1Err)) {
  101. if (pbEncoded)
  102. Asn1Err = ASN1_ERR_OVERFLOW;
  103. else
  104. Asn1Err = ASN1_SUCCESS;
  105. cbEncoded = pEnc->len;
  106. PkiAsn1FreeEncoded(pEnc, pEnc->buf);
  107. }
  108. } else {
  109. Asn1Err = ASN1_Encode(
  110. pEnc,
  111. pvAsn1Info,
  112. id,
  113. ASN1ENCODE_SETBUFFER,
  114. pbEncoded,
  115. cbEncoded
  116. );
  117. if (ASN1_SUCCEEDED(Asn1Err)) {
  118. Asn1Err = ASN1_SUCCESS;
  119. cbEncoded = pEnc->len;
  120. } else if (ASN1_ERR_OVERFLOW == Asn1Err) {
  121. // Re-do as length only calculation
  122. Asn1Err = PkiAsn1Encode2(
  123. pEnc,
  124. pvAsn1Info,
  125. id,
  126. NULL, // pbEncoded
  127. &cbEncoded
  128. );
  129. if (ASN1_SUCCESS == Asn1Err)
  130. Asn1Err = ASN1_ERR_OVERFLOW;
  131. } else
  132. cbEncoded = 0;
  133. }
  134. *pcbEncoded = cbEncoded;
  135. return Asn1Err;
  136. }
  137. //+-------------------------------------------------------------------------
  138. // Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
  139. // be freed by calling PkiAsn1FreeDecoded().
  140. //--------------------------------------------------------------------------
  141. ASN1error_e
  142. WINAPI
  143. PkiAsn1Decode(
  144. IN ASN1decoding_t pDec,
  145. OUT void **ppvAsn1Info,
  146. IN ASN1uint32_t id,
  147. IN const BYTE *pbEncoded,
  148. IN DWORD cbEncoded
  149. )
  150. {
  151. ASN1error_e Asn1Err;
  152. *ppvAsn1Info = NULL;
  153. Asn1Err = ASN1_Decode(
  154. pDec,
  155. ppvAsn1Info,
  156. id,
  157. ASN1DECODE_SETBUFFER,
  158. (BYTE *) pbEncoded,
  159. cbEncoded
  160. );
  161. if (ASN1_SUCCEEDED(Asn1Err))
  162. Asn1Err = ASN1_SUCCESS;
  163. else {
  164. if (ASN1_ERR_BADARGS == Asn1Err)
  165. Asn1Err = ASN1_ERR_EOD;
  166. *ppvAsn1Info = NULL;
  167. }
  168. return Asn1Err;
  169. }
  170. //+-------------------------------------------------------------------------
  171. // Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
  172. // be freed by calling PkiAsn1FreeDecoded().
  173. //
  174. // For a successful decode, *ppbEncoded is advanced
  175. // past the decoded bytes and *pcbDecoded is decremented by the number
  176. // of decoded bytes.
  177. //--------------------------------------------------------------------------
  178. ASN1error_e
  179. WINAPI
  180. PkiAsn1Decode2(
  181. IN ASN1decoding_t pDec,
  182. OUT void **ppvAsn1Info,
  183. IN ASN1uint32_t id,
  184. IN OUT BYTE **ppbEncoded,
  185. IN OUT DWORD *pcbEncoded
  186. )
  187. {
  188. ASN1error_e Asn1Err;
  189. *ppvAsn1Info = NULL;
  190. Asn1Err = ASN1_Decode(
  191. pDec,
  192. ppvAsn1Info,
  193. id,
  194. ASN1DECODE_SETBUFFER,
  195. *ppbEncoded,
  196. *pcbEncoded
  197. );
  198. if (ASN1_SUCCEEDED(Asn1Err)) {
  199. Asn1Err = ASN1_SUCCESS;
  200. *ppbEncoded += pDec->len;
  201. *pcbEncoded -= pDec->len;
  202. } else {
  203. if (ASN1_ERR_BADARGS == Asn1Err)
  204. Asn1Err = ASN1_ERR_EOD;
  205. *ppvAsn1Info = NULL;
  206. }
  207. return Asn1Err;
  208. }
  209. //+-------------------------------------------------------------------------
  210. // Asn1 Set/Get encoding rules functions
  211. //--------------------------------------------------------------------------
  212. ASN1error_e
  213. WINAPI
  214. PkiAsn1SetEncodingRule(
  215. IN ASN1encoding_t pEnc,
  216. IN ASN1encodingrule_e eRule
  217. )
  218. {
  219. ASN1optionparam_s OptParam;
  220. OptParam.eOption = ASN1OPT_CHANGE_RULE;
  221. OptParam.eRule = eRule;
  222. return ASN1_SetEncoderOption(pEnc, &OptParam);
  223. }
  224. ASN1encodingrule_e
  225. WINAPI
  226. PkiAsn1GetEncodingRule(
  227. IN ASN1encoding_t pEnc
  228. )
  229. {
  230. ASN1error_e Asn1Err;
  231. ASN1encodingrule_e eRule;
  232. ASN1optionparam_s OptParam;
  233. OptParam.eOption = ASN1OPT_GET_RULE;
  234. Asn1Err = ASN1_GetEncoderOption(pEnc, &OptParam);
  235. if (ASN1_SUCCEEDED(Asn1Err))
  236. eRule = OptParam.eRule;
  237. else
  238. eRule = ASN1_BER_RULE_DER;
  239. return eRule;
  240. }
  241. //+-------------------------------------------------------------------------
  242. // Reverses a buffer of bytes in place
  243. //--------------------------------------------------------------------------
  244. void
  245. WINAPI
  246. PkiAsn1ReverseBytes(
  247. IN OUT PBYTE pbIn,
  248. IN DWORD cbIn
  249. )
  250. {
  251. // reverse in place
  252. PBYTE pbLo;
  253. PBYTE pbHi;
  254. BYTE bTmp;
  255. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  256. bTmp = *pbHi;
  257. *pbHi = *pbLo;
  258. *pbLo = bTmp;
  259. }
  260. }
  261. //+-------------------------------------------------------------------------
  262. // Encode an ASN1 formatted info structure.
  263. //
  264. // If CRYPT_ENCODE_ALLOC_FLAG is set, allocate memory for pbEncoded and
  265. // return *((BYTE **) pvEncoded) = pbAllocEncoded. Otherwise,
  266. // pvEncoded points to byte array to be updated.
  267. //--------------------------------------------------------------------------
  268. BOOL
  269. WINAPI
  270. PkiAsn1EncodeInfoEx(
  271. IN ASN1encoding_t pEnc,
  272. IN ASN1uint32_t id,
  273. IN void *pvAsn1Info,
  274. IN DWORD dwFlags,
  275. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  276. OUT OPTIONAL void *pvEncoded,
  277. IN OUT DWORD *pcbEncoded
  278. )
  279. {
  280. BOOL fResult;
  281. ASN1error_e Asn1Err;
  282. DWORD cbEncoded;
  283. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  284. BYTE *pbEncoded;
  285. BYTE *pbAllocEncoded;
  286. PFN_CRYPT_ALLOC pfnAlloc;
  287. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  288. Asn1Err = PkiAsn1Encode(
  289. pEnc,
  290. pvAsn1Info,
  291. id,
  292. &pbEncoded,
  293. &cbEncoded
  294. );
  295. if (ASN1_SUCCESS != Asn1Err) {
  296. *((void **) pvEncoded) = NULL;
  297. goto Asn1EncodeError;
  298. }
  299. pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
  300. if (NULL == (pbAllocEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
  301. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  302. *((void **) pvEncoded) = NULL;
  303. goto OutOfMemory;
  304. }
  305. memcpy(pbAllocEncoded, pbEncoded, cbEncoded);
  306. *((BYTE **) pvEncoded) = pbAllocEncoded;
  307. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  308. } else {
  309. cbEncoded = *pcbEncoded;
  310. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  311. Asn1Err = PkiAsn1Encode2(
  312. pEnc,
  313. pvAsn1Info,
  314. id,
  315. (BYTE *) pvEncoded,
  316. &cbEncoded
  317. );
  318. if (ASN1_SUCCESS != Asn1Err) {
  319. if (ASN1_ERR_OVERFLOW == Asn1Err)
  320. goto LengthError;
  321. else
  322. goto Asn1EncodeError;
  323. }
  324. }
  325. fResult = TRUE;
  326. CommonReturn:
  327. *pcbEncoded = cbEncoded;
  328. return fResult;
  329. ErrorReturn:
  330. fResult = FALSE;
  331. goto CommonReturn;
  332. OutOfMemory:
  333. goto ErrorReturn;
  334. LengthError:
  335. SetLastError(ERROR_MORE_DATA);
  336. goto ErrorReturn;
  337. Asn1EncodeError:
  338. SetLastError(PkiAsn1ErrToHr(Asn1Err));
  339. goto ErrorReturn;
  340. }
  341. //+-------------------------------------------------------------------------
  342. // Encode an ASN1 formatted info structure
  343. //--------------------------------------------------------------------------
  344. BOOL
  345. WINAPI
  346. PkiAsn1EncodeInfo(
  347. IN ASN1encoding_t pEnc,
  348. IN ASN1uint32_t id,
  349. IN void *pvAsn1Info,
  350. OUT OPTIONAL BYTE *pbEncoded,
  351. IN OUT DWORD *pcbEncoded
  352. )
  353. {
  354. return PkiAsn1EncodeInfoEx(
  355. pEnc,
  356. id,
  357. pvAsn1Info,
  358. 0, // dwFlags
  359. NULL, // pEncodePara
  360. pbEncoded,
  361. pcbEncoded
  362. );
  363. }
  364. //+-------------------------------------------------------------------------
  365. // Decode into an allocated, ASN1 formatted info structure
  366. //--------------------------------------------------------------------------
  367. BOOL
  368. WINAPI
  369. PkiAsn1DecodeAndAllocInfo(
  370. IN ASN1decoding_t pDec,
  371. IN ASN1uint32_t id,
  372. IN const BYTE *pbEncoded,
  373. IN DWORD cbEncoded,
  374. OUT void **ppvAsn1Info
  375. )
  376. {
  377. BOOL fResult;
  378. ASN1error_e Asn1Err;
  379. *ppvAsn1Info = NULL;
  380. if (ASN1_SUCCESS != (Asn1Err = PkiAsn1Decode(
  381. pDec,
  382. ppvAsn1Info,
  383. id,
  384. pbEncoded,
  385. cbEncoded
  386. )))
  387. goto Asn1DecodeError;
  388. fResult = TRUE;
  389. CommonReturn:
  390. return fResult;
  391. ErrorReturn:
  392. *ppvAsn1Info = NULL;
  393. fResult = FALSE;
  394. goto CommonReturn;
  395. Asn1DecodeError:
  396. SetLastError(PkiAsn1ErrToHr(Asn1Err));
  397. goto ErrorReturn;
  398. }
  399. //+-------------------------------------------------------------------------
  400. // Call the callback to convert the ASN1 structure into the 'C' structure.
  401. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  402. // structure and call the callback initially to get the length and then
  403. // a second time to update the allocated 'C' structure.
  404. //
  405. // Allocated structure is returned:
  406. // *((void **) pvStructInfo) = pvAllocStructInfo
  407. //--------------------------------------------------------------------------
  408. BOOL
  409. WINAPI
  410. PkiAsn1AllocStructInfoEx(
  411. IN void *pvAsn1Info,
  412. IN DWORD dwFlags,
  413. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  414. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  415. OUT OPTIONAL void *pvStructInfo,
  416. IN OUT DWORD *pcbStructInfo
  417. )
  418. {
  419. BOOL fResult;
  420. LONG lRemainExtra;
  421. DWORD cbStructInfo;
  422. if (NULL == pvStructInfo || (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) {
  423. cbStructInfo = 0;
  424. lRemainExtra = 0;
  425. } else {
  426. cbStructInfo = *pcbStructInfo;
  427. lRemainExtra = (LONG) cbStructInfo;
  428. }
  429. if (!pfnDecodeExCallback(
  430. pvAsn1Info,
  431. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  432. pDecodePara,
  433. pvStructInfo,
  434. &lRemainExtra
  435. )) goto DecodeCallbackError;
  436. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) {
  437. void *pv;
  438. PFN_CRYPT_ALLOC pfnAlloc = PkiGetDecodeAllocFunction(pDecodePara);
  439. assert(0 > lRemainExtra);
  440. lRemainExtra = -lRemainExtra;
  441. cbStructInfo = (DWORD) lRemainExtra;
  442. if (NULL == (pv = pfnAlloc(cbStructInfo)))
  443. goto OutOfMemory;
  444. if (!pfnDecodeExCallback(
  445. pvAsn1Info,
  446. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  447. pDecodePara,
  448. pv,
  449. &lRemainExtra
  450. )) {
  451. PFN_CRYPT_FREE pfnFree = PkiGetDecodeFreeFunction(pDecodePara);
  452. pfnFree(pv);
  453. goto DecodeCallbackError;
  454. }
  455. *((void **) pvStructInfo) = pv;
  456. assert(0 <= lRemainExtra);
  457. }
  458. if (0 <= lRemainExtra) {
  459. cbStructInfo = cbStructInfo - (DWORD) lRemainExtra;
  460. } else {
  461. cbStructInfo = cbStructInfo + (DWORD) -lRemainExtra;
  462. if (pvStructInfo) {
  463. SetLastError((DWORD) ERROR_MORE_DATA);
  464. fResult = FALSE;
  465. goto CommonReturn;
  466. }
  467. }
  468. fResult = TRUE;
  469. CommonReturn:
  470. *pcbStructInfo = cbStructInfo;
  471. return fResult;
  472. ErrorReturn:
  473. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  474. *((void **) pvStructInfo) = NULL;
  475. cbStructInfo = 0;
  476. fResult = FALSE;
  477. goto CommonReturn;
  478. DecodeCallbackError:
  479. goto ErrorReturn;
  480. OutOfMemory:
  481. goto ErrorReturn;
  482. }
  483. //+-------------------------------------------------------------------------
  484. // Decode the ASN1 formatted info structure and call the callback
  485. // function to convert the ASN1 structure to the 'C' structure.
  486. //
  487. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  488. // structure and call the callback initially to get the length and then
  489. // a second time to update the allocated 'C' structure.
  490. //
  491. // Allocated structure is returned:
  492. // *((void **) pvStructInfo) = pvAllocStructInfo
  493. //--------------------------------------------------------------------------
  494. BOOL
  495. WINAPI
  496. PkiAsn1DecodeAndAllocInfoEx(
  497. IN ASN1decoding_t pDec,
  498. IN ASN1uint32_t id,
  499. IN const BYTE *pbEncoded,
  500. IN DWORD cbEncoded,
  501. IN DWORD dwFlags,
  502. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  503. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  504. OUT OPTIONAL void *pvStructInfo,
  505. IN OUT DWORD *pcbStructInfo
  506. )
  507. {
  508. BOOL fResult;
  509. void *pvAsn1Info = NULL;
  510. if (!PkiAsn1DecodeAndAllocInfo(
  511. pDec,
  512. id,
  513. pbEncoded,
  514. cbEncoded,
  515. &pvAsn1Info
  516. )) goto Asn1DecodeError;
  517. fResult = PkiAsn1AllocStructInfoEx(
  518. pvAsn1Info,
  519. dwFlags,
  520. pDecodePara,
  521. pfnDecodeExCallback,
  522. pvStructInfo,
  523. pcbStructInfo
  524. );
  525. CommonReturn:
  526. PkiAsn1FreeInfo(pDec, id, pvAsn1Info);
  527. return fResult;
  528. ErrorReturn:
  529. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  530. *((void **) pvStructInfo) = NULL;
  531. *pcbStructInfo = 0;
  532. fResult = FALSE;
  533. goto CommonReturn;
  534. Asn1DecodeError:
  535. goto ErrorReturn;
  536. }
  537. //+-------------------------------------------------------------------------
  538. // Convert the ascii string ("1.2.9999") to ASN1's Object Identifier
  539. // represented as an array of unsigned longs.
  540. //
  541. // Returns TRUE for a successful conversion.
  542. //--------------------------------------------------------------------------
  543. BOOL
  544. WINAPI
  545. PkiAsn1ToObjectIdentifier(
  546. IN LPCSTR pszObjId,
  547. IN OUT ASN1uint16_t *pCount,
  548. OUT ASN1uint32_t rgulValue[]
  549. )
  550. {
  551. BOOL fResult = TRUE;
  552. unsigned short c = 0;
  553. LPSTR psz = (LPSTR) pszObjId;
  554. char ch;
  555. if (psz) {
  556. ASN1uint16_t cMax = *pCount;
  557. ASN1uint32_t *pul = rgulValue;
  558. while ((ch = *psz) != '\0' && c++ < cMax) {
  559. *pul++ = (ASN1uint32_t)atol(psz);
  560. while (my_isdigit(ch = *psz++))
  561. ;
  562. if (ch != '.')
  563. break;
  564. }
  565. if (ch != '\0')
  566. fResult = FALSE;
  567. }
  568. *pCount = c;
  569. return fResult;
  570. }
  571. //+-------------------------------------------------------------------------
  572. // Convert from ASN1's Object Identifier represented as an array of
  573. // unsigned longs to an ascii string ("1.2.9999").
  574. //
  575. // Returns TRUE for a successful conversion
  576. //--------------------------------------------------------------------------
  577. BOOL
  578. WINAPI
  579. PkiAsn1FromObjectIdentifier(
  580. IN ASN1uint16_t Count,
  581. IN ASN1uint32_t rgulValue[],
  582. OUT LPSTR pszObjId,
  583. IN OUT DWORD *pcbObjId
  584. )
  585. {
  586. BOOL fResult = TRUE;
  587. LONG lRemain;
  588. if (pszObjId == NULL)
  589. *pcbObjId = 0;
  590. lRemain = (LONG) *pcbObjId;
  591. if (Count == 0) {
  592. if (--lRemain > 0)
  593. pszObjId++;
  594. } else {
  595. char rgch[36];
  596. LONG lData;
  597. ASN1uint32_t *pul = rgulValue;
  598. for (; Count > 0; Count--, pul++) {
  599. _ltoa(*pul, rgch, 10);
  600. lData = strlen(rgch);
  601. lRemain -= lData + 1;
  602. if (lRemain >= 0) {
  603. if (lData > 0) {
  604. memcpy(pszObjId, rgch, lData);
  605. pszObjId += lData;
  606. }
  607. *pszObjId++ = '.';
  608. }
  609. }
  610. }
  611. if (lRemain >= 0) {
  612. *(pszObjId -1) = '\0';
  613. *pcbObjId = *pcbObjId - (DWORD) lRemain;
  614. } else {
  615. *pcbObjId = *pcbObjId + (DWORD) -lRemain;
  616. if (pszObjId) {
  617. SetLastError((DWORD) ERROR_MORE_DATA);
  618. fResult = FALSE;
  619. }
  620. }
  621. return fResult;
  622. }