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.

659 lines
19 KiB

  1. /*-----------------------------------------------------------------------------
  2. * Copyright (C) Microsoft Corporation, 1995 - 1996.
  3. * All rights reserved.
  4. *
  5. * This file is part of the Microsoft Private Communication Technology
  6. * reference implementation, version 1.0
  7. *
  8. * The Private Communication Technology reference implementation, version 1.0
  9. * ("PCTRef"), is being provided by Microsoft to encourage the development and
  10. * enhancement of an open standard for secure general-purpose business and
  11. * personal communications on open networks. Microsoft is distributing PCTRef
  12. * at no charge irrespective of whether you use PCTRef for non-commercial or
  13. * commercial use.
  14. *
  15. * Microsoft expressly disclaims any warranty for PCTRef and all derivatives of
  16. * it. PCTRef and any related documentation is provided "as is" without
  17. * warranty of any kind, either express or implied, including, without
  18. * limitation, the implied warranties or merchantability, fitness for a
  19. * particular purpose, or noninfringement. Microsoft shall have no obligation
  20. * to provide maintenance, support, upgrades or new releases to you or to anyone
  21. * receiving from you PCTRef or your modifications. The entire risk arising out
  22. * of use or performance of PCTRef remains with you.
  23. *
  24. * Please see the file LICENSE.txt,
  25. * or http://pct.microsoft.com/pct/pctlicen.txt
  26. * for more information on licensing.
  27. *
  28. * Please see http://pct.microsoft.com/pct/pct.htm for The Private
  29. * Communication Technology Specification version 1.0 ("PCT Specification")
  30. *
  31. * 1/23/96
  32. *----------------------------------------------------------------------------*/
  33. #include <spbase.h>
  34. #include <ber.h>
  35. typedef struct __EncAlgs {
  36. DWORD Id;
  37. UCHAR Sequence[16];
  38. DWORD SequenceLen;
  39. } _EncAlgs;
  40. #define iso_member 0x2a, /* iso(1) memberbody(2) */
  41. #define us 0x86, 0x48, /* us(840) */
  42. #define rsadsi 0x86, 0xf7, 0x0d, /* rsadsi(113549) */
  43. #define pkcs 0x01, /* pkcs(1) */
  44. #define pkcs_1 iso_member us rsadsi pkcs
  45. #define pkcs_len 7
  46. #define rsa_dsi iso_member us rsadsi
  47. #define rsa_dsi_len 6
  48. #define joint_iso_ccitt_ds 0x55,
  49. #define attributetype 0x04,
  50. #define attributeType joint_iso_ccitt_ds attributetype
  51. #define attrtype_len 2
  52. _EncAlgs EncKnownAlgs[] =
  53. {
  54. {ALGTYPE_SIG_RSA_MD5, {pkcs_1 1, 4}, pkcs_len + 2},
  55. {ALGTYPE_KEYEXCH_RSA_MD5, {pkcs_1 1, 1}, pkcs_len + 2},
  56. {ALGTYPE_CIPHER_RC4_MD5, {rsa_dsi 3, 4}, rsa_dsi_len + 2},
  57. {ALGTYPE_KEYEXCH_DH, {pkcs_1 3, 1}, pkcs_len + 2},
  58. };
  59. typedef struct _NameTypes {
  60. PSTR Prefix;
  61. DWORD PrefixLen;
  62. UCHAR Sequence[8];
  63. DWORD SequenceLen;
  64. } NameTypes;
  65. #define CNTYPE_INDEX 0
  66. NameTypes EncKnownNameTypes[] =
  67. {
  68. {"CN=", 3, {attributeType 3}, attrtype_len + 1},
  69. {"C=", 2, {attributeType 6}, attrtype_len + 1},
  70. {"L=", 2, {attributeType 7}, attrtype_len + 1},
  71. {"S=", 2, {attributeType 8}, attrtype_len + 1},
  72. {"O=", 2, {attributeType 10}, attrtype_len + 1},
  73. {"OU=", 3, {attributeType 11}, attrtype_len + 1}
  74. };
  75. /************************************************************/
  76. /* EncodeLength ASN1 encodes a length field. The parameter */
  77. /* dwLen is the length to be encoded, it is a DWORD and */
  78. /* therefore may be no larger than 2^32. The pbEncoded */
  79. /* parameter is the encoded result, and memory must be */
  80. /* allocated for it by the caller. The Writeflag parameter */
  81. /* indicates if the result is to be written to the pbEncoded*/
  82. /* parameter. The function cannot fail and returns the */
  83. /* number of total bytes in the encoded length. */
  84. /* encoded length. */
  85. /************************************************************/
  86. // Notes: Encodes 0x0000 to 0x007f as <lobyte>
  87. // Encodes 0x0080 to 0x00ff as <81>, <lobyte>
  88. // Encodes 0x0100 to 0xffff as <82>, <hibyte>, <lobyte>
  89. long
  90. EncodeLength(
  91. BYTE * pbEncoded,
  92. DWORD dwLen,
  93. BOOL Writeflag)
  94. {
  95. // length is between 2^8 and 2^16 - 1
  96. if (dwLen > 0xFF)
  97. {
  98. if (Writeflag)
  99. {
  100. pbEncoded[0] = 0x82;
  101. pbEncoded[1] = (BYTE) (dwLen >> 8);
  102. pbEncoded[2] = (BYTE) dwLen;
  103. }
  104. return (3);
  105. }
  106. // length is between 2^7 and 2^8 - 1
  107. if (dwLen > 0x7F)
  108. {
  109. if (Writeflag)
  110. {
  111. pbEncoded[0] = 0x81;
  112. pbEncoded[1] = (BYTE) dwLen;
  113. }
  114. return (2);
  115. }
  116. // length is between 0 and 2^7 - 1
  117. if (Writeflag)
  118. {
  119. pbEncoded[0] = (BYTE) dwLen;
  120. }
  121. return (1);
  122. }
  123. /****************************************************************/
  124. /* EncodeInteger ASN1 encodes an integer. The pbInt parameter */
  125. /* is the integer as an array of bytes, and dwLen is the number */
  126. /* of bytes in the array. The least significant byte of the */
  127. /* integer is the zeroth byte of the array. The encoded result */
  128. /* is passed back in the pbEncoded parameter. The Writeflag */
  129. /* indicates if the result is to be written to the pbEncoded */
  130. /* parameter. The function cannot fail and returns the number */
  131. /* of total bytes in the encoded integer. */
  132. /* This implementation will only deal with positive integers. */
  133. /****************************************************************/
  134. long
  135. EncodeInteger(
  136. BYTE *pbEncoded,
  137. BYTE *pbInt,
  138. DWORD dwLen,
  139. BOOL Writeflag)
  140. {
  141. DWORD i;
  142. long j; // Must be signed!
  143. BYTE *pb = pbEncoded;
  144. if (Writeflag)
  145. {
  146. *pb = INTEGER_TAG;
  147. }
  148. pb++;
  149. /* find the most significant non-zero byte */
  150. for (i = dwLen - 1; pbInt[i] == 0; i--)
  151. {
  152. if (i == 0) /* if the integer value is 0 */
  153. {
  154. if (Writeflag)
  155. {
  156. pb[0] = 0x01;
  157. pb[1] = 0x00;
  158. }
  159. return(3);
  160. }
  161. }
  162. /* if the most significant bit of the most sig byte is set */
  163. /* then need to add a 0 byte to the beginning. */
  164. if (pbInt[i] > 0x7F)
  165. {
  166. /* encode the length */
  167. pb += EncodeLength(pb, i + 2, Writeflag);
  168. if (Writeflag)
  169. {
  170. /* set the first byte of the integer to 0 and increment pointer */
  171. *pb = 0;
  172. }
  173. pb++;
  174. }
  175. else
  176. {
  177. /* encode the length */
  178. pb += EncodeLength(pb, i + 1, Writeflag);
  179. }
  180. /* copy the integer bytes into the encoded buffer */
  181. if (Writeflag)
  182. {
  183. /* copy the integer bytes into the encoded buffer */
  184. for (j = i; j >= 0; j--)
  185. {
  186. *pb++ = pbInt[j];
  187. }
  188. }
  189. else
  190. {
  191. pb += i;
  192. }
  193. return (long)(pb - pbEncoded);
  194. }
  195. /****************************************************************/
  196. /* EncodeString ASN1 encodes a character string. The pbStr */
  197. /* parameter is the string as an array of characters, and dwLen */
  198. /* is the number of characters in the array. The encoded result*/
  199. /* is passed back in the pbEncoded parameter. The Writeflag */
  200. /* indicates if the result is to be written to the pbEncoded */
  201. /* parameter. The function cannot fail and returns the number */
  202. /* of total bytes in the encoded string. */
  203. /****************************************************************/
  204. long
  205. EncodeString(
  206. BYTE * pbEncoded,
  207. BYTE * pbStr,
  208. DWORD dwLen,
  209. BOOL Writeflag)
  210. {
  211. long lengthlen;
  212. if (Writeflag)
  213. {
  214. *pbEncoded++ = CHAR_STRING_TAG;
  215. }
  216. lengthlen = EncodeLength(pbEncoded, dwLen, Writeflag);
  217. if (Writeflag)
  218. {
  219. CopyMemory(pbEncoded + lengthlen, pbStr, dwLen);
  220. }
  221. return(1 + lengthlen + dwLen);
  222. }
  223. /****************************************************************/
  224. /* EncodeOctetString ASN1 encodes a string of hex valued */
  225. /* characters. The pbStr parameter is an array of characters, */
  226. /* and dwLen is the number of characters in the array. The */
  227. /* encoded result is passed back in the pbEncoded parameter. The*/
  228. /* Writeflag parameter indicates if the result is to be written */
  229. /* to the pbEncoded parameter. The function cannot fail and */
  230. /* returns the number of total bytes in the encoded octet string*/
  231. /****************************************************************/
  232. long
  233. EncodeOctetString(
  234. BYTE * pbEncoded,
  235. BYTE * pbStr,
  236. DWORD dwLen,
  237. BOOL Writeflag)
  238. {
  239. long lengthlen;
  240. if (Writeflag)
  241. {
  242. *pbEncoded++ = OCTET_STRING_TAG;
  243. }
  244. lengthlen = EncodeLength(pbEncoded, dwLen, Writeflag);
  245. if (Writeflag)
  246. {
  247. CopyMemory(pbEncoded + lengthlen, pbStr, dwLen);
  248. }
  249. return(1 + lengthlen + dwLen);
  250. }
  251. /****************************************************************/
  252. /* EncodeBitString ASN1 encodes a string of bit characters. The */
  253. /* pbStr parameter is an array of characters (bits), and dwLen */
  254. /* is the number of characters in the array. The encoded result*/
  255. /* is passed back in the pbEncoded parameter. The Writeflag */
  256. /* indicates if the result is to be written to the pbEncoded */
  257. /* parameter. The function cannot fail and returns the number */
  258. /* of total bytes in the encoded string. This function uses */
  259. /* the DER. */
  260. /****************************************************************/
  261. long
  262. EncodeBitString(
  263. BYTE * pbEncoded,
  264. BYTE * pbStr,
  265. DWORD dwLen,
  266. BOOL Writeflag)
  267. {
  268. long lengthlen;
  269. if (Writeflag)
  270. {
  271. *pbEncoded++ = BIT_STRING_TAG;
  272. }
  273. lengthlen = EncodeLength(pbEncoded, dwLen + 1, Writeflag);
  274. if (Writeflag)
  275. {
  276. pbEncoded += lengthlen;
  277. // the next byte tells how many unused bits there are in the last byte,
  278. // but this will always be zero in this implementation (DER)
  279. *pbEncoded++ = 0;
  280. CopyMemory(pbEncoded, pbStr, dwLen);
  281. }
  282. return(1 + lengthlen + 1 + (long) dwLen);
  283. }
  284. /****************************************************************/
  285. /* EncodeHeader ASN1 encodes a header for a sequence type. The */
  286. /* dwLen is the length of the encoded information in the */
  287. /* sequence. The Writeflag indicates if the result is to be */
  288. /* written to the pbEncoded parameter. The function cannot */
  289. /* fail and returns the number of total bytes in the encoded */
  290. /* header. */
  291. /****************************************************************/
  292. // Notes: Encodes header as <SEQUENCE_TAG>, <length>
  293. long
  294. EncodeHeader(
  295. BYTE * pbEncoded,
  296. DWORD dwLen,
  297. BOOL Writeflag)
  298. {
  299. if (Writeflag)
  300. {
  301. *pbEncoded++ = SEQUENCE_TAG;
  302. }
  303. return(1 + EncodeLength(pbEncoded, dwLen, Writeflag));
  304. }
  305. /****************************************************************/
  306. /* EncodeSetOfHeader ASN1 encodes a header for a set of type. */
  307. /* The dwLen is the length of the encoded information in the */
  308. /* set of. The Writeflag indicates if the result is to be */
  309. /* written to the pbEncoded parameter. The function cannot */
  310. /* fail and returns the number of total bytes in the encoded */
  311. /* header. */
  312. /****************************************************************/
  313. // Notes: Encodes header as <SET_OF_TAG>, <length>
  314. long
  315. EncodeSetOfHeader(
  316. BYTE * pbEncoded,
  317. DWORD dwLen,
  318. BOOL Writeflag)
  319. {
  320. if (Writeflag)
  321. {
  322. *pbEncoded++ = SET_OF_TAG;
  323. }
  324. return(1 + EncodeLength(pbEncoded, dwLen, Writeflag));
  325. }
  326. // Notes: Encodes header as <ATTRIBUTE_TAG>, <length>
  327. long
  328. EncodeAttributeHeader(
  329. BYTE * pbEncoded,
  330. DWORD dwLen,
  331. BOOL Writeflag)
  332. {
  333. if (Writeflag)
  334. {
  335. *pbEncoded++ = ATTRIBUTE_TAG;
  336. }
  337. return(1 + EncodeLength(pbEncoded, dwLen, Writeflag));
  338. }
  339. // Notes: Encodes header as <BER_SET>, <length>
  340. long
  341. EncodeSetHeader(
  342. BYTE * pbEncoded,
  343. DWORD dwLen,
  344. BOOL WriteFlag)
  345. {
  346. if (WriteFlag)
  347. {
  348. *pbEncoded++ = BER_SET;
  349. }
  350. return(1 + EncodeLength(pbEncoded, dwLen, WriteFlag));
  351. }
  352. /****************************************************************/
  353. /* EncodeName ASN1 encodes a Name type. The pbName parameter is */
  354. /* the name and dwLen is the length of the name in bytes. */
  355. /* The Writeflag indicates if the result is to be written to */
  356. /* the pbEncoded parameter. The function cannot fail and */
  357. /* returns the number of total bytes in the encoded name. */
  358. /****************************************************************/
  359. long
  360. EncodeName(
  361. BYTE * pbEncoded,
  362. BYTE * pbName,
  363. DWORD dwLen,
  364. BOOL Writeflag)
  365. {
  366. BYTE Type[MAXOBJIDLEN];
  367. long TypeLen;
  368. BYTE Value[MAXNAMEVALUELEN+MINHEADERLEN];
  369. long ValueLen;
  370. BYTE Attribute[MAXNAMELEN];
  371. long AttributeLen;
  372. BYTE SetHdr[MINHEADERLEN];
  373. long HdrLen;
  374. long NameLen;
  375. /* encode the name value */
  376. ValueLen = EncodeString(Value, pbName, dwLen, Writeflag);
  377. SP_ASSERT(ValueLen > 0 && ValueLen <= sizeof(Value));
  378. /* encode the attribute type, this is an object identifier and here it */
  379. /* is a fake encoding */
  380. Type[0] = 0x06;
  381. Type[1] = 0x01;
  382. Type[2] = 0x00;
  383. TypeLen = 3;
  384. /* enocde the header for the attribute */
  385. AttributeLen = EncodeHeader(
  386. Attribute,
  387. (DWORD) (ValueLen + TypeLen),
  388. Writeflag);
  389. SP_ASSERT(AttributeLen > 0);
  390. SP_ASSERT(AttributeLen + TypeLen + ValueLen <= sizeof(Attribute));
  391. /* copy the attribute type and value into the attribute */
  392. CopyMemory(Attribute + AttributeLen, Type, (size_t) TypeLen);
  393. AttributeLen += TypeLen;
  394. CopyMemory(Attribute + AttributeLen, Value, (size_t) ValueLen);
  395. AttributeLen += ValueLen;
  396. /* encode set of header */
  397. HdrLen = EncodeSetOfHeader(SetHdr, (DWORD) AttributeLen, Writeflag);
  398. SP_ASSERT(HdrLen > 0 && HdrLen <= sizeof(SetHdr));
  399. /* encode Name header */
  400. NameLen = EncodeHeader(
  401. pbEncoded,
  402. (DWORD) (HdrLen + AttributeLen),
  403. Writeflag);
  404. SP_ASSERT(NameLen > 0);
  405. CopyMemory(pbEncoded + NameLen, SetHdr, (size_t) HdrLen);
  406. NameLen += HdrLen;
  407. CopyMemory(pbEncoded + NameLen, Attribute, (size_t) AttributeLen);
  408. return(NameLen + AttributeLen);
  409. }
  410. long
  411. EncodeRDN(
  412. BYTE * pbEncoded,
  413. PSTR pszRDN,
  414. BOOL WriteFlag)
  415. {
  416. LONG Result;
  417. DWORD RelLength;
  418. long Length;
  419. NameTypes *pNameType;
  420. char ach[4];
  421. SP_ASSERT(pszRDN != NULL);
  422. if (pszRDN[0] == '\0' ||
  423. pszRDN[1] == '\0' ||
  424. pszRDN[2] == '\0' ||
  425. (pszRDN[1] != '=' && pszRDN[2] != '='))
  426. {
  427. return(-1);
  428. }
  429. ach[0] = pszRDN[0];
  430. ach[1] = pszRDN[1];
  431. if (ach[1] == '=')
  432. {
  433. ach[2] = '\0';
  434. }
  435. else
  436. {
  437. ach[2] = pszRDN[2];
  438. ach[3] = '\0';
  439. }
  440. for (pNameType = EncKnownNameTypes; ; pNameType++)
  441. {
  442. if (pNameType ==
  443. &EncKnownNameTypes[sizeof(EncKnownNameTypes) /
  444. sizeof(EncKnownNameTypes[0])])
  445. {
  446. return(-1);
  447. }
  448. SP_ASSERT(lstrlen(pNameType->Prefix) < sizeof(ach));
  449. if (lstrcmpi(ach, pNameType->Prefix) == 0)
  450. {
  451. break;
  452. }
  453. }
  454. RelLength = lstrlen(&pszRDN[pNameType->PrefixLen]);
  455. // Prefix data takes up 9 bytes
  456. Length = EncodeSetHeader(pbEncoded, RelLength + 9, WriteFlag);
  457. pbEncoded += Length;
  458. Result = EncodeHeader(pbEncoded, RelLength + 7, WriteFlag);
  459. pbEncoded += Result;
  460. Length += Result + 2 + pNameType->SequenceLen;
  461. if (WriteFlag)
  462. {
  463. *pbEncoded++ = OBJECT_ID_TAG;
  464. *pbEncoded++ = (BYTE) pNameType->SequenceLen;
  465. CopyMemory(pbEncoded, pNameType->Sequence, pNameType->SequenceLen);
  466. pbEncoded += pNameType->SequenceLen;
  467. *pbEncoded++ =
  468. pNameType == &EncKnownNameTypes[CNTYPE_INDEX]?
  469. TELETEX_STRING_TAG : PRINTABLE_STRING_TAG;
  470. }
  471. Length++;
  472. Result = EncodeLength(pbEncoded, RelLength, WriteFlag);
  473. Length += Result;
  474. if (WriteFlag)
  475. {
  476. CopyMemory(
  477. pbEncoded + Result,
  478. &pszRDN[pNameType->PrefixLen],
  479. RelLength);
  480. }
  481. return(Length + RelLength);
  482. }
  483. long
  484. EncodeDN(
  485. BYTE * pbEncoded,
  486. PSTR pszDN,
  487. BOOL WriteFlag)
  488. {
  489. PSTR pszRDN;
  490. long Result = 0;
  491. long Length;
  492. long SaveResult;
  493. SP_ASSERT(pszDN != NULL);
  494. SaveResult = 0; // force one full iteration
  495. Length = 2 * lstrlen(pszDN); // your guess is as good as mine
  496. while (TRUE)
  497. {
  498. PSTR pszNext;
  499. BYTE *pb;
  500. pb = pbEncoded;
  501. Result = EncodeHeader(pb, Length, WriteFlag);
  502. if (SaveResult == Result)
  503. {
  504. break;
  505. }
  506. pb += Result;
  507. SaveResult = Result;
  508. Length = 0;
  509. pszRDN = pszDN;
  510. while (*pszRDN != '\0')
  511. {
  512. for (pszNext = pszRDN; ; pszNext++)
  513. {
  514. if (*pszNext == ',')
  515. {
  516. *pszNext = '\0';
  517. break;
  518. }
  519. if (*pszNext == '\0')
  520. {
  521. pszNext = NULL;
  522. break;
  523. }
  524. }
  525. Result = EncodeRDN(pb, pszRDN, WriteFlag);
  526. // Restore the comma before checking for error
  527. if (NULL != pszNext)
  528. {
  529. *pszNext = ',';
  530. }
  531. if (Result < 0)
  532. {
  533. DebugLog((DEB_TRACE, "EncodeDN: Error: %s\n", pszRDN));
  534. Length = 0;
  535. goto error; // return(-1)
  536. }
  537. pb += Result;
  538. Length += Result;
  539. if (NULL == pszNext)
  540. {
  541. break;
  542. }
  543. pszRDN = pszNext + 1;
  544. while (*pszRDN == ' ')
  545. {
  546. pszRDN++;
  547. }
  548. DebugLog((DEB_TRACE, "EncodeDN: Length = %d\n", Length));
  549. }
  550. }
  551. SP_ASSERT(0 != SaveResult);
  552. error:
  553. return(Result + Length);
  554. }