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.

1580 lines
44 KiB

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