Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

779 lines
20 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. example.cpp
  5. Abstract:
  6. This is a plug-in for the smart card driver test suite.
  7. This plug-in is smart card dependent
  8. Author:
  9. Klaus U. Schutz
  10. Environment:
  11. Win32 application
  12. Revision History :
  13. Nov. 1997 - initial version
  14. --*/
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <afx.h>
  19. #include <afxtempl.h>
  20. #include <winioctl.h>
  21. #include <winsmcrd.h>
  22. #include "ifdtest.h"
  23. void MyCardEntry(class CCardProvider& in_CCardProvider);
  24. //
  25. // Create a card provider object
  26. // Note: all global varibales and all functions have to be static
  27. //
  28. static class CCardProvider MyCard(MyCardEntry);
  29. //
  30. // This structure represents the result file
  31. // that is stored in the smart card
  32. //
  33. typedef struct _RESULT_FILE {
  34. // Offset to first test result
  35. UCHAR Offset;
  36. // Number of times the card has been reset
  37. UCHAR CardResetCount;
  38. // Version number of this card
  39. UCHAR CardMajorVersion;
  40. UCHAR CardMinorVersion;
  41. // RFU
  42. UCHAR Reserved[6];
  43. //
  44. // The following structures store the results
  45. // of the tests. Each result comes with the
  46. // reset count when the test was performed.
  47. // This is used to make sure that we read not
  48. // the result from an old test, maybe even
  49. // performed with another reader/driver.
  50. //
  51. struct {
  52. UCHAR Result;
  53. UCHAR ResetCount;
  54. } Wtx;
  55. struct {
  56. UCHAR Result;
  57. UCHAR ResetCount;
  58. } ResyncRead;
  59. struct {
  60. UCHAR Result;
  61. UCHAR ResetCount;
  62. } ResyncWrite;
  63. struct {
  64. UCHAR Result;
  65. UCHAR ResetCount;
  66. } Seqnum;
  67. struct {
  68. UCHAR Result;
  69. UCHAR ResetCount;
  70. } IfscRequest;
  71. struct {
  72. UCHAR Result;
  73. UCHAR ResetCount;
  74. } IfsdRequest;
  75. struct {
  76. UCHAR Result;
  77. UCHAR ResetCount;
  78. } Timeout;
  79. } RESULT_FILE, *PRESULT_FILE;
  80. static void
  81. sleep(
  82. clock_t wait
  83. )
  84. {
  85. clock_t goal;
  86. goal = wait + clock();
  87. while( goal > clock() )
  88. ;
  89. }
  90. static ULONG
  91. MyCardSetProtocol(
  92. class CCardProvider& in_CCardProvider,
  93. class CReader& in_CReader
  94. )
  95. /*++
  96. Routine Description:
  97. This function will be called after the card has been correctly
  98. identified. We should here set the protocol that we need
  99. for further transmissions
  100. Arguments:
  101. in_CCardProvider - ref. to our card provider object
  102. in_CReader - ref. to the reader object
  103. Return Value:
  104. IFDSTATUS_FAILED - we were unable to set the protocol correctly
  105. IFDSTATUS_SUCCESS - protocol set correctly
  106. --*/
  107. {
  108. ULONG l_lResult;
  109. TestStart("Try to set incorrect protocol T=0");
  110. l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T0);
  111. // The test MUST fail with the incorrect protocol
  112. TEST_CHECK_NOT_SUPPORTED("Set protocol failed", l_lResult);
  113. TestEnd();
  114. // Now set the correct protocol
  115. TestStart("Set protocol T=1");
  116. l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T1);
  117. TEST_CHECK_SUCCESS("Set protocol failed", l_lResult);
  118. TestEnd();
  119. if (l_lResult != ERROR_SUCCESS) {
  120. return IFDSTATUS_FAILED;
  121. }
  122. return IFDSTATUS_SUCCESS;
  123. }
  124. static ULONG
  125. MyCardTest(
  126. class CCardProvider& in_CCardProvider,
  127. class CReader& in_CReader
  128. )
  129. /*++
  130. Routine Description:
  131. This serves as the test function for a particular smart card
  132. Arguments:
  133. in_CReader - ref. to class that provides all information for the test
  134. Return Value:
  135. IFDSTATUS value
  136. --*/
  137. {
  138. ULONG l_lResult, l_uResultLength, l_uIndex;
  139. PUCHAR l_pchResult;
  140. UCHAR l_rgchBuffer[512];
  141. CHAR l_chFileId;
  142. if (in_CCardProvider.GetTestNo() > 1 && in_CCardProvider.GetTestNo() < 7) {
  143. //
  144. // Select the appropriate file for the test
  145. // Each test is tied to a particular file
  146. //
  147. l_chFileId = (CHAR) in_CCardProvider.GetTestNo() - 1;
  148. //
  149. // APDU for select file
  150. //
  151. PCHAR l_pchFileDesc[] = {
  152. "wtx",
  153. "resync",
  154. "seqnum",
  155. "ifs",
  156. "timeout"
  157. };
  158. memcpy(l_rgchBuffer, "\x00\xa4\x08\x04\x04\x3e\x00\x00\x00", 9);
  159. //
  160. // add file number to select
  161. //
  162. l_rgchBuffer[8] = l_chFileId;
  163. //
  164. // select a file
  165. //
  166. TestStart("SELECT FILE EF%s", l_pchFileDesc[l_chFileId - 1]);
  167. l_lResult = in_CReader.Transmit(
  168. (PUCHAR) l_rgchBuffer,
  169. 9,
  170. &l_pchResult,
  171. &l_uResultLength
  172. );
  173. TestCheck(
  174. l_lResult, "==", ERROR_SUCCESS,
  175. l_uResultLength, 2,
  176. l_pchResult[0], l_pchResult[1], 0x90, 0x00,
  177. NULL, NULL, NULL
  178. );
  179. TEST_END();
  180. //
  181. // Generate a 'test' pattern which will be written to the card
  182. //
  183. for (l_uIndex = 0; l_uIndex < 256; l_uIndex++) {
  184. l_rgchBuffer[5 + l_uIndex] = (UCHAR) l_uIndex;
  185. }
  186. }
  187. switch (in_CCardProvider.GetTestNo()) {
  188. case 1:
  189. //
  190. // First test
  191. //
  192. TestStart("Buffer boundary test");
  193. //
  194. // Check if the reader correctly determines that
  195. // our receive buffer is too small
  196. //
  197. in_CReader.SetReplyBufferSize(9);
  198. l_lResult = in_CReader.Transmit(
  199. (PUCHAR) "\x08\x84\x00\x00\x08",
  200. 5,
  201. &l_pchResult,
  202. &l_uResultLength
  203. );
  204. TestCheck(
  205. l_lResult == ERROR_INSUFFICIENT_BUFFER,
  206. "Transmit should fail due to too small buffer\nReturned %2lxH\nExpected %2lxH",
  207. l_lResult,
  208. ERROR_INSUFFICIENT_BUFFER
  209. );
  210. TestEnd();
  211. in_CReader.SetReplyBufferSize(2048);
  212. break;
  213. case 2: {
  214. //
  215. // Wtx test file id 00 01
  216. // This test checks if the reader/driver correctly handles WTX requests
  217. //
  218. ULONG l_auNumBytes[] = { 1 , 2, 5, 30 };
  219. for (ULONG l_uTest = 0;
  220. l_uTest < sizeof(l_auNumBytes) / sizeof(l_auNumBytes[0]);
  221. l_uTest++) {
  222. ULONG l_uNumBytes = l_auNumBytes[l_uTest];
  223. //
  224. // Now read from this file
  225. // The number of bytes we read corresponds to
  226. // the waiting time extension this command produces
  227. //
  228. TestStart("READ BINARY %3d byte(s)", l_uNumBytes);
  229. //
  230. // apdu for read binary
  231. //
  232. memcpy(l_rgchBuffer, "\x00\xB0\x00\x00", 4);
  233. //
  234. // Append number of bytes
  235. //
  236. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  237. l_lResult = in_CReader.Transmit(
  238. l_rgchBuffer,
  239. 5,
  240. &l_pchResult,
  241. &l_uResultLength
  242. );
  243. TestCheck(
  244. l_lResult, "==", ERROR_SUCCESS,
  245. l_uResultLength, l_uNumBytes + 2,
  246. l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1],
  247. 0x90, 0x00,
  248. l_pchResult, l_rgchBuffer + 5, l_uNumBytes
  249. );
  250. TEST_END();
  251. }
  252. break;
  253. }
  254. case 3: {
  255. ULONG l_uNumBytes = 255;
  256. // resync. on write file id 00 02
  257. TestStart("WRITE BINARY %3d bytes", l_uNumBytes);
  258. // Tpdu for write binary
  259. memcpy(l_rgchBuffer, "\x00\xd6\x00\x00", 4);
  260. // Append number of bytes (note: the buffer contains the pattern already)
  261. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  262. l_lResult = in_CReader.Transmit(
  263. l_rgchBuffer,
  264. 5 + l_uNumBytes,
  265. &l_pchResult,
  266. &l_uResultLength
  267. );
  268. TestCheck(
  269. l_lResult, "==", ERROR_IO_DEVICE,
  270. 0, 0,
  271. 0, 0, 0, 0,
  272. NULL, NULL, 0
  273. );
  274. TEST_END();
  275. // resync. on read file id 00 02
  276. TestStart("READ BINARY %3d byte(s)", l_uNumBytes);
  277. // tpdu for read binary
  278. memcpy(l_rgchBuffer, "\x00\xB0\x00\x00", 4);
  279. // Append number of bytes
  280. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  281. l_lResult = in_CReader.Transmit(
  282. l_rgchBuffer,
  283. 5,
  284. &l_pchResult,
  285. &l_uResultLength
  286. );
  287. TestCheck(
  288. l_lResult, "==", ERROR_IO_DEVICE,
  289. 0, 0,
  290. 0, 0, 0, 0,
  291. NULL, NULL, 0
  292. );
  293. TEST_END();
  294. break;
  295. }
  296. case 4: {
  297. // wrong block seq. no file id 00 03
  298. ULONG l_uNumBytes = 255;
  299. TestStart("READ BINARY %3d bytes", l_uNumBytes);
  300. // Tpdu for read binary
  301. memcpy(l_rgchBuffer, "\x00\xb0\x00\x00", 4);
  302. // Append number of bytes (note: the buffer contains the pattern already)
  303. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  304. l_lResult = in_CReader.Transmit(
  305. l_rgchBuffer,
  306. 5,
  307. &l_pchResult,
  308. &l_uResultLength
  309. );
  310. TestCheck(
  311. l_lResult, "==", ERROR_IO_DEVICE,
  312. 0, 0,
  313. 0, 0, 0, 0,
  314. NULL, NULL, 0
  315. );
  316. TEST_END();
  317. break;
  318. }
  319. case 5: {
  320. // ifsc request file id 00 04
  321. ULONG l_uNumBytes = 255;
  322. TestStart("WRITE BINARY %3d bytes", l_uNumBytes);
  323. // Tpdu for write binary
  324. memcpy(l_rgchBuffer, "\x00\xd6\x00\x00", 4);
  325. // Append number of bytes (note: the buffer contains the pattern already)
  326. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  327. l_lResult = in_CReader.Transmit(
  328. l_rgchBuffer,
  329. 5 + l_uNumBytes,
  330. &l_pchResult,
  331. &l_uResultLength
  332. );
  333. TestCheck(
  334. l_lResult, "==", ERROR_SUCCESS,
  335. l_uResultLength, 2,
  336. l_pchResult[0], l_pchResult[1], 0x90, 0x00,
  337. NULL, NULL, NULL
  338. );
  339. TEST_END();
  340. #ifdef junk
  341. l_uNumBytes = 255;
  342. TestStart("READ BINARY %3d byte(s)", l_uNumBytes);
  343. // tpdu for read binary
  344. memcpy(l_rgchBuffer, "\x00\xB0\x00\x00", 4);
  345. // Append number of bytes
  346. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  347. l_lResult = in_CReader.Transmit(
  348. l_rgchBuffer,
  349. 5,
  350. &l_pchResult,
  351. &l_uResultLength
  352. );
  353. TestCheck(
  354. l_lResult, "==", ERROR_SUCCESS,
  355. l_uResultLength, l_uNumBytes + 2,
  356. l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1],
  357. 0x90, 0x00,
  358. l_pchResult, l_rgchBuffer + 5, l_uNumBytes
  359. );
  360. TEST_END();
  361. #endif
  362. break;
  363. }
  364. case 6: {
  365. // forced timeout file id 00 05
  366. ULONG l_uNumBytes = 254;
  367. TestStart("READ BINARY %3d bytes", l_uNumBytes);
  368. // tpdu for read binary
  369. memcpy(l_rgchBuffer, "\x00\xB0\x00\x00", 4);
  370. // Append number of bytes
  371. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  372. l_lResult = in_CReader.Transmit(
  373. l_rgchBuffer,
  374. 5,
  375. &l_pchResult,
  376. &l_uResultLength
  377. );
  378. TestCheck(
  379. l_lResult, "==", ERROR_IO_DEVICE,
  380. 0, 0,
  381. 0, 0, 0, 0,
  382. NULL, NULL, 0
  383. );
  384. TEST_END();
  385. break;
  386. }
  387. case 7:{
  388. //
  389. // Read the result file from the smart card.
  390. // The card stores results of each test in
  391. // a special file
  392. //
  393. ULONG l_uNumBytes = sizeof(RESULT_FILE);
  394. PRESULT_FILE pCResultFile;
  395. TestStart("SELECT FILE EFresult");
  396. l_lResult = in_CReader.Transmit(
  397. (PUCHAR) "\x00\xa4\x08\x04\x04\x3e\x00\xA0\x00",
  398. 9,
  399. &l_pchResult,
  400. &l_uResultLength
  401. );
  402. TestCheck(
  403. l_lResult, "==", ERROR_SUCCESS,
  404. l_uResultLength, 2,
  405. l_pchResult[0], l_pchResult[1], 0x90, 0x00,
  406. NULL, NULL, NULL
  407. );
  408. TEST_END();
  409. // Read
  410. TestStart("READ BINARY %3d bytes", l_uNumBytes);
  411. // apdu for read binary
  412. memcpy(l_rgchBuffer, "\x00\xB0\x00\x00", 4);
  413. // Append number of bytes
  414. l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
  415. l_lResult = in_CReader.Transmit(
  416. l_rgchBuffer,
  417. 5,
  418. &l_pchResult,
  419. &l_uResultLength
  420. );
  421. TestCheck(
  422. l_lResult, "==", ERROR_SUCCESS,
  423. l_uResultLength, l_uNumBytes + 2,
  424. l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1],
  425. 0x90, 0x00,
  426. NULL, NULL, NULL
  427. );
  428. TEST_END();
  429. pCResultFile = (PRESULT_FILE) l_pchResult;
  430. //
  431. // Now check the result file.
  432. //
  433. //
  434. // Check wtx result
  435. //
  436. TestStart("WTX result");
  437. TestCheck(
  438. pCResultFile->Wtx.ResetCount == pCResultFile->CardResetCount,
  439. "Test not performed"
  440. );
  441. TestCheck(
  442. (pCResultFile->Wtx.Result & 0x01) == 0,
  443. "Smart card received no WTX reply"
  444. );
  445. TestCheck(
  446. (pCResultFile->Wtx.Result & 0x02) == 0,
  447. "Smart card received wrong WTX reply"
  448. );
  449. TestCheck(
  450. pCResultFile->Wtx.Result == 0,
  451. "Test failed. Error code %02xH",
  452. pCResultFile->Wtx.Result
  453. );
  454. TestEnd();
  455. //
  456. // Check resync. read result
  457. //
  458. TestStart("RESYNCH read result");
  459. TestCheck(
  460. pCResultFile->ResyncRead.ResetCount == pCResultFile->CardResetCount,
  461. "Test not performed"
  462. );
  463. TestCheck(
  464. (pCResultFile->ResyncRead.Result & 0x01) == 0,
  465. "Smart card received no RESYNCH request"
  466. );
  467. TestCheck(
  468. pCResultFile->ResyncRead.Result == 0,
  469. "Test failed. Error code %02xH",
  470. pCResultFile->ResyncRead.Result
  471. );
  472. TestEnd();
  473. //
  474. // Check resync. write result
  475. //
  476. TestStart("RESYNCH write result");
  477. TestCheck(
  478. pCResultFile->ResyncWrite.ResetCount == pCResultFile->CardResetCount,
  479. "Test not performed"
  480. );
  481. TestCheck(
  482. (pCResultFile->ResyncWrite.Result & 0x01) == 0,
  483. "Smart card received no RESYNCH request"
  484. );
  485. TestCheck(
  486. (pCResultFile->ResyncWrite.Result & 0x02) == 0,
  487. "Smart card received incorrect data"
  488. );
  489. TestCheck(
  490. pCResultFile->ResyncWrite.Result == 0,
  491. "Test failed. Error code %02xH",
  492. pCResultFile->ResyncWrite.Result
  493. );
  494. TestEnd();
  495. //
  496. // Sequence number result
  497. //
  498. TestStart("Sequence number result");
  499. TestCheck(
  500. pCResultFile->ResyncRead.ResetCount == pCResultFile->CardResetCount,
  501. "Test not performed"
  502. );
  503. TestCheck(
  504. (pCResultFile->Seqnum.Result & 0x01) == 0,
  505. "Smart card received no RESYNCH request"
  506. );
  507. TestCheck(
  508. (pCResultFile->Seqnum.Result & 0x02) == 0,
  509. "Smart card received incorrect data"
  510. );
  511. TestCheck(
  512. pCResultFile->Seqnum.Result == 0,
  513. "Test failed. Error code %02xH",
  514. pCResultFile->Seqnum.Result
  515. );
  516. TestEnd();
  517. //
  518. // IFSC Request
  519. //
  520. TestStart("IFSC request");
  521. TestCheck(
  522. pCResultFile->IfscRequest.ResetCount == pCResultFile->CardResetCount,
  523. "Test not performed"
  524. );
  525. TestCheck(
  526. (pCResultFile->IfscRequest.Result & 0x01) == 0,
  527. "Smart card received no IFSC reply"
  528. );
  529. TestCheck(
  530. (pCResultFile->IfscRequest.Result & 0x02) == 0,
  531. "Smart card received incorrect data"
  532. );
  533. TestCheck(
  534. (pCResultFile->IfscRequest.Result & 0x04) == 0,
  535. "Block size BEFORE IFSC request incorrect",
  536. pCResultFile->IfscRequest.Result
  537. );
  538. TestCheck(
  539. (pCResultFile->IfscRequest.Result & 0x08) == 0,
  540. "Block size AFTER IFSC request incorrect",
  541. pCResultFile->IfscRequest.Result
  542. );
  543. TestCheck(
  544. pCResultFile->IfscRequest.Result == 0x00,
  545. "Test failed. Error code %02xH",
  546. pCResultFile->IfscRequest.Result
  547. );
  548. TestEnd();
  549. //
  550. // IFSD Request
  551. //
  552. TestStart("IFSD request");
  553. TestCheck(
  554. pCResultFile->IfsdRequest.ResetCount == pCResultFile->CardResetCount,
  555. "Test not performed"
  556. );
  557. TestCheck(
  558. (pCResultFile->IfsdRequest.Result & 0x01) == 0,
  559. "Smart card received no IFSD request"
  560. );
  561. TestCheck(
  562. pCResultFile->IfsdRequest.Result == 0x00,
  563. "Test failed. Error code %02xH",
  564. pCResultFile->IfsdRequest.Result
  565. );
  566. TestEnd();
  567. //
  568. // Timeout
  569. //
  570. TestStart("Forced timeout result");
  571. TestCheck(
  572. pCResultFile->Timeout.ResetCount == pCResultFile->CardResetCount,
  573. "Test not performed"
  574. );
  575. TestCheck(
  576. pCResultFile->Timeout.Result == 0,
  577. "Test failed. Error code %02xH",
  578. pCResultFile->Timeout.Result
  579. );
  580. TestEnd();
  581. return IFDSTATUS_END;
  582. }
  583. default:
  584. return IFDSTATUS_FAILED;
  585. }
  586. return IFDSTATUS_SUCCESS;
  587. }
  588. static void
  589. MyCardEntry(
  590. class CCardProvider& in_CCardProvider
  591. )
  592. /*++
  593. Routine Description:
  594. This function registers all callbacks from the test suite
  595. Arguments:
  596. CCardProvider - ref. to card provider class
  597. Return Value:
  598. -
  599. --*/
  600. {
  601. // Set protocol callback
  602. in_CCardProvider.SetProtocol(MyCardSetProtocol);
  603. // Card test callback
  604. in_CCardProvider.SetCardTest(MyCardTest);
  605. // Name of our card
  606. in_CCardProvider.SetCardName("SIEMENS NIXDORF");
  607. // Set ATR of our card
  608. in_CCardProvider.SetAtr(
  609. (PBYTE) "\x3b\xef\x00\x00\x81\x31\x20\x49\x00\x5c\x50\x43\x54\x10\x27\xf8\xd2\x76\x00\x00\x38\x33\x00\x4d",
  610. 24
  611. );
  612. }