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.

770 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: enc.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include "encode.h"
  13. OIDTRANSLATE const *
  14. LookupOidTranslate(
  15. IN CHAR const *pszObjId)
  16. {
  17. DWORD i;
  18. OIDTRANSLATE const *pOid = NULL;
  19. for (i = 0; i < g_cOidTranslate; i++)
  20. {
  21. if (0 == strcmp(pszObjId, g_aOidTranslate[i].pszObjId))
  22. {
  23. pOid = &g_aOidTranslate[i];
  24. break;
  25. }
  26. }
  27. CSASSERT(NULL != pOid);
  28. return(pOid);
  29. }
  30. long
  31. EncodeObjId(
  32. OPTIONAL OUT BYTE *pbEncoded,
  33. IN CHAR const *pszObjId)
  34. {
  35. OIDTRANSLATE const *pOid;
  36. long cbLength;
  37. pOid = LookupOidTranslate(pszObjId);
  38. if (NULL != pbEncoded)
  39. {
  40. *pbEncoded++ = BER_OBJECT_ID;
  41. }
  42. cbLength = EncodeLength(pbEncoded, pOid->cbOIDEncoded);
  43. if (NULL != pbEncoded)
  44. {
  45. CopyMemory(
  46. pbEncoded + cbLength,
  47. pOid->abOIDEncoded,
  48. pOid->cbOIDEncoded);
  49. }
  50. return(1 + cbLength + pOid->cbOIDEncoded);
  51. }
  52. //+*************************************************************************
  53. // EncodeLength ASN1 encodes a length field. The parameter
  54. // dwLen is the length to be encoded, it is a DWORD and
  55. // therefore may be no larger than 2^32. The pbEncoded
  56. // parameter is the encoded result, and memory must be
  57. // allocated for it by the caller. The pbEncoded parameter
  58. // indicates if the result is to be written to the pbEncoded
  59. // parameter. The function cannot fail and returns the
  60. // number of total bytes in the encoded length.
  61. // encoded length.
  62. //**************************************************************************
  63. // Notes: Encodes 0x0000 to 0x007f as <lobyte>
  64. // Encodes 0x0080 to 0x00ff as <81>, <lobyte>
  65. // Encodes 0x0100 to 0xffff as <82>, <hibyte>, <lobyte>
  66. long
  67. EncodeLength(
  68. OPTIONAL OUT BYTE *pbEncoded,
  69. IN DWORD dwLen)
  70. {
  71. // length is between 2^8 and 2^16 - 1
  72. if (dwLen > 0xff)
  73. {
  74. if (NULL != pbEncoded)
  75. {
  76. pbEncoded[0] = 0x82;
  77. pbEncoded[1] = (BYTE) (dwLen >> 8);
  78. pbEncoded[2] = (BYTE) dwLen;
  79. }
  80. return(3);
  81. }
  82. // length is between 2^7 and 2^8 - 1
  83. if (dwLen > 0x7f)
  84. {
  85. if (NULL != pbEncoded)
  86. {
  87. pbEncoded[0] = 0x81;
  88. pbEncoded[1] = (BYTE) dwLen;
  89. }
  90. return(2);
  91. }
  92. // length is between 0 and 2^7 - 1
  93. if (NULL != pbEncoded)
  94. {
  95. pbEncoded[0] = (BYTE) dwLen;
  96. }
  97. return(1);
  98. }
  99. long
  100. EncodeNull(
  101. OPTIONAL OUT BYTE *pbEncoded)
  102. {
  103. if (NULL != pbEncoded)
  104. {
  105. *pbEncoded++ = BER_NULL;
  106. *pbEncoded = 0;
  107. }
  108. return(2);
  109. }
  110. //+*************************************************************************
  111. // EncodeAlgid ASN1 encodes an algorithm identifier. The
  112. // parameter Algid is the algorithm identifier as an ALG_ID
  113. // type. pbEncoded is the parameter used to pass back the
  114. // encoded result, and memory must be allocated for it by
  115. // the caller. The pbEncoded parameter indicates if the
  116. // result is to be written to the pbEncoded parameter
  117. // The function returns a -1 if it fails and otherwise
  118. // returns the number of total bytes in the encoded
  119. // algorithm identifier.
  120. //**************************************************************************
  121. long
  122. EncodeAlgid(
  123. OPTIONAL OUT BYTE *pbEncoded,
  124. IN DWORD Algid)
  125. {
  126. DWORD i;
  127. LONG cb = -1;
  128. // determine the algorithm id which is to be encoded and
  129. // copy the appropriate encoded algid into the destination
  130. for (i = 0; i < g_cAlgIdTranslate; i++)
  131. {
  132. if (Algid == g_aAlgIdTranslate[i].AlgId)
  133. {
  134. cb = EncodeObjId(pbEncoded, g_aAlgIdTranslate[i].pszObjId);
  135. break;
  136. }
  137. }
  138. return(cb);
  139. }
  140. long
  141. EncodeAlgorithm(
  142. OPTIONAL OUT BYTE *pbEncoded,
  143. IN DWORD AlgId)
  144. {
  145. BYTE abTemp[32];
  146. long cbResult;
  147. BYTE *pb;
  148. pb = abTemp;
  149. // Take a guess at the total length:
  150. pb += EncodeHeader(pb, sizeof(abTemp));
  151. cbResult = EncodeAlgid(pb, AlgId);
  152. if (cbResult == -1)
  153. {
  154. return(-1);
  155. }
  156. pb += cbResult;
  157. cbResult += EncodeNull(pb);
  158. // Fix up the total length:
  159. cbResult += EncodeHeader(abTemp, cbResult);
  160. if (NULL != pbEncoded)
  161. {
  162. CopyMemory(pbEncoded, abTemp, cbResult);
  163. }
  164. return(cbResult);
  165. }
  166. //+*************************************************************************
  167. // EncodeInteger ASN1 encodes an integer. The pbInt parameter
  168. // is the integer as an array of bytes, and dwLen is the number
  169. // of bytes in the array. The least significant byte of the
  170. // integer is the zeroth byte of the array. The encoded result
  171. // is passed back in the pbEncoded parameter. The pbEncoded
  172. // indicates if the result is to be written to the pbEncoded
  173. // parameter. The function cannot fail and returns the number
  174. // of total bytes in the encoded integer.
  175. // This implementation will only deal with positive integers.
  176. //**************************************************************************
  177. long
  178. EncodeInteger(
  179. OPTIONAL OUT BYTE *pbEncoded,
  180. IN BYTE const *pbInt,
  181. IN DWORD dwLen)
  182. {
  183. DWORD iInt;
  184. long j; // Must be signed!
  185. LONG cbResult;
  186. LONG cbLength;
  187. if (NULL != pbEncoded)
  188. {
  189. *pbEncoded++ = BER_INTEGER;
  190. }
  191. cbResult = 1;
  192. // find the most significant non-zero byte
  193. for (iInt = dwLen - 1; pbInt[iInt] == 0; iInt--)
  194. {
  195. if (iInt == 0) // if the integer value is 0
  196. {
  197. if (NULL != pbEncoded)
  198. {
  199. *pbEncoded++ = 0x01;
  200. *pbEncoded++ = 0x00;
  201. }
  202. return(cbResult + 2);
  203. }
  204. }
  205. // if the most significant bit of the most significant byte is set then add
  206. // a 0 byte to the beginning.
  207. if (pbInt[iInt] > 0x7f)
  208. {
  209. // encode the length
  210. cbLength = EncodeLength(pbEncoded, iInt + 2);
  211. // set the first byte of the integer to 0 and increment pointer
  212. if (NULL != pbEncoded)
  213. {
  214. pbEncoded += cbLength;
  215. *pbEncoded++ = 0;
  216. }
  217. cbResult++;
  218. }
  219. else
  220. {
  221. // encode the length
  222. cbLength = EncodeLength(pbEncoded, iInt + 1);
  223. if (NULL != pbEncoded)
  224. {
  225. pbEncoded += cbLength;
  226. }
  227. }
  228. cbResult += cbLength;
  229. // copy the integer bytes into the encoded buffer
  230. if (NULL != pbEncoded)
  231. {
  232. // copy the integer bytes into the encoded buffer
  233. for (j = iInt; j >= 0; j--)
  234. {
  235. *pbEncoded++ = pbInt[j];
  236. }
  237. }
  238. cbResult += iInt + 1;
  239. return(cbResult);
  240. }
  241. long
  242. EncodeUnicodeString(
  243. OPTIONAL OUT BYTE *pbEncoded,
  244. IN WCHAR const *pwsz)
  245. {
  246. long cbLength;
  247. long cbData = wcslen(pwsz) * sizeof(WCHAR);
  248. if (NULL != pbEncoded)
  249. {
  250. *pbEncoded++ = BER_UNICODE_STRING;
  251. }
  252. cbLength = EncodeLength(pbEncoded, cbData);
  253. if (NULL != pbEncoded)
  254. {
  255. pbEncoded += cbLength;
  256. for ( ; L'\0' != *pwsz; pwsz++)
  257. {
  258. *pbEncoded++ = (BYTE) (*pwsz >> 8);
  259. *pbEncoded++ = (BYTE) *pwsz;
  260. }
  261. }
  262. return(1 + cbLength + cbData);
  263. }
  264. //+*************************************************************************
  265. // EncodeIA5String ASN1 encodes a character string. The pbStr
  266. // parameter is the string as an array of characters, and dwLen
  267. // is the number of characters in the array. The encoded result
  268. // is passed back in the pbEncoded parameter. The pbEncoded
  269. // indicates if the result is to be written to the pbEncoded
  270. // parameter. The function cannot fail and returns the number
  271. // of total bytes in the encoded string.
  272. //**************************************************************************
  273. long
  274. EncodeIA5String(
  275. OPTIONAL OUT BYTE *pbEncoded,
  276. IN BYTE const *pbStr,
  277. IN DWORD dwLen)
  278. {
  279. long cbLength;
  280. if (NULL != pbEncoded)
  281. {
  282. *pbEncoded++ = BER_IA5_STRING;
  283. }
  284. cbLength = EncodeLength(pbEncoded, dwLen);
  285. if (NULL != pbEncoded)
  286. {
  287. CopyMemory(pbEncoded + cbLength, pbStr, dwLen);
  288. }
  289. return(1 + cbLength + dwLen);
  290. }
  291. //+*************************************************************************
  292. // EncodeOctetString ASN1 encodes a string of hex valued
  293. // characters. The pbStr parameter is an array of characters,
  294. // and dwLen is the number of characters in the array. The
  295. // encoded result is passed back in the pbEncoded parameter. The
  296. // pbEncoded parameter indicates if the result is to be written
  297. // to the pbEncoded parameter. The function cannot fail and
  298. // returns the number of total bytes in the encoded octet string
  299. //**************************************************************************
  300. long
  301. EncodeOctetString(
  302. OPTIONAL OUT BYTE *pbEncoded,
  303. IN BYTE const *pbStr,
  304. IN DWORD dwLen)
  305. {
  306. long cbLength;
  307. if (NULL != pbEncoded)
  308. {
  309. *pbEncoded++ = BER_OCTET_STRING;
  310. }
  311. cbLength = EncodeLength(pbEncoded, dwLen);
  312. if (NULL != pbEncoded)
  313. {
  314. CopyMemory(pbEncoded + cbLength, pbStr, dwLen);
  315. }
  316. return(1 + cbLength + dwLen);
  317. }
  318. //+*************************************************************************
  319. // EncodeBitString ASN1 encodes a string of bit characters. The
  320. // pbStr parameter is an array of characters (bits), and dwLen
  321. // is the number of characters in the array. The encoded result
  322. // is passed back in the pbEncoded parameter. The pbEncoded
  323. // indicates if the result is to be written to the pbEncoded
  324. // parameter. The function cannot fail and returns the number
  325. // of total bytes in the encoded string. This function uses
  326. // the DER.
  327. //**************************************************************************
  328. long
  329. EncodeBitString(
  330. OPTIONAL OUT BYTE *pbEncoded,
  331. IN BYTE const *pbStr,
  332. IN DWORD dwLen)
  333. {
  334. long cbLength;
  335. if (NULL != pbEncoded)
  336. {
  337. *pbEncoded++ = BER_BIT_STRING;
  338. }
  339. cbLength = EncodeLength(pbEncoded, dwLen + 1);
  340. if (NULL != pbEncoded)
  341. {
  342. pbEncoded += cbLength;
  343. // the next byte tells how many unused bits there are in the last byte,
  344. // but this will always be zero in this implementation (DER)
  345. *pbEncoded++ = 0;
  346. CopyMemory(pbEncoded, pbStr, dwLen);
  347. }
  348. return(1 + cbLength + 1 + dwLen);
  349. }
  350. //+---------------------------------------------------------------------------
  351. //
  352. // Function: EncodeFileTime
  353. //
  354. // Synopsis: Encodes a FILETIME to a ASN.1 format time string.
  355. //
  356. // Arguments: [pbEncoded] --
  357. // [Time] --
  358. // [UTC] -- Indicate Time is UTC (true) or local (false)
  359. // [WriteFlag] --
  360. //
  361. // History: 8-10-95 RichardW Created
  362. //
  363. // Notes:
  364. //
  365. //----------------------------------------------------------------------------
  366. long
  367. EncodeFileTime(
  368. OPTIONAL OUT BYTE *pbEncoded,
  369. IN FILETIME Time,
  370. IN BOOL UTC)
  371. {
  372. if (NULL != pbEncoded)
  373. {
  374. SYSTEMTIME st;
  375. FILETIME ft;
  376. int count;
  377. if (UTC)
  378. {
  379. ft = Time;
  380. }
  381. else
  382. {
  383. LocalFileTimeToFileTime(&Time, &ft);
  384. }
  385. FileTimeToSystemTime(&ft, &st);
  386. *pbEncoded++ = BER_UTC_TIME;
  387. count = EncodeLength(pbEncoded, 13);
  388. // NOTE ON Y2K COMPLIANCE: This is test tool. WE WILL NOT FIX THIS
  389. // CODE! It is only used to encode current dates, anyway,
  390. pbEncoded++;
  391. st.wYear %= 100;
  392. *pbEncoded++ = (BYTE) ((st.wYear / 10) + '0');
  393. *pbEncoded++ = (BYTE) ((st.wYear % 10) + '0');
  394. *pbEncoded++ = (BYTE) ((st.wMonth / 10) + '0');
  395. *pbEncoded++ = (BYTE) ((st.wMonth % 10) + '0');
  396. *pbEncoded++ = (BYTE) ((st.wDay / 10) + '0');
  397. *pbEncoded++ = (BYTE) ((st.wDay % 10) + '0');
  398. *pbEncoded++ = (BYTE) ((st.wHour / 10) + '0');
  399. *pbEncoded++ = (BYTE) ((st.wHour % 10) + '0');
  400. *pbEncoded++ = (BYTE) ((st.wMinute / 10) + '0');
  401. *pbEncoded++ = (BYTE) ((st.wMinute % 10) + '0');
  402. *pbEncoded++ = (BYTE) ((st.wSecond / 10) + '0');
  403. *pbEncoded++ = (BYTE) ((st.wSecond % 10) + '0');
  404. *pbEncoded = 'Z';
  405. }
  406. // Tag(1) + Len(1) + Year(2) + Month(2) + Day(2) +
  407. // Hour(2) + Min(2) + Sec(2) + 'Z'(1) --> 15
  408. return(15);
  409. }
  410. //+*************************************************************************
  411. // EncodeHeader ASN1 encodes a header for a sequence type. The
  412. // dwLen is the length of the encoded information in the
  413. // sequence. The pbEncoded indicates if the result is to be
  414. // written to the pbEncoded parameter. The function cannot
  415. // fail and returns the number of total bytes in the encoded
  416. // header.
  417. //**************************************************************************
  418. // Notes: Encodes header as <BER_SEQUENCE>, <length>
  419. long
  420. EncodeHeader(
  421. OPTIONAL OUT BYTE *pbEncoded,
  422. IN DWORD dwLen)
  423. {
  424. if (NULL != pbEncoded)
  425. {
  426. *pbEncoded++ = BER_SEQUENCE;
  427. }
  428. return(1 + EncodeLength(pbEncoded, dwLen));
  429. }
  430. //+*************************************************************************
  431. // EncodeSetOfHeader ASN1 encodes a header for a set of type.
  432. // The dwLen is the length of the encoded information in the
  433. // set of. The pbEncoded indicates if the result is to be
  434. // written to the pbEncoded parameter. The function cannot
  435. // fail and returns the number of total bytes in the encoded
  436. // header.
  437. //**************************************************************************
  438. // Notes: Encodes header as <SET_OF_TAG>, <length>
  439. long
  440. EncodeSetOfHeader(
  441. OPTIONAL OUT BYTE *pbEncoded,
  442. IN DWORD dwLen)
  443. {
  444. if (NULL != pbEncoded)
  445. {
  446. *pbEncoded++ = BER_SET_RAW;
  447. }
  448. return(1 + EncodeLength(pbEncoded, dwLen));
  449. }
  450. // Notes: Encodes header as <BER_OPTIONAL | 0>, <length>
  451. long
  452. EncodeAttributeHeader(
  453. OPTIONAL OUT BYTE *pbEncoded,
  454. IN DWORD dwLen)
  455. {
  456. if (NULL != pbEncoded)
  457. {
  458. *pbEncoded++ = BER_OPTIONAL | 0;
  459. }
  460. return(1 + EncodeLength(pbEncoded, dwLen));
  461. }
  462. // Notes: Encodes header as <BER_SET>, <length>
  463. long
  464. EncodeSetHeader(
  465. OPTIONAL OUT BYTE *pbEncoded,
  466. IN DWORD dwLen)
  467. {
  468. if (NULL != pbEncoded)
  469. {
  470. *pbEncoded++ = BER_SET;
  471. }
  472. return(1 + EncodeLength(pbEncoded, dwLen));
  473. }
  474. //+*************************************************************************
  475. // EncodeName ASN1 encodes a Name type. The pbName parameter is
  476. // the name and dwLen is the length of the name in bytes.
  477. // The pbEncoded indicates if the result is to be written to
  478. // the pbEncoded parameter. The function cannot fail and
  479. // returns the number of total bytes in the encoded name.
  480. //**************************************************************************
  481. long
  482. EncodeName(
  483. OPTIONAL OUT BYTE *pbEncoded,
  484. IN BYTE const *pbName,
  485. IN DWORD dwLen)
  486. {
  487. BYTE Type[MAXOBJIDLEN];
  488. long TypeLen;
  489. BYTE Value[MAXNAMEVALUELEN+MINHEADERLEN];
  490. long ValueLen;
  491. BYTE Attribute[MAXNAMELEN];
  492. long AttributeLen;
  493. BYTE SetHdr[MINHEADERLEN];
  494. long HdrLen;
  495. long NameLen;
  496. // encode the name value
  497. ValueLen = EncodeIA5String(Value, pbName, dwLen);
  498. // encode the attribute type, this is an object identifier and here it
  499. // is a fake encoding
  500. Type[0] = 0x06;
  501. Type[1] = 0x01;
  502. Type[2] = 0x00;
  503. TypeLen = 3;
  504. // encode the header for the attribute
  505. AttributeLen = EncodeHeader(Attribute, ValueLen + TypeLen);
  506. // copy the attribute type and value into the attribute
  507. CopyMemory(Attribute + AttributeLen, Type, TypeLen);
  508. AttributeLen += TypeLen;
  509. CopyMemory(Attribute + AttributeLen, Value, ValueLen);
  510. AttributeLen += ValueLen;
  511. // encode set of header
  512. HdrLen = EncodeSetOfHeader(SetHdr, AttributeLen);
  513. // encode Name header
  514. NameLen = EncodeHeader(pbEncoded, HdrLen + AttributeLen);
  515. if (NULL != pbEncoded)
  516. {
  517. CopyMemory(pbEncoded + NameLen, SetHdr, HdrLen);
  518. }
  519. NameLen += HdrLen;
  520. if (NULL != pbEncoded)
  521. {
  522. CopyMemory(pbEncoded + NameLen, Attribute, AttributeLen);
  523. }
  524. return(NameLen + AttributeLen);
  525. }
  526. long
  527. EncodeRDN(
  528. OPTIONAL OUT BYTE *pbEncoded,
  529. IN NAMEENTRY const *pNameEntry)
  530. {
  531. LONG cbResult;
  532. LONG Length;
  533. DWORD cbOIDandData;
  534. DWORD cbSequence;
  535. OIDTRANSLATE const *pOidName;
  536. // Compute the size of the encoded OID and RDN string, with BER encoding
  537. // tags and lengths.
  538. pOidName = LookupOidTranslate(pNameEntry->pszObjId);
  539. cbOIDandData =
  540. 1 +
  541. EncodeLength(NULL, pOidName->cbOIDEncoded) +
  542. pOidName->cbOIDEncoded +
  543. 1 +
  544. EncodeLength(NULL, pNameEntry->cbData) +
  545. pNameEntry->cbData;
  546. cbSequence = 1 + EncodeLength(NULL, cbOIDandData) + cbOIDandData;
  547. Length = EncodeSetHeader(pbEncoded, cbSequence);
  548. if (NULL != pbEncoded)
  549. {
  550. pbEncoded += Length;
  551. }
  552. cbResult = EncodeHeader(pbEncoded, cbOIDandData);
  553. if (NULL != pbEncoded)
  554. {
  555. pbEncoded += cbResult;
  556. *pbEncoded++ = BER_OBJECT_ID;
  557. }
  558. Length += cbResult + 1;
  559. cbResult = EncodeLength(pbEncoded, pOidName->cbOIDEncoded);
  560. if (NULL != pbEncoded)
  561. {
  562. pbEncoded += cbResult;
  563. CopyMemory(pbEncoded, pOidName->abOIDEncoded, pOidName->cbOIDEncoded);
  564. pbEncoded += pOidName->cbOIDEncoded;
  565. *pbEncoded++ = pNameEntry->BerTag;
  566. }
  567. Length += cbResult + pOidName->cbOIDEncoded + 1;
  568. cbResult = EncodeLength(pbEncoded, pNameEntry->cbData);
  569. Length += cbResult;
  570. if (NULL != pbEncoded)
  571. {
  572. CopyMemory(pbEncoded + cbResult, pNameEntry->pbData, pNameEntry->cbData);
  573. }
  574. return(Length + pNameEntry->cbData);
  575. }
  576. long
  577. EncodeDN(
  578. OPTIONAL OUT BYTE *pbEncoded,
  579. IN NAMETABLE const *pNameTable)
  580. {
  581. CHAR *pszNext;
  582. CHAR *pszRDN;
  583. long Result;
  584. long Length;
  585. long SaveResult;
  586. NAMEENTRY const *pNameEntry;
  587. DWORD i;
  588. SaveResult = 0; // force one full iteration
  589. pNameEntry = pNameTable->pNameEntry;
  590. Length = 0;
  591. for (i = 0; i < pNameTable->cnt; i++)
  592. {
  593. Length += 9 + pNameEntry->cbData;
  594. pNameEntry++;
  595. }
  596. while (TRUE)
  597. {
  598. BYTE *pb;
  599. pb = pbEncoded;
  600. Result = EncodeHeader(pb, Length);
  601. if (SaveResult == Result)
  602. {
  603. break;
  604. }
  605. if (NULL != pb)
  606. {
  607. pb += Result;
  608. }
  609. SaveResult = Result;
  610. Length = 0;
  611. pNameEntry = pNameTable->pNameEntry;
  612. for (i = 0; i < pNameTable->cnt; i++)
  613. {
  614. Result = EncodeRDN(pb, pNameEntry);
  615. if (Result < 0)
  616. {
  617. Length = 0;
  618. goto error; // return(-1)
  619. }
  620. if (NULL != pb)
  621. {
  622. pb += Result;
  623. }
  624. Length += Result;
  625. pNameEntry++;
  626. }
  627. }
  628. error:
  629. return(Result + Length);
  630. }