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.

694 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. if (0 == cbIn)
  256. return;
  257. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  258. bTmp = *pbHi;
  259. *pbHi = *pbLo;
  260. *pbLo = bTmp;
  261. }
  262. }
  263. //+-------------------------------------------------------------------------
  264. // Encode an ASN1 formatted info structure.
  265. //
  266. // If CRYPT_ENCODE_ALLOC_FLAG is set, allocate memory for pbEncoded and
  267. // return *((BYTE **) pvEncoded) = pbAllocEncoded. Otherwise,
  268. // pvEncoded points to byte array to be updated.
  269. //--------------------------------------------------------------------------
  270. BOOL
  271. WINAPI
  272. PkiAsn1EncodeInfoEx(
  273. IN ASN1encoding_t pEnc,
  274. IN ASN1uint32_t id,
  275. IN void *pvAsn1Info,
  276. IN DWORD dwFlags,
  277. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  278. OUT OPTIONAL void *pvEncoded,
  279. IN OUT DWORD *pcbEncoded
  280. )
  281. {
  282. BOOL fResult;
  283. ASN1error_e Asn1Err;
  284. DWORD cbEncoded;
  285. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  286. BYTE *pbEncoded;
  287. BYTE *pbAllocEncoded;
  288. PFN_CRYPT_ALLOC pfnAlloc;
  289. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  290. Asn1Err = PkiAsn1Encode(
  291. pEnc,
  292. pvAsn1Info,
  293. id,
  294. &pbEncoded,
  295. &cbEncoded
  296. );
  297. if (ASN1_SUCCESS != Asn1Err) {
  298. *((void **) pvEncoded) = NULL;
  299. goto Asn1EncodeError;
  300. }
  301. pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
  302. if (NULL == (pbAllocEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
  303. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  304. *((void **) pvEncoded) = NULL;
  305. goto OutOfMemory;
  306. }
  307. memcpy(pbAllocEncoded, pbEncoded, cbEncoded);
  308. *((BYTE **) pvEncoded) = pbAllocEncoded;
  309. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  310. } else {
  311. cbEncoded = *pcbEncoded;
  312. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  313. Asn1Err = PkiAsn1Encode2(
  314. pEnc,
  315. pvAsn1Info,
  316. id,
  317. (BYTE *) pvEncoded,
  318. &cbEncoded
  319. );
  320. if (ASN1_SUCCESS != Asn1Err) {
  321. if (ASN1_ERR_OVERFLOW == Asn1Err)
  322. goto LengthError;
  323. else
  324. goto Asn1EncodeError;
  325. }
  326. }
  327. fResult = TRUE;
  328. CommonReturn:
  329. *pcbEncoded = cbEncoded;
  330. return fResult;
  331. ErrorReturn:
  332. fResult = FALSE;
  333. goto CommonReturn;
  334. OutOfMemory:
  335. goto ErrorReturn;
  336. LengthError:
  337. SetLastError(ERROR_MORE_DATA);
  338. goto ErrorReturn;
  339. Asn1EncodeError:
  340. SetLastError(PkiAsn1ErrToHr(Asn1Err));
  341. goto ErrorReturn;
  342. }
  343. //+-------------------------------------------------------------------------
  344. // Encode an ASN1 formatted info structure
  345. //--------------------------------------------------------------------------
  346. BOOL
  347. WINAPI
  348. PkiAsn1EncodeInfo(
  349. IN ASN1encoding_t pEnc,
  350. IN ASN1uint32_t id,
  351. IN void *pvAsn1Info,
  352. OUT OPTIONAL BYTE *pbEncoded,
  353. IN OUT DWORD *pcbEncoded
  354. )
  355. {
  356. return PkiAsn1EncodeInfoEx(
  357. pEnc,
  358. id,
  359. pvAsn1Info,
  360. 0, // dwFlags
  361. NULL, // pEncodePara
  362. pbEncoded,
  363. pcbEncoded
  364. );
  365. }
  366. //+-------------------------------------------------------------------------
  367. // Decode into an allocated, ASN1 formatted info structure
  368. //--------------------------------------------------------------------------
  369. BOOL
  370. WINAPI
  371. PkiAsn1DecodeAndAllocInfo(
  372. IN ASN1decoding_t pDec,
  373. IN ASN1uint32_t id,
  374. IN const BYTE *pbEncoded,
  375. IN DWORD cbEncoded,
  376. OUT void **ppvAsn1Info
  377. )
  378. {
  379. BOOL fResult;
  380. ASN1error_e Asn1Err;
  381. *ppvAsn1Info = NULL;
  382. if (ASN1_SUCCESS != (Asn1Err = PkiAsn1Decode(
  383. pDec,
  384. ppvAsn1Info,
  385. id,
  386. pbEncoded,
  387. cbEncoded
  388. )))
  389. goto Asn1DecodeError;
  390. fResult = TRUE;
  391. CommonReturn:
  392. return fResult;
  393. ErrorReturn:
  394. *ppvAsn1Info = NULL;
  395. fResult = FALSE;
  396. goto CommonReturn;
  397. Asn1DecodeError:
  398. SetLastError(PkiAsn1ErrToHr(Asn1Err));
  399. goto ErrorReturn;
  400. }
  401. //+-------------------------------------------------------------------------
  402. // Call the callback to convert the ASN1 structure into the 'C' structure.
  403. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  404. // structure and call the callback initially to get the length and then
  405. // a second time to update the allocated 'C' structure.
  406. //
  407. // Allocated structure is returned:
  408. // *((void **) pvStructInfo) = pvAllocStructInfo
  409. //--------------------------------------------------------------------------
  410. BOOL
  411. WINAPI
  412. PkiAsn1AllocStructInfoEx(
  413. IN void *pvAsn1Info,
  414. IN DWORD dwFlags,
  415. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  416. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  417. OUT OPTIONAL void *pvStructInfo,
  418. IN OUT DWORD *pcbStructInfo
  419. )
  420. {
  421. BOOL fResult;
  422. LONG lRemainExtra;
  423. DWORD cbStructInfo;
  424. if (NULL == pvStructInfo || (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) {
  425. cbStructInfo = 0;
  426. lRemainExtra = 0;
  427. } else {
  428. cbStructInfo = *pcbStructInfo;
  429. lRemainExtra = (LONG) cbStructInfo;
  430. }
  431. if (!pfnDecodeExCallback(
  432. pvAsn1Info,
  433. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  434. pDecodePara,
  435. pvStructInfo,
  436. &lRemainExtra
  437. )) goto DecodeCallbackError;
  438. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) {
  439. void *pv;
  440. PFN_CRYPT_ALLOC pfnAlloc = PkiGetDecodeAllocFunction(pDecodePara);
  441. assert(0 > lRemainExtra);
  442. lRemainExtra = -lRemainExtra;
  443. cbStructInfo = (DWORD) lRemainExtra;
  444. if (NULL == (pv = pfnAlloc(cbStructInfo)))
  445. goto OutOfMemory;
  446. if (!pfnDecodeExCallback(
  447. pvAsn1Info,
  448. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  449. pDecodePara,
  450. pv,
  451. &lRemainExtra
  452. )) {
  453. PFN_CRYPT_FREE pfnFree = PkiGetDecodeFreeFunction(pDecodePara);
  454. pfnFree(pv);
  455. goto DecodeCallbackError;
  456. }
  457. *((void **) pvStructInfo) = pv;
  458. assert(0 <= lRemainExtra);
  459. }
  460. if (0 <= lRemainExtra) {
  461. cbStructInfo = cbStructInfo - (DWORD) lRemainExtra;
  462. } else {
  463. cbStructInfo = cbStructInfo + (DWORD) -lRemainExtra;
  464. if (pvStructInfo) {
  465. SetLastError((DWORD) ERROR_MORE_DATA);
  466. fResult = FALSE;
  467. goto CommonReturn;
  468. }
  469. }
  470. fResult = TRUE;
  471. CommonReturn:
  472. *pcbStructInfo = cbStructInfo;
  473. return fResult;
  474. ErrorReturn:
  475. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  476. *((void **) pvStructInfo) = NULL;
  477. cbStructInfo = 0;
  478. fResult = FALSE;
  479. goto CommonReturn;
  480. DecodeCallbackError:
  481. goto ErrorReturn;
  482. OutOfMemory:
  483. goto ErrorReturn;
  484. }
  485. //+-------------------------------------------------------------------------
  486. // Decode the ASN1 formatted info structure and call the callback
  487. // function to convert the ASN1 structure to the 'C' structure.
  488. //
  489. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  490. // structure and call the callback initially to get the length and then
  491. // a second time to update the allocated 'C' structure.
  492. //
  493. // Allocated structure is returned:
  494. // *((void **) pvStructInfo) = pvAllocStructInfo
  495. //--------------------------------------------------------------------------
  496. BOOL
  497. WINAPI
  498. PkiAsn1DecodeAndAllocInfoEx(
  499. IN ASN1decoding_t pDec,
  500. IN ASN1uint32_t id,
  501. IN const BYTE *pbEncoded,
  502. IN DWORD cbEncoded,
  503. IN DWORD dwFlags,
  504. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  505. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  506. OUT OPTIONAL void *pvStructInfo,
  507. IN OUT DWORD *pcbStructInfo
  508. )
  509. {
  510. BOOL fResult;
  511. void *pvAsn1Info = NULL;
  512. if (!PkiAsn1DecodeAndAllocInfo(
  513. pDec,
  514. id,
  515. pbEncoded,
  516. cbEncoded,
  517. &pvAsn1Info
  518. )) goto Asn1DecodeError;
  519. fResult = PkiAsn1AllocStructInfoEx(
  520. pvAsn1Info,
  521. dwFlags,
  522. pDecodePara,
  523. pfnDecodeExCallback,
  524. pvStructInfo,
  525. pcbStructInfo
  526. );
  527. CommonReturn:
  528. PkiAsn1FreeInfo(pDec, id, pvAsn1Info);
  529. return fResult;
  530. ErrorReturn:
  531. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  532. *((void **) pvStructInfo) = NULL;
  533. *pcbStructInfo = 0;
  534. fResult = FALSE;
  535. goto CommonReturn;
  536. Asn1DecodeError:
  537. goto ErrorReturn;
  538. }
  539. //+-------------------------------------------------------------------------
  540. // Convert the ascii string ("1.2.9999") to ASN1's Object Identifier
  541. // represented as an array of unsigned longs.
  542. //
  543. // Returns TRUE for a successful conversion.
  544. //--------------------------------------------------------------------------
  545. BOOL
  546. WINAPI
  547. PkiAsn1ToObjectIdentifier(
  548. IN LPCSTR pszObjId,
  549. IN OUT ASN1uint16_t *pCount,
  550. OUT ASN1uint32_t rgulValue[]
  551. )
  552. {
  553. BOOL fResult = TRUE;
  554. unsigned short c = 0;
  555. LPSTR psz = (LPSTR) pszObjId;
  556. char ch;
  557. if (psz) {
  558. ASN1uint16_t cMax = *pCount;
  559. ASN1uint32_t *pul = rgulValue;
  560. while ((ch = *psz) != '\0' && c++ < cMax) {
  561. *pul++ = (ASN1uint32_t)atol(psz);
  562. while (my_isdigit(ch = *psz++))
  563. ;
  564. if (ch != '.')
  565. break;
  566. }
  567. if (ch != '\0')
  568. fResult = FALSE;
  569. }
  570. *pCount = c;
  571. return fResult;
  572. }
  573. //+-------------------------------------------------------------------------
  574. // Convert from ASN1's Object Identifier represented as an array of
  575. // unsigned longs to an ascii string ("1.2.9999").
  576. //
  577. // Returns TRUE for a successful conversion
  578. //--------------------------------------------------------------------------
  579. BOOL
  580. WINAPI
  581. PkiAsn1FromObjectIdentifier(
  582. IN ASN1uint16_t Count,
  583. IN ASN1uint32_t rgulValue[],
  584. OUT LPSTR pszObjId,
  585. IN OUT DWORD *pcbObjId
  586. )
  587. {
  588. BOOL fResult = TRUE;
  589. LONG lRemain;
  590. if (pszObjId == NULL)
  591. *pcbObjId = 0;
  592. lRemain = (LONG) *pcbObjId;
  593. if (Count == 0) {
  594. if (--lRemain > 0)
  595. pszObjId++;
  596. } else {
  597. char rgch[36];
  598. LONG lData;
  599. ASN1uint32_t *pul = rgulValue;
  600. for (; Count > 0; Count--, pul++) {
  601. _ltoa(*pul, rgch, 10);
  602. lData = strlen(rgch);
  603. lRemain -= lData + 1;
  604. if (lRemain >= 0) {
  605. if (lData > 0) {
  606. memcpy(pszObjId, rgch, lData);
  607. pszObjId += lData;
  608. }
  609. *pszObjId++ = '.';
  610. }
  611. }
  612. }
  613. if (lRemain >= 0) {
  614. *(pszObjId -1) = '\0';
  615. *pcbObjId = *pcbObjId - (DWORD) lRemain;
  616. } else {
  617. *pcbObjId = *pcbObjId + (DWORD) -lRemain;
  618. if (pszObjId) {
  619. SetLastError((DWORD) ERROR_MORE_DATA);
  620. fResult = FALSE;
  621. }
  622. }
  623. return fResult;
  624. }