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.

1548 lines
43 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: PkiAsn1ErrToHr
  11. // PkiAsn1Encode
  12. // PkiAsn1Decode
  13. // PkiAsn1SetEncodingRule
  14. // PkiAsn1GetEncodingRule
  15. //
  16. // PkiAsn1ReverseBytes
  17. // PkiAsn1AllocAndReverseBytes
  18. // PkiAsn1GetOctetString
  19. // PkiAsn1SetHugeInteger
  20. // PkiAsn1FreeHugeInteger
  21. // PkiAsn1GetHugeInteger
  22. // PkiAsn1SetHugeUINT
  23. // PkiAsn1GetHugeUINT
  24. // PkiAsn1SetBitString
  25. // PkiAsn1GetBitString
  26. // PkiAsn1GetIA5String
  27. // PkiAsn1SetUnicodeConvertedToIA5String
  28. // PkiAsn1FreeUnicodeConvertedToIA5String
  29. // PkiAsn1GetIA5StringConvertedToUnicode
  30. // PkiAsn1GetBMPString
  31. // PkiAsn1SetAny
  32. // PkiAsn1GetAny
  33. // PkiAsn1EncodeInfoEx
  34. // PkiAsn1EncodeInfo
  35. // PkiAsn1DecodeAndAllocInfo
  36. // PkiAsn1AllocStructInfoEx
  37. // PkiAsn1DecodeAndAllocInfoEx
  38. //
  39. // PkiAsn1ToObjectIdentifier
  40. // PkiAsn1FromObjectIdentifier
  41. // PkiAsn1ToUTCTime
  42. // PkiAsn1FromUTCTime
  43. // PkiAsn1ToGeneralizedTime
  44. // PkiAsn1FromGeneralizedTime
  45. // PkiAsn1ToChoiceOfTime
  46. // PkiAsn1FromChoiceOfTime
  47. //
  48. // The Get functions decrement *plRemainExtra and advance
  49. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  50. // with the length calculation but stop doing any copies.
  51. // The functions don't return an error for a negative *plRemainExtra.
  52. //
  53. // According to the <draft-ietf-pkix-ipki-part1-04.txt> :
  54. // For UTCTime. Where YY is greater than 50, the year shall
  55. // be interpreted as 19YY. Where YY is less than or equal to
  56. // 50, the year shall be interpreted as 20YY.
  57. //
  58. // History: 23-Oct-98 philh created
  59. //--------------------------------------------------------------------------
  60. #ifdef SMIME_V3
  61. #include <windows.h>
  62. #include "msasn1.h"
  63. #include "msber.h"
  64. #include "utf8.h"
  65. #include "crypttls.h"
  66. #include "badstrfunctions.h"
  67. #include "demand2.h"
  68. #include "pkiasn1.h"
  69. //#include "pkialloc.h"
  70. //#include "global.hxx"
  71. #include <dbgdef.h>
  72. #define assert(a)
  73. // All the *pvInfo extra stuff needs to be aligned
  74. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  75. #define MSASN1_SUPPORTS_NOCOPY
  76. #define wcslen my_wcslen
  77. extern int my_wcslen(LPCWSTR pwsz)
  78. {
  79. int i = 0;
  80. while (*pwsz++ != 0) i += 1;
  81. return i;
  82. }
  83. //
  84. // UTCTime in X.509 certs are represented using a 2-digit year
  85. // field (yuk! but true).
  86. //
  87. // According to IETF draft, YY years greater than this are
  88. // to be interpreted as 19YY; YY years less than this are 20YY. Sigh.
  89. //
  90. #define MAGICYEAR 50
  91. #define YEARFIRST 1951
  92. #define YEARLAST 2050
  93. #define YEARFIRSTGENERALIZED 2050
  94. inline BOOL my_isdigit( char ch)
  95. {
  96. return (ch >= '0') && (ch <= '9');
  97. }
  98. //+-------------------------------------------------------------------------
  99. // Asn1 Encode function. The encoded output is allocated and must be freed
  100. // by calling PkiAsn1FreeEncoded().
  101. //--------------------------------------------------------------------------
  102. ASN1error_e
  103. WINAPI
  104. PkiAsn1Encode(
  105. IN ASN1encoding_t pEnc,
  106. IN void *pvAsn1Info,
  107. IN ASN1uint32_t id,
  108. OUT BYTE **ppbEncoded,
  109. OUT DWORD *pcbEncoded
  110. )
  111. {
  112. ASN1error_e Asn1Err;
  113. Asn1Err = ASN1_Encode(
  114. pEnc,
  115. pvAsn1Info,
  116. id,
  117. ASN1ENCODE_ALLOCATEBUFFER,
  118. NULL, // pbBuf
  119. 0 // cbBufSize
  120. );
  121. if (ASN1_SUCCEEDED(Asn1Err)) {
  122. Asn1Err = ASN1_SUCCESS;
  123. *ppbEncoded = pEnc->buf;
  124. *pcbEncoded = pEnc->len;
  125. } else {
  126. *ppbEncoded = NULL;
  127. *pcbEncoded = 0;
  128. }
  129. return Asn1Err;
  130. }
  131. //+-------------------------------------------------------------------------
  132. // Asn1 Encode function. The encoded output isn't allocated.
  133. //
  134. // If pbEncoded is NULL, does a length only calculation.
  135. //--------------------------------------------------------------------------
  136. ASN1error_e
  137. WINAPI
  138. PkiAsn1Encode2(
  139. IN ASN1encoding_t pEnc,
  140. IN void *pvAsn1Info,
  141. IN ASN1uint32_t id,
  142. OUT OPTIONAL BYTE *pbEncoded,
  143. IN OUT DWORD *pcbEncoded
  144. )
  145. {
  146. ASN1error_e Asn1Err;
  147. DWORD cbEncoded;
  148. if (NULL == pbEncoded)
  149. cbEncoded = 0;
  150. else
  151. cbEncoded = *pcbEncoded;
  152. if (0 == cbEncoded) {
  153. // Length only calculation
  154. Asn1Err = ASN1_Encode(
  155. pEnc,
  156. pvAsn1Info,
  157. id,
  158. ASN1ENCODE_ALLOCATEBUFFER,
  159. NULL, // pbBuf
  160. 0 // cbBufSize
  161. );
  162. if (ASN1_SUCCEEDED(Asn1Err)) {
  163. if (pbEncoded)
  164. Asn1Err = ASN1_ERR_OVERFLOW;
  165. else
  166. Asn1Err = ASN1_SUCCESS;
  167. cbEncoded = pEnc->len;
  168. PkiAsn1FreeEncoded(pEnc, pEnc->buf);
  169. }
  170. } else {
  171. Asn1Err = ASN1_Encode(
  172. pEnc,
  173. pvAsn1Info,
  174. id,
  175. ASN1ENCODE_SETBUFFER,
  176. pbEncoded,
  177. cbEncoded
  178. );
  179. if (ASN1_SUCCEEDED(Asn1Err)) {
  180. Asn1Err = ASN1_SUCCESS;
  181. cbEncoded = pEnc->len;
  182. } else if (ASN1_ERR_OVERFLOW == Asn1Err) {
  183. // Re-do as length only calculation
  184. Asn1Err = PkiAsn1Encode2(
  185. pEnc,
  186. pvAsn1Info,
  187. id,
  188. NULL, // pbEncoded
  189. &cbEncoded
  190. );
  191. if (ASN1_SUCCESS == Asn1Err)
  192. Asn1Err = ASN1_ERR_OVERFLOW;
  193. } else
  194. cbEncoded = 0;
  195. }
  196. *pcbEncoded = cbEncoded;
  197. return Asn1Err;
  198. }
  199. //+-------------------------------------------------------------------------
  200. // Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
  201. // be freed by calling PkiAsn1FreeDecoded().
  202. //--------------------------------------------------------------------------
  203. ASN1error_e
  204. WINAPI
  205. PkiAsn1Decode(
  206. IN ASN1decoding_t pDec,
  207. OUT void **ppvAsn1Info,
  208. IN ASN1uint32_t id,
  209. IN const BYTE *pbEncoded,
  210. IN DWORD cbEncoded
  211. )
  212. {
  213. ASN1error_e Asn1Err;
  214. *ppvAsn1Info = NULL;
  215. Asn1Err = ASN1_Decode(
  216. pDec,
  217. ppvAsn1Info,
  218. id,
  219. ASN1DECODE_SETBUFFER,
  220. (BYTE *) pbEncoded,
  221. cbEncoded
  222. );
  223. if (ASN1_SUCCEEDED(Asn1Err))
  224. Asn1Err = ASN1_SUCCESS;
  225. else {
  226. if (ASN1_ERR_BADARGS == Asn1Err)
  227. Asn1Err = ASN1_ERR_EOD;
  228. *ppvAsn1Info = NULL;
  229. }
  230. return Asn1Err;
  231. }
  232. //+-------------------------------------------------------------------------
  233. // Asn1 Decode function. The allocated, decoded structure, **pvAsn1Info, must
  234. // be freed by calling PkiAsn1FreeDecoded().
  235. //
  236. // For a successful decode, *ppbEncoded is advanced
  237. // past the decoded bytes and *pcbDecoded is decremented by the number
  238. // of decoded bytes.
  239. //--------------------------------------------------------------------------
  240. ASN1error_e
  241. WINAPI
  242. PkiAsn1Decode2(
  243. IN ASN1decoding_t pDec,
  244. OUT void **ppvAsn1Info,
  245. IN ASN1uint32_t id,
  246. IN OUT BYTE **ppbEncoded,
  247. IN OUT DWORD *pcbEncoded
  248. )
  249. {
  250. ASN1error_e Asn1Err;
  251. *ppvAsn1Info = NULL;
  252. Asn1Err = ASN1_Decode(
  253. pDec,
  254. ppvAsn1Info,
  255. id,
  256. ASN1DECODE_SETBUFFER,
  257. *ppbEncoded,
  258. *pcbEncoded
  259. );
  260. if (ASN1_SUCCEEDED(Asn1Err)) {
  261. Asn1Err = ASN1_SUCCESS;
  262. *ppbEncoded += pDec->len;
  263. *pcbEncoded -= pDec->len;
  264. } else {
  265. if (ASN1_ERR_BADARGS == Asn1Err)
  266. Asn1Err = ASN1_ERR_EOD;
  267. *ppvAsn1Info = NULL;
  268. }
  269. return Asn1Err;
  270. }
  271. //+-------------------------------------------------------------------------
  272. // Asn1 Set/Get encoding rules functions
  273. //--------------------------------------------------------------------------
  274. ASN1error_e
  275. WINAPI
  276. PkiAsn1SetEncodingRule(
  277. IN ASN1encoding_t pEnc,
  278. IN ASN1encodingrule_e eRule
  279. )
  280. {
  281. ASN1optionparam_s OptParam;
  282. OptParam.eOption = ASN1OPT_CHANGE_RULE;
  283. OptParam.eRule = eRule;
  284. return ASN1_SetEncoderOption(pEnc, &OptParam);
  285. }
  286. ASN1encodingrule_e
  287. WINAPI
  288. PkiAsn1GetEncodingRule(
  289. IN ASN1encoding_t pEnc
  290. )
  291. {
  292. ASN1error_e Asn1Err;
  293. ASN1encodingrule_e eRule;
  294. ASN1optionparam_s OptParam;
  295. OptParam.eOption = ASN1OPT_GET_RULE;
  296. Asn1Err = ASN1_GetEncoderOption(pEnc, &OptParam);
  297. if (ASN1_SUCCEEDED(Asn1Err))
  298. eRule = OptParam.eRule;
  299. else
  300. eRule = ASN1_BER_RULE_DER;
  301. return eRule;
  302. }
  303. //+-------------------------------------------------------------------------
  304. // Reverses a buffer of bytes in place
  305. //--------------------------------------------------------------------------
  306. void
  307. WINAPI
  308. PkiAsn1ReverseBytes(
  309. IN OUT PBYTE pbIn,
  310. IN DWORD cbIn
  311. )
  312. {
  313. // reverse in place
  314. PBYTE pbLo;
  315. PBYTE pbHi;
  316. BYTE bTmp;
  317. for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
  318. bTmp = *pbHi;
  319. *pbHi = *pbLo;
  320. *pbLo = bTmp;
  321. }
  322. }
  323. //+-------------------------------------------------------------------------
  324. // Reverses a buffer of bytes to a new buffer. PkiAsn1Free() must be
  325. // called to free allocated bytes.
  326. //--------------------------------------------------------------------------
  327. PBYTE
  328. WINAPI
  329. PkiAsn1AllocAndReverseBytes(
  330. IN PBYTE pbIn,
  331. IN DWORD cbIn
  332. )
  333. {
  334. PBYTE pbOut;
  335. PBYTE pbSrc;
  336. PBYTE pbDst;
  337. DWORD cb;
  338. if (NULL == (pbOut = (PBYTE)PkiAsn1Alloc(cbIn)))
  339. return NULL;
  340. for (pbSrc = pbIn, pbDst = pbOut + cbIn - 1, cb = cbIn; cb > 0; cb--)
  341. *pbDst-- = *pbSrc++;
  342. return pbOut;
  343. }
  344. //+-------------------------------------------------------------------------
  345. // Get Octet String
  346. //--------------------------------------------------------------------------
  347. void
  348. WINAPI
  349. PkiAsn1GetOctetString(
  350. IN ASN1uint32_t Asn1Length,
  351. IN ASN1octet_t *pAsn1Value,
  352. IN DWORD dwFlags,
  353. OUT PCRYPT_DATA_BLOB pInfo,
  354. IN OUT BYTE **ppbExtra,
  355. IN OUT LONG *plRemainExtra
  356. )
  357. {
  358. #ifndef MSASN1_SUPPORTS_NOCOPY
  359. dwFlags &= ~CRYPT_DECODE_NOCOPY_FLAG;
  360. #endif
  361. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
  362. if (*plRemainExtra >= 0) {
  363. pInfo->cbData = Asn1Length;
  364. pInfo->pbData = pAsn1Value;
  365. }
  366. } else {
  367. LONG lRemainExtra = *plRemainExtra;
  368. BYTE *pbExtra = *ppbExtra;
  369. LONG lAlignExtra;
  370. LONG lData;
  371. lData = (LONG) Asn1Length;
  372. lAlignExtra = INFO_LEN_ALIGN(lData);
  373. lRemainExtra -= lAlignExtra;
  374. if (lRemainExtra >= 0) {
  375. if (lData > 0) {
  376. pInfo->pbData = pbExtra;
  377. pInfo->cbData = (DWORD) lData;
  378. memcpy(pbExtra, pAsn1Value, lData);
  379. } else
  380. memset(pInfo, 0, sizeof(*pInfo));
  381. pbExtra += lAlignExtra;
  382. }
  383. *plRemainExtra = lRemainExtra;
  384. *ppbExtra = pbExtra;
  385. }
  386. }
  387. //+-------------------------------------------------------------------------
  388. // Set/Free/Get HugeInteger
  389. //
  390. // For PkiAsn1SetHugeInteger, PkiAsn1FreeHugeInteger must be called to free
  391. // the allocated Asn1Value.
  392. //--------------------------------------------------------------------------
  393. BOOL
  394. WINAPI
  395. PkiAsn1SetHugeInteger(
  396. IN PCRYPT_INTEGER_BLOB pInfo,
  397. OUT ASN1uint32_t *pAsn1Length,
  398. OUT ASN1octet_t **ppAsn1Value
  399. )
  400. {
  401. if (pInfo->cbData > 0) {
  402. if (NULL == (*ppAsn1Value = PkiAsn1AllocAndReverseBytes(
  403. pInfo->pbData, pInfo->cbData))) {
  404. *pAsn1Length = 0;
  405. return FALSE;
  406. }
  407. } else
  408. *ppAsn1Value = NULL;
  409. *pAsn1Length = pInfo->cbData;
  410. return TRUE;
  411. }
  412. void
  413. WINAPI
  414. PkiAsn1FreeHugeInteger(
  415. IN ASN1octet_t *pAsn1Value
  416. )
  417. {
  418. // Only for BYTE reversal
  419. PkiAsn1Free(pAsn1Value);
  420. }
  421. void
  422. WINAPI
  423. PkiAsn1GetHugeInteger(
  424. IN ASN1uint32_t Asn1Length,
  425. IN ASN1octet_t *pAsn1Value,
  426. IN DWORD dwFlags,
  427. OUT PCRYPT_INTEGER_BLOB pInfo,
  428. IN OUT BYTE **ppbExtra,
  429. IN OUT LONG *plRemainExtra
  430. )
  431. {
  432. // Since bytes need to be reversed, always need to do a copy (dwFlags = 0)
  433. PkiAsn1GetOctetString(Asn1Length, pAsn1Value, 0,
  434. pInfo, ppbExtra, plRemainExtra);
  435. if (*plRemainExtra >= 0 && pInfo->cbData > 0)
  436. PkiAsn1ReverseBytes(pInfo->pbData, pInfo->cbData);
  437. }
  438. //+-------------------------------------------------------------------------
  439. // Set/Free/Get Huge Unsigned Integer
  440. //
  441. // Set inserts a leading 0x00 before reversing. Note, any extra leading
  442. // 0x00's are removed by ASN1 before ASN.1 encoding.
  443. //
  444. // Get removes a leading 0x00 if present, after reversing.
  445. //
  446. // PkiAsn1FreeHugeUINT must be called to free the allocated Asn1Value.
  447. // PkiAsn1FreeHugeUINT has been #define'd to PkiAsn1FreeHugeInteger.
  448. //--------------------------------------------------------------------------
  449. BOOL
  450. WINAPI
  451. PkiAsn1SetHugeUINT(
  452. IN PCRYPT_UINT_BLOB pInfo,
  453. OUT ASN1uint32_t *pAsn1Length,
  454. OUT ASN1octet_t **ppAsn1Value
  455. )
  456. {
  457. BOOL fResult;
  458. DWORD cb = pInfo->cbData;
  459. BYTE *pb;
  460. DWORD i;
  461. if (cb > 0) {
  462. if (NULL == (pb = (BYTE *) PkiAsn1Alloc(cb + 1)))
  463. goto ErrorReturn;
  464. *pb = 0x00;
  465. for (i = 0; i < cb; i++)
  466. pb[1 + i] = pInfo->pbData[cb - 1 - i];
  467. cb++;
  468. } else
  469. pb = NULL;
  470. fResult = TRUE;
  471. CommonReturn:
  472. *pAsn1Length = cb;
  473. *ppAsn1Value = pb;
  474. return fResult;
  475. ErrorReturn:
  476. cb = 0;
  477. fResult = FALSE;
  478. goto CommonReturn;
  479. }
  480. void
  481. WINAPI
  482. PkiAsn1GetHugeUINT(
  483. IN ASN1uint32_t Asn1Length,
  484. IN ASN1octet_t *pAsn1Value,
  485. IN DWORD dwFlags,
  486. OUT PCRYPT_UINT_BLOB pInfo,
  487. IN OUT BYTE **ppbExtra,
  488. IN OUT LONG *plRemainExtra
  489. )
  490. {
  491. // Check for and advance past a leading 0x00.
  492. if (Asn1Length > 1 && *pAsn1Value == 0) {
  493. pAsn1Value++;
  494. Asn1Length--;
  495. }
  496. PkiAsn1GetHugeInteger(
  497. Asn1Length,
  498. pAsn1Value,
  499. dwFlags,
  500. pInfo,
  501. ppbExtra,
  502. plRemainExtra
  503. );
  504. }
  505. //+-------------------------------------------------------------------------
  506. // Set/Get BitString
  507. //--------------------------------------------------------------------------
  508. void
  509. WINAPI
  510. PkiAsn1SetBitString(
  511. IN PCRYPT_BIT_BLOB pInfo,
  512. OUT ASN1uint32_t *pAsn1BitLength,
  513. OUT ASN1octet_t **ppAsn1Value
  514. )
  515. {
  516. if (pInfo->cbData) {
  517. *ppAsn1Value = pInfo->pbData;
  518. assert(pInfo->cUnusedBits <= 7);
  519. *pAsn1BitLength = pInfo->cbData * 8 - pInfo->cUnusedBits;
  520. } else {
  521. *ppAsn1Value = NULL;
  522. *pAsn1BitLength = 0;
  523. }
  524. }
  525. static const BYTE rgbUnusedAndMask[8] =
  526. {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
  527. void
  528. WINAPI
  529. PkiAsn1GetBitString(
  530. IN ASN1uint32_t Asn1BitLength,
  531. IN ASN1octet_t *pAsn1Value,
  532. IN DWORD dwFlags,
  533. OUT PCRYPT_BIT_BLOB pInfo,
  534. IN OUT BYTE **ppbExtra,
  535. IN OUT LONG *plRemainExtra
  536. )
  537. {
  538. #ifndef MSASN1_SUPPORTS_NOCOPY
  539. dwFlags &= ~CRYPT_DECODE_NOCOPY_FLAG;
  540. #endif
  541. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG && 0 == (Asn1BitLength % 8)) {
  542. if (*plRemainExtra >= 0) {
  543. pInfo->cbData = Asn1BitLength / 8;
  544. pInfo->cUnusedBits = 0;
  545. pInfo->pbData = pAsn1Value;
  546. }
  547. } else {
  548. LONG lRemainExtra = *plRemainExtra;
  549. BYTE *pbExtra = *ppbExtra;
  550. LONG lAlignExtra;
  551. LONG lData;
  552. DWORD cUnusedBits;
  553. lData = (LONG) Asn1BitLength / 8;
  554. cUnusedBits = Asn1BitLength % 8;
  555. if (cUnusedBits) {
  556. cUnusedBits = 8 - cUnusedBits;
  557. lData++;
  558. }
  559. lAlignExtra = INFO_LEN_ALIGN(lData);
  560. lRemainExtra -= lAlignExtra;
  561. if (lRemainExtra >= 0) {
  562. if (lData > 0) {
  563. pInfo->pbData = pbExtra;
  564. pInfo->cbData = (DWORD) lData;
  565. pInfo->cUnusedBits = cUnusedBits;
  566. memcpy(pbExtra, pAsn1Value, lData);
  567. if (cUnusedBits)
  568. *(pbExtra + lData - 1) &= rgbUnusedAndMask[cUnusedBits];
  569. } else
  570. memset(pInfo, 0, sizeof(*pInfo));
  571. pbExtra += lAlignExtra;
  572. }
  573. *plRemainExtra = lRemainExtra;
  574. *ppbExtra = pbExtra;
  575. }
  576. }
  577. //+-------------------------------------------------------------------------
  578. // Get IA5 String
  579. //--------------------------------------------------------------------------
  580. void
  581. WINAPI
  582. PkiAsn1GetIA5String(
  583. IN ASN1uint32_t Asn1Length,
  584. IN ASN1char_t *pAsn1Value,
  585. IN DWORD dwFlags,
  586. OUT LPSTR *ppsz,
  587. IN OUT BYTE **ppbExtra,
  588. IN OUT LONG *plRemainExtra
  589. )
  590. {
  591. LONG lRemainExtra = *plRemainExtra;
  592. BYTE *pbExtra = *ppbExtra;
  593. LONG lAlignExtra;
  594. LONG lData;
  595. lData = (LONG) Asn1Length;
  596. lAlignExtra = INFO_LEN_ALIGN(lData + 1);
  597. lRemainExtra -= lAlignExtra;
  598. if (lRemainExtra >= 0) {
  599. if (lData > 0)
  600. memcpy(pbExtra, pAsn1Value, lData);
  601. *(pbExtra + lData) = 0;
  602. *ppsz = (LPSTR) pbExtra;
  603. pbExtra += lAlignExtra;
  604. }
  605. *plRemainExtra = lRemainExtra;
  606. *ppbExtra = pbExtra;
  607. }
  608. //+-------------------------------------------------------------------------
  609. // Set/Free/Get Unicode mapped to IA5 String
  610. //--------------------------------------------------------------------------
  611. BOOL
  612. WINAPI
  613. PkiAsn1SetUnicodeConvertedToIA5String(
  614. IN LPWSTR pwsz,
  615. OUT ASN1uint32_t *pAsn1Length,
  616. OUT ASN1char_t **ppAsn1Value
  617. )
  618. {
  619. BOOL fResult;
  620. LPSTR psz = NULL;
  621. int cchUTF8;
  622. int cchWideChar;
  623. int i;
  624. cchWideChar = wcslen(pwsz);
  625. if (cchWideChar == 0) {
  626. *pAsn1Length = 0;
  627. *ppAsn1Value = 0;
  628. return TRUE;
  629. }
  630. // Check that the input string contains valid IA5 characters
  631. for (i = 0; i < cchWideChar; i++) {
  632. if (pwsz[i] > 0x7F) {
  633. SetLastError((DWORD) CRYPT_E_INVALID_IA5_STRING);
  634. *pAsn1Length = (unsigned int) i;
  635. goto InvalidIA5;
  636. }
  637. }
  638. cchUTF8 = WideCharToUTF8(
  639. pwsz,
  640. cchWideChar,
  641. NULL, // lpUTF8Str
  642. 0 // cchUTF8
  643. );
  644. if (cchUTF8 <= 0)
  645. goto ErrorReturn;
  646. if (NULL == (psz = (LPSTR) PkiAsn1Alloc(cchUTF8)))
  647. goto ErrorReturn;
  648. cchUTF8 = WideCharToUTF8(
  649. pwsz,
  650. cchWideChar,
  651. psz,
  652. cchUTF8
  653. );
  654. *ppAsn1Value = psz;
  655. *pAsn1Length = cchUTF8;
  656. fResult = TRUE;
  657. goto CommonReturn;
  658. ErrorReturn:
  659. *pAsn1Length = 0;
  660. InvalidIA5:
  661. *ppAsn1Value = NULL;
  662. fResult = FALSE;
  663. CommonReturn:
  664. return fResult;
  665. }
  666. void
  667. WINAPI
  668. PkiAsn1FreeUnicodeConvertedToIA5String(
  669. IN ASN1char_t *pAsn1Value
  670. )
  671. {
  672. PkiAsn1Free(pAsn1Value);
  673. }
  674. void
  675. WINAPI
  676. PkiAsn1GetIA5StringConvertedToUnicode(
  677. IN ASN1uint32_t Asn1Length,
  678. IN ASN1char_t *pAsn1Value,
  679. IN DWORD dwFlags,
  680. OUT LPWSTR *ppwsz,
  681. IN OUT BYTE **ppbExtra,
  682. IN OUT LONG *plRemainExtra
  683. )
  684. {
  685. LONG lRemainExtra = *plRemainExtra;
  686. BYTE *pbExtra = *ppbExtra;
  687. LONG lAlignExtra;
  688. LONG lData;
  689. int cchWideChar;
  690. cchWideChar = UTF8ToWideChar(
  691. (LPSTR) pAsn1Value,
  692. Asn1Length,
  693. NULL, // lpWideCharStr
  694. 0 // cchWideChar
  695. );
  696. if (cchWideChar > 0)
  697. lData = cchWideChar * sizeof(WCHAR);
  698. else
  699. lData = 0;
  700. lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
  701. lRemainExtra -= lAlignExtra;
  702. if (lRemainExtra >= 0) {
  703. if (lData > 0)
  704. UTF8ToWideChar(pAsn1Value, Asn1Length,
  705. (LPWSTR) pbExtra, cchWideChar);
  706. memset(pbExtra + lData, 0, sizeof(WCHAR));
  707. *ppwsz = (LPWSTR) pbExtra;
  708. pbExtra += lAlignExtra;
  709. }
  710. *plRemainExtra = lRemainExtra;
  711. *ppbExtra = pbExtra;
  712. }
  713. //+-------------------------------------------------------------------------
  714. // Get BMP String
  715. //--------------------------------------------------------------------------
  716. void
  717. WINAPI
  718. PkiAsn1GetBMPString(
  719. IN ASN1uint32_t Asn1Length,
  720. IN ASN1char16_t *pAsn1Value,
  721. IN DWORD dwFlags,
  722. OUT LPWSTR *ppwsz,
  723. IN OUT BYTE **ppbExtra,
  724. IN OUT LONG *plRemainExtra
  725. )
  726. {
  727. LONG lRemainExtra = *plRemainExtra;
  728. BYTE *pbExtra = *ppbExtra;
  729. LONG lAlignExtra;
  730. LONG lData;
  731. lData = (LONG) Asn1Length * sizeof(WCHAR);
  732. lAlignExtra = INFO_LEN_ALIGN(lData + sizeof(WCHAR));
  733. lRemainExtra -= lAlignExtra;
  734. if (lRemainExtra >= 0) {
  735. if (lData > 0)
  736. memcpy(pbExtra, pAsn1Value, lData);
  737. memset(pbExtra + lData, 0, sizeof(WCHAR));
  738. *ppwsz = (LPWSTR) pbExtra;
  739. pbExtra += lAlignExtra;
  740. }
  741. *plRemainExtra = lRemainExtra;
  742. *ppbExtra = pbExtra;
  743. }
  744. //+-------------------------------------------------------------------------
  745. // Set/Get "Any" DER BLOB
  746. //--------------------------------------------------------------------------
  747. void
  748. WINAPI
  749. PkiAsn1SetAny(
  750. IN PCRYPT_OBJID_BLOB pInfo,
  751. OUT ASN1open_t *pAsn1
  752. )
  753. {
  754. memset(pAsn1, 0, sizeof(*pAsn1));
  755. pAsn1->encoded = pInfo->pbData;
  756. pAsn1->length = pInfo->cbData;
  757. }
  758. void
  759. WINAPI
  760. PkiAsn1GetAny(
  761. IN ASN1open_t *pAsn1,
  762. IN DWORD dwFlags,
  763. OUT PCRYPT_OBJID_BLOB pInfo,
  764. IN OUT BYTE **ppbExtra,
  765. IN OUT LONG *plRemainExtra
  766. )
  767. {
  768. #ifndef MSASN1_SUPPORTS_NOCOPY
  769. dwFlags &= ~CRYPT_DECODE_NOCOPY_FLAG;
  770. #endif
  771. if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) {
  772. if (*plRemainExtra >= 0) {
  773. pInfo->cbData = pAsn1->length;
  774. pInfo->pbData = (BYTE *) pAsn1->encoded;
  775. }
  776. } else {
  777. LONG lRemainExtra = *plRemainExtra;
  778. BYTE *pbExtra = *ppbExtra;
  779. LONG lAlignExtra;
  780. LONG lData;
  781. lData = (LONG) pAsn1->length;
  782. lAlignExtra = INFO_LEN_ALIGN(lData);
  783. lRemainExtra -= lAlignExtra;
  784. if (lRemainExtra >= 0) {
  785. if (lData > 0) {
  786. pInfo->pbData = pbExtra;
  787. pInfo->cbData = (DWORD) lData;
  788. memcpy(pbExtra, pAsn1->encoded, lData);
  789. } else
  790. memset(pInfo, 0, sizeof(*pInfo));
  791. pbExtra += lAlignExtra;
  792. }
  793. *plRemainExtra = lRemainExtra;
  794. *ppbExtra = pbExtra;
  795. }
  796. }
  797. //+-------------------------------------------------------------------------
  798. // Encode an ASN1 formatted info structure.
  799. //
  800. // If CRYPT_ENCODE_ALLOC_FLAG is set, allocate memory for pbEncoded and
  801. // return *((BYTE **) pvEncoded) = pbAllocEncoded. Otherwise,
  802. // pvEncoded points to byte array to be updated.
  803. //--------------------------------------------------------------------------
  804. BOOL
  805. WINAPI
  806. PkiAsn1EncodeInfoEx(
  807. IN ASN1encoding_t pEnc,
  808. IN ASN1uint32_t id,
  809. IN void *pvAsn1Info,
  810. IN DWORD dwFlags,
  811. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  812. OUT OPTIONAL void *pvEncoded,
  813. IN OUT DWORD *pcbEncoded
  814. )
  815. {
  816. BOOL fResult;
  817. ASN1error_e Asn1Err;
  818. DWORD cbEncoded;
  819. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  820. BYTE *pbEncoded;
  821. BYTE *pbAllocEncoded;
  822. PFN_CRYPT_ALLOC pfnAlloc;
  823. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  824. Asn1Err = PkiAsn1Encode(
  825. pEnc,
  826. pvAsn1Info,
  827. id,
  828. &pbEncoded,
  829. &cbEncoded
  830. );
  831. if (ASN1_SUCCESS != Asn1Err) {
  832. *((void **) pvEncoded) = NULL;
  833. goto Asn1EncodeError;
  834. }
  835. pfnAlloc = PkiGetEncodeAllocFunction(pEncodePara);
  836. if (NULL == (pbAllocEncoded = (BYTE *) pfnAlloc(cbEncoded))) {
  837. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  838. *((void **) pvEncoded) = NULL;
  839. goto OutOfMemory;
  840. }
  841. memcpy(pbAllocEncoded, pbEncoded, cbEncoded);
  842. *((BYTE **) pvEncoded) = pbAllocEncoded;
  843. PkiAsn1FreeEncoded(pEnc, pbEncoded);
  844. } else {
  845. cbEncoded = *pcbEncoded;
  846. PkiAsn1SetEncodingRule(pEnc, ASN1_BER_RULE_DER);
  847. Asn1Err = PkiAsn1Encode2(
  848. pEnc,
  849. pvAsn1Info,
  850. id,
  851. (BYTE *) pvEncoded,
  852. &cbEncoded
  853. );
  854. if (ASN1_SUCCESS != Asn1Err) {
  855. if (ASN1_ERR_OVERFLOW == Asn1Err)
  856. goto LengthError;
  857. else
  858. goto Asn1EncodeError;
  859. }
  860. }
  861. fResult = TRUE;
  862. CommonReturn:
  863. *pcbEncoded = cbEncoded;
  864. return fResult;
  865. ErrorReturn:
  866. fResult = FALSE;
  867. goto CommonReturn;
  868. TRACE_ERROR(OutOfMemory)
  869. SET_ERROR(LengthError, ERROR_MORE_DATA)
  870. SET_ERROR_VAR(Asn1EncodeError, PkiAsn1ErrToHr(Asn1Err))
  871. }
  872. //+-------------------------------------------------------------------------
  873. // Encode an ASN1 formatted info structure
  874. //--------------------------------------------------------------------------
  875. BOOL
  876. WINAPI
  877. PkiAsn1EncodeInfo(
  878. IN ASN1encoding_t pEnc,
  879. IN ASN1uint32_t id,
  880. IN void *pvAsn1Info,
  881. OUT OPTIONAL BYTE *pbEncoded,
  882. IN OUT DWORD *pcbEncoded
  883. )
  884. {
  885. return PkiAsn1EncodeInfoEx(
  886. pEnc,
  887. id,
  888. pvAsn1Info,
  889. 0, // dwFlags
  890. NULL, // pEncodePara
  891. pbEncoded,
  892. pcbEncoded
  893. );
  894. }
  895. //+-------------------------------------------------------------------------
  896. // Decode into an allocated, ASN1 formatted info structure
  897. //--------------------------------------------------------------------------
  898. BOOL
  899. WINAPI
  900. PkiAsn1DecodeAndAllocInfo(
  901. IN ASN1decoding_t pDec,
  902. IN ASN1uint32_t id,
  903. IN const BYTE *pbEncoded,
  904. IN DWORD cbEncoded,
  905. OUT void **ppvAsn1Info
  906. )
  907. {
  908. BOOL fResult;
  909. ASN1error_e Asn1Err;
  910. *ppvAsn1Info = NULL;
  911. if (ASN1_SUCCESS != (Asn1Err = PkiAsn1Decode(
  912. pDec,
  913. ppvAsn1Info,
  914. id,
  915. pbEncoded,
  916. cbEncoded
  917. )))
  918. goto Asn1DecodeError;
  919. fResult = TRUE;
  920. CommonReturn:
  921. return fResult;
  922. ErrorReturn:
  923. *ppvAsn1Info = NULL;
  924. fResult = FALSE;
  925. goto CommonReturn;
  926. SET_ERROR_VAR(Asn1DecodeError, PkiAsn1ErrToHr(Asn1Err))
  927. }
  928. //+-------------------------------------------------------------------------
  929. // Call the callback to convert the ASN1 structure into the 'C' structure.
  930. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  931. // structure and call the callback initially to get the length and then
  932. // a second time to update the allocated 'C' structure.
  933. //
  934. // Allocated structure is returned:
  935. // *((void **) pvStructInfo) = pvAllocStructInfo
  936. //--------------------------------------------------------------------------
  937. BOOL
  938. WINAPI
  939. PkiAsn1AllocStructInfoEx(
  940. IN void *pvAsn1Info,
  941. IN DWORD dwFlags,
  942. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  943. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  944. OUT OPTIONAL void *pvStructInfo,
  945. IN OUT DWORD *pcbStructInfo
  946. )
  947. {
  948. BOOL fResult;
  949. LONG lRemainExtra;
  950. DWORD cbStructInfo;
  951. if (NULL == pvStructInfo || (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) {
  952. cbStructInfo = 0;
  953. lRemainExtra = 0;
  954. } else {
  955. cbStructInfo = *pcbStructInfo;
  956. lRemainExtra = (LONG) cbStructInfo;
  957. }
  958. if (!pfnDecodeExCallback(
  959. pvAsn1Info,
  960. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  961. pDecodePara,
  962. pvStructInfo,
  963. &lRemainExtra
  964. )) goto DecodeCallbackError;
  965. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) {
  966. void *pv;
  967. PFN_CRYPT_ALLOC pfnAlloc = PkiGetDecodeAllocFunction(pDecodePara);
  968. assert(0 > lRemainExtra);
  969. lRemainExtra = -lRemainExtra;
  970. cbStructInfo = (DWORD) lRemainExtra;
  971. if (NULL == (pv = pfnAlloc(cbStructInfo)))
  972. goto OutOfMemory;
  973. if (!pfnDecodeExCallback(
  974. pvAsn1Info,
  975. dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
  976. pDecodePara,
  977. pv,
  978. &lRemainExtra
  979. )) {
  980. PFN_CRYPT_FREE pfnFree = PkiGetDecodeFreeFunction(pDecodePara);
  981. pfnFree(pv);
  982. goto DecodeCallbackError;
  983. }
  984. *((void **) pvStructInfo) = pv;
  985. assert(0 <= lRemainExtra);
  986. }
  987. if (0 <= lRemainExtra) {
  988. cbStructInfo = cbStructInfo - (DWORD) lRemainExtra;
  989. } else {
  990. cbStructInfo = cbStructInfo + (DWORD) -lRemainExtra;
  991. if (pvStructInfo) {
  992. SetLastError((DWORD) ERROR_MORE_DATA);
  993. fResult = FALSE;
  994. goto CommonReturn;
  995. }
  996. }
  997. fResult = TRUE;
  998. CommonReturn:
  999. *pcbStructInfo = cbStructInfo;
  1000. return fResult;
  1001. ErrorReturn:
  1002. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  1003. *((void **) pvStructInfo) = NULL;
  1004. cbStructInfo = 0;
  1005. fResult = FALSE;
  1006. goto CommonReturn;
  1007. TRACE_ERROR(DecodeCallbackError)
  1008. TRACE_ERROR(OutOfMemory)
  1009. }
  1010. //+-------------------------------------------------------------------------
  1011. // Decode the ASN1 formatted info structure and call the callback
  1012. // function to convert the ASN1 structure to the 'C' structure.
  1013. //
  1014. // If CRYPT_DECODE_ALLOC_FLAG is set allocate memory for the 'C'
  1015. // structure and call the callback initially to get the length and then
  1016. // a second time to update the allocated 'C' structure.
  1017. //
  1018. // Allocated structure is returned:
  1019. // *((void **) pvStructInfo) = pvAllocStructInfo
  1020. //--------------------------------------------------------------------------
  1021. BOOL
  1022. WINAPI
  1023. PkiAsn1DecodeAndAllocInfoEx(
  1024. IN ASN1decoding_t pDec,
  1025. IN ASN1uint32_t id,
  1026. IN const BYTE *pbEncoded,
  1027. IN DWORD cbEncoded,
  1028. IN DWORD dwFlags,
  1029. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1030. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  1031. OUT OPTIONAL void *pvStructInfo,
  1032. IN OUT DWORD *pcbStructInfo
  1033. )
  1034. {
  1035. BOOL fResult;
  1036. void *pvAsn1Info = NULL;
  1037. if (!PkiAsn1DecodeAndAllocInfo(
  1038. pDec,
  1039. id,
  1040. pbEncoded,
  1041. cbEncoded,
  1042. &pvAsn1Info
  1043. )) goto Asn1DecodeError;
  1044. fResult = PkiAsn1AllocStructInfoEx(
  1045. pvAsn1Info,
  1046. dwFlags,
  1047. pDecodePara,
  1048. pfnDecodeExCallback,
  1049. pvStructInfo,
  1050. pcbStructInfo
  1051. );
  1052. CommonReturn:
  1053. PkiAsn1FreeInfo(pDec, id, pvAsn1Info);
  1054. return fResult;
  1055. ErrorReturn:
  1056. if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
  1057. *((void **) pvStructInfo) = NULL;
  1058. *pcbStructInfo = 0;
  1059. fResult = FALSE;
  1060. goto CommonReturn;
  1061. TRACE_ERROR(Asn1DecodeError)
  1062. }
  1063. //+-------------------------------------------------------------------------
  1064. // Convert the ascii string ("1.2.9999") to ASN1's Object Identifier
  1065. // represented as an array of unsigned longs.
  1066. //
  1067. // Returns TRUE for a successful conversion.
  1068. //--------------------------------------------------------------------------
  1069. BOOL
  1070. WINAPI
  1071. PkiAsn1ToObjectIdentifier(
  1072. IN LPCSTR pszObjId,
  1073. IN OUT ASN1uint16_t *pCount,
  1074. OUT ASN1uint32_t rgulValue[]
  1075. )
  1076. {
  1077. BOOL fResult = TRUE;
  1078. unsigned short c = 0;
  1079. LPSTR psz = (LPSTR) pszObjId;
  1080. char ch;
  1081. if (psz) {
  1082. ASN1uint16_t cMax = *pCount;
  1083. ASN1uint32_t *pul = rgulValue;
  1084. while ((ch = *psz) != '\0' && c++ < cMax) {
  1085. *pul = 0;
  1086. while (my_isdigit(ch = *psz++)) {
  1087. *pul = (*pul * 10) + (ch - '0');
  1088. }
  1089. pul++;
  1090. if (ch != '.')
  1091. break;
  1092. }
  1093. if (ch != '\0')
  1094. fResult = FALSE;
  1095. }
  1096. *pCount = c;
  1097. return fResult;
  1098. }
  1099. //+-------------------------------------------------------------------------
  1100. // Convert from ASN1's Object Identifier represented as an array of
  1101. // unsigned longs to an ascii string ("1.2.9999").
  1102. //
  1103. // Returns TRUE for a successful conversion
  1104. //--------------------------------------------------------------------------
  1105. BOOL
  1106. WINAPI
  1107. PkiAsn1FromObjectIdentifier(
  1108. IN ASN1uint16_t Count,
  1109. IN ASN1uint32_t rgulValue[],
  1110. OUT LPSTR * ppszObjId,
  1111. IN OUT BYTE **ppbExtra,
  1112. IN OUT LONG *plRemainExtra
  1113. )
  1114. {
  1115. BOOL fResult = TRUE;
  1116. LONG lRemain;
  1117. LPSTR pszObjId = NULL;
  1118. if (ppbExtra != NULL) {
  1119. pszObjId = (LPSTR) *ppbExtra;
  1120. }
  1121. lRemain = (LONG) *plRemainExtra;
  1122. if (Count == 0) {
  1123. if (--lRemain > 0)
  1124. pszObjId++;
  1125. } else {
  1126. char rgch[36];
  1127. LONG lData;
  1128. ASN1uint32_t *pul = rgulValue;
  1129. for (; Count > 0; Count--, pul++) {
  1130. _ltoa(*pul, rgch, 10);
  1131. lData = strlen(rgch);
  1132. lRemain -= lData + 1;
  1133. if (lRemain >= 0) {
  1134. if (lData > 0) {
  1135. memcpy(pszObjId, rgch, lData);
  1136. pszObjId += lData;
  1137. }
  1138. *pszObjId++ = '.';
  1139. }
  1140. }
  1141. }
  1142. if (lRemain >= 0) {
  1143. *(pszObjId -1) = '\0';
  1144. *ppszObjId = (LPSTR) *ppbExtra;
  1145. *ppbExtra = (LPBYTE) pszObjId;
  1146. *plRemainExtra = lRemain;
  1147. } else {
  1148. *plRemainExtra = lRemain;
  1149. if (pszObjId) {
  1150. SetLastError((DWORD) ERROR_MORE_DATA);
  1151. fResult = FALSE;
  1152. }
  1153. }
  1154. return fResult;
  1155. }
  1156. //+-------------------------------------------------------------------------
  1157. // Adjust FILETIME for timezone.
  1158. //
  1159. // Returns FALSE iff conversion failed.
  1160. //--------------------------------------------------------------------------
  1161. static BOOL AdjustFileTime(
  1162. IN OUT LPFILETIME pFileTime,
  1163. IN ASN1int16_t mindiff,
  1164. IN ASN1bool_t utc
  1165. )
  1166. {
  1167. if (utc || mindiff == 0)
  1168. return TRUE;
  1169. BOOL fResult;
  1170. SYSTEMTIME stmDiff;
  1171. FILETIME ftmDiff;
  1172. short absmindiff;
  1173. memset(&stmDiff, 0, sizeof(stmDiff));
  1174. // Note: FILETIME is 100 nanoseconds interval since January 1, 1601
  1175. stmDiff.wYear = 1601;
  1176. stmDiff.wMonth = 1;
  1177. stmDiff.wDay = 1;
  1178. absmindiff = mindiff > 0 ? mindiff : -mindiff;
  1179. stmDiff.wHour = absmindiff / 60;
  1180. stmDiff.wMinute = absmindiff % 60;
  1181. if (stmDiff.wHour >= 24) {
  1182. stmDiff.wDay += stmDiff.wHour / 24;
  1183. stmDiff.wHour %= 24;
  1184. }
  1185. // Note, FILETIME is only 32 bit aligned. __int64 is 64 bit aligned.
  1186. if ((fResult = SystemTimeToFileTime(&stmDiff, &ftmDiff))) {
  1187. unsigned __int64 uTime;
  1188. unsigned __int64 uDiff;
  1189. memcpy(&uTime, pFileTime, sizeof(uTime));
  1190. memcpy(&uDiff, &ftmDiff, sizeof(uDiff));
  1191. if (mindiff > 0)
  1192. uTime += uDiff;
  1193. else
  1194. uTime -= uDiff;
  1195. memcpy(pFileTime, &uTime, sizeof(*pFileTime));
  1196. }
  1197. return fResult;
  1198. }
  1199. //+-------------------------------------------------------------------------
  1200. // Convert FILETIME to ASN1's UTCTime.
  1201. //
  1202. // Returns TRUE for a successful conversion
  1203. //--------------------------------------------------------------------------
  1204. BOOL
  1205. WINAPI
  1206. PkiAsn1ToUTCTime(
  1207. IN LPFILETIME pFileTime,
  1208. OUT ASN1utctime_t *pAsn1Time
  1209. )
  1210. {
  1211. BOOL fRet;
  1212. SYSTEMTIME t;
  1213. memset(pAsn1Time, 0, sizeof(*pAsn1Time));
  1214. if (!FileTimeToSystemTime(pFileTime, &t))
  1215. goto FileTimeToSystemTimeError;
  1216. if (t.wYear < YEARFIRST || t.wYear > YEARLAST)
  1217. goto YearRangeError;
  1218. pAsn1Time->year = (ASN1uint8_t) (t.wYear % 100);
  1219. pAsn1Time->month = (ASN1uint8_t) t.wMonth;
  1220. pAsn1Time->day = (ASN1uint8_t) t.wDay;
  1221. pAsn1Time->hour = (ASN1uint8_t) t.wHour;
  1222. pAsn1Time->minute = (ASN1uint8_t) t.wMinute;
  1223. pAsn1Time->second = (ASN1uint8_t) t.wSecond;
  1224. pAsn1Time->universal = TRUE;
  1225. fRet = TRUE;
  1226. CommonReturn:
  1227. return fRet;
  1228. ErrorReturn:
  1229. fRet = FALSE;
  1230. goto CommonReturn;
  1231. TRACE_ERROR(FileTimeToSystemTimeError)
  1232. TRACE_ERROR(YearRangeError)
  1233. }
  1234. //+-------------------------------------------------------------------------
  1235. // Convert from ASN1's UTCTime to FILETIME.
  1236. //
  1237. // Returns TRUE for a successful conversion
  1238. //--------------------------------------------------------------------------
  1239. BOOL
  1240. WINAPI
  1241. PkiAsn1FromUTCTime(
  1242. IN ASN1utctime_t *pAsn1Time,
  1243. OUT LPFILETIME pFileTime
  1244. )
  1245. {
  1246. BOOL fRet;
  1247. SYSTEMTIME t;
  1248. memset(&t, 0, sizeof(t));
  1249. t.wYear = pAsn1Time->year > MAGICYEAR ?
  1250. (1900 + pAsn1Time->year) : (2000 + pAsn1Time->year);
  1251. t.wMonth = pAsn1Time->month;
  1252. t.wDay = pAsn1Time->day;
  1253. t.wHour = pAsn1Time->hour;
  1254. t.wMinute = pAsn1Time->minute;
  1255. t.wSecond = pAsn1Time->second;
  1256. if (!SystemTimeToFileTime(&t, pFileTime))
  1257. goto SystemTimeToFileTimeError;
  1258. fRet = AdjustFileTime(
  1259. pFileTime,
  1260. pAsn1Time->diff,
  1261. pAsn1Time->universal
  1262. );
  1263. CommonReturn:
  1264. return fRet;
  1265. ErrorReturn:
  1266. fRet = FALSE;
  1267. goto CommonReturn;
  1268. TRACE_ERROR(SystemTimeToFileTimeError)
  1269. }
  1270. //+-------------------------------------------------------------------------
  1271. // Convert FILETIME to ASN1's GeneralizedTime.
  1272. //
  1273. // Returns TRUE for a successful conversion
  1274. //--------------------------------------------------------------------------
  1275. BOOL
  1276. WINAPI
  1277. PkiAsn1ToGeneralizedTime(
  1278. IN LPFILETIME pFileTime,
  1279. OUT ASN1generalizedtime_t *pAsn1Time
  1280. )
  1281. {
  1282. BOOL fRet;
  1283. SYSTEMTIME t;
  1284. memset(pAsn1Time, 0, sizeof(*pAsn1Time));
  1285. if (!FileTimeToSystemTime(pFileTime, &t))
  1286. goto FileTimeToSystemTimeError;
  1287. pAsn1Time->year = t.wYear;
  1288. pAsn1Time->month = (ASN1uint8_t) t.wMonth;
  1289. pAsn1Time->day = (ASN1uint8_t) t.wDay;
  1290. pAsn1Time->hour = (ASN1uint8_t) t.wHour;
  1291. pAsn1Time->minute = (ASN1uint8_t) t.wMinute;
  1292. pAsn1Time->second = (ASN1uint8_t) t.wSecond;
  1293. pAsn1Time->millisecond = 0; // t.wMilliseconds;
  1294. pAsn1Time->universal = TRUE;
  1295. fRet = TRUE;
  1296. CommonReturn:
  1297. return fRet;
  1298. ErrorReturn:
  1299. fRet = FALSE;
  1300. goto CommonReturn;
  1301. TRACE_ERROR(FileTimeToSystemTimeError)
  1302. }
  1303. //+-------------------------------------------------------------------------
  1304. // Convert from ASN1's GeneralizedTime to FILETIME.
  1305. //
  1306. // Returns TRUE for a successful conversion
  1307. //--------------------------------------------------------------------------
  1308. BOOL
  1309. WINAPI
  1310. PkiAsn1FromGeneralizedTime(
  1311. IN ASN1generalizedtime_t *pAsn1Time,
  1312. OUT LPFILETIME pFileTime
  1313. )
  1314. {
  1315. BOOL fRet;
  1316. SYSTEMTIME t;
  1317. memset(&t, 0, sizeof(t));
  1318. t.wYear = pAsn1Time->year;
  1319. t.wMonth = pAsn1Time->month;
  1320. t.wDay = pAsn1Time->day;
  1321. t.wHour = pAsn1Time->hour;
  1322. t.wMinute = pAsn1Time->minute;
  1323. t.wSecond = pAsn1Time->second;
  1324. t.wMilliseconds = pAsn1Time->millisecond;
  1325. if (!SystemTimeToFileTime(&t, pFileTime))
  1326. goto SystemTimeToFileTimeError;
  1327. fRet = AdjustFileTime(
  1328. pFileTime,
  1329. pAsn1Time->diff,
  1330. pAsn1Time->universal
  1331. );
  1332. CommonReturn:
  1333. return fRet;
  1334. ErrorReturn:
  1335. fRet = FALSE;
  1336. goto CommonReturn;
  1337. TRACE_ERROR(SystemTimeToFileTimeError)
  1338. }
  1339. //+-------------------------------------------------------------------------
  1340. // Convert FILETIME to ASN1's UTCTime or GeneralizedTime.
  1341. //
  1342. // If 1950 < FILETIME < 2005, then UTCTime is chosen. Otherwise,
  1343. // GeneralizedTime is chosen. GeneralizedTime values shall not include
  1344. // fractional seconds.
  1345. //
  1346. // Returns TRUE for a successful conversion
  1347. //--------------------------------------------------------------------------
  1348. BOOL
  1349. WINAPI
  1350. PkiAsn1ToChoiceOfTime(
  1351. IN LPFILETIME pFileTime,
  1352. OUT WORD *pwChoice,
  1353. OUT ASN1generalizedtime_t *pGeneralTime,
  1354. OUT ASN1utctime_t *pUtcTime
  1355. )
  1356. {
  1357. BOOL fRet;
  1358. SYSTEMTIME t;
  1359. if (!FileTimeToSystemTime(pFileTime, &t))
  1360. goto FileTimeToSystemTimeError;
  1361. if (t.wYear < YEARFIRST || t.wYear >= YEARFIRSTGENERALIZED) {
  1362. *pwChoice = PKI_ASN1_GENERALIZED_TIME_CHOICE;
  1363. memset(pGeneralTime, 0, sizeof(*pGeneralTime));
  1364. pGeneralTime->year = t.wYear;
  1365. pGeneralTime->month = (ASN1uint8_t) t.wMonth;
  1366. pGeneralTime->day = (ASN1uint8_t) t.wDay;
  1367. pGeneralTime->hour = (ASN1uint8_t) t.wHour;
  1368. pGeneralTime->minute = (ASN1uint8_t) t.wMinute;
  1369. pGeneralTime->second = (ASN1uint8_t) t.wSecond;
  1370. pGeneralTime->universal = TRUE;
  1371. } else {
  1372. *pwChoice = PKI_ASN1_UTC_TIME_CHOICE;
  1373. memset(pUtcTime, 0, sizeof(*pUtcTime));
  1374. pUtcTime->year = (ASN1uint8_t) (t.wYear % 100);
  1375. pUtcTime->month = (ASN1uint8_t) t.wMonth;
  1376. pUtcTime->day = (ASN1uint8_t) t.wDay;
  1377. pUtcTime->hour = (ASN1uint8_t) t.wHour;
  1378. pUtcTime->minute = (ASN1uint8_t) t.wMinute;
  1379. pUtcTime->second = (ASN1uint8_t) t.wSecond;
  1380. pUtcTime->universal = TRUE;
  1381. }
  1382. fRet = TRUE;
  1383. CommonReturn:
  1384. return fRet;
  1385. ErrorReturn:
  1386. fRet = FALSE;
  1387. *pwChoice = 0;
  1388. memset(pGeneralTime, 0, sizeof(*pGeneralTime));
  1389. memset(pUtcTime, 0, sizeof(*pUtcTime));
  1390. goto CommonReturn;
  1391. TRACE_ERROR(FileTimeToSystemTimeError)
  1392. }
  1393. //+-------------------------------------------------------------------------
  1394. // Convert from ASN1's UTCTime or GeneralizedTime to FILETIME.
  1395. //
  1396. // Returns TRUE for a successful conversion.
  1397. //
  1398. // Note, in asn1hdr.h, UTCTime has same typedef as GeneralizedTime.
  1399. //--------------------------------------------------------------------------
  1400. BOOL
  1401. WINAPI
  1402. PkiAsn1FromChoiceOfTime(
  1403. IN WORD wChoice,
  1404. IN ASN1generalizedtime_t *pGeneralTime,
  1405. IN ASN1utctime_t *pUtcTime,
  1406. OUT LPFILETIME pFileTime
  1407. )
  1408. {
  1409. if (PKI_ASN1_UTC_TIME_CHOICE == wChoice) {
  1410. return PkiAsn1FromUTCTime(pUtcTime, pFileTime);
  1411. } else
  1412. return PkiAsn1FromGeneralizedTime(pGeneralTime, pFileTime);
  1413. }
  1414. #endif // SMIME_V3