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.

966 lines
27 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995 - 1999
  5. //
  6. // File: ossutil.cpp
  7. //
  8. // Contents: OSS ASN.1 compiler utility helper functions.
  9. //
  10. // Functions: OssUtilReverseBytes
  11. // OssUtilAllocAndReverseBytes
  12. // OssUtilGetOctetString
  13. // OssUtilSetHugeInteger
  14. // OssUtilFreeHugeInteger
  15. // OssUtilGetHugeInteger
  16. // OssUtilSetHugeUINT
  17. // OssUtilGetHugeUINT
  18. // OssUtilSetBitString
  19. // OssUtilGetBitString
  20. // OssUtilSetBitStringWithoutTrailingZeroes
  21. // OssUtilGetIA5String
  22. // OssUtilSetUnicodeConvertedToIA5String
  23. // OssUtilFreeUnicodeConvertedToIA5String
  24. // OssUtilGetIA5StringConvertedToUnicode
  25. // OssUtilGetBMPString
  26. // OssUtilSetAny
  27. // OssUtilGetAny
  28. // OssUtilEncodeInfoEx
  29. // OssUtilEncodeInfo
  30. // OssUtilDecodeAndAllocInfo
  31. // OssUtilFreeInfo
  32. // OssUtilAllocStructInfoEx
  33. // OssUtilDecodeAndAllocInfoEx
  34. //
  35. // The Get functions decrement *plRemainExtra and advance
  36. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  37. // with the length calculation but stop doing any copies.
  38. // The functions don't return an error for a negative *plRemainExtra.
  39. //
  40. // History: 17-Nov-96 philh created
  41. //--------------------------------------------------------------------------
  42. #include "global.hxx"
  43. #include <dbgdef.h>
  44. // All the *pvInfo extra stuff needs to be aligned
  45. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  46. //+-------------------------------------------------------------------------
  47. // Reverses a buffer of bytes in place
  48. //--------------------------------------------------------------------------
  49. void
  50. WINAPI
  51. OssUtilReverseBytes(
  52. IN OUT PBYTE pbIn,
  53. IN DWORD cbIn
  54. )
  55. {
  56. // reverse in place
  57. PBYTE pbLo;
  58. PBYTE pbHi;
  59. BYTE bTmp;
  60. if (0 == cbIn)
  61. return;
  62. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  63. bTmp = *pbHi;
  64. *pbHi = *pbLo;
  65. *pbLo = bTmp;
  66. }
  67. }
  68. //+-------------------------------------------------------------------------
  69. // Reverses a buffer of bytes to a new buffer. OssUtilFree() must be
  70. // called to free allocated bytes.
  71. //--------------------------------------------------------------------------
  72. PBYTE
  73. WINAPI
  74. OssUtilAllocAndReverseBytes(
  75. IN PBYTE pbIn,
  76. IN DWORD cbIn
  77. )
  78. {
  79. PBYTE pbOut;
  80. PBYTE pbSrc;
  81. PBYTE pbDst;
  82. DWORD cb;
  83. if (NULL == (pbOut = (PBYTE)OssUtilAlloc(cbIn)))
  84. return NULL;
  85. for (pbSrc = pbIn, pbDst = pbOut + cbIn - 1, cb = cbIn; cb > 0; cb--)
  86. *pbDst-- = *pbSrc++;
  87. return pbOut;
  88. }
  89. //+-------------------------------------------------------------------------
  90. // Get Octet String
  91. //--------------------------------------------------------------------------
  92. void
  93. WINAPI
  94. OssUtilGetOctetString(
  95. IN unsigned int OssLength,
  96. IN unsigned char *OssValue,
  97. IN DWORD dwFlags,
  98. OUT PCRYPT_DATA_BLOB pInfo,
  99. IN OUT BYTE **ppbExtra,
  100. IN OUT LONG *plRemainExtra
  101. )
  102. {
  103. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
  104. if (*plRemainExtra >= 0) {
  105. pInfo->cbData = OssLength;
  106. pInfo->pbData = OssValue;
  107. }
  108. } else {
  109. LONG lRemainExtra = *plRemainExtra;
  110. BYTE *pbExtra = *ppbExtra;
  111. LONG lAlignExtra;
  112. LONG lData;
  113. lData = (LONG) OssLength;
  114. lAlignExtra = INFO_LEN_ALIGN(lData);
  115. lRemainExtra -= lAlignExtra;
  116. if (lRemainExtra >= 0) {
  117. if (lData > 0) {
  118. pInfo->pbData = pbExtra;
  119. pInfo->cbData = (DWORD) lData;
  120. memcpy(pbExtra, OssValue, lData);
  121. } else
  122. memset(pInfo, 0, sizeof(*pInfo));
  123. pbExtra += lAlignExtra;
  124. }
  125. *plRemainExtra = lRemainExtra;
  126. *ppbExtra = pbExtra;
  127. }
  128. }
  129. //+-------------------------------------------------------------------------
  130. // Set/Free/Get HugeInteger
  131. //
  132. // BYTE reversal::
  133. // - this only needs to be done for little endian processors
  134. //
  135. // For OssUtilSetInteger, OssUtilFreeInteger must be called to free
  136. // the allocated OssValue.
  137. //--------------------------------------------------------------------------
  138. BOOL
  139. WINAPI
  140. OssUtilSetHugeInteger(
  141. IN PCRYPT_INTEGER_BLOB pInfo,
  142. OUT unsigned int *pOssLength,
  143. OUT unsigned char **ppOssValue
  144. )
  145. {
  146. if (pInfo->cbData > 0) {
  147. if (NULL == (*ppOssValue = OssUtilAllocAndReverseBytes(
  148. pInfo->pbData, pInfo->cbData))) {
  149. *pOssLength = 0;
  150. return FALSE;
  151. }
  152. } else
  153. *ppOssValue = NULL;
  154. *pOssLength = pInfo->cbData;
  155. return TRUE;
  156. }
  157. void
  158. WINAPI
  159. OssUtilFreeHugeInteger(
  160. IN unsigned char *pOssValue
  161. )
  162. {
  163. // Only for BYTE reversal
  164. OssUtilFree(pOssValue);
  165. }
  166. void
  167. WINAPI
  168. OssUtilGetHugeInteger(
  169. IN unsigned int OssLength,
  170. IN unsigned char *pOssValue,
  171. IN DWORD dwFlags,
  172. OUT PCRYPT_INTEGER_BLOB pInfo,
  173. IN OUT BYTE **ppbExtra,
  174. IN OUT LONG *plRemainExtra
  175. )
  176. {
  177. // Since bytes need to be reversed, always need to do a copy (dwFlags = 0)
  178. OssUtilGetOctetString(OssLength, pOssValue, 0,
  179. pInfo, ppbExtra, plRemainExtra);
  180. if (*plRemainExtra >= 0 && pInfo->cbData > 0)
  181. OssUtilReverseBytes(pInfo->pbData, pInfo->cbData);
  182. }
  183. //+-------------------------------------------------------------------------
  184. // Set/Free/Get Huge Unsigned Integer
  185. //
  186. // Set inserts a leading 0x00 before reversing. Note, any extra leading
  187. // 0x00's are removed by OSS before ASN.1 encoding.
  188. //
  189. // Get removes a leading 0x00 if present, after reversing.
  190. //
  191. // OssUtilFreeHugeUINT must be called to free the allocated OssValue.
  192. // OssUtilFreeHugeUINT has been #define'd to OssUtilFreeHugeInteger.
  193. //--------------------------------------------------------------------------
  194. BOOL
  195. WINAPI
  196. OssUtilSetHugeUINT(
  197. IN PCRYPT_UINT_BLOB pInfo,
  198. OUT unsigned int *pOssLength,
  199. OUT unsigned char **ppOssValue
  200. )
  201. {
  202. BOOL fResult;
  203. DWORD cb = pInfo->cbData;
  204. BYTE *pb;
  205. DWORD i;
  206. if (cb > 0) {
  207. if (NULL == (pb = (BYTE *) OssUtilAlloc(cb + 1)))
  208. goto ErrorReturn;
  209. *pb = 0x00;
  210. for (i = 0; i < cb; i++)
  211. pb[1 + i] = pInfo->pbData[cb - 1 - i];
  212. cb++;
  213. } else
  214. pb = NULL;
  215. fResult = TRUE;
  216. CommonReturn:
  217. *pOssLength = cb;
  218. *ppOssValue = pb;
  219. return fResult;
  220. ErrorReturn:
  221. cb = 0;
  222. fResult = FALSE;
  223. goto CommonReturn;
  224. }
  225. void
  226. WINAPI
  227. OssUtilGetHugeUINT(
  228. IN unsigned int OssLength,
  229. IN unsigned char *pOssValue,
  230. IN DWORD dwFlags,
  231. OUT PCRYPT_UINT_BLOB pInfo,
  232. IN OUT BYTE **ppbExtra,
  233. IN OUT LONG *plRemainExtra
  234. )
  235. {
  236. // Check for and advance past a leading 0x00.
  237. if (OssLength > 1 && *pOssValue == 0) {
  238. pOssValue++;
  239. OssLength--;
  240. }
  241. OssUtilGetHugeInteger(
  242. OssLength,
  243. pOssValue,
  244. dwFlags,
  245. pInfo,
  246. ppbExtra,
  247. plRemainExtra
  248. );
  249. }
  250. //+-------------------------------------------------------------------------
  251. // Set/Get BitString
  252. //--------------------------------------------------------------------------
  253. void
  254. WINAPI
  255. OssUtilSetBitString(
  256. IN PCRYPT_BIT_BLOB pInfo,
  257. OUT unsigned int *pOssBitLength,
  258. OUT unsigned char **ppOssValue
  259. )
  260. {
  261. if (pInfo->cbData) {
  262. *ppOssValue = pInfo->pbData;
  263. assert(pInfo->cUnusedBits <= 7);
  264. *pOssBitLength = pInfo->cbData * 8 - pInfo->cUnusedBits;
  265. } else {
  266. *ppOssValue = NULL;
  267. *pOssBitLength = 0;
  268. }
  269. }
  270. static const BYTE rgbUnusedAndMask[8] =
  271. {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
  272. void
  273. WINAPI
  274. OssUtilGetBitString(
  275. IN unsigned int OssBitLength,
  276. IN unsigned char *pOssValue,
  277. IN DWORD dwFlags,
  278. OUT PCRYPT_BIT_BLOB pInfo,
  279. IN OUT BYTE **ppbExtra,
  280. IN OUT LONG *plRemainExtra
  281. )
  282. {
  283. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG && 0 == (OssBitLength % 8)) {
  284. if (*plRemainExtra >= 0) {
  285. pInfo->cbData = OssBitLength / 8;
  286. pInfo->cUnusedBits = 0;
  287. pInfo->pbData = pOssValue;
  288. }
  289. } else {
  290. LONG lRemainExtra = *plRemainExtra;
  291. BYTE *pbExtra = *ppbExtra;
  292. LONG lAlignExtra;
  293. LONG lData;
  294. DWORD cUnusedBits;
  295. lData = (LONG) OssBitLength / 8;
  296. cUnusedBits = OssBitLength % 8;
  297. if (cUnusedBits) {
  298. cUnusedBits = 8 - cUnusedBits;
  299. lData++;
  300. }
  301. lAlignExtra = INFO_LEN_ALIGN(lData);
  302. lRemainExtra -= lAlignExtra;
  303. if (lRemainExtra >= 0) {
  304. if (lData > 0) {
  305. pInfo->pbData = pbExtra;
  306. pInfo->cbData = (DWORD) lData;
  307. pInfo->cUnusedBits = cUnusedBits;
  308. memcpy(pbExtra, pOssValue, lData);
  309. if (cUnusedBits)
  310. *(pbExtra + lData - 1) &= rgbUnusedAndMask[cUnusedBits];
  311. } else
  312. memset(pInfo, 0, sizeof(*pInfo));
  313. pbExtra += lAlignExtra;
  314. }
  315. *plRemainExtra = lRemainExtra;
  316. *ppbExtra = pbExtra;
  317. }
  318. }
  319. //+-------------------------------------------------------------------------
  320. // Set BitString Without Trailing Zeroes
  321. //--------------------------------------------------------------------------
  322. void
  323. WINAPI
  324. OssUtilSetBitStringWithoutTrailingZeroes(
  325. IN PCRYPT_BIT_BLOB pInfo,
  326. OUT unsigned int *pOssBitLength,
  327. OUT unsigned char **ppOssValue
  328. )
  329. {
  330. DWORD cbData;
  331. DWORD cUnusedBits;
  332. cbData = pInfo->cbData;
  333. cUnusedBits = pInfo->cUnusedBits;
  334. assert(cUnusedBits <= 7);
  335. if (cbData) {
  336. BYTE *pb;
  337. // Until we find a nonzero byte (starting with the last byte),
  338. // decrement cbData. For the last byte don't look at any unused bits.
  339. pb = pInfo->pbData + cbData - 1;
  340. if (0 == (*pb & rgbUnusedAndMask[cUnusedBits])) {
  341. cUnusedBits = 0;
  342. cbData--;
  343. pb--;
  344. for ( ; 0 < cbData && 0 == *pb; cbData--, pb--)
  345. ;
  346. }
  347. }
  348. if (cbData) {
  349. BYTE b;
  350. // Determine the number of unused bits in the last byte. Treat any
  351. // trailing zeroes as unused.
  352. b = *(pInfo->pbData + cbData - 1);
  353. assert(b);
  354. if (cUnusedBits)
  355. b = b >> cUnusedBits;
  356. for (; 7 > cUnusedBits && 0 == (b & 0x01); cUnusedBits++) {
  357. b = b >> 1;
  358. }
  359. assert(b & 0x01);
  360. assert(cUnusedBits <= 7);
  361. *ppOssValue = pInfo->pbData;
  362. *pOssBitLength = cbData * 8 - cUnusedBits;
  363. } else {
  364. *ppOssValue = NULL;
  365. *pOssBitLength = 0;
  366. }
  367. }
  368. //+-------------------------------------------------------------------------
  369. // Get IA5 String
  370. //--------------------------------------------------------------------------
  371. void
  372. WINAPI
  373. OssUtilGetIA5String(
  374. IN unsigned int OssLength,
  375. IN char *pOssValue,
  376. IN DWORD dwFlags,
  377. OUT LPSTR *ppsz,
  378. IN OUT BYTE **ppbExtra,
  379. IN OUT LONG *plRemainExtra
  380. )
  381. {
  382. LONG lRemainExtra = *plRemainExtra;
  383. BYTE *pbExtra = *ppbExtra;
  384. LONG lAlignExtra;
  385. LONG lData;
  386. lData = (LONG) OssLength;
  387. lAlignExtra = INFO_LEN_ALIGN(lData + 1);
  388. lRemainExtra -= lAlignExtra;
  389. if (lRemainExtra >= 0) {
  390. if (lData > 0)
  391. memcpy(pbExtra, pOssValue, lData);
  392. *(pbExtra + lData) = 0;
  393. *ppsz = (LPSTR) pbExtra;
  394. pbExtra += lAlignExtra;
  395. }
  396. *plRemainExtra = lRemainExtra;
  397. *ppbExtra = pbExtra;
  398. }
  399. //+-------------------------------------------------------------------------
  400. // Set/Free/Get Unicode mapped to IA5 String
  401. //--------------------------------------------------------------------------
  402. BOOL
  403. WINAPI
  404. OssUtilSetUnicodeConvertedToIA5String(
  405. IN LPWSTR pwsz,
  406. OUT unsigned int *pOssLength,
  407. OUT char **ppOssValue
  408. )
  409. {
  410. BOOL fResult;
  411. LPSTR psz = NULL;
  412. int cchUTF8;
  413. int cchWideChar;
  414. int i;
  415. cchWideChar = wcslen(pwsz);
  416. if (cchWideChar == 0) {
  417. *pOssLength = 0;
  418. *ppOssValue = 0;
  419. return TRUE;
  420. }
  421. // Check that the input string contains valid IA5 characters
  422. for (i = 0; i < cchWideChar; i++) {
  423. if (pwsz[i] > 0x7F) {
  424. SetLastError((DWORD) CRYPT_E_INVALID_IA5_STRING);
  425. *pOssLength = (unsigned int) i;
  426. goto InvalidIA5;
  427. }
  428. }
  429. cchUTF8 = WideCharToUTF8(
  430. pwsz,
  431. cchWideChar,
  432. NULL, // lpUTF8Str
  433. 0 // cchUTF8
  434. );
  435. if (cchUTF8 <= 0)
  436. goto ErrorReturn;
  437. if (NULL == (psz = (LPSTR) OssUtilAlloc(cchUTF8)))
  438. goto ErrorReturn;
  439. cchUTF8 = WideCharToUTF8(
  440. pwsz,
  441. cchWideChar,
  442. psz,
  443. cchUTF8
  444. );
  445. *ppOssValue = psz;
  446. *pOssLength = cchUTF8;
  447. fResult = TRUE;
  448. goto CommonReturn;
  449. ErrorReturn:
  450. *pOssLength = 0;
  451. InvalidIA5:
  452. *ppOssValue = NULL;
  453. fResult = FALSE;
  454. CommonReturn:
  455. return fResult;
  456. }
  457. void
  458. WINAPI
  459. OssUtilFreeUnicodeConvertedToIA5String(
  460. IN char *pOssValue
  461. )
  462. {
  463. OssUtilFree(pOssValue);
  464. }
  465. void
  466. WINAPI
  467. OssUtilGetIA5StringConvertedToUnicode(
  468. IN unsigned int OssLength,
  469. IN char *pOssValue,
  470. IN DWORD dwFlags,
  471. OUT LPWSTR *ppwsz,
  472. IN OUT BYTE **ppbExtra,
  473. IN OUT LONG *plRemainExtra
  474. )
  475. {
  476. LONG lRemainExtra = *plRemainExtra;
  477. BYTE *pbExtra = *ppbExtra;
  478. LONG lAlignExtra;
  479. LONG lData;
  480. int cchWideChar;
  481. cchWideChar = UTF8ToWideChar(
  482. (LPSTR) pOssValue,
  483. OssLength,
  484. NULL, // lpWideCharStr
  485. 0 // cchWideChar
  486. );
  487. if (cchWideChar > 0)
  488. lData = cchWideChar * sizeof(WCHAR);
  489. else
  490. lData = 0;
  491. lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
  492. lRemainExtra -= lAlignExtra;
  493. if (lRemainExtra >= 0) {
  494. if (lData > 0)
  495. UTF8ToWideChar(pOssValue, OssLength,
  496. (LPWSTR) pbExtra, cchWideChar);
  497. memset(pbExtra + lData, 0, sizeof(WCHAR));
  498. *ppwsz = (LPWSTR) pbExtra;
  499. pbExtra += lAlignExtra;
  500. }
  501. *plRemainExtra = lRemainExtra;
  502. *ppbExtra = pbExtra;
  503. }
  504. //+-------------------------------------------------------------------------
  505. // Get BMP String
  506. //--------------------------------------------------------------------------
  507. void
  508. WINAPI
  509. OssUtilGetBMPString(
  510. IN unsigned int OssLength,
  511. IN unsigned short *pOssValue,
  512. IN DWORD dwFlags,
  513. OUT LPWSTR *ppwsz,
  514. IN OUT BYTE **ppbExtra,
  515. IN OUT LONG *plRemainExtra
  516. )
  517. {
  518. LONG lRemainExtra = *plRemainExtra;
  519. BYTE *pbExtra = *ppbExtra;
  520. LONG lAlignExtra;
  521. LONG lData;
  522. lData = (LONG) OssLength * sizeof(WCHAR);
  523. lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
  524. lRemainExtra -= lAlignExtra;
  525. if (lRemainExtra >= 0) {
  526. if (lData > 0)
  527. memcpy(pbExtra, pOssValue, lData);
  528. memset(pbExtra + lData, 0, sizeof(WCHAR));
  529. *ppwsz = (LPWSTR) pbExtra;
  530. pbExtra += lAlignExtra;
  531. }
  532. *plRemainExtra = lRemainExtra;
  533. *ppbExtra = pbExtra;
  534. }
  535. //+-------------------------------------------------------------------------
  536. // Set/Get "Any" DER BLOB
  537. //--------------------------------------------------------------------------
  538. void
  539. WINAPI
  540. OssUtilSetAny(
  541. IN PCRYPT_OBJID_BLOB pInfo,
  542. OUT OpenType *pOss
  543. )
  544. {
  545. memset(pOss, 0, sizeof(*pOss));
  546. pOss->encoded = pInfo->pbData;
  547. pOss->length = pInfo->cbData;
  548. }
  549. void
  550. WINAPI
  551. OssUtilGetAny(
  552. IN OpenType *pOss,
  553. IN DWORD dwFlags,
  554. OUT PCRYPT_OBJID_BLOB pInfo,
  555. IN OUT BYTE **ppbExtra,
  556. IN OUT LONG *plRemainExtra
  557. )
  558. {
  559. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
  560. if (*plRemainExtra >= 0) {
  561. pInfo->cbData = pOss->length;
  562. pInfo->pbData = (BYTE *) pOss->encoded;
  563. }
  564. } else {
  565. LONG lRemainExtra = *plRemainExtra;
  566. BYTE *pbExtra = *ppbExtra;
  567. LONG lAlignExtra;
  568. LONG lData;
  569. lData = (LONG) pOss->length;
  570. lAlignExtra = INFO_LEN_ALIGN(lData);
  571. lRemainExtra -= lAlignExtra;
  572. if (lRemainExtra >= 0) {
  573. if (lData > 0) {
  574. pInfo->pbData = pbExtra;
  575. pInfo->cbData = (DWORD) lData;
  576. memcpy(pbExtra, pOss->encoded, lData);
  577. } else
  578. memset(pInfo, 0, sizeof(*pInfo));
  579. pbExtra += lAlignExtra;
  580. }
  581. *plRemainExtra = lRemainExtra;
  582. *ppbExtra = pbExtra;
  583. }
  584. }
  585. //+-------------------------------------------------------------------------
  586. // Encode an OSS formatted info structure.
  587. //
  588. // If CRYPT_ENCODE_ALLOC_FLAG is set, allocate memory for pbEncoded and
  589. // return *((BYTE **) pvEncoded) = pbAllocEncoded. Otherwise,
  590. // pvEncoded points to byte array to be updated.
  591. //--------------------------------------------------------------------------
  592. BOOL
  593. WINAPI
  594. OssUtilEncodeInfoEx(
  595. IN OssGlobal *Pog,
  596. IN int pdunum,
  597. IN void *pvOssInfo,
  598. IN DWORD dwFlags,
  599. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  600. OUT OPTIONAL void *pvEncoded,
  601. IN OUT DWORD *pcbEncoded
  602. )
  603. {
  604. BOOL fResult;
  605. DWORD cbEncoded;
  606. OssBuf OssEncoded;
  607. int OssStatus;
  608. unsigned char *value;
  609. if (NULL == pvEncoded || (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
  610. cbEncoded = 0;
  611. else
  612. cbEncoded = *pcbEncoded;
  613. OssEncoded.length = cbEncoded;
  614. if (cbEncoded == 0)
  615. value = NULL;
  616. else
  617. value = (unsigned char *) pvEncoded;
  618. OssEncoded.value = value;
  619. ossSetEncodingRules(Pog, OSS_DER);
  620. OssStatus = ossEncode(
  621. Pog,
  622. pdunum,
  623. pvOssInfo,
  624. &OssEncoded);
  625. cbEncoded = OssEncoded.length;
  626. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  627. PFN_CRYPT_ALLOC pfnAlloc;
  628. BYTE *pbEncoded;
  629. if (0 != OssStatus || 0 == cbEncoded) {
  630. ossFreeBuf(Pog, OssEncoded.value);
  631. *((void **) pvEncoded) = NULL;
  632. goto OssError;
  633. }
  634. pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
  635. if (NULL == (pbEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
  636. ossFreeBuf(Pog, OssEncoded.value);
  637. *((void **) pvEncoded) = NULL;
  638. goto OutOfMemory;
  639. }
  640. memcpy(pbEncoded, OssEncoded.value, cbEncoded);
  641. *((BYTE **) pvEncoded) = pbEncoded;
  642. ossFreeBuf(Pog, OssEncoded.value);
  643. goto SuccessReturn;
  644. } else if (value == NULL && OssEncoded.value) {
  645. // Length only calculation with a throw away allocation
  646. ossFreeBuf(Pog, OssEncoded.value);
  647. if (pvEncoded && 0 == OssStatus) {
  648. // Upon entry *pcbEncoded == 0
  649. goto LengthError;
  650. }
  651. }
  652. if (0 != OssStatus) {
  653. // For MORE_BUF:: redo as a length only calculation
  654. if (OssStatus == MORE_BUF && pvEncoded &&
  655. OssUtilEncodeInfoEx(
  656. Pog,
  657. pdunum,
  658. pvOssInfo,
  659. 0, // dwFlags
  660. NULL, // pEncodePara
  661. NULL, // pbEncoded
  662. &cbEncoded))
  663. goto LengthError;
  664. else {
  665. cbEncoded = 0;
  666. goto OssError;
  667. }
  668. }
  669. SuccessReturn:
  670. fResult = TRUE;
  671. CommonReturn:
  672. *pcbEncoded = cbEncoded;
  673. return fResult;
  674. ErrorReturn:
  675. fResult = FALSE;
  676. goto CommonReturn;
  677. TRACE_ERROR(OutOfMemory)
  678. SET_ERROR(LengthError, ERROR_MORE_DATA)
  679. SET_ERROR_VAR(OssError, CRYPT_E_OSS_ERROR + OssStatus)
  680. }
  681. //+-------------------------------------------------------------------------
  682. // Encode an OSS formatted info structure
  683. //--------------------------------------------------------------------------
  684. BOOL
  685. WINAPI
  686. OssUtilEncodeInfo(
  687. IN OssGlobal *Pog,
  688. IN int pdunum,
  689. IN void *pvOssInfo,
  690. OUT OPTIONAL BYTE *pbEncoded,
  691. IN OUT DWORD *pcbEncoded
  692. )
  693. {
  694. return OssUtilEncodeInfoEx(
  695. Pog,
  696. pdunum,
  697. pvOssInfo,
  698. 0, // dwFlags
  699. NULL, // pEncodePara
  700. pbEncoded,
  701. pcbEncoded
  702. );
  703. }
  704. //+-------------------------------------------------------------------------
  705. // Decode into an allocated, OSS formatted info structure
  706. //--------------------------------------------------------------------------
  707. BOOL
  708. WINAPI
  709. OssUtilDecodeAndAllocInfo(
  710. IN OssGlobal *Pog,
  711. IN int pdunum,
  712. IN const BYTE *pbEncoded,
  713. IN DWORD cbEncoded,
  714. OUT void **ppvOssInfo
  715. )
  716. {
  717. BOOL fResult;
  718. OssBuf OssEncoded;
  719. int OssStatus;
  720. OssEncoded.length = cbEncoded;
  721. OssEncoded.value = (unsigned char *) pbEncoded;
  722. ossSetEncodingRules(Pog, OSS_BER);
  723. *ppvOssInfo = NULL;
  724. if (0 != (OssStatus = ossDecode(
  725. Pog,
  726. &pdunum,
  727. &OssEncoded,
  728. ppvOssInfo)))
  729. goto OssError;
  730. fResult = TRUE;
  731. CommonReturn:
  732. return fResult;
  733. ErrorReturn:
  734. *ppvOssInfo = NULL;
  735. fResult = FALSE;
  736. goto CommonReturn;
  737. SET_ERROR_VAR(OssError, CRYPT_E_OSS_ERROR + OssStatus)
  738. }
  739. //+-------------------------------------------------------------------------
  740. // Free an allocated, OSS formatted info structure
  741. //--------------------------------------------------------------------------
  742. void
  743. WINAPI
  744. OssUtilFreeInfo(
  745. IN OssGlobal *Pog,
  746. IN int pdunum,
  747. IN void *pvOssInfo
  748. )
  749. {
  750. if (pvOssInfo) {
  751. ossFreePDU(Pog, pdunum, pvOssInfo);
  752. }
  753. }
  754. //+-------------------------------------------------------------------------
  755. // Call the callback to convert the OSS structure into the 'C' structure.
  756. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  757. // structure and call the callback initially to get the length and then
  758. // a second time to update the allocated 'C' structure.
  759. //
  760. // Allocated structure is returned:
  761. // *((void **) pvStructInfo) = pvAllocStructInfo
  762. //--------------------------------------------------------------------------
  763. BOOL
  764. WINAPI
  765. OssUtilAllocStructInfoEx(
  766. IN void *pvOssInfo,
  767. IN DWORD dwFlags,
  768. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  769. IN PFN_OSS_UTIL_DECODE_EX_CALLBACK pfnDecodeExCallback,
  770. OUT OPTIONAL void *pvStructInfo,
  771. IN OUT DWORD *pcbStructInfo
  772. )
  773. {
  774. BOOL fResult;
  775. LONG lRemainExtra;
  776. DWORD cbStructInfo;
  777. if (NULL == pvStructInfo || (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) {
  778. cbStructInfo = 0;
  779. lRemainExtra = 0;
  780. } else {
  781. cbStructInfo = *pcbStructInfo;
  782. lRemainExtra = (LONG) cbStructInfo;
  783. }
  784. if (!pfnDecodeExCallback(
  785. pvOssInfo,
  786. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  787. pDecodePara,
  788. pvStructInfo,
  789. &lRemainExtra
  790. )) goto DecodeCallbackError;
  791. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) {
  792. void *pv;
  793. PFN_CRYPT_ALLOC pfnAlloc = PkiGetDecodeAllocFunction(pDecodePara);
  794. assert(0 > lRemainExtra);
  795. lRemainExtra = -lRemainExtra;
  796. cbStructInfo = (DWORD) lRemainExtra;
  797. if (NULL == (pv = pfnAlloc(cbStructInfo)))
  798. goto OutOfMemory;
  799. if (!pfnDecodeExCallback(
  800. pvOssInfo,
  801. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  802. pDecodePara,
  803. pv,
  804. &lRemainExtra
  805. )) {
  806. PFN_CRYPT_FREE pfnFree = PkiGetDecodeFreeFunction(pDecodePara);
  807. pfnFree(pv);
  808. goto DecodeCallbackError;
  809. }
  810. *((void **) pvStructInfo) = pv;
  811. assert(0 <= lRemainExtra);
  812. }
  813. if (0 <= lRemainExtra) {
  814. cbStructInfo = cbStructInfo - (DWORD) lRemainExtra;
  815. } else {
  816. cbStructInfo = cbStructInfo + (DWORD) -lRemainExtra;
  817. if (pvStructInfo) {
  818. SetLastError((DWORD) ERROR_MORE_DATA);
  819. fResult = FALSE;
  820. goto CommonReturn;
  821. }
  822. }
  823. fResult = TRUE;
  824. CommonReturn:
  825. *pcbStructInfo = cbStructInfo;
  826. return fResult;
  827. ErrorReturn:
  828. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  829. *((void **) pvStructInfo) = NULL;
  830. cbStructInfo = 0;
  831. fResult = FALSE;
  832. goto CommonReturn;
  833. TRACE_ERROR(DecodeCallbackError)
  834. TRACE_ERROR(OutOfMemory)
  835. }
  836. //+-------------------------------------------------------------------------
  837. // Decode the OSS formatted info structure and call the callback
  838. // function to convert the OSS structure to the 'C' structure.
  839. //
  840. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  841. // structure and call the callback initially to get the length and then
  842. // a second time to update the allocated 'C' structure.
  843. //
  844. // Allocated structure is returned:
  845. // *((void **) pvStructInfo) = pvAllocStructInfo
  846. //--------------------------------------------------------------------------
  847. BOOL
  848. WINAPI
  849. OssUtilDecodeAndAllocInfoEx(
  850. IN OssGlobal *Pog,
  851. IN int pdunum,
  852. IN const BYTE *pbEncoded,
  853. IN DWORD cbEncoded,
  854. IN DWORD dwFlags,
  855. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  856. IN PFN_OSS_UTIL_DECODE_EX_CALLBACK pfnDecodeExCallback,
  857. OUT OPTIONAL void *pvStructInfo,
  858. IN OUT DWORD *pcbStructInfo
  859. )
  860. {
  861. BOOL fResult;
  862. void *pvOssInfo = NULL;
  863. if (!OssUtilDecodeAndAllocInfo(
  864. Pog,
  865. pdunum,
  866. pbEncoded,
  867. cbEncoded,
  868. &pvOssInfo
  869. )) goto OssDecodeError;
  870. fResult = OssUtilAllocStructInfoEx(
  871. pvOssInfo,
  872. dwFlags,
  873. pDecodePara,
  874. pfnDecodeExCallback,
  875. pvStructInfo,
  876. pcbStructInfo
  877. );
  878. CommonReturn:
  879. OssUtilFreeInfo(Pog, pdunum, pvOssInfo);
  880. return fResult;
  881. ErrorReturn:
  882. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  883. *((void **) pvStructInfo) = NULL;
  884. *pcbStructInfo = 0;
  885. fResult = FALSE;
  886. goto CommonReturn;
  887. TRACE_ERROR(OssDecodeError)
  888. }