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.

2826 lines
88 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: tencode.cpp
  8. //
  9. // Contents: Test the encode/decode APIs. Test all the different length
  10. // cases.
  11. //
  12. //
  13. // Functions: main
  14. //
  15. // History: 17-Dec-96 philh created
  16. //
  17. //--------------------------------------------------------------------------
  18. #include <windows.h>
  19. #include <assert.h>
  20. #include "wincrypt.h"
  21. #include "certtest.h"
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <memory.h>
  26. #include <time.h>
  27. #include <stddef.h>
  28. #define DELTA_MORE_LENGTH 32
  29. #define DELTA_LESS_LENGTH 8
  30. static CRYPT_ENCODE_PARA TestEncodePara = {
  31. offsetof(CRYPT_ENCODE_PARA, pfnFree) + sizeof(TestEncodePara.pfnFree),
  32. TestAlloc,
  33. TestFree
  34. };
  35. static BOOL AllocAndEncodeObject(
  36. IN LPCSTR lpszStructType,
  37. IN const void *pvStructInfo,
  38. OUT BYTE **ppbEncoded,
  39. OUT DWORD *pcbEncoded,
  40. IN DWORD dwFlags = 0,
  41. IN BOOL fIgnoreError = FALSE
  42. )
  43. {
  44. BOOL fResult;
  45. fResult = CryptEncodeObjectEx(
  46. dwCertEncodingType,
  47. lpszStructType,
  48. pvStructInfo,
  49. dwFlags | CRYPT_ENCODE_ALLOC_FLAG,
  50. &TestEncodePara,
  51. (void *) ppbEncoded,
  52. pcbEncoded
  53. );
  54. if (!fResult && !fIgnoreError) {
  55. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  56. printf("CryptEncodeObject(StructType: %d)",
  57. (DWORD)(DWORD_PTR) lpszStructType);
  58. else
  59. printf("CryptEncodeObject(StructType: %s)",
  60. lpszStructType);
  61. PrintLastError("");
  62. }
  63. return fResult;
  64. }
  65. static CRYPT_DECODE_PARA TestDecodePara = {
  66. offsetof(CRYPT_DECODE_PARA, pfnFree) + sizeof(TestDecodePara.pfnFree),
  67. TestAlloc,
  68. TestFree
  69. };
  70. static void *AllocAndDecodeObject(
  71. IN LPCSTR lpszStructType,
  72. IN const BYTE *pbEncoded,
  73. IN DWORD cbEncoded,
  74. OUT DWORD *pcbStructInfo = NULL,
  75. IN DWORD dwFlags = 0
  76. )
  77. {
  78. DWORD cbStructInfo;
  79. void *pvStructInfo;
  80. if (!CryptDecodeObjectEx(
  81. dwCertEncodingType,
  82. lpszStructType,
  83. pbEncoded,
  84. cbEncoded,
  85. dwFlags | CRYPT_DECODE_NOCOPY_FLAG | CRYPT_DECODE_ALLOC_FLAG,
  86. &TestDecodePara,
  87. (void *) &pvStructInfo,
  88. &cbStructInfo
  89. ))
  90. goto ErrorReturn;
  91. CommonReturn:
  92. if (pcbStructInfo)
  93. *pcbStructInfo = cbStructInfo;
  94. return pvStructInfo;
  95. ErrorReturn:
  96. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  97. printf("CryptDecodeObject(StructType: %d)",
  98. (DWORD)(DWORD_PTR) lpszStructType);
  99. else
  100. printf("CryptDecodeObject(StructType: %s)",
  101. lpszStructType);
  102. PrintLastError("");
  103. pvStructInfo = NULL;
  104. goto CommonReturn;
  105. }
  106. static void TestX942OtherInfo()
  107. {
  108. BOOL fResult;
  109. BYTE *pbEncoded = NULL;
  110. DWORD cbEncoded;
  111. PCRYPT_X942_OTHER_INFO pInfo = NULL;
  112. CRYPT_X942_OTHER_INFO X942OtherInfo;
  113. LPCSTR pszObjId = "1.2.33.44.55";
  114. BYTE rgbPubInfo[] = {0x11, 0x22, 0x33, 0x44, 0x55};
  115. X942OtherInfo.pszContentEncryptionObjId = (LPSTR) pszObjId;
  116. X942OtherInfo.rgbCounter[0] = 0x00;
  117. X942OtherInfo.rgbCounter[1] = 0x11;
  118. X942OtherInfo.rgbCounter[2] = 0x22;
  119. X942OtherInfo.rgbCounter[3] = 0x33;
  120. X942OtherInfo.rgbKeyLength[0] = 192;
  121. X942OtherInfo.rgbKeyLength[1] = 0x00;
  122. X942OtherInfo.rgbKeyLength[2] = 0x00;
  123. X942OtherInfo.rgbKeyLength[3] = 0x00;
  124. X942OtherInfo.PubInfo.cbData = sizeof(rgbPubInfo);
  125. X942OtherInfo.PubInfo.pbData = rgbPubInfo;
  126. printf("Test encode/decode X942_OTHER_INFO\n");
  127. if (!AllocAndEncodeObject(
  128. X942_OTHER_INFO,
  129. &X942OtherInfo,
  130. &pbEncoded,
  131. &cbEncoded))
  132. goto CommonReturn;
  133. if (NULL == (pInfo = (PCRYPT_X942_OTHER_INFO) AllocAndDecodeObject(
  134. X942_OTHER_INFO,
  135. pbEncoded,
  136. cbEncoded
  137. ))) goto CommonReturn;
  138. if (0 != strcmp(pInfo->pszContentEncryptionObjId, pszObjId) ||
  139. pInfo->PubInfo.cbData != sizeof(rgbPubInfo) ||
  140. 0 != memcmp(pInfo->PubInfo.pbData, rgbPubInfo,
  141. sizeof(rgbPubInfo)) ||
  142. 0 != memcmp(X942OtherInfo.rgbCounter, pInfo->rgbCounter,
  143. sizeof(X942OtherInfo.rgbCounter)) ||
  144. 0 != memcmp(X942OtherInfo.rgbKeyLength, pInfo->rgbKeyLength,
  145. sizeof(X942OtherInfo.rgbKeyLength)))
  146. printf("X942_OTHER_INFO failed => decode != encode input\n");
  147. printf("Test encode/decode X942_OTHER_INFO with No PubInfo\n");
  148. X942OtherInfo.PubInfo.cbData = 0;
  149. X942OtherInfo.PubInfo.pbData = NULL;
  150. TestFree(pbEncoded);
  151. if (!AllocAndEncodeObject(
  152. X942_OTHER_INFO,
  153. &X942OtherInfo,
  154. &pbEncoded,
  155. &cbEncoded))
  156. goto CommonReturn;
  157. TestFree(pInfo);
  158. if (NULL == (pInfo = (PCRYPT_X942_OTHER_INFO) AllocAndDecodeObject(
  159. X942_OTHER_INFO,
  160. pbEncoded,
  161. cbEncoded
  162. ))) goto CommonReturn;
  163. if (0 != strcmp(pInfo->pszContentEncryptionObjId, pszObjId) ||
  164. pInfo->PubInfo.cbData != 0 ||
  165. 0 != memcmp(X942OtherInfo.rgbCounter, pInfo->rgbCounter,
  166. sizeof(X942OtherInfo.rgbCounter)) ||
  167. 0 != memcmp(X942OtherInfo.rgbKeyLength, pInfo->rgbKeyLength,
  168. sizeof(X942OtherInfo.rgbKeyLength)))
  169. printf("X942_OTHER_INFO failed => decode != encode input\n");
  170. CommonReturn:
  171. if (pbEncoded)
  172. TestFree(pbEncoded);
  173. if (pInfo)
  174. TestFree(pInfo);
  175. }
  176. static void TestExtensions()
  177. {
  178. BOOL fResult;
  179. BYTE *pbEncoded = NULL;
  180. DWORD cbEncoded;
  181. BYTE *pbT61Encoded = NULL;
  182. DWORD cbT61Encoded;
  183. PCERT_EXTENSIONS pInfo = NULL;
  184. BYTE rgbExt[] = {0x1, 0x2, 0x3};
  185. CERT_EXTENSION Ext[2] = {
  186. "1.2.3.4.5", TRUE, sizeof(rgbExt), rgbExt,
  187. "1.2.3.6.7", FALSE, sizeof(rgbExt), rgbExt
  188. };
  189. CERT_EXTENSIONS ExtsInfo;
  190. CERT_NAME_VALUE T61ExtsInfo;
  191. ExtsInfo.cExtension = 2;
  192. ExtsInfo.rgExtension = Ext;
  193. printf("Test encode/decode X509_EXTENSIONS\n");
  194. if (!AllocAndEncodeObject(
  195. X509_EXTENSIONS,
  196. &ExtsInfo,
  197. &pbEncoded,
  198. &cbEncoded))
  199. goto CommonReturn;
  200. if (NULL == (pInfo = (PCERT_EXTENSIONS) AllocAndDecodeObject(
  201. X509_EXTENSIONS,
  202. pbEncoded,
  203. cbEncoded
  204. ))) goto CommonReturn;
  205. if (pInfo->cExtension != ExtsInfo.cExtension ||
  206. 0 != strcmp(pInfo->rgExtension[0].pszObjId,
  207. ExtsInfo.rgExtension[0].pszObjId))
  208. printf("X509_EXTENSIONS failed => decode != encode input\n");
  209. TestFree(pInfo);
  210. pInfo = NULL;
  211. printf("Test encode/decode T61 wrapped X509_EXTENSIONS\n");
  212. T61ExtsInfo.dwValueType = CERT_RDN_T61_STRING;
  213. T61ExtsInfo.Value.cbData = cbEncoded;
  214. T61ExtsInfo.Value.pbData = pbEncoded;
  215. if (!AllocAndEncodeObject(
  216. X509_ANY_STRING,
  217. &T61ExtsInfo,
  218. &pbT61Encoded,
  219. &cbT61Encoded))
  220. goto CommonReturn;
  221. if (NULL == (pInfo = (PCERT_EXTENSIONS) AllocAndDecodeObject(
  222. X509_EXTENSIONS,
  223. pbT61Encoded,
  224. cbT61Encoded
  225. ))) goto CommonReturn;
  226. if (pInfo->cExtension != ExtsInfo.cExtension ||
  227. 0 != strcmp(pInfo->rgExtension[0].pszObjId,
  228. ExtsInfo.rgExtension[0].pszObjId))
  229. printf("T61 wrapped X509_EXTENSIONS failed => decode != encode input\n");
  230. CommonReturn:
  231. if (pbEncoded)
  232. TestFree(pbEncoded);
  233. if (pbT61Encoded)
  234. TestFree(pbT61Encoded);
  235. if (pInfo)
  236. TestFree(pInfo);
  237. }
  238. static void TestPKCSAttribute()
  239. {
  240. BOOL fResult;
  241. BYTE *pbEncoded = NULL;
  242. DWORD cbEncoded;
  243. PCRYPT_ATTRIBUTE pInfo = NULL;
  244. CRYPT_ATTRIBUTE Attribute;
  245. LPCSTR pszObjId = "1.2.33.44.55";
  246. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  247. BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  248. CRYPT_ATTR_BLOB rgValue[2] = {
  249. sizeof(rgb0), rgb0,
  250. sizeof(rgb1), rgb1
  251. };
  252. Attribute.pszObjId = (LPSTR) pszObjId;
  253. Attribute.cValue = 2;
  254. Attribute.rgValue = rgValue;
  255. printf("Test encode/decode PKCS_ATTRIBUTE\n");
  256. if (!AllocAndEncodeObject(
  257. PKCS_ATTRIBUTE,
  258. &Attribute,
  259. &pbEncoded,
  260. &cbEncoded))
  261. goto CommonReturn;
  262. if (NULL == (pInfo = (PCRYPT_ATTRIBUTE) AllocAndDecodeObject(
  263. PKCS_ATTRIBUTE,
  264. pbEncoded,
  265. cbEncoded
  266. ))) goto CommonReturn;
  267. if (0 != strcmp(pInfo->pszObjId, pszObjId) ||
  268. pInfo->cValue != 2 ||
  269. pInfo->rgValue[0].cbData != sizeof(rgb0) ||
  270. 0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
  271. pInfo->rgValue[1].cbData != sizeof(rgb1) ||
  272. 0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
  273. printf("PKCS_ATTRIBUTE failed => decode != encode input\n");
  274. printf("Test encode/decode PKCS_ATTRIBUTE with empty OID\n");
  275. TestFree(pbEncoded);
  276. Attribute.pszObjId = "";
  277. if (AllocAndEncodeObject(
  278. PKCS_ATTRIBUTE,
  279. &Attribute,
  280. &pbEncoded,
  281. &cbEncoded,
  282. 0, // dwFlags
  283. TRUE)) // fIgnoreError
  284. printf(" failed => expected error\n");
  285. else {
  286. DWORD dwErr = GetLastError();
  287. printf(" Got LastError: 0x%x (%d)\n", dwErr, dwErr);
  288. }
  289. CommonReturn:
  290. if (pbEncoded)
  291. TestFree(pbEncoded);
  292. if (pInfo)
  293. TestFree(pInfo);
  294. }
  295. static void TestPKCSAttributes()
  296. {
  297. BOOL fResult;
  298. BYTE *pbEncoded = NULL;
  299. DWORD cbEncoded;
  300. PCRYPT_ATTRIBUTES pInfo = NULL;
  301. DWORD i;
  302. #define ATTRIBUTE_CNT 3
  303. CRYPT_ATTRIBUTES Attributes;
  304. CRYPT_ATTRIBUTE rgAttribute[ATTRIBUTE_CNT];
  305. LPCSTR pszObjId = "1.2.33.44.55";
  306. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  307. BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  308. CRYPT_ATTR_BLOB rgValue[2] = {
  309. sizeof(rgb0), rgb0,
  310. sizeof(rgb1), rgb1
  311. };
  312. for (i = 0; i < ATTRIBUTE_CNT; i++) {
  313. rgAttribute[i].pszObjId = (LPSTR) pszObjId;
  314. rgAttribute[i].cValue = 2;
  315. rgAttribute[i].rgValue = rgValue;
  316. }
  317. Attributes.cAttr = ATTRIBUTE_CNT;
  318. Attributes.rgAttr = rgAttribute;
  319. printf("Test encode/decode PKCS_ATTRIBUTES\n");
  320. if (!AllocAndEncodeObject(
  321. PKCS_ATTRIBUTES,
  322. &Attributes,
  323. &pbEncoded,
  324. &cbEncoded))
  325. goto CommonReturn;
  326. if (NULL == (pInfo = (PCRYPT_ATTRIBUTES) AllocAndDecodeObject(
  327. PKCS_ATTRIBUTES,
  328. pbEncoded,
  329. cbEncoded
  330. ))) goto CommonReturn;
  331. // Note, ATTRIBUTES is a SET OF. Entries are re-ordered
  332. if (pInfo->cAttr != ATTRIBUTE_CNT)
  333. printf("PKCS_ATTRIBUTES failed => decode != encode attr count\n");
  334. else {
  335. for (i = 0; i < ATTRIBUTE_CNT; i++) {
  336. PCRYPT_ATTRIBUTE pAttr = &pInfo->rgAttr[i];
  337. if (0 != strcmp(pAttr->pszObjId, pszObjId) ||
  338. pAttr->cValue != 2 ||
  339. pAttr->rgValue[0].cbData != sizeof(rgb0) ||
  340. 0 != memcmp(pAttr->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
  341. pAttr->rgValue[1].cbData != sizeof(rgb1) ||
  342. 0 != memcmp(pAttr->rgValue[1].pbData, rgb1, sizeof(rgb1))) {
  343. printf("PKCS_ATTRIBUTES failed => decode != encode input\n");
  344. break;
  345. }
  346. }
  347. }
  348. CommonReturn:
  349. if (pbEncoded)
  350. TestFree(pbEncoded);
  351. if (pInfo)
  352. TestFree(pInfo);
  353. }
  354. static void TestContentInfoSequenceOfAny()
  355. {
  356. BOOL fResult;
  357. BYTE *pbEncoded = NULL;
  358. DWORD cbEncoded;
  359. PCRYPT_CONTENT_INFO_SEQUENCE_OF_ANY pInfo = NULL;
  360. CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY SeqOfAny;
  361. BYTE rgb0[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  362. BYTE rgb1[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  363. CRYPT_DER_BLOB rgValue[2] = {
  364. sizeof(rgb0), rgb0,
  365. sizeof(rgb1), rgb1
  366. };
  367. SeqOfAny.pszObjId = szOID_NETSCAPE_CERT_SEQUENCE;
  368. SeqOfAny.cValue = 2;
  369. SeqOfAny.rgValue = rgValue;
  370. printf("Test encode/decode PKCS_CONTENT_INFO_SEQUENCE_OF_ANY\n");
  371. if (!AllocAndEncodeObject(
  372. PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
  373. &SeqOfAny,
  374. &pbEncoded,
  375. &cbEncoded))
  376. goto CommonReturn;
  377. if (NULL == (pInfo =
  378. (PCRYPT_CONTENT_INFO_SEQUENCE_OF_ANY) AllocAndDecodeObject(
  379. PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
  380. pbEncoded,
  381. cbEncoded
  382. ))) goto CommonReturn;
  383. if (0 != strcmp(pInfo->pszObjId, szOID_NETSCAPE_CERT_SEQUENCE) ||
  384. pInfo->cValue != 2 ||
  385. pInfo->rgValue[0].cbData != sizeof(rgb0) ||
  386. 0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
  387. pInfo->rgValue[1].cbData != sizeof(rgb1) ||
  388. 0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
  389. printf("PKCS_CONTENT_INFO_SEQUENCE_OF_ANY failed => decode != encode input\n");
  390. CommonReturn:
  391. if (pbEncoded)
  392. TestFree(pbEncoded);
  393. if (pInfo)
  394. TestFree(pInfo);
  395. }
  396. static void TestSequenceOfAny()
  397. {
  398. BOOL fResult;
  399. BYTE *pbEncoded = NULL;
  400. DWORD cbEncoded;
  401. PCRYPT_SEQUENCE_OF_ANY pInfo = NULL;
  402. CRYPT_SEQUENCE_OF_ANY SeqOfAny;
  403. BYTE rgb0[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  404. BYTE rgb1[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  405. CRYPT_DER_BLOB rgValue[2] = {
  406. sizeof(rgb0), rgb0,
  407. sizeof(rgb1), rgb1
  408. };
  409. SeqOfAny.cValue = 2;
  410. SeqOfAny.rgValue = rgValue;
  411. printf("Test encode/decode X509_SEQUENCE_OF_ANY\n");
  412. if (!AllocAndEncodeObject(
  413. X509_SEQUENCE_OF_ANY,
  414. &SeqOfAny,
  415. &pbEncoded,
  416. &cbEncoded))
  417. goto CommonReturn;
  418. if (NULL == (pInfo =
  419. (PCRYPT_SEQUENCE_OF_ANY) AllocAndDecodeObject(
  420. X509_SEQUENCE_OF_ANY,
  421. pbEncoded,
  422. cbEncoded
  423. ))) goto CommonReturn;
  424. if (pInfo->cValue != 2 ||
  425. pInfo->rgValue[0].cbData != sizeof(rgb0) ||
  426. 0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
  427. pInfo->rgValue[1].cbData != sizeof(rgb1) ||
  428. 0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
  429. printf("X509_SEQUENCE_OF_ANY failed => decode != encode input\n");
  430. CommonReturn:
  431. if (pbEncoded)
  432. TestFree(pbEncoded);
  433. if (pInfo)
  434. TestFree(pInfo);
  435. }
  436. static void TestInteger(
  437. int iEncode
  438. )
  439. {
  440. BOOL fResult;
  441. BYTE *pbEncoded = NULL;
  442. DWORD cbEncoded;
  443. int iDecode = 0;
  444. DWORD cbInfo;
  445. printf("Test encode/decode X509_INTEGER: 0x%x (%d)\n", iEncode, iEncode);
  446. if (!AllocAndEncodeObject(
  447. X509_INTEGER,
  448. &iEncode,
  449. &pbEncoded,
  450. &cbEncoded))
  451. goto CommonReturn;
  452. cbInfo = sizeof(iDecode);
  453. if (!CryptDecodeObject(
  454. dwCertEncodingType,
  455. X509_INTEGER,
  456. pbEncoded,
  457. cbEncoded,
  458. 0, // dwFlags
  459. &iDecode,
  460. &cbInfo
  461. )) {
  462. PrintLastError("CryptDecodeObject(X509_INTEGER)");
  463. goto CommonReturn;
  464. }
  465. if (cbInfo != sizeof(iDecode))
  466. printf("X509_INTEGER failed => unexpected decode length\n");
  467. if (iEncode != iDecode)
  468. printf("X509_INTEGER failed => decoded output (%d) != encode input\n",
  469. iDecode);
  470. CommonReturn:
  471. if (pbEncoded)
  472. TestFree(pbEncoded);
  473. }
  474. static void TestInteger()
  475. {
  476. TestInteger(0);
  477. TestInteger(0x12345678);
  478. TestInteger(-1234);
  479. TestInteger(123);
  480. }
  481. static void TestMultiByteInteger(
  482. BYTE *pb,
  483. DWORD cb
  484. )
  485. {
  486. BOOL fResult;
  487. BYTE *pbEncoded = NULL;
  488. DWORD cbEncoded;
  489. PCRYPT_INTEGER_BLOB pInfo = NULL;
  490. CRYPT_INTEGER_BLOB MultiByteInteger = {cb, pb };
  491. printf("Test encode/decode X509_MULTI_BYTE_INTEGER\n");
  492. PrintBytes(" ", pb, cb);
  493. if (!AllocAndEncodeObject(
  494. X509_MULTI_BYTE_INTEGER,
  495. &MultiByteInteger,
  496. &pbEncoded,
  497. &cbEncoded))
  498. goto CommonReturn;
  499. if (NULL == (pInfo = (PCRYPT_INTEGER_BLOB) AllocAndDecodeObject(
  500. X509_MULTI_BYTE_INTEGER,
  501. pbEncoded,
  502. cbEncoded
  503. ))) goto CommonReturn;
  504. if (!CertCompareIntegerBlob(pInfo, &MultiByteInteger))
  505. printf("X509_MULTI_BYTE_INTEGER failed => decode != encode input\n");
  506. CommonReturn:
  507. if (pbEncoded)
  508. TestFree(pbEncoded);
  509. if (pInfo)
  510. TestFree(pInfo);
  511. }
  512. static void TestMultiByteInteger()
  513. {
  514. BYTE rgb1[] = {0x11, 0x22, 0x33, 0x44, 0x55};
  515. BYTE rgb2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xFF, 0x00};
  516. BYTE rgb3[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xFF, 0xFF};
  517. BYTE rgb4[] = {0x11, 0x22, 0x33, 0x44, 0x80, 0xFF, 0xFF};
  518. BYTE rgb5[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x00};
  519. BYTE rgb6[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00, 0x00};
  520. TestMultiByteInteger(rgb1, sizeof(rgb1));
  521. TestMultiByteInteger(rgb2, sizeof(rgb2));
  522. TestMultiByteInteger(rgb3, sizeof(rgb2));
  523. TestMultiByteInteger(rgb4, sizeof(rgb2));
  524. TestMultiByteInteger(rgb5, sizeof(rgb2));
  525. TestMultiByteInteger(rgb6, sizeof(rgb2));
  526. }
  527. static const BYTE rgbUnusedAndMask[8] =
  528. {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
  529. static void TestBits(
  530. PCRYPT_BIT_BLOB pBits
  531. )
  532. {
  533. BOOL fResult;
  534. BYTE *pbEncoded = NULL;
  535. DWORD cbEncoded;
  536. PCRYPT_BIT_BLOB pInfo = NULL;
  537. printf("Test encode/decode X509_BITS(cb:%d, cUnused: %d)\n",
  538. pBits->cbData, pBits->cUnusedBits);
  539. PrintBytes(" ", pBits->pbData, pBits->cbData);
  540. if (!AllocAndEncodeObject(
  541. X509_BITS,
  542. pBits,
  543. &pbEncoded,
  544. &cbEncoded))
  545. goto CommonReturn;
  546. if (NULL == (pInfo = (PCRYPT_BIT_BLOB) AllocAndDecodeObject(
  547. X509_BITS,
  548. pbEncoded,
  549. cbEncoded
  550. ))) goto CommonReturn;
  551. if (pInfo->cbData != pBits->cbData ||
  552. pInfo->cUnusedBits != pBits->cUnusedBits)
  553. printf("X509_BITS failed => decode != encode (cbData or cUnusedBits)\n");
  554. else {
  555. DWORD cbData = pInfo->cbData;
  556. if (cbData > 1) {
  557. if (0 != memcmp(pInfo->pbData, pBits->pbData, cbData - 1))
  558. printf("X509_BITS failed => decode != encode input\n");
  559. }
  560. if (cbData > 0) {
  561. if ((pBits->pbData[cbData - 1] &
  562. rgbUnusedAndMask[pInfo->cUnusedBits]) !=
  563. pInfo->pbData[cbData - 1])
  564. printf("X509_BITS failed => decode != encode (last byte)\n");
  565. }
  566. }
  567. CommonReturn:
  568. if (pbEncoded)
  569. TestFree(pbEncoded);
  570. if (pInfo)
  571. TestFree(pInfo);
  572. }
  573. static void TestBits()
  574. {
  575. BYTE rgb1[] = {0xFF, 0x00, 0x00, 0x00};
  576. BYTE rgb2[] = {0x00, 0xFE, 0xFC};
  577. CRYPT_BIT_BLOB Bits;
  578. memset(&Bits, 0, sizeof(Bits));
  579. TestBits(&Bits);
  580. Bits.pbData = rgb1;
  581. TestBits(&Bits);
  582. Bits.cbData = 1;
  583. TestBits(&Bits);
  584. Bits.cUnusedBits = 1;
  585. TestBits(&Bits);
  586. Bits.cUnusedBits = 7;
  587. TestBits(&Bits);
  588. Bits.cbData = sizeof(rgb1);
  589. Bits.cUnusedBits = 0;
  590. TestBits(&Bits);
  591. Bits.cUnusedBits = 1;
  592. TestBits(&Bits);
  593. Bits.cUnusedBits = 7;
  594. TestBits(&Bits);
  595. Bits.pbData = rgb2;
  596. Bits.cUnusedBits = 0;
  597. Bits.cbData = 1;
  598. TestBits(&Bits);
  599. Bits.cUnusedBits = 1;
  600. TestBits(&Bits);
  601. Bits.cUnusedBits = 7;
  602. TestBits(&Bits);
  603. Bits.cbData = sizeof(rgb2);
  604. Bits.cUnusedBits = 0;
  605. TestBits(&Bits);
  606. Bits.cUnusedBits = 1;
  607. TestBits(&Bits);
  608. Bits.cUnusedBits = 7;
  609. TestBits(&Bits);
  610. }
  611. static void TestBitsWithoutTrailingZeroes(
  612. PCRYPT_BIT_BLOB pBits,
  613. DWORD cbData,
  614. DWORD cUnusedBits
  615. )
  616. {
  617. BOOL fResult;
  618. BYTE *pbEncoded = NULL;
  619. DWORD cbEncoded;
  620. PCRYPT_BIT_BLOB pInfo = NULL;
  621. printf("Test encode/decode X509_BITS_WO_ZEROES(cb:%d, cUnused: %d) Expected(cb:%d, cUnused:%d)\n",
  622. pBits->cbData, pBits->cUnusedBits, cbData, cUnusedBits);
  623. PrintBytes(" Input:: ", pBits->pbData, pBits->cbData);
  624. if (!AllocAndEncodeObject(
  625. X509_BITS_WITHOUT_TRAILING_ZEROES,
  626. pBits,
  627. &pbEncoded,
  628. &cbEncoded))
  629. goto CommonReturn;
  630. if (NULL == (pInfo = (PCRYPT_BIT_BLOB) AllocAndDecodeObject(
  631. X509_BITS_WITHOUT_TRAILING_ZEROES,
  632. pbEncoded,
  633. cbEncoded
  634. ))) goto CommonReturn;
  635. PrintBytes(" Encoded:: ", pbEncoded, cbEncoded);
  636. if (pInfo->cbData != cbData ||
  637. pInfo->cUnusedBits != cUnusedBits)
  638. printf("X509_BITS_WO_ZEROES failed => decode != encode (cbData or cUnusedBits)\n");
  639. else {
  640. if (cbData > 1) {
  641. if (0 != memcmp(pInfo->pbData, pBits->pbData, cbData - 1))
  642. printf("X509_BITS_WO_ZEROES failed => decode != encode input\n");
  643. }
  644. if (cbData > 0) {
  645. if ((pBits->pbData[cbData - 1] &
  646. rgbUnusedAndMask[cUnusedBits]) !=
  647. pInfo->pbData[cbData - 1])
  648. printf("X509_BITS_WO_ZEROES failed => decode != encode (last byte)\n");
  649. }
  650. }
  651. CommonReturn:
  652. if (pbEncoded)
  653. TestFree(pbEncoded);
  654. if (pInfo)
  655. TestFree(pInfo);
  656. }
  657. static void TestBitsWithoutTrailingZeroes()
  658. {
  659. BYTE rgb1[] = {0xFF, 0x00, 0x00, 0x00};
  660. BYTE rgb2[] = {0x00, 0xFE, 0xFC};
  661. BYTE rgb3[] = {0x00, 0x18, 0x00, 0x20};
  662. CRYPT_BIT_BLOB Bits;
  663. int i;
  664. BYTE b;
  665. memset(&Bits, 0, sizeof(Bits));
  666. TestBitsWithoutTrailingZeroes(&Bits, 0,0);
  667. Bits.pbData = rgb1;
  668. TestBitsWithoutTrailingZeroes(&Bits, 0,0);
  669. Bits.cbData = 1;
  670. TestBitsWithoutTrailingZeroes(&Bits, 1,0);
  671. Bits.cUnusedBits = 1;
  672. TestBitsWithoutTrailingZeroes(&Bits, 1,1);
  673. Bits.cUnusedBits = 7;
  674. TestBitsWithoutTrailingZeroes(&Bits, 1,7);
  675. Bits.cbData = sizeof(rgb1);
  676. Bits.cUnusedBits = 0;
  677. TestBitsWithoutTrailingZeroes(&Bits, 1,0);
  678. Bits.cUnusedBits = 1;
  679. TestBitsWithoutTrailingZeroes(&Bits, 1,0);
  680. Bits.cUnusedBits = 7;
  681. TestBitsWithoutTrailingZeroes(&Bits, 1,0);
  682. Bits.pbData = rgb2;
  683. Bits.cUnusedBits = 0;
  684. Bits.cbData = 1;
  685. TestBitsWithoutTrailingZeroes(&Bits, 0,0);
  686. Bits.cUnusedBits = 1;
  687. TestBitsWithoutTrailingZeroes(&Bits, 0,0);
  688. Bits.cUnusedBits = 7;
  689. TestBitsWithoutTrailingZeroes(&Bits, 0,0);
  690. Bits.cbData = sizeof(rgb2);
  691. Bits.cUnusedBits = 0;
  692. TestBitsWithoutTrailingZeroes(&Bits, 3,2);
  693. Bits.cUnusedBits = 1;
  694. TestBitsWithoutTrailingZeroes(&Bits, 3,2);
  695. Bits.cUnusedBits = 2;
  696. TestBitsWithoutTrailingZeroes(&Bits, 3,2);
  697. Bits.cUnusedBits = 4;
  698. TestBitsWithoutTrailingZeroes(&Bits, 3,4);
  699. Bits.cUnusedBits = 7;
  700. TestBitsWithoutTrailingZeroes(&Bits, 3,7);
  701. Bits.pbData = rgb3;
  702. Bits.cbData = sizeof(rgb3);
  703. Bits.cUnusedBits = 0;
  704. TestBitsWithoutTrailingZeroes(&Bits, 4,5);
  705. Bits.cUnusedBits = 3;
  706. TestBitsWithoutTrailingZeroes(&Bits, 4,5);
  707. Bits.cUnusedBits = 4;
  708. TestBitsWithoutTrailingZeroes(&Bits, 4,5);
  709. Bits.cUnusedBits = 5;
  710. TestBitsWithoutTrailingZeroes(&Bits, 4,5);
  711. Bits.cUnusedBits = 6;
  712. TestBitsWithoutTrailingZeroes(&Bits, 2,3);
  713. Bits.cUnusedBits = 7;
  714. TestBitsWithoutTrailingZeroes(&Bits, 2,3);
  715. Bits.pbData = &b;
  716. Bits.cbData = 1;
  717. for (i = 0; i <= 7; i++) {
  718. b = 1 << i;
  719. Bits.cUnusedBits = 0;
  720. TestBitsWithoutTrailingZeroes(&Bits, 1,i);
  721. Bits.cUnusedBits = i;
  722. TestBitsWithoutTrailingZeroes(&Bits, 1,i);
  723. }
  724. }
  725. static void TestOID(
  726. IN LPCSTR pszObjId
  727. )
  728. {
  729. BOOL fResult;
  730. BYTE *pbEncoded = NULL;
  731. DWORD cbEncoded;
  732. PCRYPT_ATTRIBUTE pInfo = NULL;
  733. CRYPT_ATTRIBUTE Attribute;
  734. memset(&Attribute, 0, sizeof(Attribute));
  735. Attribute.pszObjId = (LPSTR) pszObjId;
  736. printf("Test encode/decode OID: %s\n", pszObjId);
  737. if (!AllocAndEncodeObject(
  738. PKCS_ATTRIBUTE,
  739. &Attribute,
  740. &pbEncoded,
  741. &cbEncoded))
  742. goto CommonReturn;
  743. if (NULL == (pInfo = (PCRYPT_ATTRIBUTE) AllocAndDecodeObject(
  744. PKCS_ATTRIBUTE,
  745. pbEncoded,
  746. cbEncoded
  747. ))) goto CommonReturn;
  748. if (0 != strcmp(pInfo->pszObjId, pszObjId))
  749. printf("OID failed => decode != encode input\n");
  750. CommonReturn:
  751. if (pbEncoded)
  752. TestFree(pbEncoded);
  753. if (pInfo)
  754. TestFree(pInfo);
  755. }
  756. static void TestOID()
  757. {
  758. TestOID("0.1");
  759. TestOID("0.9.2342.19200300.100.1.25");
  760. TestOID("1.2.3.111111111144444444444");
  761. TestOID("1.2.3.111111111144444444444.55555555555555555.666666666666666");
  762. TestOID("1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20");
  763. }
  764. static void TestUnicodeAnyString(
  765. DWORD dwValueType,
  766. LPCWSTR pwszValue,
  767. DWORD dwExpectedErr,
  768. DWORD dwExpectedErrLocation,
  769. DWORD dwFlags = 0
  770. )
  771. {
  772. BOOL fResult;
  773. BYTE *pbEncoded = NULL;
  774. DWORD cbEncoded;
  775. PCERT_NAME_VALUE pInfo = NULL;
  776. CERT_NAME_VALUE NameValue;
  777. memset(&NameValue, 0, sizeof(NameValue));
  778. NameValue.dwValueType = dwValueType;
  779. NameValue.Value.pbData = (BYTE *) pwszValue;
  780. if (dwExpectedErr ) {
  781. printf("Test encode X509_UNICODE_ANY_STRING:: dwValueType: %d 0x%x Expected Err: 0x%x Location: %d\n",
  782. dwValueType, dwValueType, dwExpectedErr, dwExpectedErrLocation);
  783. if (CryptEncodeObject(
  784. dwCertEncodingType,
  785. X509_UNICODE_ANY_STRING,
  786. &NameValue,
  787. NULL, // pbEncoded
  788. &cbEncoded
  789. ))
  790. printf(" failed => expected error\n");
  791. else {
  792. DWORD dwErr = GetLastError();
  793. if (dwErr != dwExpectedErr)
  794. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  795. dwExpectedErr, dwExpectedErr, dwErr, dwErr);
  796. if (dwExpectedErrLocation != cbEncoded)
  797. printf(" ErrLocation failed => expected: %d, got: %d\n",
  798. dwExpectedErrLocation, cbEncoded);
  799. }
  800. }
  801. printf("Test alloc encode/decode X509_UNICODE_ANY_STRING:: dwValueType: %d 0x%x string: %S\n",
  802. dwValueType, dwValueType, pwszValue);
  803. if (!AllocAndEncodeObject(
  804. X509_UNICODE_ANY_STRING,
  805. &NameValue,
  806. &pbEncoded,
  807. &cbEncoded,
  808. dwFlags,
  809. dwExpectedErr != 0 // fIgnoreError
  810. )) {
  811. if (dwExpectedErr) {
  812. DWORD dwErr = GetLastError();
  813. if (dwErr != dwExpectedErr)
  814. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  815. dwExpectedErr, dwExpectedErr, dwErr, dwErr);
  816. if (dwExpectedErrLocation != cbEncoded)
  817. printf(" ErrLocation failed => expected: %d, got: %d\n",
  818. dwExpectedErrLocation, cbEncoded);
  819. }
  820. goto CommonReturn;
  821. } else if (dwExpectedErr)
  822. printf(" failed => expected error\n");
  823. if (NULL == (pInfo = (PCERT_NAME_VALUE) AllocAndDecodeObject(
  824. X509_UNICODE_ANY_STRING,
  825. pbEncoded,
  826. cbEncoded,
  827. NULL,
  828. dwFlags
  829. ))) goto CommonReturn;
  830. if (wcslen(pwszValue) != wcslen((LPWSTR) pInfo->Value.pbData) ||
  831. wcslen(pwszValue) * 2 != pInfo->Value.cbData ||
  832. 0 != wcscmp(pwszValue, (LPWSTR) pInfo->Value.pbData))
  833. printf("X509_UNICODE_ANY_STRING failed => decoded output (%S) != encode input\n",
  834. (LPWSTR) pInfo->Value.pbData);
  835. CommonReturn:
  836. if (pbEncoded)
  837. TestFree(pbEncoded);
  838. if (pInfo)
  839. TestFree(pInfo);
  840. }
  841. static void TestUnicodeAnyString(
  842. DWORD dwValueType,
  843. PCRYPT_DATA_BLOB pDataBlob,
  844. DWORD dwExpectedErr
  845. )
  846. {
  847. BOOL fResult;
  848. BYTE *pbEncoded = NULL;
  849. DWORD cbEncoded;
  850. DWORD cbInfo;
  851. CERT_NAME_VALUE NameValue;
  852. memset(&NameValue, 0, sizeof(NameValue));
  853. NameValue.dwValueType = dwValueType;
  854. NameValue.Value.pbData = pDataBlob->pbData;
  855. NameValue.Value.cbData = pDataBlob->cbData;
  856. printf("Test encode/decode X509_UNICODE_ANY_STRING:: dwValueType: %d Expected Err: 0x%x\n",
  857. dwValueType, dwExpectedErr);
  858. if (CryptEncodeObject(
  859. dwCertEncodingType,
  860. X509_UNICODE_ANY_STRING,
  861. &NameValue,
  862. NULL, // pbEncoded
  863. &cbEncoded
  864. ))
  865. printf(" Encode failed => expected error\n");
  866. else {
  867. DWORD dwErr = GetLastError();
  868. if (dwErr != dwExpectedErr)
  869. printf(" Encode LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  870. dwExpectedErr, dwExpectedErr, dwErr, dwErr);
  871. }
  872. if (!AllocAndEncodeObject(
  873. X509_ANY_STRING,
  874. &NameValue,
  875. &pbEncoded,
  876. &cbEncoded))
  877. goto CommonReturn;
  878. if (CryptDecodeObject(
  879. dwCertEncodingType,
  880. X509_UNICODE_ANY_STRING,
  881. pbEncoded,
  882. cbEncoded,
  883. 0, // dwFlags
  884. NULL, // pInfo
  885. &cbInfo
  886. ))
  887. printf(" Decode failed => expected error\n");
  888. else {
  889. DWORD dwErr = GetLastError();
  890. if (dwErr != dwExpectedErr)
  891. printf(" Decode LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  892. dwExpectedErr, dwExpectedErr, dwErr, dwErr);
  893. }
  894. CommonReturn:
  895. if (pbEncoded)
  896. TestFree(pbEncoded);
  897. }
  898. static void TestUnicodeAnyString()
  899. {
  900. DWORD dwValueType;
  901. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x80, 0x33, 0x00};
  902. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // Encoded INTEGER
  903. CRYPT_DATA_BLOB EncodedBlob = {sizeof(rgb0), rgb0};
  904. BYTE rgb1[] = {0, 0x11, 0x22, 0x33, 0x44, 0x55};
  905. CRYPT_DATA_BLOB OctetString = {sizeof(rgb1), rgb1};
  906. TestUnicodeAnyString(CERT_RDN_ENCODED_BLOB, &EncodedBlob,
  907. (DWORD) CRYPT_E_NOT_CHAR_STRING);
  908. TestUnicodeAnyString(CERT_RDN_OCTET_STRING, &OctetString,
  909. (DWORD) CRYPT_E_NOT_CHAR_STRING);
  910. TestUnicodeAnyString(CERT_RDN_NUMERIC_STRING,
  911. L"0123456789 ",
  912. 0, 0);
  913. for (dwValueType = CERT_RDN_PRINTABLE_STRING;
  914. dwValueType <= CERT_RDN_BMP_STRING; dwValueType++)
  915. TestUnicodeAnyString(dwValueType,
  916. L"UNICODE string to be encoded",
  917. 0, 0);
  918. TestUnicodeAnyString(CERT_RDN_ANY_TYPE, L"InvalidArg",
  919. (DWORD) CRYPT_E_NOT_CHAR_STRING, 0);
  920. TestUnicodeAnyString(CERT_RDN_NUMERIC_STRING,
  921. // 0123456789012345678901234567890
  922. L"0123456789a013",
  923. (DWORD) CRYPT_E_INVALID_NUMERIC_STRING, 10);
  924. TestUnicodeAnyString(CERT_RDN_PRINTABLE_STRING,
  925. // 0123456789012345678901234567890
  926. L"Invalid printable ### az AZ 09 \'()+,-./:=?",
  927. (DWORD) CRYPT_E_INVALID_PRINTABLE_STRING, 18);
  928. TestUnicodeAnyString(CERT_RDN_DISABLE_CHECK_TYPE_FLAG |
  929. CERT_RDN_PRINTABLE_STRING,
  930. // 0123456789012345678901234567890
  931. L"Invalid printable ### az AZ 09 \'()+,-./:=?",
  932. 0, 0);
  933. TestUnicodeAnyString(CERT_RDN_PRINTABLE_STRING,
  934. // 0123456789012345678901234567890
  935. L"Invalid printable ### az AZ 09 \'()+,-./:=?",
  936. 0, 0,
  937. CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG);
  938. TestUnicodeAnyString(CERT_RDN_T61_STRING,
  939. // 0123456789012345678901234567890
  940. L"T61 ### az AZ 09 \'()+,-./:=?",
  941. 0, 0, 0);
  942. TestUnicodeAnyString(CERT_RDN_T61_STRING,
  943. // 0123456789012345678901234567890
  944. L"T61 ### az AZ 09 \'()+,-./:=?",
  945. 0, 0, CERT_RDN_DISABLE_IE4_UTF8_FLAG);
  946. TestUnicodeAnyString(CERT_RDN_IA5_STRING,
  947. rgwBadIA5,
  948. (DWORD) CRYPT_E_INVALID_IA5_STRING, 3);
  949. }
  950. static void TestUniversalString()
  951. {
  952. BOOL fResult;
  953. BYTE *pbEncoded = NULL;
  954. DWORD cbEncoded;
  955. PCERT_NAME_VALUE pInfo = NULL;
  956. CERT_NAME_VALUE NameValue;
  957. DWORD rgdwUniversal[] = {
  958. 0x00ffff,
  959. 0x110000,
  960. 0x010000,
  961. 0xffffffff,
  962. 0x110001,
  963. 0x10FFFF,
  964. };
  965. LPWSTR pwszExpectedUniversal =
  966. L"\xffff"
  967. L"\xfffd"
  968. L"\xd800\xdc00"
  969. L"\xfffd"
  970. L"\xfffd"
  971. L"\xdbff\xdfff"
  972. ;
  973. TestUnicodeAnyString(CERT_RDN_UNIVERSAL_STRING,
  974. L"SPECIAL UNIVERSAL with Surrogate Pairs: "
  975. L"\xd800\xdc00\xdbff\xdfff"
  976. L"\xdbfe\xdc03\xd801\xdfcf"
  977. L"\xd801\x0081\xdc01\xdc02"
  978. L"\xd805\xd806\xd807\xdc04"
  979. L"\xd802\xd803\xfffe\xd804",
  980. 0, 0, 0);
  981. // Encode a universal string containing characters > 0x10FFFF. These
  982. // Should be converted to 0xFFFD
  983. memset(&NameValue, 0, sizeof(NameValue));
  984. NameValue.dwValueType = CERT_RDN_UNIVERSAL_STRING;
  985. NameValue.Value.pbData = (BYTE *) rgdwUniversal;
  986. NameValue.Value.cbData = sizeof(rgdwUniversal);
  987. if (!AllocAndEncodeObject(
  988. X509_ANY_STRING,
  989. &NameValue,
  990. &pbEncoded,
  991. &cbEncoded
  992. )) {
  993. goto CommonReturn;
  994. }
  995. if (NULL == (pInfo = (PCERT_NAME_VALUE) AllocAndDecodeObject(
  996. X509_UNICODE_ANY_STRING,
  997. pbEncoded,
  998. cbEncoded,
  999. NULL
  1000. ))) goto CommonReturn;
  1001. if (wcslen(pwszExpectedUniversal) != wcslen((LPWSTR) pInfo->Value.pbData) ||
  1002. wcslen(pwszExpectedUniversal) * 2 != pInfo->Value.cbData ||
  1003. 0 != wcscmp(pwszExpectedUniversal, (LPWSTR) pInfo->Value.pbData))
  1004. printf("UniversalString encode/decode failed\n");
  1005. CommonReturn:
  1006. if (pbEncoded)
  1007. TestFree(pbEncoded);
  1008. if (pInfo)
  1009. TestFree(pInfo);
  1010. }
  1011. static void TestChoiceOfTime(
  1012. FILETIME *pftEncode
  1013. )
  1014. {
  1015. BOOL fResult;
  1016. BYTE *pbEncoded = NULL;
  1017. DWORD cbEncoded;
  1018. FILETIME ftDecode;
  1019. DWORD cbInfo;
  1020. printf("Test encode/decode X509_CHOICE_OF_TIME: %s\n",
  1021. FileTimeText(pftEncode));
  1022. if (!AllocAndEncodeObject(
  1023. X509_CHOICE_OF_TIME,
  1024. pftEncode,
  1025. &pbEncoded,
  1026. &cbEncoded))
  1027. goto CommonReturn;
  1028. cbInfo = sizeof(ftDecode);
  1029. if (!CryptDecodeObject(
  1030. dwCertEncodingType,
  1031. X509_CHOICE_OF_TIME,
  1032. pbEncoded,
  1033. cbEncoded,
  1034. 0, // dwFlags
  1035. &ftDecode,
  1036. &cbInfo
  1037. )) {
  1038. PrintLastError("CryptDecodeObject(X509_CHOICE_OF_TIME)");
  1039. goto CommonReturn;
  1040. }
  1041. if (cbInfo != sizeof(ftDecode))
  1042. printf("X509_CHOICE_OF_TIME failed => unexpected decode length\n");
  1043. if (0 != memcmp(pftEncode, &ftDecode, sizeof(ftDecode)))
  1044. printf("X509_CHOICE_OF_TIME failed => decode (%s) != encode input\n",
  1045. FileTimeText(&ftDecode));
  1046. CommonReturn:
  1047. if (pbEncoded)
  1048. TestFree(pbEncoded);
  1049. }
  1050. static void TestChoiceOfTime()
  1051. {
  1052. FILETIME ft;
  1053. SYSTEMTIME t;
  1054. memset(&t, 0, sizeof(t));
  1055. t.wYear = 2000;
  1056. t.wMonth = 1;
  1057. t.wDay = 2;
  1058. t.wHour = 3;
  1059. t.wMinute = 4;
  1060. t.wSecond = 5;
  1061. if (!SystemTimeToFileTime(&t, &ft)) {
  1062. PrintLastError("SystemTimeToFileTime");
  1063. return;
  1064. }
  1065. TestChoiceOfTime(&ft);
  1066. t.wYear = 1900;
  1067. if (!SystemTimeToFileTime(&t, &ft)) {
  1068. PrintLastError("SystemTimeToFileTime");
  1069. return;
  1070. }
  1071. TestChoiceOfTime(&ft);
  1072. t.wYear = 2080;
  1073. if (!SystemTimeToFileTime(&t, &ft)) {
  1074. PrintLastError("SystemTimeToFileTime");
  1075. return;
  1076. }
  1077. TestChoiceOfTime(&ft);
  1078. }
  1079. static void TestUtcTime(
  1080. FILETIME *pftEncode
  1081. )
  1082. {
  1083. BOOL fResult;
  1084. BYTE *pbEncoded = NULL;
  1085. DWORD cbEncoded;
  1086. FILETIME ftDecode;
  1087. DWORD cbInfo;
  1088. printf("Test encode/decode PKCS_UTC_TIME: %s\n",
  1089. FileTimeText(pftEncode));
  1090. if (!AllocAndEncodeObject(
  1091. PKCS_UTC_TIME,
  1092. pftEncode,
  1093. &pbEncoded,
  1094. &cbEncoded))
  1095. goto CommonReturn;
  1096. cbInfo = sizeof(ftDecode);
  1097. if (!CryptDecodeObject(
  1098. dwCertEncodingType,
  1099. PKCS_UTC_TIME,
  1100. pbEncoded,
  1101. cbEncoded,
  1102. 0, // dwFlags
  1103. &ftDecode,
  1104. &cbInfo
  1105. )) {
  1106. PrintLastError("CryptDecodeObject(PKCS_UTC_TIME)");
  1107. goto CommonReturn;
  1108. }
  1109. if (cbInfo != sizeof(ftDecode))
  1110. printf("PKCS_UTC_TIME failed => unexpected decode length\n");
  1111. if (0 != memcmp(pftEncode, &ftDecode, sizeof(ftDecode)))
  1112. printf("PKCS_UTC_TIME failed => decode (%s) != encode input\n",
  1113. FileTimeText(&ftDecode));
  1114. CommonReturn:
  1115. if (pbEncoded)
  1116. TestFree(pbEncoded);
  1117. }
  1118. static void TestUtcTime()
  1119. {
  1120. FILETIME ft;
  1121. SYSTEMTIME t;
  1122. memset(&t, 0, sizeof(t));
  1123. t.wYear = 1950;
  1124. t.wMonth = 1;
  1125. t.wDay = 2;
  1126. t.wHour = 3;
  1127. t.wMinute = 4;
  1128. t.wSecond = 5;
  1129. if (!SystemTimeToFileTime(&t, &ft)) {
  1130. PrintLastError("SystemTimeToFileTime");
  1131. return;
  1132. }
  1133. TestUtcTime(&ft);
  1134. t.wYear = 2049;
  1135. if (!SystemTimeToFileTime(&t, &ft)) {
  1136. PrintLastError("SystemTimeToFileTime");
  1137. return;
  1138. }
  1139. TestUtcTime(&ft);
  1140. t.wMonth = 1;
  1141. t.wDay = 1;
  1142. t.wHour = 0;
  1143. t.wMinute = 0;
  1144. t.wSecond = 0;
  1145. if (!SystemTimeToFileTime(&t, &ft)) {
  1146. PrintLastError("SystemTimeToFileTime");
  1147. return;
  1148. }
  1149. TestUtcTime(&ft);
  1150. }
  1151. static void TestBadAltName(
  1152. PCERT_ALT_NAME_INFO pInfo,
  1153. DWORD dwEntryIndex,
  1154. DWORD dwValueIndex
  1155. )
  1156. {
  1157. DWORD cbEncoded;
  1158. printf("Test encode X509_ALTERNATE_NAME:: Bad Entry: %d Value: %d\n",
  1159. dwEntryIndex, dwValueIndex);
  1160. if (CryptEncodeObject(
  1161. dwCertEncodingType,
  1162. X509_ALTERNATE_NAME,
  1163. pInfo,
  1164. NULL, // pbEncoded
  1165. &cbEncoded
  1166. ))
  1167. printf(" failed => expected error\n");
  1168. else {
  1169. DWORD dwErr = GetLastError();
  1170. if (CRYPT_E_INVALID_IA5_STRING != dwErr)
  1171. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  1172. CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
  1173. dwErr, dwErr);
  1174. if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
  1175. printf(" EntryIndex failed => expected: %d, got: %d\n",
  1176. dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
  1177. if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
  1178. printf(" ValueIndex failed => expected: %d, got: %d\n",
  1179. dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
  1180. }
  1181. }
  1182. static void TestBadAltName()
  1183. {
  1184. CERT_ALT_NAME_INFO AltNameInfo;
  1185. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
  1186. #define ALT_NAME_ENTRY_CNT 4
  1187. CERT_ALT_NAME_ENTRY rgAltNameEntry[ALT_NAME_ENTRY_CNT];
  1188. rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1189. rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
  1190. rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
  1191. rgAltNameEntry[1].pwszURL = L"URL string";
  1192. rgAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_URL;
  1193. rgAltNameEntry[2].pwszURL = rgwBadIA5;
  1194. rgAltNameEntry[3].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1195. rgAltNameEntry[3].pwszRfc822Name = L"RFC822";
  1196. AltNameInfo.cAltEntry = ALT_NAME_ENTRY_CNT;
  1197. AltNameInfo.rgAltEntry = rgAltNameEntry;
  1198. TestBadAltName(&AltNameInfo, 2, 4);
  1199. }
  1200. static void TestBadAuthorityInfoAccess(
  1201. PCERT_AUTHORITY_INFO_ACCESS pInfo,
  1202. DWORD dwEntryIndex,
  1203. DWORD dwValueIndex
  1204. )
  1205. {
  1206. DWORD cbEncoded;
  1207. printf("Test encode X509_AUTHORITY_INFO_ACCESS:: Bad Entry: %d Value: %d\n",
  1208. dwEntryIndex, dwValueIndex);
  1209. if (CryptEncodeObject(
  1210. dwCertEncodingType,
  1211. X509_AUTHORITY_INFO_ACCESS,
  1212. pInfo,
  1213. NULL, // pbEncoded
  1214. &cbEncoded
  1215. ))
  1216. printf(" failed => expected error\n");
  1217. else {
  1218. DWORD dwErr = GetLastError();
  1219. if (CRYPT_E_INVALID_IA5_STRING != dwErr)
  1220. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  1221. CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
  1222. dwErr, dwErr);
  1223. if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
  1224. printf(" EntryIndex failed => expected: %d, got: %d\n",
  1225. dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
  1226. if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
  1227. printf(" ValueIndex failed => expected: %d, got: %d\n",
  1228. dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
  1229. }
  1230. }
  1231. static void TestBadAuthorityInfoAccess()
  1232. {
  1233. CERT_AUTHORITY_INFO_ACCESS AuthorityInfoAccess;
  1234. CERT_ACCESS_DESCRIPTION rgAccess[5];
  1235. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x80, 0x37, 0x00};
  1236. rgAccess[0].pszAccessMethod = szOID_PKIX_OCSP;
  1237. rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  1238. rgAccess[0].AccessLocation.pwszURL = L"URL to the stars";
  1239. rgAccess[1].pszAccessMethod = szOID_PKIX_OCSP;
  1240. rgAccess[1].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  1241. rgAccess[1].AccessLocation.pwszURL = L"URL to the stars";
  1242. rgAccess[2].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
  1243. rgAccess[2].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1244. rgAccess[2].AccessLocation.pwszRfc822Name = L"[email protected]";
  1245. rgAccess[3].pszAccessMethod = szOID_PKIX_OCSP;
  1246. rgAccess[3].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  1247. rgAccess[3].AccessLocation.pwszURL = rgwBadIA5;
  1248. rgAccess[4].pszAccessMethod = szOID_PKIX_OCSP;
  1249. rgAccess[4].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  1250. rgAccess[4].AccessLocation.pwszURL = L"URL to the POLICY";
  1251. AuthorityInfoAccess.cAccDescr = 5;
  1252. AuthorityInfoAccess.rgAccDescr = rgAccess;
  1253. TestBadAuthorityInfoAccess(&AuthorityInfoAccess, 3, 6);
  1254. }
  1255. static void TestBadAuthorityKeyId2(
  1256. PCERT_AUTHORITY_KEY_ID2_INFO pInfo,
  1257. DWORD dwEntryIndex,
  1258. DWORD dwValueIndex
  1259. )
  1260. {
  1261. DWORD cbEncoded;
  1262. printf("Test encode X509_AUTHORITY_KEY_ID2:: Bad Entry: %d Value: %d\n",
  1263. dwEntryIndex, dwValueIndex);
  1264. if (CryptEncodeObject(
  1265. dwCertEncodingType,
  1266. X509_AUTHORITY_KEY_ID2,
  1267. pInfo,
  1268. NULL, // pbEncoded
  1269. &cbEncoded
  1270. ))
  1271. printf(" failed => expected error\n");
  1272. else {
  1273. DWORD dwErr = GetLastError();
  1274. if (CRYPT_E_INVALID_IA5_STRING != dwErr)
  1275. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  1276. CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
  1277. dwErr, dwErr);
  1278. if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
  1279. printf(" EntryIndex failed => expected: %d, got: %d\n",
  1280. dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
  1281. if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
  1282. printf(" ValueIndex failed => expected: %d, got: %d\n",
  1283. dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
  1284. }
  1285. }
  1286. static void TestBadAuthorityKeyId2()
  1287. {
  1288. CERT_AUTHORITY_KEY_ID2_INFO KeyId2Info;
  1289. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
  1290. #define KEY_ID_ALT_NAME_ENTRY_CNT 2
  1291. CERT_ALT_NAME_ENTRY rgAltNameEntry[KEY_ID_ALT_NAME_ENTRY_CNT];
  1292. rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1293. rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
  1294. rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
  1295. rgAltNameEntry[1].pwszURL = rgwBadIA5;
  1296. memset(&KeyId2Info, 0, sizeof(KeyId2Info));
  1297. KeyId2Info.AuthorityCertIssuer.cAltEntry = KEY_ID_ALT_NAME_ENTRY_CNT;
  1298. KeyId2Info.AuthorityCertIssuer.rgAltEntry = rgAltNameEntry;
  1299. TestBadAuthorityKeyId2(&KeyId2Info, 1, 4);
  1300. }
  1301. static void TestBadNameConstraints(
  1302. PCERT_NAME_CONSTRAINTS_INFO pInfo,
  1303. DWORD dwEntryIndex,
  1304. DWORD dwValueIndex,
  1305. BOOL fExcludedSubtree
  1306. )
  1307. {
  1308. DWORD cbEncoded;
  1309. printf("Test encode NAME_CONSTRAINTS:: Bad Entry: %d Value: %d fExcluded: %d\n",
  1310. dwEntryIndex, dwValueIndex, fExcludedSubtree);
  1311. if (CryptEncodeObject(
  1312. dwCertEncodingType,
  1313. X509_NAME_CONSTRAINTS,
  1314. pInfo,
  1315. NULL, // pbEncoded
  1316. &cbEncoded
  1317. ))
  1318. printf(" failed => expected error\n");
  1319. else {
  1320. DWORD dwErr = GetLastError();
  1321. if (CRYPT_E_INVALID_IA5_STRING != dwErr)
  1322. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  1323. CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
  1324. dwErr, dwErr);
  1325. if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
  1326. printf(" EntryIndex failed => expected: %d, got: %d\n",
  1327. dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
  1328. if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
  1329. printf(" ValueIndex failed => expected: %d, got: %d\n",
  1330. dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
  1331. if (fExcludedSubtree != IS_CERT_EXCLUDED_SUBTREE(cbEncoded))
  1332. printf(" fExcludedSubtree failed => expected: %d, got: %d\n",
  1333. fExcludedSubtree, IS_CERT_EXCLUDED_SUBTREE(cbEncoded));
  1334. }
  1335. }
  1336. static void TestBadNameConstraints()
  1337. {
  1338. CERT_NAME_CONSTRAINTS_INFO Info;
  1339. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
  1340. #define NAME_CONSTRAINTS_SUBTREE_CNT 2
  1341. CERT_GENERAL_SUBTREE rgSubtree[NAME_CONSTRAINTS_SUBTREE_CNT];
  1342. memset(rgSubtree, 0, sizeof(rgSubtree));
  1343. rgSubtree[0].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1344. rgSubtree[0].Base.pwszRfc822Name = L"RFC822";
  1345. rgSubtree[1].Base.dwAltNameChoice = CERT_ALT_NAME_URL;
  1346. rgSubtree[1].Base.pwszURL = rgwBadIA5;
  1347. memset(&Info, 0, sizeof(Info));
  1348. Info.cPermittedSubtree = NAME_CONSTRAINTS_SUBTREE_CNT;
  1349. Info.rgPermittedSubtree = rgSubtree;
  1350. TestBadNameConstraints(&Info, 1, 4, FALSE);
  1351. memset(&Info, 0, sizeof(Info));
  1352. Info.cExcludedSubtree = NAME_CONSTRAINTS_SUBTREE_CNT;
  1353. Info.rgExcludedSubtree = rgSubtree;
  1354. TestBadNameConstraints(&Info, 1, 4, TRUE);
  1355. }
  1356. static void TestBadIssuingDistPoint(
  1357. PCRL_ISSUING_DIST_POINT pInfo,
  1358. DWORD dwEntryIndex,
  1359. DWORD dwValueIndex
  1360. )
  1361. {
  1362. DWORD cbEncoded;
  1363. printf("Test encode ISSUING_DIST_POINT:: Bad Entry: %d Value: %d\n",
  1364. dwEntryIndex, dwValueIndex);
  1365. if (CryptEncodeObject(
  1366. dwCertEncodingType,
  1367. X509_ISSUING_DIST_POINT,
  1368. pInfo,
  1369. NULL, // pbEncoded
  1370. &cbEncoded
  1371. ))
  1372. printf(" failed => expected error\n");
  1373. else {
  1374. DWORD dwErr = GetLastError();
  1375. if (CRYPT_E_INVALID_IA5_STRING != dwErr)
  1376. printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
  1377. CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
  1378. dwErr, dwErr);
  1379. if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
  1380. printf(" EntryIndex failed => expected: %d, got: %d\n",
  1381. dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
  1382. if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
  1383. printf(" ValueIndex failed => expected: %d, got: %d\n",
  1384. dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
  1385. }
  1386. }
  1387. static void TestBadIssuingDistPoint()
  1388. {
  1389. CRL_ISSUING_DIST_POINT Info;
  1390. WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
  1391. #define IDP_ALT_NAME_ENTRY_CNT 2
  1392. CERT_ALT_NAME_ENTRY rgAltNameEntry[IDP_ALT_NAME_ENTRY_CNT];
  1393. rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1394. rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
  1395. rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
  1396. rgAltNameEntry[1].pwszURL = rgwBadIA5;
  1397. memset(&Info, 0, sizeof(Info));
  1398. Info.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
  1399. Info.DistPointName.FullName.cAltEntry = IDP_ALT_NAME_ENTRY_CNT;
  1400. Info.DistPointName.FullName.rgAltEntry = rgAltNameEntry;
  1401. TestBadIssuingDistPoint(&Info, 1, 4);
  1402. }
  1403. static void TestCryptExportPublicKeyInfo()
  1404. {
  1405. BOOL fResult;
  1406. LPCSTR pszResult;
  1407. HCRYPTPROV hProv = 0;
  1408. PCERT_PUBLIC_KEY_INFO pCorrectInfo = NULL;
  1409. DWORD cbCorrectInfo;
  1410. PCERT_PUBLIC_KEY_INFO pInfo = NULL;
  1411. DWORD cbInfo;
  1412. DWORD cbTotal;
  1413. printf("\n");
  1414. if (0 == (hProv = GetCryptProv()))
  1415. goto ErrorReturn;
  1416. // Test: cbInfo == correct length
  1417. if (!CryptExportPublicKeyInfo(
  1418. hProv,
  1419. AT_SIGNATURE,
  1420. dwCertEncodingType,
  1421. NULL, // pInfo
  1422. &cbCorrectInfo
  1423. )) {
  1424. PrintLastError("CryptExportPublicKeyInfo(pInfo == NULL)");
  1425. goto ErrorReturn;
  1426. }
  1427. if (NULL == (pCorrectInfo = (PCERT_PUBLIC_KEY_INFO) TestAlloc(
  1428. cbCorrectInfo)))
  1429. goto ErrorReturn;
  1430. cbTotal = cbCorrectInfo + DELTA_MORE_LENGTH;
  1431. if (NULL == (pInfo = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbTotal)))
  1432. goto ErrorReturn;
  1433. memset(pCorrectInfo, 0, cbCorrectInfo);
  1434. if (!CryptExportPublicKeyInfo(
  1435. hProv,
  1436. AT_SIGNATURE,
  1437. dwCertEncodingType,
  1438. pCorrectInfo,
  1439. &cbCorrectInfo
  1440. )) {
  1441. PrintLastError("CryptExportPublicKeyInfo(cbInfo == correct length)");
  1442. goto ErrorReturn;
  1443. }
  1444. printf("For cbInfo == correct length\n");
  1445. printf("Info Length = %d (0x%x) Content::\n",
  1446. cbCorrectInfo, cbCorrectInfo);
  1447. PrintBytes(" ", (BYTE *)pCorrectInfo, cbCorrectInfo);
  1448. // Test: cbInfo < correct length
  1449. printf("\n");
  1450. memset(pInfo, 0, cbTotal);
  1451. cbInfo = cbCorrectInfo - DELTA_LESS_LENGTH;
  1452. fResult = CryptExportPublicKeyInfo(
  1453. hProv,
  1454. AT_SIGNATURE,
  1455. dwCertEncodingType,
  1456. pInfo,
  1457. &cbInfo
  1458. );
  1459. if (fResult) {
  1460. pszResult = "TRUE";
  1461. printf("failed => CryptExportPublicKeyInfo(cbInfo < correct length) returned success\n");
  1462. } else {
  1463. DWORD dwErr = GetLastError();
  1464. pszResult = "FALSE";
  1465. if (0 == dwErr)
  1466. printf("failed => CryptExportPublicKey(cbInfo < correct length) LastError == 0\n");
  1467. else
  1468. printf(
  1469. "CryptExportPublicKey(cbInfo < correct length) LastError = 0x%x (%d)\n",
  1470. dwErr, dwErr);
  1471. }
  1472. printf("For cbInfo < correct length, fResult = %s\n", pszResult);
  1473. printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
  1474. PrintBytes(" ", (BYTE *) pInfo, cbTotal);
  1475. if (cbInfo != cbCorrectInfo)
  1476. printf("failed => for cbInfo < correct length:: wrong cbInfo\n");
  1477. // Test: cbInfo > correct length
  1478. printf("\n");
  1479. memset(pInfo, 0, cbTotal);
  1480. cbInfo = cbTotal;
  1481. fResult = CryptExportPublicKeyInfo(
  1482. hProv,
  1483. AT_SIGNATURE,
  1484. dwCertEncodingType,
  1485. pInfo,
  1486. &cbInfo
  1487. );
  1488. if (fResult)
  1489. pszResult = "TRUE";
  1490. else {
  1491. pszResult = "FALSE";
  1492. PrintLastError("CryptExportPublicKeyInfo(cbInfo > correct length)");
  1493. }
  1494. printf("For cbInfo > correct length, fResult = %s\n", pszResult);
  1495. printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
  1496. PrintBytes(" ", (BYTE *) pInfo, cbTotal);
  1497. if (cbInfo != cbCorrectInfo)
  1498. printf("failed => for cbInfo > correct length:: wrong cbInfo\n");
  1499. // Test: pInfo != NULL, cbInfo == 0
  1500. printf("\n");
  1501. memset(pInfo, 0, cbTotal);
  1502. cbInfo = 0;
  1503. fResult = CryptExportPublicKeyInfo(
  1504. hProv,
  1505. AT_SIGNATURE,
  1506. dwCertEncodingType,
  1507. pInfo,
  1508. &cbInfo
  1509. );
  1510. if (fResult) {
  1511. pszResult = "TRUE";
  1512. printf("failed => CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) returned success\n");
  1513. } else {
  1514. DWORD dwErr = GetLastError();
  1515. pszResult = "FALSE";
  1516. if (0 == dwErr)
  1517. printf("failed => CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) LastError == 0\n");
  1518. else
  1519. printf(
  1520. "CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) LastError = 0x%x (%d)\n",
  1521. dwErr, dwErr);
  1522. }
  1523. printf("For pInfo != NULL, cbInfo == 0, fResult = %s\n", pszResult);
  1524. printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
  1525. PrintBytes(" ", (BYTE *) pInfo, cbTotal);
  1526. CommonReturn:
  1527. if (pInfo)
  1528. TestFree(pInfo);
  1529. if (pCorrectInfo)
  1530. TestFree(pCorrectInfo);
  1531. if (hProv)
  1532. CryptReleaseContext(hProv, 0);
  1533. return;
  1534. ErrorReturn:
  1535. goto CommonReturn;
  1536. }
  1537. //+-------------------------------------------------------------------------
  1538. // Compare 2 CRYPT_DATA_BLOB structs.
  1539. //
  1540. // Returns: FALSE iff differ
  1541. //--------------------------------------------------------------------------
  1542. BOOL
  1543. WINAPI
  1544. EqualCryptDataBlob(
  1545. IN PCRYPT_DATA_BLOB p1,
  1546. IN PCRYPT_DATA_BLOB p2)
  1547. {
  1548. if (p1->cbData != p2->cbData)
  1549. return FALSE;
  1550. if (p1->cbData == 0)
  1551. return TRUE;
  1552. return (0 == memcmp(p1->pbData, p2->pbData, p1->cbData));
  1553. }
  1554. //+-------------------------------------------------------------------------
  1555. // Compare 2 CRYPT_ATTRIBUTE structs.
  1556. //
  1557. // Returns: FALSE iff differ
  1558. //--------------------------------------------------------------------------
  1559. BOOL
  1560. WINAPI
  1561. EqualAttribute(
  1562. IN PCRYPT_ATTRIBUTE patr1,
  1563. IN PCRYPT_ATTRIBUTE patr2)
  1564. {
  1565. BOOL fRet;
  1566. DWORD i;
  1567. PCRYPT_ATTR_BLOB pabl1;
  1568. PCRYPT_ATTR_BLOB pabl2;
  1569. fRet = (0 == strcmp( patr1->pszObjId, patr2->pszObjId));
  1570. fRet &= (patr1->cValue == patr2->cValue);
  1571. if (fRet) {
  1572. for (i=patr1->cValue, pabl1=patr1->rgValue, pabl2=patr2->rgValue;
  1573. i>0;
  1574. i--, pabl1++, pabl2++) {
  1575. fRet &= (pabl1->cbData == pabl2->cbData);
  1576. if (fRet) {
  1577. fRet &= (0 == memcmp( pabl1->pbData,
  1578. pabl2->pbData,
  1579. pabl1->cbData));
  1580. }
  1581. }
  1582. }
  1583. return fRet;
  1584. }
  1585. static void TestCmcData()
  1586. {
  1587. BOOL fResult;
  1588. BYTE *pbEncoded = NULL;
  1589. DWORD cbEncoded;
  1590. PCMC_DATA_INFO pInfo = NULL;
  1591. CMC_DATA_INFO CmcData;
  1592. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  1593. BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  1594. BYTE rgb2[] = {0x30, 0x0}; // Empty SEQUENCE
  1595. CRYPT_ATTR_BLOB rgValue[3] = {
  1596. sizeof(rgb0), rgb0,
  1597. sizeof(rgb1), rgb1,
  1598. sizeof(rgb2), rgb2
  1599. };
  1600. CMC_TAGGED_ATTRIBUTE rgTagAttr[2];
  1601. CMC_TAGGED_CERT_REQUEST rgTagCertReq[3];
  1602. CMC_TAGGED_REQUEST rgTagReq[3];
  1603. CMC_TAGGED_CONTENT_INFO rgTagContentInfo[2];
  1604. CMC_TAGGED_OTHER_MSG rgTagOtherMsg[2];
  1605. DWORD i;
  1606. rgTagAttr[0].dwBodyPartID = 0x7FFFFFFF;
  1607. rgTagAttr[0].Attribute.pszObjId = "1.2.3.4";
  1608. rgTagAttr[0].Attribute.cValue = 2;
  1609. rgTagAttr[0].Attribute.rgValue = rgValue;
  1610. rgTagAttr[1].dwBodyPartID = 0x80000001;
  1611. rgTagAttr[1].Attribute.pszObjId = "1.2.3.5";
  1612. rgTagAttr[1].Attribute.cValue = 0;
  1613. rgTagAttr[1].Attribute.rgValue = NULL;
  1614. CmcData.cTaggedAttribute = 2;
  1615. CmcData.rgTaggedAttribute = rgTagAttr;
  1616. rgTagCertReq[0].dwBodyPartID = 0x12345678;
  1617. rgTagCertReq[0].SignedCertRequest = rgValue[0];
  1618. rgTagCertReq[1].dwBodyPartID = 0x87654321;
  1619. rgTagCertReq[1].SignedCertRequest = rgValue[1];
  1620. rgTagCertReq[2].dwBodyPartID = 0x1;
  1621. rgTagCertReq[2].SignedCertRequest = rgValue[2];
  1622. rgTagReq[0].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
  1623. rgTagReq[0].pTaggedCertRequest = &rgTagCertReq[0];
  1624. rgTagReq[1].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
  1625. rgTagReq[1].pTaggedCertRequest = &rgTagCertReq[1];
  1626. rgTagReq[2].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
  1627. rgTagReq[2].pTaggedCertRequest = &rgTagCertReq[2];
  1628. CmcData.cTaggedRequest = 3;
  1629. CmcData.rgTaggedRequest = rgTagReq;
  1630. rgTagContentInfo[0].dwBodyPartID = 2;
  1631. rgTagContentInfo[0].EncodedContentInfo = rgValue[0];
  1632. rgTagContentInfo[1].dwBodyPartID = 3;
  1633. rgTagContentInfo[1].EncodedContentInfo = rgValue[2];
  1634. CmcData.cTaggedContentInfo = 2;
  1635. CmcData.rgTaggedContentInfo = rgTagContentInfo;
  1636. rgTagOtherMsg[0].dwBodyPartID = 14;
  1637. rgTagOtherMsg[0].pszObjId = "1.2.44.55.66";
  1638. rgTagOtherMsg[0].Value = rgValue[0];
  1639. rgTagOtherMsg[1].dwBodyPartID = 15;
  1640. rgTagOtherMsg[1].pszObjId = "1.2.44.55.66.77";
  1641. rgTagOtherMsg[1].Value = rgValue[1];
  1642. CmcData.cTaggedOtherMsg = 2;
  1643. CmcData.rgTaggedOtherMsg = rgTagOtherMsg;
  1644. printf("Test encode/decode CMC_DATA\n");
  1645. if (!AllocAndEncodeObject(
  1646. CMC_DATA,
  1647. &CmcData,
  1648. &pbEncoded,
  1649. &cbEncoded))
  1650. goto CommonReturn;
  1651. if (NULL == (pInfo =
  1652. (PCMC_DATA_INFO) AllocAndDecodeObject(
  1653. CMC_DATA,
  1654. pbEncoded,
  1655. cbEncoded
  1656. ))) goto CommonReturn;
  1657. if (pInfo->cTaggedAttribute != CmcData.cTaggedAttribute ||
  1658. pInfo->cTaggedRequest != CmcData.cTaggedRequest ||
  1659. pInfo->cTaggedContentInfo != CmcData.cTaggedContentInfo ||
  1660. pInfo->cTaggedOtherMsg != CmcData.cTaggedOtherMsg) {
  1661. printf("CMC_DATA failed => invalid decoded tag counts\n");
  1662. goto CommonReturn;
  1663. }
  1664. for (i = 0; i < CmcData.cTaggedAttribute; i++) {
  1665. if (CmcData.rgTaggedAttribute[i].dwBodyPartID !=
  1666. pInfo->rgTaggedAttribute[i].dwBodyPartID ||
  1667. !EqualAttribute(&CmcData.rgTaggedAttribute[i].Attribute,
  1668. &pInfo->rgTaggedAttribute[i].Attribute)) {
  1669. printf("CMC_DATA failed => invalid decoded tagged attribute\n");
  1670. goto CommonReturn;
  1671. }
  1672. }
  1673. for (i = 0; i < CmcData.cTaggedRequest; i++) {
  1674. PCMC_TAGGED_CERT_REQUEST pEncodeTagReq;
  1675. PCMC_TAGGED_CERT_REQUEST pDecodeTagReq;
  1676. if (CMC_TAGGED_CERT_REQUEST_CHOICE !=
  1677. pInfo->rgTaggedRequest[i].dwTaggedRequestChoice) {
  1678. printf("CMC_DATA failed => invalid decoded tagged request\n");
  1679. goto CommonReturn;
  1680. }
  1681. pEncodeTagReq = CmcData.rgTaggedRequest[i].pTaggedCertRequest;
  1682. pDecodeTagReq = pInfo->rgTaggedRequest[i].pTaggedCertRequest;
  1683. if (pEncodeTagReq->dwBodyPartID != pDecodeTagReq->dwBodyPartID ||
  1684. !EqualCryptDataBlob(&pEncodeTagReq->SignedCertRequest,
  1685. &pDecodeTagReq->SignedCertRequest)) {
  1686. printf("CMC_DATA failed => invalid decoded tagged request\n");
  1687. goto CommonReturn;
  1688. }
  1689. }
  1690. for (i = 0; i < CmcData.cTaggedContentInfo; i++) {
  1691. if (CmcData.rgTaggedContentInfo[i].dwBodyPartID !=
  1692. pInfo->rgTaggedContentInfo[i].dwBodyPartID ||
  1693. !EqualCryptDataBlob(
  1694. &CmcData.rgTaggedContentInfo[i].EncodedContentInfo,
  1695. &pInfo->rgTaggedContentInfo[i].EncodedContentInfo)) {
  1696. printf("CMC_DATA failed => invalid decoded tagged ContentInfo\n");
  1697. goto CommonReturn;
  1698. }
  1699. }
  1700. for (i = 0; i < CmcData.cTaggedOtherMsg; i++) {
  1701. if (CmcData.rgTaggedOtherMsg[i].dwBodyPartID !=
  1702. pInfo->rgTaggedOtherMsg[i].dwBodyPartID ||
  1703. 0 != strcmp(CmcData.rgTaggedOtherMsg[i].pszObjId,
  1704. pInfo->rgTaggedOtherMsg[i].pszObjId) ||
  1705. !EqualCryptDataBlob(&CmcData.rgTaggedOtherMsg[i].Value,
  1706. &pInfo->rgTaggedOtherMsg[i].Value)) {
  1707. printf("CMC_DATA failed => invalid decoded tagged OtherMsg\n");
  1708. goto CommonReturn;
  1709. }
  1710. }
  1711. TestFree(pbEncoded);
  1712. pbEncoded = NULL;
  1713. TestFree(pInfo);
  1714. pInfo = NULL;
  1715. // Do and encode/decode without any tagged entries
  1716. memset(&CmcData, 0, sizeof(CmcData));
  1717. printf("Test encode/decode CMC_DATA(No Tagged Entries)\n");
  1718. if (!AllocAndEncodeObject(
  1719. CMC_DATA,
  1720. &CmcData,
  1721. &pbEncoded,
  1722. &cbEncoded))
  1723. goto CommonReturn;
  1724. if (NULL == (pInfo =
  1725. (PCMC_DATA_INFO) AllocAndDecodeObject(
  1726. CMC_DATA,
  1727. pbEncoded,
  1728. cbEncoded
  1729. ))) goto CommonReturn;
  1730. if (pInfo->cTaggedAttribute != 0 ||
  1731. pInfo->cTaggedRequest != 0 ||
  1732. pInfo->cTaggedContentInfo != 0 ||
  1733. pInfo->cTaggedOtherMsg != 0) {
  1734. printf("CMC_DATA failed => invalid decoded tag counts\n");
  1735. goto CommonReturn;
  1736. }
  1737. CommonReturn:
  1738. if (pbEncoded)
  1739. TestFree(pbEncoded);
  1740. if (pInfo)
  1741. TestFree(pInfo);
  1742. }
  1743. static void TestCmcResponse()
  1744. {
  1745. BOOL fResult;
  1746. BYTE *pbEncoded = NULL;
  1747. DWORD cbEncoded;
  1748. PCMC_RESPONSE_INFO pInfo = NULL;
  1749. CMC_RESPONSE_INFO CmcResponse;
  1750. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  1751. BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  1752. BYTE rgb2[] = {0x30, 0x0}; // Empty SEQUENCE
  1753. CRYPT_ATTR_BLOB rgValue[3] = {
  1754. sizeof(rgb0), rgb0,
  1755. sizeof(rgb1), rgb1,
  1756. sizeof(rgb2), rgb2
  1757. };
  1758. CMC_TAGGED_ATTRIBUTE rgTagAttr[2];
  1759. CMC_TAGGED_CONTENT_INFO rgTagContentInfo[2];
  1760. CMC_TAGGED_OTHER_MSG rgTagOtherMsg[2];
  1761. DWORD i;
  1762. rgTagAttr[0].dwBodyPartID = 0x7FFFFFFF;
  1763. rgTagAttr[0].Attribute.pszObjId = "1.2.3.4";
  1764. rgTagAttr[0].Attribute.cValue = 2;
  1765. rgTagAttr[0].Attribute.rgValue = rgValue;
  1766. rgTagAttr[1].dwBodyPartID = 0x80000001;
  1767. rgTagAttr[1].Attribute.pszObjId = "1.2.3.5";
  1768. rgTagAttr[1].Attribute.cValue = 0;
  1769. rgTagAttr[1].Attribute.rgValue = NULL;
  1770. CmcResponse.cTaggedAttribute = 2;
  1771. CmcResponse.rgTaggedAttribute = rgTagAttr;
  1772. rgTagContentInfo[0].dwBodyPartID = 2;
  1773. rgTagContentInfo[0].EncodedContentInfo = rgValue[0];
  1774. rgTagContentInfo[1].dwBodyPartID = 3;
  1775. rgTagContentInfo[1].EncodedContentInfo = rgValue[2];
  1776. CmcResponse.cTaggedContentInfo = 2;
  1777. CmcResponse.rgTaggedContentInfo = rgTagContentInfo;
  1778. rgTagOtherMsg[0].dwBodyPartID = 14;
  1779. rgTagOtherMsg[0].pszObjId = "1.2.44.55.66";
  1780. rgTagOtherMsg[0].Value = rgValue[0];
  1781. rgTagOtherMsg[1].dwBodyPartID = 15;
  1782. rgTagOtherMsg[1].pszObjId = "1.2.44.55.66.77";
  1783. rgTagOtherMsg[1].Value = rgValue[1];
  1784. CmcResponse.cTaggedOtherMsg = 2;
  1785. CmcResponse.rgTaggedOtherMsg = rgTagOtherMsg;
  1786. printf("Test encode/decode CMC_RESPONSE\n");
  1787. if (!AllocAndEncodeObject(
  1788. CMC_RESPONSE,
  1789. &CmcResponse,
  1790. &pbEncoded,
  1791. &cbEncoded))
  1792. goto CommonReturn;
  1793. if (NULL == (pInfo =
  1794. (PCMC_RESPONSE_INFO) AllocAndDecodeObject(
  1795. CMC_RESPONSE,
  1796. pbEncoded,
  1797. cbEncoded
  1798. ))) goto CommonReturn;
  1799. if (pInfo->cTaggedAttribute != CmcResponse.cTaggedAttribute ||
  1800. pInfo->cTaggedContentInfo != CmcResponse.cTaggedContentInfo ||
  1801. pInfo->cTaggedOtherMsg != CmcResponse.cTaggedOtherMsg) {
  1802. printf("CMC_RESPONSE failed => invalid decoded tag counts\n");
  1803. goto CommonReturn;
  1804. }
  1805. for (i = 0; i < CmcResponse.cTaggedAttribute; i++) {
  1806. if (CmcResponse.rgTaggedAttribute[i].dwBodyPartID !=
  1807. pInfo->rgTaggedAttribute[i].dwBodyPartID ||
  1808. !EqualAttribute(&CmcResponse.rgTaggedAttribute[i].Attribute,
  1809. &pInfo->rgTaggedAttribute[i].Attribute)) {
  1810. printf("CMC_RESPONSE failed => invalid decoded tagged attribute\n");
  1811. goto CommonReturn;
  1812. }
  1813. }
  1814. for (i = 0; i < CmcResponse.cTaggedContentInfo; i++) {
  1815. if (CmcResponse.rgTaggedContentInfo[i].dwBodyPartID !=
  1816. pInfo->rgTaggedContentInfo[i].dwBodyPartID ||
  1817. !EqualCryptDataBlob(
  1818. &CmcResponse.rgTaggedContentInfo[i].EncodedContentInfo,
  1819. &pInfo->rgTaggedContentInfo[i].EncodedContentInfo)) {
  1820. printf("CMC_RESPONSE failed => invalid decoded tagged ContentInfo\n");
  1821. goto CommonReturn;
  1822. }
  1823. }
  1824. for (i = 0; i < CmcResponse.cTaggedOtherMsg; i++) {
  1825. if (CmcResponse.rgTaggedOtherMsg[i].dwBodyPartID !=
  1826. pInfo->rgTaggedOtherMsg[i].dwBodyPartID ||
  1827. 0 != strcmp(CmcResponse.rgTaggedOtherMsg[i].pszObjId,
  1828. pInfo->rgTaggedOtherMsg[i].pszObjId) ||
  1829. !EqualCryptDataBlob(&CmcResponse.rgTaggedOtherMsg[i].Value,
  1830. &pInfo->rgTaggedOtherMsg[i].Value)) {
  1831. printf("CMC_RESPONSE failed => invalid decoded tagged OtherMsg\n");
  1832. goto CommonReturn;
  1833. }
  1834. }
  1835. CommonReturn:
  1836. if (pbEncoded)
  1837. TestFree(pbEncoded);
  1838. if (pInfo)
  1839. TestFree(pInfo);
  1840. }
  1841. static void TestCmcStatus(
  1842. DWORD dwOtherInfoChoice
  1843. )
  1844. {
  1845. BOOL fResult;
  1846. BYTE *pbEncoded = NULL;
  1847. DWORD cbEncoded;
  1848. PCMC_STATUS_INFO pInfo = NULL;
  1849. CMC_STATUS_INFO CmcStatus;
  1850. DWORD rgdwBodyList[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
  1851. BYTE rgbPendToken[] = {1,2,3,4,5};
  1852. CMC_PEND_INFO PendInfo;
  1853. SYSTEMTIME t;
  1854. DWORD i;
  1855. CmcStatus.dwStatus = 0x12345678;
  1856. CmcStatus.cBodyList = 3;
  1857. CmcStatus.rgdwBodyList = rgdwBodyList;
  1858. switch (dwOtherInfoChoice) {
  1859. case CMC_OTHER_INFO_FAIL_CHOICE:
  1860. CmcStatus.pwszStatusString = L"\0";
  1861. CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_FAIL_CHOICE;
  1862. CmcStatus.dwFailInfo = 0x11223344;
  1863. break;
  1864. case CMC_OTHER_INFO_PEND_CHOICE:
  1865. CmcStatus.pwszStatusString = L"Status String";
  1866. CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_PEND_CHOICE;
  1867. CmcStatus.pPendInfo = &PendInfo;
  1868. PendInfo.PendToken.cbData = sizeof(rgbPendToken);
  1869. PendInfo.PendToken.pbData = rgbPendToken;
  1870. memset(&t, 0, sizeof(t));
  1871. t.wYear = 2000;
  1872. t.wMonth = 1;
  1873. t.wDay = 2;
  1874. t.wHour = 3;
  1875. t.wMinute = 4;
  1876. t.wSecond = 5;
  1877. t.wMilliseconds = 678;
  1878. if (!SystemTimeToFileTime(&t, &PendInfo.PendTime)) {
  1879. PrintLastError("SystemTimeToFileTime");
  1880. return;
  1881. }
  1882. break;
  1883. case CMC_OTHER_INFO_NO_CHOICE:
  1884. default:
  1885. CmcStatus.pwszStatusString = NULL;
  1886. CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_NO_CHOICE;
  1887. CmcStatus.cBodyList = 0;
  1888. CmcStatus.rgdwBodyList = NULL;
  1889. }
  1890. printf("Test encode/decode CMC_STATUS(OtherInfoChoice:%d)\n",
  1891. dwOtherInfoChoice);
  1892. if (!AllocAndEncodeObject(
  1893. CMC_STATUS,
  1894. &CmcStatus,
  1895. &pbEncoded,
  1896. &cbEncoded))
  1897. goto CommonReturn;
  1898. if (NULL == (pInfo =
  1899. (PCMC_STATUS_INFO) AllocAndDecodeObject(
  1900. CMC_STATUS,
  1901. pbEncoded,
  1902. cbEncoded
  1903. ))) goto CommonReturn;
  1904. if (CmcStatus.dwStatus != pInfo->dwStatus ||
  1905. CmcStatus.cBodyList != pInfo->cBodyList ||
  1906. CmcStatus.dwOtherInfoChoice != pInfo->dwOtherInfoChoice) {
  1907. printf("CMC_STATUS failed => encode/decode mismatch\n");
  1908. goto CommonReturn;
  1909. }
  1910. switch (CmcStatus.dwOtherInfoChoice) {
  1911. case CMC_OTHER_INFO_FAIL_CHOICE:
  1912. if (pInfo->pwszStatusString != NULL)
  1913. printf("CMC_STATUS failed => expected NULL StatusString\n");
  1914. if (CmcStatus.dwFailInfo != pInfo->dwFailInfo)
  1915. printf("CMC_STATUS failed => bad FailInfo\n");
  1916. break;
  1917. case CMC_OTHER_INFO_PEND_CHOICE:
  1918. {
  1919. PCMC_PEND_INFO pEncodePendInfo;
  1920. PCMC_PEND_INFO pDecodePendInfo;
  1921. if (pInfo->pwszStatusString == NULL ||
  1922. 0 != wcscmp(CmcStatus.pwszStatusString,
  1923. pInfo->pwszStatusString))
  1924. printf("CMC_STATUS failed => bad StatusString\n");
  1925. pEncodePendInfo = CmcStatus.pPendInfo;
  1926. pDecodePendInfo = pInfo->pPendInfo;
  1927. if (!EqualCryptDataBlob(
  1928. &pEncodePendInfo->PendToken,
  1929. &pDecodePendInfo->PendToken))
  1930. printf("CMC_STATUS failed => bad PendToken\n");
  1931. if (0 != memcmp(&pEncodePendInfo->PendTime,
  1932. &pDecodePendInfo->PendTime,
  1933. sizeof(pDecodePendInfo->PendTime)))
  1934. printf("CMC_STATUS failed => bad PendTime\n");
  1935. }
  1936. break;
  1937. case CMC_OTHER_INFO_NO_CHOICE:
  1938. default:
  1939. if (pInfo->pwszStatusString != NULL)
  1940. printf("CMC_STATUS failed => expected NULL StatusString\n");
  1941. }
  1942. for (i = 0; i < CmcStatus.cBodyList; i++) {
  1943. if (CmcStatus.rgdwBodyList[i] != pInfo->rgdwBodyList[i]) {
  1944. printf("CMC_STATUS failed => invalid decoded tagged BodyList\n");
  1945. goto CommonReturn;
  1946. }
  1947. }
  1948. CommonReturn:
  1949. if (pbEncoded)
  1950. TestFree(pbEncoded);
  1951. if (pInfo)
  1952. TestFree(pInfo);
  1953. }
  1954. static void TestCmcAddExtensions()
  1955. {
  1956. BOOL fResult;
  1957. BYTE *pbEncoded = NULL;
  1958. DWORD cbEncoded;
  1959. PCMC_ADD_EXTENSIONS_INFO pInfo = NULL;
  1960. CMC_ADD_EXTENSIONS_INFO CmcAddExtensions;
  1961. DWORD rgdwCertReference[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
  1962. BYTE rgbExt[] = {0x1, 0x2, 0x3};
  1963. CERT_EXTENSION rgExt[2] = {
  1964. "1.2.3.4.5", TRUE, sizeof(rgbExt), rgbExt,
  1965. "1.2.3.6.7", FALSE, sizeof(rgbExt), rgbExt
  1966. };
  1967. DWORD i;
  1968. CmcAddExtensions.dwCmcDataReference = 0x12345678;
  1969. CmcAddExtensions.cCertReference = 3;
  1970. CmcAddExtensions.rgdwCertReference = rgdwCertReference;
  1971. CmcAddExtensions.cExtension = 2;
  1972. CmcAddExtensions.rgExtension = rgExt;
  1973. printf("Test encode/decode CMC_ADD_EXTENSIONS\n");
  1974. if (!AllocAndEncodeObject(
  1975. CMC_ADD_EXTENSIONS,
  1976. &CmcAddExtensions,
  1977. &pbEncoded,
  1978. &cbEncoded))
  1979. goto CommonReturn;
  1980. if (NULL == (pInfo =
  1981. (PCMC_ADD_EXTENSIONS_INFO) AllocAndDecodeObject(
  1982. CMC_ADD_EXTENSIONS,
  1983. pbEncoded,
  1984. cbEncoded
  1985. ))) goto CommonReturn;
  1986. if (CmcAddExtensions.dwCmcDataReference != pInfo->dwCmcDataReference ||
  1987. CmcAddExtensions.cCertReference != pInfo->cCertReference ||
  1988. CmcAddExtensions.cExtension != pInfo->cExtension) {
  1989. printf("CMC_ADD_EXTENSIONS failed => encode/decode mismatch\n");
  1990. goto CommonReturn;
  1991. }
  1992. for (i = 0; i < CmcAddExtensions.cCertReference; i++) {
  1993. if (CmcAddExtensions.rgdwCertReference[i] !=
  1994. pInfo->rgdwCertReference[i]) {
  1995. printf("CMC_ADD_EXTENSIONS failed => invalid decoded CertReference\n");
  1996. goto CommonReturn;
  1997. }
  1998. }
  1999. for (i = 0; i < CmcAddExtensions.cExtension; i++) {
  2000. PCERT_EXTENSION pEncodeExt = &CmcAddExtensions.rgExtension[i];
  2001. PCERT_EXTENSION pDecodeExt = &pInfo->rgExtension[i];
  2002. if (0 != strcmp(pEncodeExt->pszObjId, pDecodeExt->pszObjId) ||
  2003. pEncodeExt->fCritical != pDecodeExt->fCritical ||
  2004. !EqualCryptDataBlob(&pEncodeExt->Value, &pEncodeExt->Value)) {
  2005. printf("CMC_ADD_EXTENSIONS failed => invalid decoded Extensions\n");
  2006. goto CommonReturn;
  2007. }
  2008. }
  2009. CommonReturn:
  2010. if (pbEncoded)
  2011. TestFree(pbEncoded);
  2012. if (pInfo)
  2013. TestFree(pInfo);
  2014. }
  2015. static void TestCmcAddAttributes()
  2016. {
  2017. BOOL fResult;
  2018. BYTE *pbEncoded = NULL;
  2019. DWORD cbEncoded;
  2020. PCMC_ADD_ATTRIBUTES_INFO pInfo = NULL;
  2021. CMC_ADD_ATTRIBUTES_INFO CmcAddAttributes;
  2022. DWORD rgdwCertReference[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
  2023. BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
  2024. BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
  2025. CRYPT_ATTR_BLOB rgValue[2] = {
  2026. sizeof(rgb0), rgb0,
  2027. sizeof(rgb1), rgb1
  2028. };
  2029. CRYPT_ATTRIBUTE rgAttr[3] = {
  2030. "1.2.3.6.8", 0, NULL,
  2031. "1.2.3.6.7", 1, rgValue,
  2032. "1.2.3.4.5", 2, rgValue,
  2033. };
  2034. DWORD i;
  2035. CmcAddAttributes.dwCmcDataReference = 0x12345678;
  2036. CmcAddAttributes.cCertReference = 3;
  2037. CmcAddAttributes.rgdwCertReference = rgdwCertReference;
  2038. CmcAddAttributes.cAttribute = 3;
  2039. CmcAddAttributes.rgAttribute = rgAttr;
  2040. printf("Test encode/decode CMC_ADD_ATTRIBUTES\n");
  2041. if (!AllocAndEncodeObject(
  2042. CMC_ADD_ATTRIBUTES,
  2043. &CmcAddAttributes,
  2044. &pbEncoded,
  2045. &cbEncoded))
  2046. goto CommonReturn;
  2047. if (NULL == (pInfo =
  2048. (PCMC_ADD_ATTRIBUTES_INFO) AllocAndDecodeObject(
  2049. CMC_ADD_ATTRIBUTES,
  2050. pbEncoded,
  2051. cbEncoded
  2052. ))) goto CommonReturn;
  2053. if (CmcAddAttributes.dwCmcDataReference != pInfo->dwCmcDataReference ||
  2054. CmcAddAttributes.cCertReference != pInfo->cCertReference ||
  2055. CmcAddAttributes.cAttribute != pInfo->cAttribute) {
  2056. printf("CMC_ADD_ATTRIBUTES failed => encode/decode mismatch\n");
  2057. goto CommonReturn;
  2058. }
  2059. for (i = 0; i < CmcAddAttributes.cCertReference; i++) {
  2060. if (CmcAddAttributes.rgdwCertReference[i] !=
  2061. pInfo->rgdwCertReference[i]) {
  2062. printf("CMC_ADD_ATTRIBUTES failed => invalid decoded CertReference\n");
  2063. goto CommonReturn;
  2064. }
  2065. }
  2066. for (i = 0; i < CmcAddAttributes.cAttribute; i++) {
  2067. PCRYPT_ATTRIBUTE pEncodeAttr = &CmcAddAttributes.rgAttribute[i];
  2068. PCRYPT_ATTRIBUTE pDecodeAttr = &pInfo->rgAttribute[i];
  2069. if (!EqualAttribute(pEncodeAttr, pDecodeAttr))
  2070. printf("CMC_ADD_ATTRIBUTES failed => invalid decoded Attributes\n");
  2071. }
  2072. CommonReturn:
  2073. if (pbEncoded)
  2074. TestFree(pbEncoded);
  2075. if (pInfo)
  2076. TestFree(pInfo);
  2077. }
  2078. static void TestCertTemplate()
  2079. {
  2080. BOOL fResult;
  2081. BYTE *pbEncoded = NULL;
  2082. DWORD cbEncoded;
  2083. PCERT_TEMPLATE_EXT pInfo = NULL;
  2084. CERT_TEMPLATE_EXT CertTemplate;
  2085. CertTemplate.pszObjId = "1.2.3.4.5.6.7.8.9";
  2086. CertTemplate.dwMajorVersion = 0x11223344;
  2087. CertTemplate.fMinorVersion = FALSE;
  2088. printf("Test encode/decode X509_CERTIFICATE_TEMPLATE\n");
  2089. if (!AllocAndEncodeObject(
  2090. X509_CERTIFICATE_TEMPLATE,
  2091. &CertTemplate,
  2092. &pbEncoded,
  2093. &cbEncoded))
  2094. goto CommonReturn;
  2095. if (NULL == (pInfo =
  2096. (PCERT_TEMPLATE_EXT) AllocAndDecodeObject(
  2097. X509_CERTIFICATE_TEMPLATE,
  2098. pbEncoded,
  2099. cbEncoded
  2100. ))) goto CommonReturn;
  2101. if (0 != strcmp(pInfo->pszObjId, CertTemplate.pszObjId) ||
  2102. pInfo->dwMajorVersion != CertTemplate.dwMajorVersion ||
  2103. pInfo->fMinorVersion != CertTemplate.fMinorVersion)
  2104. printf("X509_CERTIFICATE_TEMPLATE failed => decode != encode input\n");
  2105. TestFree(pbEncoded);
  2106. pbEncoded = NULL;
  2107. TestFree(pInfo);
  2108. pInfo = NULL;
  2109. CertTemplate.fMinorVersion = TRUE;
  2110. CertTemplate.dwMinorVersion = 12345678;
  2111. if (!AllocAndEncodeObject(
  2112. szOID_CERTIFICATE_TEMPLATE,
  2113. &CertTemplate,
  2114. &pbEncoded,
  2115. &cbEncoded))
  2116. goto CommonReturn;
  2117. if (NULL == (pInfo =
  2118. (PCERT_TEMPLATE_EXT) AllocAndDecodeObject(
  2119. szOID_CERTIFICATE_TEMPLATE,
  2120. pbEncoded,
  2121. cbEncoded
  2122. ))) goto CommonReturn;
  2123. if (0 != strcmp(pInfo->pszObjId, CertTemplate.pszObjId) ||
  2124. pInfo->dwMajorVersion != CertTemplate.dwMajorVersion ||
  2125. pInfo->fMinorVersion != CertTemplate.fMinorVersion ||
  2126. pInfo->dwMinorVersion != CertTemplate.dwMinorVersion)
  2127. printf("szOID_CERTIFICATE_TEMPLATE failed => decode != encode input\n");
  2128. CommonReturn:
  2129. if (pbEncoded)
  2130. TestFree(pbEncoded);
  2131. if (pInfo)
  2132. TestFree(pInfo);
  2133. }
  2134. int _cdecl main(int argc, char * argv[])
  2135. {
  2136. BOOL fResult;
  2137. LPCSTR pszResult;
  2138. CERT_NAME_INFO Name;
  2139. CERT_RDN Rdn[2];
  2140. CERT_RDN_ATTR RdnAttr[2];
  2141. #define ATTR_VALUE0 "Name 0"
  2142. RdnAttr[0].pszObjId = "1.2.3.4";
  2143. RdnAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
  2144. RdnAttr[0].Value.pbData = (BYTE *) ATTR_VALUE0;
  2145. RdnAttr[0].Value.cbData = strlen(ATTR_VALUE0);
  2146. #define ATTR_VALUE1 "Name 11111"
  2147. RdnAttr[1].pszObjId = "1.2.3.4.1";
  2148. RdnAttr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
  2149. RdnAttr[1].Value.pbData = (BYTE *) ATTR_VALUE1;
  2150. RdnAttr[1].Value.cbData = strlen(ATTR_VALUE1);
  2151. Rdn[0].cRDNAttr = 2;
  2152. Rdn[0].rgRDNAttr = RdnAttr;
  2153. Rdn[1].cRDNAttr = 1;
  2154. Rdn[1].rgRDNAttr = &RdnAttr[1];
  2155. Name.cRDN = 2;
  2156. Name.rgRDN = Rdn;
  2157. BYTE *pbEncoded = NULL;
  2158. DWORD cbEncoded;
  2159. BYTE *pbCorrectEncoded = NULL;
  2160. DWORD cbCorrectEncoded;
  2161. DWORD cbTotal;
  2162. PCERT_NAME_INFO pDecodedInfo = NULL;
  2163. DWORD cbDecodedInfo;
  2164. PCERT_NAME_INFO pCorrectDecodedInfo = NULL;
  2165. DWORD cbCorrectDecodedInfo;
  2166. printf("command line: %s\n", GetCommandLine());
  2167. TestExtensions();
  2168. TestX942OtherInfo();
  2169. TestPKCSAttribute();
  2170. TestPKCSAttributes();
  2171. TestContentInfoSequenceOfAny();
  2172. TestSequenceOfAny();
  2173. TestInteger();
  2174. TestMultiByteInteger();
  2175. TestBits();
  2176. TestBitsWithoutTrailingZeroes();
  2177. TestOID();
  2178. TestUnicodeAnyString();
  2179. TestUniversalString();
  2180. TestChoiceOfTime();
  2181. TestUtcTime();
  2182. TestBadAltName();
  2183. TestBadAuthorityInfoAccess();
  2184. TestBadAuthorityKeyId2();
  2185. TestBadNameConstraints();
  2186. TestBadIssuingDistPoint();
  2187. TestCmcData();
  2188. TestCmcResponse();
  2189. TestCmcStatus(CMC_OTHER_INFO_NO_CHOICE);
  2190. TestCmcStatus(CMC_OTHER_INFO_FAIL_CHOICE);
  2191. TestCmcStatus(CMC_OTHER_INFO_PEND_CHOICE);
  2192. TestCmcAddExtensions();
  2193. TestCmcAddAttributes();
  2194. TestCertTemplate();
  2195. TestCryptExportPublicKeyInfo();
  2196. // Test: cbEncoded == correct length
  2197. if (!CryptEncodeObject(
  2198. dwCertEncodingType,
  2199. X509_NAME,
  2200. &Name,
  2201. NULL, // pbEncoded
  2202. &cbCorrectEncoded
  2203. )) {
  2204. PrintLastError("CryptEncodeObject(pbEncoded == NULL)");
  2205. goto ErrorReturn;
  2206. }
  2207. if (NULL == (pbCorrectEncoded = (BYTE *) TestAlloc(cbCorrectEncoded)))
  2208. goto ErrorReturn;
  2209. cbTotal = cbCorrectEncoded + DELTA_MORE_LENGTH;
  2210. if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbTotal)))
  2211. goto ErrorReturn;
  2212. memset(pbCorrectEncoded, 0, cbCorrectEncoded);
  2213. if (!CryptEncodeObject(
  2214. dwCertEncodingType,
  2215. X509_NAME,
  2216. &Name,
  2217. pbCorrectEncoded,
  2218. &cbCorrectEncoded
  2219. )) {
  2220. PrintLastError("CryptEncodeObject(cbEncoded == correct length)");
  2221. goto ErrorReturn;
  2222. }
  2223. printf("For cbEncoded == correct length\n");
  2224. printf("Encoded Length = %d (0x%x) Content::\n",
  2225. cbCorrectEncoded, cbCorrectEncoded);
  2226. PrintBytes(" ", pbCorrectEncoded, cbCorrectEncoded);
  2227. // Test: cbEncoded < correct length
  2228. printf("\n");
  2229. memset(pbEncoded, 0, cbTotal);
  2230. cbEncoded = cbCorrectEncoded - DELTA_LESS_LENGTH;
  2231. fResult = CryptEncodeObject(
  2232. dwCertEncodingType,
  2233. X509_NAME,
  2234. &Name,
  2235. pbEncoded,
  2236. &cbEncoded
  2237. );
  2238. if (fResult) {
  2239. pszResult = "TRUE";
  2240. printf("failed => CryptEncodeObject(cbEncoded < correct length) returned success\n");
  2241. } else {
  2242. DWORD dwErr = GetLastError();
  2243. pszResult = "FALSE";
  2244. if (0 == dwErr)
  2245. printf("failed => CryptEncodeObject(cbEncoded < correct length) LastError == 0\n");
  2246. else
  2247. printf(
  2248. "CryptEncodeObject(cbEncoded < correct length) LastError = 0x%x (%d)\n",
  2249. dwErr, dwErr);
  2250. }
  2251. printf("For cbEncoded < correct length, fResult = %s\n", pszResult);
  2252. printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
  2253. PrintBytes(" ", pbEncoded, cbTotal);
  2254. if (cbEncoded != cbCorrectEncoded)
  2255. printf("failed => for cbEncoded < correct length:: wrong cbEncoded\n");
  2256. // Test: cbEncoded > correct length
  2257. printf("\n");
  2258. memset(pbEncoded, 0, cbTotal);
  2259. cbEncoded = cbTotal;
  2260. fResult = CryptEncodeObject(
  2261. dwCertEncodingType,
  2262. X509_NAME,
  2263. &Name,
  2264. pbEncoded,
  2265. &cbEncoded
  2266. );
  2267. if (fResult)
  2268. pszResult = "TRUE";
  2269. else {
  2270. pszResult = "FALSE";
  2271. PrintLastError("CryptEncodeObject(cbEncoded > correct length)");
  2272. }
  2273. printf("For cbEncoded > correct length, fResult = %s\n", pszResult);
  2274. printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
  2275. PrintBytes(" ", pbEncoded, cbTotal);
  2276. if (cbEncoded != cbCorrectEncoded)
  2277. printf("failed => for cbEncoded > correct length:: wrong cbEncoded\n");
  2278. else if (0 != memcmp(pbEncoded, pbCorrectEncoded, cbCorrectEncoded))
  2279. printf("failed => for cbEncoded > correct length:: bad pbEncoded content\n");
  2280. // Test: pbEncoded != NULL, cbEncoded == 0
  2281. printf("\n");
  2282. memset(pbEncoded, 0, cbTotal);
  2283. cbEncoded = 0;
  2284. fResult = CryptEncodeObject(
  2285. dwCertEncodingType,
  2286. X509_NAME,
  2287. &Name,
  2288. pbEncoded,
  2289. &cbEncoded
  2290. );
  2291. if (fResult) {
  2292. pszResult = "TRUE";
  2293. printf("failed => CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) returned success\n");
  2294. } else {
  2295. DWORD dwErr = GetLastError();
  2296. pszResult = "FALSE";
  2297. if (0 == dwErr)
  2298. printf("failed => CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) LastError == 0\n");
  2299. else
  2300. printf(
  2301. "CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) LastError = 0x%x (%d)\n",
  2302. dwErr, dwErr);
  2303. }
  2304. printf("For pbEncoded != NULL, cbEncoded == 0, fResult = %s\n", pszResult);
  2305. printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
  2306. PrintBytes(" ", pbEncoded, cbTotal);
  2307. printf("\n");
  2308. // Test: cbDecodedInfo == correct length
  2309. if (!CryptDecodeObject(
  2310. dwCertEncodingType,
  2311. X509_NAME,
  2312. pbCorrectEncoded,
  2313. cbCorrectEncoded,
  2314. 0, // dwFlags
  2315. NULL, // pvStructInfo
  2316. &cbCorrectDecodedInfo
  2317. )) {
  2318. PrintLastError("CryptDecodeObject(pvStructInfo == NULL)");
  2319. goto ErrorReturn;
  2320. }
  2321. if (NULL == (pCorrectDecodedInfo = (PCERT_NAME_INFO) TestAlloc(
  2322. cbCorrectDecodedInfo)))
  2323. goto ErrorReturn;
  2324. cbTotal = cbCorrectDecodedInfo + DELTA_MORE_LENGTH;
  2325. if (NULL == (pDecodedInfo = (PCERT_NAME_INFO) TestAlloc(cbTotal)))
  2326. goto ErrorReturn;
  2327. memset(pCorrectDecodedInfo, 0, cbCorrectDecodedInfo);
  2328. if (!CryptDecodeObject(
  2329. dwCertEncodingType,
  2330. X509_NAME,
  2331. pbCorrectEncoded,
  2332. cbCorrectEncoded,
  2333. 0, // dwFlags
  2334. pCorrectDecodedInfo,
  2335. &cbCorrectDecodedInfo
  2336. )) {
  2337. PrintLastError("CryptDecodeObject(cbStructInfo == correct length)");
  2338. goto ErrorReturn;
  2339. }
  2340. // Test: cbDecodedInfo > correct length
  2341. memset(pDecodedInfo, 0, cbTotal);
  2342. cbDecodedInfo = cbTotal;
  2343. fResult = CryptDecodeObject(
  2344. dwCertEncodingType,
  2345. X509_NAME,
  2346. pbCorrectEncoded,
  2347. cbCorrectEncoded,
  2348. 0, // dwFlags
  2349. pDecodedInfo,
  2350. &cbDecodedInfo
  2351. );
  2352. if (!fResult)
  2353. PrintLastError("CryptDecodeObject(cbStructInfo > correct length)");
  2354. if (cbDecodedInfo != cbCorrectDecodedInfo)
  2355. printf("failed => for cbStructInfo > correct length:: wrong cbStructInfo\n");
  2356. // Test: cbDecodedInfo < correct length
  2357. memset(pDecodedInfo, 0, cbTotal);
  2358. cbDecodedInfo = cbCorrectDecodedInfo - DELTA_LESS_LENGTH;
  2359. fResult = CryptDecodeObject(
  2360. dwCertEncodingType,
  2361. X509_NAME,
  2362. pbCorrectEncoded,
  2363. cbCorrectEncoded,
  2364. 0, // dwFlags
  2365. pDecodedInfo,
  2366. &cbDecodedInfo
  2367. );
  2368. if (fResult)
  2369. printf("failed => CryptDecodeObject(cbStructInfo < correct length) returned success\n");
  2370. else {
  2371. DWORD dwErr = GetLastError();
  2372. if (0 == dwErr)
  2373. printf("failed => CryptDecodeObject(cbStructInfo < correct length) LastError == 0\n");
  2374. else
  2375. printf(
  2376. "CryptDecodeObject(cbStructInfo < correct length) LastError = 0x%x (%d)\n",
  2377. dwErr, dwErr);
  2378. }
  2379. if (cbDecodedInfo != cbCorrectDecodedInfo)
  2380. printf("failed => for cbStructInfo < correct length:: wrong cbStructInfo\n");
  2381. // Test: pvStructInfo != NULL, cbStructInfo == 0
  2382. memset(pDecodedInfo, 0, cbTotal);
  2383. cbDecodedInfo = 0;
  2384. fResult = CryptDecodeObject(
  2385. dwCertEncodingType,
  2386. X509_NAME,
  2387. pbCorrectEncoded,
  2388. cbCorrectEncoded,
  2389. 0, // dwFlags
  2390. pDecodedInfo,
  2391. &cbDecodedInfo
  2392. );
  2393. if (fResult)
  2394. printf("failed => CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) returned success\n");
  2395. else {
  2396. DWORD dwErr = GetLastError();
  2397. if (0 == dwErr)
  2398. printf("failed => CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) LastError == 0\n");
  2399. else
  2400. printf(
  2401. "CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) LastError = 0x%x (%d)\n",
  2402. dwErr, dwErr);
  2403. }
  2404. // Test decoding missing the last bytes
  2405. memset(pDecodedInfo, 0, cbTotal);
  2406. cbDecodedInfo = cbCorrectDecodedInfo;
  2407. fResult = CryptDecodeObject(
  2408. dwCertEncodingType,
  2409. X509_NAME,
  2410. pbCorrectEncoded,
  2411. cbCorrectEncoded -30,
  2412. 0, // dwFlags
  2413. pDecodedInfo,
  2414. &cbDecodedInfo
  2415. );
  2416. if (fResult)
  2417. printf("failed => CryptDecodeObject(incomplete cbEncoded) returned success\n");
  2418. else {
  2419. DWORD dwErr = GetLastError();
  2420. if (0 == dwErr)
  2421. printf("failed => CryptDecodeObject(incomplete cbEncoded) LastError == 0\n");
  2422. else
  2423. printf(
  2424. "CryptDecodeObject(incomplete cbEncoded) LastError = 0x%x (%d)\n",
  2425. dwErr, dwErr);
  2426. }
  2427. ErrorReturn:
  2428. if (pbEncoded)
  2429. TestFree(pbEncoded);
  2430. if (pbCorrectEncoded)
  2431. TestFree(pbCorrectEncoded);
  2432. if (pDecodedInfo)
  2433. TestFree(pDecodedInfo);
  2434. if (pCorrectDecodedInfo)
  2435. TestFree(pCorrectDecodedInfo);
  2436. printf("Done.\n");
  2437. return 0;
  2438. }