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.

426 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: ossconv.cpp
  8. //
  9. // Contents: Conversion APIs to/from OSS ASN.1 data structures
  10. //
  11. // Functions: OssConvToObjectIdentifier
  12. // OssConvFromObjectIdentifier
  13. // OssConvToUTCTime
  14. // OssConvFromUTCTime
  15. // OssConvToGeneralizedTime
  16. // OssConvFromGeneralizedTime
  17. // OssConvToChoiceOfTime
  18. // OssConvFromChoiceOfTime
  19. // OssConvToAttribute
  20. // OssConvToAlgorithmIdentifier
  21. // OssConvFromAlgorithmIdentifier
  22. //
  23. // According to the <draft-ietf-pkix-ipki-part1-10.txt> :
  24. // For UTCTime. Where YY is greater than or equal to 50, the year shall
  25. // be interpreted as 19YY. Where YY is less than
  26. // 50, the year shall be interpreted as 20YY.
  27. //
  28. // History: 28-Mar-96 philh created
  29. // 03-May-96 kevinr merged from wincrmsg
  30. //
  31. //--------------------------------------------------------------------------
  32. #include "global.hxx"
  33. #include <dbgdef.h>
  34. //
  35. // UTCTime in X.509 certs are represented using a 2-digit year
  36. // field (yuk! but true).
  37. //
  38. // According to IETF draft, YY years greater or equal than this are
  39. // to be interpreted as 19YY; YY years less than this are 20YY. Sigh.
  40. //
  41. #define MAGICYEAR 50
  42. #define YEARFIRST 1950
  43. #define YEARLAST 2049
  44. #define YEARFIRSTGENERALIZED 2050
  45. inline BOOL my_isdigit( char ch)
  46. {
  47. return (ch >= '0') && (ch <= '9');
  48. }
  49. //+-------------------------------------------------------------------------
  50. // Convert the ascii string ("1.2.9999") to OSS's Object Identifier
  51. // represented as an array of unsigned longs.
  52. //
  53. // Returns TRUE for a successful conversion.
  54. //--------------------------------------------------------------------------
  55. BOOL
  56. WINAPI
  57. OssConvToObjectIdentifier(
  58. IN LPCSTR pszObjId,
  59. IN OUT unsigned short *pCount,
  60. OUT unsigned long rgulValue[]
  61. )
  62. {
  63. BOOL fResult = TRUE;
  64. unsigned short c = 0;
  65. LPSTR psz = (LPSTR) pszObjId;
  66. char ch;
  67. if (psz) {
  68. unsigned short cMax = *pCount;
  69. unsigned long *pul = rgulValue;
  70. while ((ch = *psz) != '\0' && c++ < cMax) {
  71. *pul++ = (unsigned long)atol(psz);
  72. while (my_isdigit(ch = *psz++))
  73. ;
  74. if (ch != '.')
  75. break;
  76. }
  77. if (ch != '\0')
  78. fResult = FALSE;
  79. }
  80. *pCount = c;
  81. return fResult;
  82. }
  83. //+-------------------------------------------------------------------------
  84. // Convert from OSS's Object Identifier represented as an array of
  85. // unsigned longs to an ascii string ("1.2.9999").
  86. //
  87. // Returns TRUE for a successful conversion
  88. //--------------------------------------------------------------------------
  89. BOOL
  90. WINAPI
  91. OssConvFromObjectIdentifier(
  92. IN unsigned short Count,
  93. IN unsigned long rgulValue[],
  94. OUT LPSTR pszObjId,
  95. IN OUT DWORD *pcbObjId
  96. )
  97. {
  98. BOOL fResult = TRUE;
  99. LONG lRemain;
  100. if (pszObjId == NULL)
  101. *pcbObjId = 0;
  102. lRemain = (LONG) *pcbObjId;
  103. if (Count == 0) {
  104. if (--lRemain > 0)
  105. pszObjId++;
  106. } else {
  107. char rgch[36];
  108. LONG lData;
  109. unsigned long *pul = rgulValue;
  110. for (; Count > 0; Count--, pul++) {
  111. _ltoa(*pul, rgch, 10);
  112. lData = strlen(rgch);
  113. lRemain -= lData + 1;
  114. if (lRemain >= 0) {
  115. if (lData > 0) {
  116. memcpy(pszObjId, rgch, lData);
  117. pszObjId += lData;
  118. }
  119. *pszObjId++ = '.';
  120. }
  121. }
  122. }
  123. if (lRemain >= 0) {
  124. *(pszObjId -1) = '\0';
  125. *pcbObjId = *pcbObjId - (DWORD) lRemain;
  126. } else {
  127. *pcbObjId = *pcbObjId + (DWORD) -lRemain;
  128. if (pszObjId) {
  129. SetLastError((DWORD) ERROR_MORE_DATA);
  130. fResult = FALSE;
  131. }
  132. }
  133. return fResult;
  134. }
  135. //+-------------------------------------------------------------------------
  136. // Adjust FILETIME for timezone.
  137. //
  138. // Returns FALSE iff conversion failed.
  139. //--------------------------------------------------------------------------
  140. static BOOL AdjustFileTime(
  141. IN OUT LPFILETIME pFileTime,
  142. IN short mindiff,
  143. IN ossBoolean utc
  144. )
  145. {
  146. if (utc || mindiff == 0)
  147. return TRUE;
  148. BOOL fResult;
  149. SYSTEMTIME stmDiff;
  150. FILETIME ftmDiff;
  151. short absmindiff;
  152. memset(&stmDiff, 0, sizeof(stmDiff));
  153. // Note: FILETIME is 100 nanoseconds interval since January 1, 1601
  154. stmDiff.wYear = 1601;
  155. stmDiff.wMonth = 1;
  156. stmDiff.wDay = 1;
  157. absmindiff = mindiff > 0 ? mindiff : -mindiff;
  158. stmDiff.wHour = absmindiff / 60;
  159. stmDiff.wMinute = absmindiff % 60;
  160. if (stmDiff.wHour >= 24) {
  161. stmDiff.wDay += stmDiff.wHour / 24;
  162. stmDiff.wHour %= 24;
  163. }
  164. // Note, FILETIME is only 32 bit aligned. __int64 is 64 bit aligned.
  165. if ((fResult = SystemTimeToFileTime(&stmDiff, &ftmDiff))) {
  166. unsigned __int64 uTime;
  167. unsigned __int64 uDiff;
  168. memcpy(&uTime, pFileTime, sizeof(uTime));
  169. memcpy(&uDiff, &ftmDiff, sizeof(uDiff));
  170. if (mindiff > 0)
  171. uTime += uDiff;
  172. else
  173. uTime -= uDiff;
  174. memcpy(pFileTime, &uTime, sizeof(*pFileTime));
  175. }
  176. return fResult;
  177. }
  178. //+-------------------------------------------------------------------------
  179. // Convert FILETIME to OSS's UTCTime.
  180. //
  181. // Returns TRUE for a successful conversion
  182. //--------------------------------------------------------------------------
  183. BOOL
  184. WINAPI
  185. OssConvToUTCTime(
  186. IN LPFILETIME pFileTime,
  187. OUT UTCTime *pOssTime
  188. )
  189. {
  190. BOOL fRet;
  191. SYSTEMTIME t;
  192. memset(pOssTime, 0, sizeof(*pOssTime));
  193. if (!FileTimeToSystemTime(pFileTime, &t))
  194. goto FileTimeToSystemTimeError;
  195. if (t.wYear < YEARFIRST || t.wYear > YEARLAST)
  196. goto YearRangeError;
  197. pOssTime->year = t.wYear % 100;
  198. pOssTime->month = t.wMonth;
  199. pOssTime->day = t.wDay;
  200. pOssTime->hour = t.wHour;
  201. pOssTime->minute = t.wMinute;
  202. pOssTime->second = t.wSecond;
  203. pOssTime->utc = TRUE;
  204. fRet = TRUE;
  205. CommonReturn:
  206. return fRet;
  207. ErrorReturn:
  208. fRet = FALSE;
  209. goto CommonReturn;
  210. TRACE_ERROR(FileTimeToSystemTimeError)
  211. TRACE_ERROR(YearRangeError)
  212. }
  213. //+-------------------------------------------------------------------------
  214. // Convert from OSS's UTCTime to FILETIME.
  215. //
  216. // Returns TRUE for a successful conversion
  217. //--------------------------------------------------------------------------
  218. BOOL
  219. WINAPI
  220. OssConvFromUTCTime(
  221. IN UTCTime *pOssTime,
  222. OUT LPFILETIME pFileTime
  223. )
  224. {
  225. BOOL fRet;
  226. SYSTEMTIME t;
  227. memset(&t, 0, sizeof(t));
  228. t.wYear = pOssTime->year >= MAGICYEAR ?
  229. (1900 + pOssTime->year) : (2000 + pOssTime->year);
  230. t.wMonth = pOssTime->month;
  231. t.wDay = pOssTime->day;
  232. t.wHour = pOssTime->hour;
  233. t.wMinute = pOssTime->minute;
  234. t.wSecond = pOssTime->second;
  235. if (!SystemTimeToFileTime(&t, pFileTime))
  236. goto SystemTimeToFileTimeError;
  237. fRet = AdjustFileTime(
  238. pFileTime,
  239. pOssTime->mindiff,
  240. pOssTime->utc
  241. );
  242. CommonReturn:
  243. return fRet;
  244. ErrorReturn:
  245. fRet = FALSE;
  246. goto CommonReturn;
  247. TRACE_ERROR(SystemTimeToFileTimeError)
  248. }
  249. //+-------------------------------------------------------------------------
  250. // Convert FILETIME to OSS's GeneralizedTime.
  251. //
  252. // Returns TRUE for a successful conversion
  253. //--------------------------------------------------------------------------
  254. BOOL
  255. WINAPI
  256. OssConvToGeneralizedTime(
  257. IN LPFILETIME pFileTime,
  258. OUT GeneralizedTime *pOssTime
  259. )
  260. {
  261. BOOL fRet;
  262. SYSTEMTIME t;
  263. memset(pOssTime, 0, sizeof(*pOssTime));
  264. if (!FileTimeToSystemTime(pFileTime, &t))
  265. goto FileTimeToSystemTimeError;
  266. pOssTime->year = t.wYear;
  267. pOssTime->month = t.wMonth;
  268. pOssTime->day = t.wDay;
  269. pOssTime->hour = t.wHour;
  270. pOssTime->minute = t.wMinute;
  271. pOssTime->second = t.wSecond;
  272. pOssTime->millisec = t.wMilliseconds;
  273. pOssTime->utc = TRUE;
  274. fRet = TRUE;
  275. CommonReturn:
  276. return fRet;
  277. ErrorReturn:
  278. fRet = FALSE;
  279. goto CommonReturn;
  280. TRACE_ERROR(FileTimeToSystemTimeError)
  281. }
  282. //+-------------------------------------------------------------------------
  283. // Convert from OSS's GeneralizedTime to FILETIME.
  284. //
  285. // Returns TRUE for a successful conversion
  286. //--------------------------------------------------------------------------
  287. BOOL
  288. WINAPI
  289. OssConvFromGeneralizedTime(
  290. IN GeneralizedTime *pOssTime,
  291. OUT LPFILETIME pFileTime
  292. )
  293. {
  294. BOOL fRet;
  295. SYSTEMTIME t;
  296. memset(&t, 0, sizeof(t));
  297. t.wYear = pOssTime->year;
  298. t.wMonth = pOssTime->month;
  299. t.wDay = pOssTime->day;
  300. t.wHour = pOssTime->hour;
  301. t.wMinute = pOssTime->minute;
  302. t.wSecond = pOssTime->second;
  303. t.wMilliseconds = pOssTime->millisec;
  304. if (!SystemTimeToFileTime(&t, pFileTime))
  305. goto SystemTimeToFileTimeError;
  306. fRet = AdjustFileTime(
  307. pFileTime,
  308. pOssTime->mindiff,
  309. pOssTime->utc
  310. );
  311. CommonReturn:
  312. return fRet;
  313. ErrorReturn:
  314. fRet = FALSE;
  315. goto CommonReturn;
  316. TRACE_ERROR(SystemTimeToFileTimeError)
  317. }
  318. //+-------------------------------------------------------------------------
  319. // Convert FILETIME to OSS's UTCTime or GeneralizedTime.
  320. //
  321. // If 1950 < FILETIME < 2005, then UTCTime is chosen. Otherwise,
  322. // GeneralizedTime is chosen. GeneralizedTime values shall not include
  323. // fractional seconds.
  324. //
  325. // Returns TRUE for a successful conversion
  326. //
  327. // Note, in asn1hdr.h, UTCTime has same typedef as GeneralizedTime.
  328. //--------------------------------------------------------------------------
  329. BOOL
  330. WINAPI
  331. OssConvToChoiceOfTime(
  332. IN LPFILETIME pFileTime,
  333. OUT WORD *pwChoice,
  334. OUT GeneralizedTime *pOssTime
  335. )
  336. {
  337. BOOL fRet;
  338. SYSTEMTIME t;
  339. memset(pOssTime, 0, sizeof(*pOssTime));
  340. if (!FileTimeToSystemTime(pFileTime, &t))
  341. goto FileTimeToSystemTimeError;
  342. if (t.wYear < YEARFIRST || t.wYear >= YEARFIRSTGENERALIZED) {
  343. *pwChoice = OSS_GENERALIZED_TIME_CHOICE;
  344. pOssTime->year = t.wYear;
  345. } else {
  346. *pwChoice = OSS_UTC_TIME_CHOICE;
  347. pOssTime->year = t.wYear % 100;
  348. }
  349. pOssTime->month = t.wMonth;
  350. pOssTime->day = t.wDay;
  351. pOssTime->hour = t.wHour;
  352. pOssTime->minute = t.wMinute;
  353. pOssTime->second = t.wSecond;
  354. pOssTime->utc = TRUE;
  355. fRet = TRUE;
  356. CommonReturn:
  357. return fRet;
  358. ErrorReturn:
  359. fRet = FALSE;
  360. *pwChoice = 0;
  361. goto CommonReturn;
  362. TRACE_ERROR(FileTimeToSystemTimeError)
  363. }
  364. //+-------------------------------------------------------------------------
  365. // Convert from OSS's UTCTime or GeneralizedTime to FILETIME.
  366. //
  367. // Returns TRUE for a successful conversion.
  368. //
  369. // Note, in asn1hdr.h, UTCTime has same typedef as GeneralizedTime.
  370. //--------------------------------------------------------------------------
  371. BOOL
  372. WINAPI
  373. OssConvFromChoiceOfTime(
  374. IN WORD wChoice,
  375. IN GeneralizedTime *pOssTime,
  376. OUT LPFILETIME pFileTime
  377. )
  378. {
  379. if (OSS_UTC_TIME_CHOICE == wChoice)
  380. return OssConvFromUTCTime(pOssTime, pFileTime);
  381. else
  382. return OssConvFromGeneralizedTime(pOssTime, pFileTime);
  383. }