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.

1819 lines
54 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. smcprot.c
  5. Author:
  6. Klaus U. Schutz
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. - Dec. 96: Initial version
  11. - Nov. 97: Release 1.0
  12. - Feb. 98: T=1 uses now the min of IFSC, IFSD for SmartcardT1Request
  13. T=1 fixed number of bytes to invert for inverse convention cards
  14. --*/
  15. #ifdef SMCLIB_VXD
  16. #define try
  17. #define leave goto __label
  18. #define finally __label:
  19. #else
  20. #ifndef SMCLIB_CE
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <ntddk.h>
  25. #endif // SMCLIB_CE
  26. #endif
  27. #include "smclib.h"
  28. #define SMARTCARD_POOL_TAG 'bLCS'
  29. #ifdef DEBUG_INTERFACE
  30. BOOLEAN
  31. DebugT1Reply(
  32. PSMARTCARD_EXTENSION SmartcardExtension
  33. );
  34. void
  35. DebugGetT1Request(
  36. PSMARTCARD_EXTENSION SmartcardExtension,
  37. NTSTATUS Status
  38. );
  39. BOOLEAN
  40. DebugSetT1Request(
  41. PSMARTCARD_EXTENSION SmartcardExtension
  42. );
  43. #endif // DEBUG_INTERFACE
  44. void
  45. DumpData(
  46. const ULONG DebugLevel,
  47. PUCHAR Data,
  48. ULONG DataLen
  49. );
  50. //
  51. // Usually an io-request consists only of the SCARD_IO_REQUEST header
  52. // followed by the data to be transmitted. To allow modification of
  53. // protocol data, it is possible to pass down the data to be modified.
  54. // These data are ASN1 encoded.
  55. //
  56. typedef struct _IO_HEADER {
  57. SCARD_IO_REQUEST ScardIoRequest;
  58. UCHAR Asn1Data[1];
  59. } IO_HEADER, *PIO_HEADER;
  60. NTSTATUS
  61. #ifdef SMCLIB_VXD
  62. SMCLIB_SmartcardRawRequest(
  63. #else
  64. SmartcardRawRequest(
  65. #endif
  66. PSMARTCARD_EXTENSION SmartcardExtension
  67. )
  68. /*++
  69. Routine Description:
  70. Arguments:
  71. Return Value:
  72. -
  73. --*/
  74. {
  75. PSMARTCARD_REQUEST smartcardRequest = &(SmartcardExtension->SmartcardRequest);
  76. if ((smartcardRequest->BufferSize < smartcardRequest->BufferLength) ||
  77. (smartcardRequest->BufferSize - smartcardRequest->BufferLength
  78. <= SmartcardExtension->IoRequest.RequestBufferLength)) {
  79. return STATUS_BUFFER_TOO_SMALL;
  80. }
  81. //
  82. // Copy request data to the buffer
  83. //
  84. RtlCopyMemory(
  85. &smartcardRequest->Buffer[smartcardRequest->BufferLength],
  86. SmartcardExtension->IoRequest.RequestBuffer,
  87. SmartcardExtension->IoRequest.RequestBufferLength
  88. );
  89. //
  90. // If the card uses invers convention invert the data
  91. //
  92. if (SmartcardExtension->CardCapabilities.InversConvention) {
  93. SmartcardInvertData(
  94. &smartcardRequest->Buffer[smartcardRequest->BufferLength],
  95. SmartcardExtension->IoRequest.RequestBufferLength
  96. );
  97. }
  98. //
  99. // number of bytes to send to the reader
  100. //
  101. smartcardRequest->BufferLength +=
  102. SmartcardExtension->IoRequest.RequestBufferLength;
  103. return STATUS_SUCCESS;
  104. }
  105. NTSTATUS
  106. #ifdef SMCLIB_VXD
  107. SMCLIB_SmartcardRawReply(
  108. #else
  109. SmartcardRawReply(
  110. #endif
  111. PSMARTCARD_EXTENSION SmartcardExtension
  112. )
  113. /*++
  114. Routine Description:
  115. Arguments:
  116. Return Value:
  117. -
  118. --*/
  119. {
  120. if (SmartcardExtension->IoRequest.ReplyBufferLength <
  121. SmartcardExtension->SmartcardReply.BufferLength) {
  122. return STATUS_BUFFER_TOO_SMALL;
  123. }
  124. //
  125. // Copy data to user buffer
  126. //
  127. RtlCopyMemory(
  128. SmartcardExtension->IoRequest.ReplyBuffer,
  129. SmartcardExtension->SmartcardReply.Buffer,
  130. SmartcardExtension->SmartcardReply.BufferLength
  131. );
  132. //
  133. // Length of data to return
  134. //
  135. *SmartcardExtension->IoRequest.Information =
  136. SmartcardExtension->SmartcardReply.BufferLength;
  137. return STATUS_SUCCESS;
  138. }
  139. NTSTATUS
  140. #ifdef SMCLIB_VXD
  141. SMCLIB_SmartcardT0Request(
  142. #else
  143. SmartcardT0Request(
  144. #endif
  145. PSMARTCARD_EXTENSION SmartcardExtension
  146. )
  147. /*++
  148. Routine Description:
  149. Prepares the buffer SmartcardExtension->SmartcardRequest.Buffer
  150. to send data to the smart card
  151. Arguments:
  152. NOTE: On input SmartcardExtension->SmartcardRequest.BufferLenght indicates
  153. the offset where we should copy the data to. This is usually
  154. used by readers that needs to have some bytes as header bytes
  155. to send to the reader before the data bytes for the card
  156. Return Value:
  157. -
  158. --*/
  159. {
  160. PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
  161. PSCARD_IO_REQUEST scardIoRequest;
  162. PUCHAR ioRequestData;
  163. ULONG ioRequestDataLength, headerSize;
  164. if ((smartcardRequest->BufferSize < smartcardRequest->BufferLength) ||
  165. (smartcardRequest->BufferSize - smartcardRequest->BufferLength
  166. <= SmartcardExtension->IoRequest.RequestBufferLength)) {
  167. SmartcardDebug(
  168. DEBUG_ERROR,
  169. (TEXT("%s!SmartcardT0Request: IoRequest.RequestBuffer too big\n"),
  170. DRIVER_NAME)
  171. );
  172. return STATUS_BUFFER_OVERFLOW;
  173. }
  174. scardIoRequest = (PSCARD_IO_REQUEST)
  175. SmartcardExtension->IoRequest.RequestBuffer;
  176. ioRequestData =
  177. SmartcardExtension->IoRequest.RequestBuffer +
  178. sizeof(SCARD_IO_REQUEST);
  179. ioRequestDataLength =
  180. SmartcardExtension->IoRequest.RequestBufferLength -
  181. sizeof(SCARD_IO_REQUEST);
  182. //
  183. // Copy T=0 protocol-info into buffer
  184. //
  185. RtlCopyMemory(
  186. &smartcardRequest->Buffer[smartcardRequest->BufferLength],
  187. ioRequestData,
  188. ioRequestDataLength
  189. );
  190. //
  191. // Remember number of bytes for the header offset
  192. //
  193. headerSize =
  194. smartcardRequest->BufferLength;
  195. //
  196. // Number of bytes to send to the reader
  197. //
  198. smartcardRequest->BufferLength +=
  199. ioRequestDataLength;
  200. if (ioRequestDataLength < 4) {
  201. //
  202. // A T=0 request needs at least 4 bytes
  203. //
  204. SmartcardDebug(
  205. DEBUG_ERROR,
  206. (TEXT("%s!SmartcardT0Request: TPDU is too short (%d). Must be at least 4 bytes\n"),
  207. DRIVER_NAME,
  208. ioRequestDataLength)
  209. );
  210. return STATUS_INVALID_PARAMETER;
  211. } else {
  212. PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
  213. if (ioRequestDataLength <= 5) {
  214. //
  215. // We request to read data from the card
  216. //
  217. SmartcardExtension->T0.Lc = 0;
  218. if (ioRequestDataLength == 4) {
  219. //
  220. // This is a special case where a 4 byte APDU is mapped to
  221. // a 5 byte TPDU (ISO 7816 - Part 4, Annex A, A.1 Case 1)
  222. // This case requires that we append a 0 to the
  223. // APDU to make it a TPDU
  224. //
  225. SmartcardExtension->T0.Le = 0;
  226. smartcardRequest->Buffer[headerSize + 4] = 0;
  227. smartcardRequest->BufferLength += 1;
  228. } else {
  229. SmartcardExtension->T0.Le =
  230. (requestBuffer[headerSize + 4] ? requestBuffer[headerSize + 4] : 256);
  231. }
  232. } else {
  233. //
  234. // We want to send data to the card
  235. //
  236. SmartcardExtension->T0.Lc = requestBuffer[headerSize + 4];
  237. SmartcardExtension->T0.Le = 0;
  238. if (SmartcardExtension->T0.Lc != ioRequestDataLength - 5) {
  239. SmartcardDebug(
  240. DEBUG_ERROR,
  241. (TEXT("%s!SmartcardT0Request: Lc(%d) in TPDU doesn't match number of bytes to send(%d).\n"),
  242. DRIVER_NAME,
  243. SmartcardExtension->T0.Lc,
  244. ioRequestDataLength - 5)
  245. );
  246. return STATUS_INVALID_PARAMETER;
  247. }
  248. }
  249. #if DEBUG
  250. {
  251. PUCHAR T0Data = requestBuffer + headerSize;
  252. SmartcardDebug(
  253. DEBUG_PROTOCOL,
  254. (TEXT(" CLA: %02X\n INS: %02X\n P1: %02X\n P2: %02X\n Lc: %02X\n Le: %02X\n"),
  255. T0Data[0], T0Data[1], T0Data[2], T0Data[3],
  256. SmartcardExtension->T0.Lc,
  257. SmartcardExtension->T0.Le)
  258. );
  259. if (SmartcardExtension->T0.Lc) {
  260. SmartcardDebug(
  261. DEBUG_PROTOCOL,
  262. (TEXT(" Data: "))
  263. );
  264. DumpData(
  265. DEBUG_PROTOCOL,
  266. T0Data + 5,
  267. SmartcardExtension->T0.Lc
  268. );
  269. }
  270. }
  271. #endif
  272. //
  273. // If the card uses invers convention invert the data
  274. //
  275. if (SmartcardExtension->CardCapabilities.InversConvention) {
  276. SmartcardInvertData(
  277. &smartcardRequest->Buffer[headerSize],
  278. smartcardRequest->BufferLength - headerSize
  279. );
  280. }
  281. return STATUS_SUCCESS;
  282. #ifdef APDU_SUPPORT
  283. ULONG requestLength = SmartcardExtension->SmartcardRequest.BufferLength;
  284. ULONG L;
  285. //
  286. // Figure out Lc and Le
  287. // (See 'Decoding of the command APDUs' in ISO Part 4, 5.3.2)
  288. // (Variable names used are according to ISO designations)
  289. //
  290. L = requestLength - 4;
  291. if (L > 65536) {
  292. return STATUS_INVALID_PARAMETER;
  293. }
  294. if (L == 0) {
  295. //
  296. // Lc = 0, No Data, Le = 0;
  297. //
  298. SmartcardExtension->T0.Lc = 0;
  299. SmartcardExtension->T0.Le = 0;
  300. } else if (L == 1) {
  301. //
  302. // Case 2S, Lc = 0, Le = B1
  303. //
  304. SmartcardExtension->T0.Lc = 0;
  305. SmartcardExtension->T0.Le = requestBuffer[4];
  306. } else {
  307. UCHAR B1 = requestBuffer[4];
  308. if (B1 != 0) {
  309. //
  310. // Short form
  311. //
  312. if (L == (ULONG) (1 + B1)) {
  313. //
  314. // Case 3S, Lc = B1, Le = 0
  315. //
  316. SmartcardExtension->T0.Lc = B1;
  317. SmartcardExtension->T0.Le = 0;
  318. } else {
  319. //
  320. // Case 4S, Lc = B1, Le = BL
  321. //
  322. SmartcardExtension->T0.Lc = B1;
  323. SmartcardExtension->T0.Le = requestBuffer[L - 1];
  324. }
  325. } else {
  326. //
  327. // Extended form
  328. //
  329. if (L == 3) {
  330. //
  331. // Case 2E, Lc = 0, Le = B(L - 1, L)
  332. //
  333. LENGTH length;
  334. length.l.l0 = 0;
  335. length.b.b0 = requestBuffer[L - 1];
  336. length.b.b1 = requestBuffer[L - 2];
  337. SmartcardExtension->T0.Lc = 0;
  338. SmartcardExtension->T0.Le = (length.l.l0 ? length.l.l0 : 65536);
  339. } else {
  340. LENGTH length;
  341. length.l.l0 = 0;
  342. length.b.b0 = requestBuffer[6];
  343. length.b.b1 = requestBuffer[5];
  344. SmartcardExtension->T0.Lc = length.l.l0;
  345. if (L == 3 + length.l.l0) {
  346. //
  347. // Case 3E, Lc = B(2,3)
  348. //
  349. SmartcardExtension->T0.Le = 0;
  350. } else {
  351. //
  352. // Case 4E, Lc = B(2,3), Le = B(L - 1, L)
  353. //
  354. LENGTH length;
  355. length.l.l0 = 0;
  356. length.b.b0 = requestBuffer[L - 1];
  357. length.b.b1 = requestBuffer[L - 2];
  358. SmartcardExtension->T0.Le = (length.l.l0 ? length.l.l0 : 65536);
  359. }
  360. }
  361. }
  362. }
  363. #endif
  364. }
  365. return STATUS_SUCCESS;
  366. }
  367. NTSTATUS
  368. #ifdef SMCLIB_VXD
  369. SMCLIB_SmartcardT0Reply(
  370. #else
  371. SmartcardT0Reply(
  372. #endif
  373. PSMARTCARD_EXTENSION SmartcardExtension
  374. )
  375. /*++
  376. Routine Description:
  377. Arguments:
  378. Return Value:
  379. -
  380. --*/
  381. {
  382. PSMARTCARD_REPLY smartcardReply = &SmartcardExtension->SmartcardReply;
  383. //
  384. // The reply must be at least to 2 bytes long. These 2 bytes are
  385. // the return value (StatusWord) from the smart card
  386. //
  387. if (smartcardReply->BufferLength < 2) {
  388. return STATUS_DEVICE_PROTOCOL_ERROR;
  389. }
  390. if (SmartcardExtension->IoRequest.ReplyBufferLength <
  391. smartcardReply->BufferLength + sizeof(SCARD_IO_REQUEST)) {
  392. SmartcardDebug(
  393. DEBUG_ERROR,
  394. (TEXT("%s!SmartcardT0Request: ReplyBuffer too small\n"),
  395. DRIVER_NAME)
  396. );
  397. return STATUS_BUFFER_TOO_SMALL;
  398. }
  399. // Copy protocol header to user buffer
  400. RtlCopyMemory(
  401. SmartcardExtension->IoRequest.ReplyBuffer,
  402. SmartcardExtension->IoRequest.RequestBuffer,
  403. sizeof(SCARD_IO_REQUEST)
  404. );
  405. // If the card uses invers convention invert the data
  406. if (SmartcardExtension->CardCapabilities.InversConvention) {
  407. SmartcardInvertData(
  408. smartcardReply->Buffer,
  409. smartcardReply->BufferLength
  410. );
  411. }
  412. // Copy all data to user buffer
  413. RtlCopyMemory(
  414. SmartcardExtension->IoRequest.ReplyBuffer + sizeof(SCARD_IO_REQUEST),
  415. smartcardReply->Buffer,
  416. smartcardReply->BufferLength
  417. );
  418. // Length of answer
  419. *SmartcardExtension->IoRequest.Information =
  420. smartcardReply->BufferLength +
  421. sizeof(SCARD_IO_REQUEST);
  422. return STATUS_SUCCESS;
  423. }
  424. BOOLEAN
  425. SmartcardT1Chksum(
  426. PUCHAR Block,
  427. UCHAR Edc,
  428. BOOLEAN Verify
  429. )
  430. /*++
  431. Routine Description:
  432. This routine calculates the epilogue field for a T1 block. It calculates the LRC
  433. for all the data in the IBlock.
  434. Arguments:
  435. Block - T1 Information block, to be sent, or just read, from the card.
  436. Edc - ErrorDetectionCode as described in ISO
  437. Verify - If this is a block that was recieved form the card, TRUE will cause this routine
  438. to check the epilogue field, included with this buffer, against the calculated one
  439. Return Value:
  440. TRUE if Verify = TRUE and epilogue fields match or Verify = FALSE
  441. FALSE if Verify = TRUE and an error was detected (mismatch)
  442. --*/
  443. {
  444. USHORT i;
  445. UCHAR lrc;
  446. USHORT crc = 0;
  447. USHORT offset = Block[2] + SCARD_T1_PROLOGUE_LENGTH;
  448. unsigned short crc16a[] = {
  449. 0000000, 0140301, 0140601, 0000500,
  450. 0141401, 0001700, 0001200, 0141101,
  451. 0143001, 0003300, 0003600, 0143501,
  452. 0002400, 0142701, 0142201, 0002100,
  453. };
  454. unsigned short crc16b[] = {
  455. 0000000, 0146001, 0154001, 0012000,
  456. 0170001, 0036000, 0024000, 0162001,
  457. 0120001, 0066000, 0074000, 0132001,
  458. 0050000, 0116001, 0104001, 0043000,
  459. };
  460. if (Edc & T1_CRC_CHECK) {
  461. UCHAR tmp;
  462. // Calculate CRC using tables.
  463. for ( i = 0; i < offset; i++) {
  464. tmp = Block[i] ^ (UCHAR) crc;
  465. crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
  466. }
  467. if (Verify) {
  468. if (crc == (Block[offset + 1] | (Block[offset] << 8))) {
  469. return TRUE;
  470. } else {
  471. return FALSE;
  472. }
  473. } else {
  474. Block[offset] = (UCHAR) (crc >> 8 ); //MSB of crc
  475. Block[offset + 1] = (UCHAR) (crc & 0x00ff); //LSB of crc
  476. return TRUE;
  477. }
  478. } else {
  479. // Calculate LRC by X-Oring all the bytes.
  480. lrc = Block[0];
  481. for(i = 1; i < offset; i++){
  482. lrc ^= Block[i];
  483. }
  484. if (Verify) {
  485. return (lrc == Block[offset] ? TRUE : FALSE);
  486. } else {
  487. Block[offset] = lrc;
  488. return TRUE;
  489. }
  490. }
  491. return TRUE;
  492. }
  493. #if (DEBUG)
  494. static
  495. void
  496. DumpT1Block(
  497. PUCHAR Buffer,
  498. UCHAR Edc
  499. )
  500. {
  501. SmartcardDebug(
  502. DEBUG_PROTOCOL,
  503. (TEXT(" NAD: %02X\n PCB: %02X\n LEN: %02X\n INF: "),
  504. Buffer[0], Buffer[1], Buffer[2])
  505. );
  506. if (Buffer[2] == 0) {
  507. SmartcardDebug(
  508. DEBUG_PROTOCOL,
  509. (TEXT("- "))
  510. );
  511. }
  512. DumpData(
  513. DEBUG_PROTOCOL,
  514. Buffer + 3,
  515. Buffer[2]
  516. );
  517. if (Edc & T1_CRC_CHECK) {
  518. SmartcardDebug(
  519. DEBUG_PROTOCOL,
  520. (TEXT("\n CRC: %02X %02X"),
  521. Buffer[Buffer[2] + 3],
  522. Buffer[Buffer[2] + 4])
  523. );
  524. } else {
  525. SmartcardDebug(
  526. DEBUG_PROTOCOL,
  527. (TEXT("\n LRC: %02X"),
  528. Buffer[Buffer[2] + 3])
  529. );
  530. }
  531. SmartcardDebug(
  532. DEBUG_PROTOCOL,
  533. (TEXT("\n"))
  534. );
  535. }
  536. #endif
  537. #if DEBUG
  538. #pragma optimize( "", off )
  539. #endif
  540. NTSTATUS
  541. #ifdef SMCLIB_VXD
  542. SMCLIB_SmartcardT1Request(
  543. #else
  544. SmartcardT1Request(
  545. #endif
  546. PSMARTCARD_EXTENSION SmartcardExtension
  547. )
  548. /*++
  549. Routine Description:
  550. Arguments:
  551. SmartcardExtension - Supplies a pointer to the smart card data
  552. Return Value:
  553. --*/
  554. {
  555. PSMARTCARD_REQUEST smartcardRequest = &(SmartcardExtension->SmartcardRequest);
  556. PIO_HEADER IoHeader = (PIO_HEADER) SmartcardExtension->IoRequest.RequestBuffer;
  557. T1_BLOCK_FRAME t1SendFrame;
  558. NTSTATUS status = STATUS_SUCCESS;
  559. #if (DEBUG)
  560. ULONG headerSize = smartcardRequest->BufferLength;
  561. #endif
  562. #ifdef DEBUG_INTERFACE
  563. if (DebugSetT1Request(SmartcardExtension)) {
  564. //
  565. // the debugger gave us a new packet that we have to
  566. // send instead of the original packet which will be sent later
  567. //
  568. return STATUS_SUCCESS;
  569. }
  570. #endif
  571. if (SmartcardExtension->T1.WaitForReply) {
  572. // we did not get an answer to our last request
  573. SmartcardExtension->T1.State = T1_INIT;
  574. }
  575. SmartcardExtension->T1.WaitForReply = TRUE;
  576. __try {
  577. switch (SmartcardExtension->T1.State) {
  578. case T1_INIT:
  579. SmartcardExtension->T1.State = T1_IFS_REQUEST;
  580. // NO break here !!!
  581. case T1_START:
  582. //
  583. // Since this is the very first block in a
  584. // transmission we reset the resynch counter
  585. //
  586. SmartcardExtension->T1.Resynch = 0;
  587. //
  588. // Allocate a buffer that receives the result.
  589. // This is necessary since we otherwise overwite our
  590. // request data which we might wish to resend in case
  591. // of an error
  592. //
  593. if (SmartcardExtension->T1.ReplyData != NULL) {
  594. #ifdef SMCLIB_VXD
  595. _HeapFree(SmartcardExtension->T1.ReplyData, 0);
  596. #elif defined(SMCLIB_CE)
  597. LocalFree(SmartcardExtension->T1.ReplyData);
  598. #else
  599. ExFreePool(SmartcardExtension->T1.ReplyData);
  600. #endif
  601. SmartcardExtension->T1.ReplyData = NULL;
  602. }
  603. if (SmartcardExtension->IoRequest.ReplyBufferLength <
  604. IoHeader->ScardIoRequest.cbPciLength + 2) {
  605. //
  606. // We should at least be able to store
  607. // the io-header plus SW1 and SW2
  608. //
  609. status = STATUS_BUFFER_TOO_SMALL;
  610. __leave;
  611. }
  612. #ifdef SMCLIB_VXD
  613. SmartcardExtension->T1.ReplyData = (PUCHAR) _HeapAllocate(
  614. SmartcardExtension->IoRequest.ReplyBufferLength,
  615. 0
  616. );
  617. #elif defined(SMCLIB_CE)
  618. SmartcardExtension->T1.ReplyData = (PUCHAR) LocalAlloc(LPTR,
  619. SmartcardExtension->IoRequest.ReplyBufferLength
  620. );
  621. #else
  622. SmartcardExtension->T1.ReplyData = ExAllocatePool(
  623. NonPagedPool,
  624. SmartcardExtension->IoRequest.ReplyBufferLength
  625. );
  626. #endif
  627. ASSERT(SmartcardExtension->T1.ReplyData != NULL);
  628. if (SmartcardExtension->T1.ReplyData == NULL) {
  629. status = STATUS_INSUFFICIENT_RESOURCES;
  630. __leave;
  631. }
  632. // No break here !!!
  633. case T1_RESTART:
  634. SmartcardDebug(
  635. DEBUG_PROTOCOL,
  636. (TEXT("%s!SmartcardT1Request: T1_%s\n"),
  637. DRIVER_NAME,
  638. (SmartcardExtension->T1.State == T1_START ? TEXT("START") : TEXT("RESTART")))
  639. );
  640. // Copy protocol header back to user buffer
  641. RtlCopyMemory(
  642. SmartcardExtension->T1.ReplyData,
  643. SmartcardExtension->IoRequest.RequestBuffer,
  644. IoHeader->ScardIoRequest.cbPciLength
  645. );
  646. //
  647. // Check for the special case where the io-header is followed
  648. // by asn1 data that contains the NAD value to be used.
  649. // This was done for VISA, because they need access to the NAD.
  650. // The NAD is ASN1 encoded as 81h 00h NAD 00h
  651. //
  652. if (IoHeader->ScardIoRequest.cbPciLength > sizeof(SCARD_IO_REQUEST) &&
  653. IoHeader->Asn1Data[0] == 0x81 &&
  654. IoHeader->Asn1Data[1] == 0x01 &&
  655. IoHeader->Asn1Data[3] == 0x00) {
  656. SmartcardExtension->T1.NAD = IoHeader->Asn1Data[2];
  657. SmartcardDebug(
  658. DEBUG_PROTOCOL,
  659. (TEXT("%s!SmartcardT1Request: NAD set to %02xh\n"),
  660. DRIVER_NAME,
  661. SmartcardExtension->T1.NAD)
  662. );
  663. }
  664. // Initialize the T1 protocol data
  665. SmartcardExtension->T1.BytesToSend =
  666. SmartcardExtension->IoRequest.RequestBufferLength -
  667. IoHeader->ScardIoRequest.cbPciLength;
  668. SmartcardExtension->T1.BytesSent = 0;
  669. SmartcardExtension->T1.BytesReceived = 0;
  670. //
  671. // This is the maximum number of bytes that the smartcard can
  672. // accept in a single block. The smartcard can extend this size
  673. // during the transmission
  674. //
  675. SmartcardExtension->T1.IFSC =
  676. SmartcardExtension->CardCapabilities.T1.IFSC;
  677. //
  678. // Since this is the first block in a transmission we reset
  679. // the re-transmission counter.
  680. //
  681. SmartcardExtension->T1.Resend = 0;
  682. SmartcardExtension->T1.OriginalState = 0;
  683. SmartcardExtension->T1.MoreData = FALSE;
  684. //
  685. // NO break here !!!
  686. //
  687. // After a card reset we first send an IFS-Request to the card.
  688. // Otherwise we start with an I-Block
  689. //
  690. case T1_IFS_REQUEST:
  691. if (SmartcardExtension->T1.State == T1_IFS_REQUEST) {
  692. SmartcardDebug(
  693. DEBUG_PROTOCOL,
  694. (TEXT("%s!SmartcardT1Request: T1_IFSD_REQUEST\n"),
  695. DRIVER_NAME)
  696. );
  697. SmartcardExtension->T1.State =
  698. T1_IFS_REQUEST;
  699. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  700. //
  701. // IFS request.
  702. // Send our IFSD size to the card
  703. //
  704. t1SendFrame.Pcb = 0xC1;
  705. t1SendFrame.Len = 1;
  706. t1SendFrame.Inf = &SmartcardExtension->T1.IFSD;
  707. break;
  708. } else {
  709. SmartcardExtension->T1.State = T1_I_BLOCK;
  710. }
  711. // No break here !!
  712. case T1_I_BLOCK:
  713. SmartcardExtension->T1.State = T1_I_BLOCK;
  714. //
  715. // Set the number of bytes we will transmit to the card.
  716. // This is the lesser of IFSD and IFSC
  717. //
  718. SmartcardExtension->T1.InfBytesSent = SmartcardExtension->T1.IFSC;
  719. if (SmartcardExtension->T1.InfBytesSent > SmartcardExtension->T1.IFSD) {
  720. SmartcardExtension->T1.InfBytesSent = SmartcardExtension->T1.IFSD;
  721. }
  722. // Send either max frame size or remaining bytes
  723. if (SmartcardExtension->T1.BytesToSend > SmartcardExtension->T1.InfBytesSent) {
  724. SmartcardExtension->T1.MoreData = TRUE;
  725. t1SendFrame.Len = SmartcardExtension->T1.InfBytesSent;
  726. } else {
  727. SmartcardExtension->T1.MoreData = FALSE;
  728. t1SendFrame.Len = (UCHAR) SmartcardExtension->T1.BytesToSend;
  729. }
  730. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  731. //
  732. // ProtocolControlByte:
  733. // b7 - SendSequenceNumber
  734. // b6 - MoreDatatBit
  735. //
  736. t1SendFrame.Pcb =
  737. (SmartcardExtension->T1.SSN) << 6 |
  738. (SmartcardExtension->T1.MoreData ? T1_MORE_DATA : 0);
  739. t1SendFrame.Inf =
  740. SmartcardExtension->IoRequest.RequestBuffer +
  741. IoHeader->ScardIoRequest.cbPciLength +
  742. SmartcardExtension->T1.BytesSent;
  743. SmartcardDebug(
  744. DEBUG_PROTOCOL,
  745. (TEXT("%s!SmartcardT1Request: I(%d.%d) ->\n"),
  746. DRIVER_NAME,
  747. SmartcardExtension->T1.SSN,
  748. (SmartcardExtension->T1.MoreData ? 1 : 0))
  749. );
  750. break;
  751. case T1_R_BLOCK:
  752. SmartcardDebug(
  753. DEBUG_PROTOCOL,
  754. (TEXT("%s!SmartcardT1Request: R(%d) ->\n"),
  755. DRIVER_NAME,
  756. SmartcardExtension->T1.RSN)
  757. );
  758. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  759. //
  760. // ProtocolControlByte:
  761. // b5 - SequenceNumber
  762. // b1-4 - ErrorCode
  763. //
  764. t1SendFrame.Pcb =
  765. 0x80 |
  766. (SmartcardExtension->T1.RSN) << 4 |
  767. (SmartcardExtension->T1.LastError);
  768. //
  769. // If this R-Block is a response to an error
  770. // we have to restore to the original state we had before
  771. //
  772. if (SmartcardExtension->T1.LastError) {
  773. SmartcardExtension->T1.LastError = 0;
  774. //
  775. // We must have a defined original state here
  776. //
  777. ASSERT(SmartcardExtension->T1.OriginalState != 0);
  778. if (SmartcardExtension->T1.OriginalState == 0) {
  779. SmartcardExtension->T1.State = T1_START;
  780. status = STATUS_INTERNAL_ERROR;
  781. __leave;
  782. }
  783. SmartcardExtension->T1.State =
  784. SmartcardExtension->T1.OriginalState;
  785. }
  786. t1SendFrame.Len = 0;
  787. t1SendFrame.Inf = NULL;
  788. break;
  789. case T1_IFS_RESPONSE:
  790. SmartcardDebug(
  791. DEBUG_PROTOCOL,
  792. (TEXT("%s!SmartcardT1Request: T1_IFSD_RESPONSE\n"),
  793. DRIVER_NAME)
  794. );
  795. // Restore to the original state we had before
  796. ASSERT(SmartcardExtension->T1.OriginalState != 0);
  797. SmartcardExtension->T1.State =
  798. SmartcardExtension->T1.OriginalState;
  799. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  800. // Send IFS response
  801. t1SendFrame.Pcb = 0xE1;
  802. t1SendFrame.Len = 1;
  803. // New length of INF-Field
  804. t1SendFrame.Inf = &SmartcardExtension->T1.IFSC;
  805. break;
  806. case T1_RESYNCH_REQUEST:
  807. SmartcardDebug(
  808. DEBUG_PROTOCOL,
  809. (TEXT("%s!SmartcardT1Request: T1_RESYNCH_REQUEST\n"),
  810. DRIVER_NAME)
  811. );
  812. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  813. // Resynch request
  814. t1SendFrame.Pcb = 0xC0;
  815. t1SendFrame.Len = 0;
  816. t1SendFrame.Inf = NULL;
  817. // Set the send sequence number to 0
  818. SmartcardExtension->T1.SSN = 0;
  819. break;
  820. case T1_ABORT_REQUEST:
  821. SmartcardDebug(
  822. DEBUG_PROTOCOL,
  823. (TEXT("%s!SmartcardT1Request: T1_ABORT_REQUEST\n"),
  824. DRIVER_NAME)
  825. );
  826. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  827. // Send ABORT request
  828. t1SendFrame.Pcb = 0xC2;
  829. t1SendFrame.Len = 0;
  830. t1SendFrame.Inf = NULL;
  831. break;
  832. case T1_ABORT_RESPONSE:
  833. SmartcardDebug(
  834. DEBUG_PROTOCOL,
  835. (TEXT("%s!SmartcardT1Request: T1_ABORT_RESPONSE\n"),
  836. DRIVER_NAME)
  837. );
  838. SmartcardExtension->T1.State = T1_START;
  839. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  840. // Send ABORT response
  841. t1SendFrame.Pcb = 0xE2;
  842. t1SendFrame.Len = 0;
  843. t1SendFrame.Inf = NULL;
  844. break;
  845. case T1_WTX_RESPONSE:
  846. SmartcardDebug(
  847. DEBUG_PROTOCOL,
  848. (TEXT("%s!SmartcardT1Request: T1_WTX_RESPONSE\n"),
  849. DRIVER_NAME)
  850. );
  851. // Restore to the original state we had before
  852. ASSERT(SmartcardExtension->T1.OriginalState != 0);
  853. SmartcardExtension->T1.State =
  854. SmartcardExtension->T1.OriginalState;
  855. SmartcardExtension->T1.OriginalState = 0;
  856. t1SendFrame.Nad = SmartcardExtension->T1.NAD;
  857. // Send WTX response
  858. t1SendFrame.Pcb = 0xE3;
  859. t1SendFrame.Len = 1;
  860. t1SendFrame.Inf = &SmartcardExtension->T1.Wtx;
  861. break;
  862. }
  863. // Insert Node Address byte
  864. smartcardRequest->Buffer[smartcardRequest->BufferLength] =
  865. t1SendFrame.Nad;
  866. // Insert ProtocolControlByte
  867. smartcardRequest->Buffer[smartcardRequest->BufferLength + 1] =
  868. t1SendFrame.Pcb;
  869. // Length of INF field
  870. smartcardRequest->Buffer[smartcardRequest->BufferLength + 2] =
  871. t1SendFrame.Len;
  872. // Insert INF field data
  873. if (t1SendFrame.Len > 0) {
  874. RtlCopyMemory(
  875. &smartcardRequest->Buffer[smartcardRequest->BufferLength + 3],
  876. t1SendFrame.Inf,
  877. t1SendFrame.Len
  878. );
  879. }
  880. // Compute checksum
  881. SmartcardT1Chksum(
  882. &smartcardRequest->Buffer[smartcardRequest->BufferLength],
  883. SmartcardExtension->CardCapabilities.T1.EDC,
  884. FALSE
  885. );
  886. #if defined(DEBUG)
  887. #if defined(SMCLIB_NT)
  888. if (SmartcardGetDebugLevel() & DEBUG_T1_TEST) {
  889. LARGE_INTEGER Ticks;
  890. UCHAR RandomVal;
  891. KeQueryTickCount(&Ticks);
  892. RandomVal = (UCHAR) Ticks.LowPart % 4;
  893. if (RandomVal == 0) {
  894. smartcardRequest->Buffer[smartcardRequest->BufferLength - 1] += 1;
  895. SmartcardDebug(
  896. DEBUG_ERROR,
  897. (TEXT("%s!SmartcardT1Request: Simulating bad checksum\n"),
  898. DRIVER_NAME)
  899. );
  900. }
  901. }
  902. #endif
  903. DumpT1Block(
  904. smartcardRequest->Buffer + headerSize,
  905. SmartcardExtension->CardCapabilities.T1.EDC
  906. );
  907. #endif
  908. //
  909. // If the card uses invers convention invert the data
  910. // NOTE: do not invert any header data the reader may use
  911. //
  912. if (SmartcardExtension->CardCapabilities.InversConvention) {
  913. SmartcardInvertData(
  914. &smartcardRequest->Buffer[smartcardRequest->BufferLength],
  915. (SmartcardExtension->CardCapabilities.T1.EDC & T1_CRC_CHECK ? 5 : 4) +
  916. t1SendFrame.Len
  917. );
  918. }
  919. //
  920. // Update the number of bytes that are in the buffer
  921. // A T1 block is at least 4 bytes long with LRC check and 5 bytes with CRC check
  922. //
  923. smartcardRequest->BufferLength +=
  924. (SmartcardExtension->CardCapabilities.T1.EDC & T1_CRC_CHECK ? 5 : 4) +
  925. t1SendFrame.Len;
  926. }
  927. __finally {
  928. #ifdef DEBUG_INTERFACE
  929. DebugGetT1Request(SmartcardExtension, status);
  930. #endif
  931. }
  932. return status;
  933. }
  934. NTSTATUS
  935. #ifdef SMCLIB_VXD
  936. SMCLIB_SmartcardT1Reply(
  937. #else
  938. SmartcardT1Reply(
  939. #endif
  940. PSMARTCARD_EXTENSION SmartcardExtension
  941. )
  942. /*++
  943. Routine Description:
  944. Arguments:
  945. DeviceObject - Supplies a pointer to the device object for this request.
  946. Return Value:
  947. --*/
  948. {
  949. T1_BLOCK_FRAME t1RecFrame;
  950. NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  951. PIO_HEADER IoHeader = (PIO_HEADER) SmartcardExtension->T1.ReplyData;
  952. BOOLEAN packetOk = TRUE, chksumOk = TRUE;
  953. ASSERT(IoHeader != NULL);
  954. if (IoHeader == NULL) {
  955. return STATUS_INTERNAL_ERROR;
  956. }
  957. #ifdef DEBUG_INTERFACE
  958. if (DebugT1Reply(SmartcardExtension)) {
  959. // the debugger processed this packet which means
  960. // that we should not parse it.
  961. return STATUS_MORE_PROCESSING_REQUIRED;
  962. }
  963. #endif
  964. // signal that we received an answer
  965. SmartcardExtension->T1.WaitForReply = FALSE;
  966. // Invert the data of an inverse convention card
  967. if (SmartcardExtension->CardCapabilities.InversConvention) {
  968. SmartcardInvertData(
  969. SmartcardExtension->SmartcardReply.Buffer,
  970. SmartcardExtension->SmartcardReply.BufferLength
  971. );
  972. }
  973. // Clear waiting time extension
  974. SmartcardExtension->T1.Wtx = 0;
  975. try {
  976. ULONG expectedLength =
  977. SCARD_T1_PROLOGUE_LENGTH +
  978. SmartcardExtension->SmartcardReply.Buffer[2] +
  979. (SmartcardExtension->CardCapabilities.T1.EDC & T1_CRC_CHECK ? 2 : 1);
  980. if (SmartcardExtension->SmartcardReply.BufferLength < 4 ||
  981. SmartcardExtension->SmartcardReply.BufferLength != expectedLength) {
  982. SmartcardDebug(
  983. DEBUG_ERROR,
  984. (TEXT("%s!SmartcardT1Reply: Packet length incorrect\n"),
  985. DRIVER_NAME)
  986. );
  987. packetOk = FALSE;
  988. } else {
  989. // calculate the checksum
  990. chksumOk = SmartcardT1Chksum(
  991. SmartcardExtension->SmartcardReply.Buffer,
  992. SmartcardExtension->CardCapabilities.T1.EDC,
  993. TRUE
  994. );
  995. #if DEBUG
  996. #ifndef SMCLIB_VXD
  997. if (SmartcardGetDebugLevel() & DEBUG_T1_TEST) {
  998. // inject some checksum errors
  999. LARGE_INTEGER Ticks;
  1000. UCHAR RandomVal;
  1001. KeQueryTickCount(&Ticks);
  1002. RandomVal = (UCHAR) Ticks.LowPart % 4;
  1003. if (RandomVal == 0) {
  1004. chksumOk = FALSE;
  1005. SmartcardDebug(
  1006. DEBUG_ERROR,
  1007. (TEXT("%s!SmartcardT1Reply: Simulating bad checksum\n"),
  1008. DRIVER_NAME)
  1009. );
  1010. }
  1011. }
  1012. #endif
  1013. #endif
  1014. }
  1015. if (chksumOk == FALSE) {
  1016. SmartcardDebug(
  1017. DEBUG_ERROR,
  1018. (TEXT("%s!SmartcardT1Reply: Bad checksum\n"),
  1019. DRIVER_NAME)
  1020. );
  1021. }
  1022. if (packetOk == FALSE || chksumOk == FALSE) {
  1023. SmartcardExtension->T1.LastError =
  1024. (chksumOk ? T1_ERROR_OTHER : T1_ERROR_CHKSUM);
  1025. if (SmartcardExtension->T1.OriginalState == 0) {
  1026. SmartcardExtension->T1.OriginalState =
  1027. SmartcardExtension->T1.State;
  1028. }
  1029. if (SmartcardExtension->T1.Resend++ == T1_MAX_RETRIES) {
  1030. SmartcardExtension->T1.Resend = 0;
  1031. // Try to resynchronize since the resend requests have failed
  1032. SmartcardExtension->T1.State = T1_RESYNCH_REQUEST;
  1033. __leave;
  1034. }
  1035. // If the last request was a resynch we try again to resynch
  1036. if (SmartcardExtension->T1.State != T1_RESYNCH_REQUEST) {
  1037. // Chksum not OK; request resend of last block
  1038. SmartcardExtension->T1.State = T1_R_BLOCK;
  1039. }
  1040. __leave;
  1041. }
  1042. //
  1043. // The checksum of the packet is ok.
  1044. // Now check the rest of the packet
  1045. //
  1046. // Clear the last error
  1047. SmartcardExtension->T1.LastError = 0;
  1048. t1RecFrame.Nad = SmartcardExtension->SmartcardReply.Buffer[0];
  1049. t1RecFrame.Pcb = SmartcardExtension->SmartcardReply.Buffer[1];
  1050. t1RecFrame.Len = SmartcardExtension->SmartcardReply.Buffer[2];
  1051. t1RecFrame.Inf = &SmartcardExtension->SmartcardReply.Buffer[3];
  1052. //
  1053. // If the last block we sent was a ifs request,
  1054. // we expect the card to reply with an ifs response.
  1055. //
  1056. if (SmartcardExtension->T1.State == T1_IFS_REQUEST) {
  1057. // Check if the card properly responded to an ifs request
  1058. if (t1RecFrame.Pcb == T1_IFS_RESPONSE) {
  1059. SmartcardDebug(
  1060. DEBUG_PROTOCOL,
  1061. (TEXT("%s!SmartcardT1Reply: T1_IFSC_RESPONSE\n"),
  1062. DRIVER_NAME)
  1063. );
  1064. // The smart card acked our ifsd size
  1065. SmartcardExtension->T1.State = T1_I_BLOCK;
  1066. __leave;
  1067. }
  1068. if ((t1RecFrame.Pcb & 0x82) == 0x82) {
  1069. //
  1070. // The card does not support ifs request, so we stop
  1071. // sending this and continue with a data block
  1072. // (the card is NOT ISO conform)
  1073. //
  1074. SmartcardDebug(
  1075. DEBUG_ERROR,
  1076. (TEXT("%s!SmartcardT1Reply: Card does not support IFS REQUEST\n"),
  1077. DRIVER_NAME)
  1078. );
  1079. SmartcardExtension->T1.State = T1_I_BLOCK;
  1080. __leave;
  1081. }
  1082. //
  1083. // The card replied with junk to our ifs request.
  1084. // It doesn't make sense to continue.
  1085. //
  1086. status = STATUS_DEVICE_PROTOCOL_ERROR;
  1087. __leave;
  1088. }
  1089. //
  1090. // If the last block was a resync. request,
  1091. // we expect the card to answer with a resynch response.
  1092. //
  1093. if (SmartcardExtension->T1.State == T1_RESYNCH_REQUEST) {
  1094. // Check if the card properly responded to an resynch request
  1095. if (t1RecFrame.Pcb != T1_RESYNCH_RESPONSE) {
  1096. SmartcardDebug(
  1097. DEBUG_ERROR,
  1098. (TEXT("%s!SmartcardT1Reply: Card response is not ISO conform! Aborting...\n"),
  1099. DRIVER_NAME)
  1100. );
  1101. status = STATUS_DEVICE_PROTOCOL_ERROR;
  1102. __leave;
  1103. }
  1104. SmartcardDebug(
  1105. DEBUG_PROTOCOL,
  1106. (TEXT("%s!SmartcardT1Reply: T1_RESYNCH_RESPONSE\n"),
  1107. DRIVER_NAME)
  1108. );
  1109. // Reset error counter
  1110. SmartcardExtension->T1.Resend = 0;
  1111. // The smart card has successfully responded to a resynch request
  1112. SmartcardExtension->T1.RSN = 0;
  1113. SmartcardExtension->T1.SSN = 0;
  1114. //
  1115. // Do a complete restart of the whole transmission
  1116. // but without resetting the resynch counter
  1117. //
  1118. SmartcardExtension->T1.State = T1_RESTART;
  1119. __leave;
  1120. }
  1121. //
  1122. // Now check for other protocol states...
  1123. //
  1124. //
  1125. // Copy NAD value back to user buffer if this is an extended io-header
  1126. // containing the nad
  1127. //
  1128. if (IoHeader->ScardIoRequest.cbPciLength > sizeof(SCARD_IO_REQUEST) &&
  1129. IoHeader->Asn1Data[0] == 0x81 &&
  1130. IoHeader->Asn1Data[1] == 0x01 &&
  1131. IoHeader->Asn1Data[3] == 0x00) {
  1132. IoHeader->Asn1Data[2] = t1RecFrame.Nad;
  1133. }
  1134. if ((t1RecFrame.Pcb & 0x80) == 0) {
  1135. // This is an I-block
  1136. SmartcardDebug(
  1137. DEBUG_PROTOCOL,
  1138. (TEXT("%s!SmartcardT1Reply: I(%d.%d) <-\n"),
  1139. DRIVER_NAME,
  1140. (t1RecFrame.Pcb & 0x40) >> 6,
  1141. (t1RecFrame.Pcb & 0x20) >> 5)
  1142. );
  1143. if (((t1RecFrame.Pcb & 0x40) >> 6) == SmartcardExtension->T1.RSN) {
  1144. // I-Block with correct sequence number
  1145. PUCHAR data;
  1146. ULONG minBufferSize;
  1147. // Reset error counter and error indicator
  1148. SmartcardExtension->T1.Resend = 0;
  1149. SmartcardExtension->T1.OriginalState = 0;
  1150. // We can 'increase' the number of correctly received I-Blocks
  1151. SmartcardExtension->T1.RSN ^= 1;
  1152. if (SmartcardExtension->T1.State == T1_I_BLOCK) {
  1153. // This I-Block is also an acknowledge for the I-Block we sent
  1154. SmartcardExtension->T1.SSN ^= 1;
  1155. }
  1156. // Check size of user buffer
  1157. minBufferSize =
  1158. IoHeader->ScardIoRequest.cbPciLength +
  1159. SmartcardExtension->T1.BytesReceived +
  1160. t1RecFrame.Len;
  1161. if (SmartcardExtension->IoRequest.ReplyBufferLength < minBufferSize) {
  1162. status = STATUS_BUFFER_TOO_SMALL;
  1163. __leave;
  1164. }
  1165. ASSERT(SmartcardExtension->T1.ReplyData);
  1166. //
  1167. // Let data pointer point behind struct.
  1168. // All reply data will be stored there.
  1169. //
  1170. data =
  1171. SmartcardExtension->T1.ReplyData +
  1172. IoHeader->ScardIoRequest.cbPciLength +
  1173. SmartcardExtension->T1.BytesReceived;
  1174. // Copy data to user buffer
  1175. RtlCopyMemory(
  1176. data,
  1177. t1RecFrame.Inf,
  1178. t1RecFrame.Len
  1179. );
  1180. SmartcardExtension->T1.BytesReceived += t1RecFrame.Len;
  1181. if (t1RecFrame.Pcb & T1_MORE_DATA) {
  1182. // Ack this block and request the next block
  1183. SmartcardExtension->T1.State = T1_R_BLOCK;
  1184. } else {
  1185. //
  1186. // This was the last block of the transmission
  1187. // Set number of bytes returned by this transmission
  1188. //
  1189. *SmartcardExtension->IoRequest.Information =
  1190. IoHeader->ScardIoRequest.cbPciLength +
  1191. SmartcardExtension->T1.BytesReceived;
  1192. // Copy the result back to the user buffer
  1193. ASSERT(SmartcardExtension->IoRequest.ReplyBuffer != NULL);
  1194. RtlCopyMemory(
  1195. SmartcardExtension->IoRequest.ReplyBuffer,
  1196. SmartcardExtension->T1.ReplyData,
  1197. IoHeader->ScardIoRequest.cbPciLength +
  1198. SmartcardExtension->T1.BytesReceived
  1199. );
  1200. status = STATUS_SUCCESS;
  1201. }
  1202. __leave;
  1203. }
  1204. //
  1205. // I-Block with wrong sequence number
  1206. // We try T1_MAX_RETRIES times to resend the last block.
  1207. // If this is unsuccessfull, we try to resynch.
  1208. // If resynch is unsuccessfull we abort the transmission.
  1209. //
  1210. SmartcardDebug(
  1211. DEBUG_ERROR,
  1212. (TEXT("%s!SmartcardT1Reply: Block number incorrect\n"),
  1213. DRIVER_NAME)
  1214. );
  1215. SmartcardExtension->T1.LastError = T1_ERROR_OTHER;
  1216. if (SmartcardExtension->T1.OriginalState == 0) {
  1217. SmartcardExtension->T1.OriginalState =
  1218. SmartcardExtension->T1.State;
  1219. }
  1220. if (SmartcardExtension->T1.Resend++ == T1_MAX_RETRIES) {
  1221. SmartcardExtension->T1.Resend = 0;
  1222. // Try to resynchronize
  1223. SmartcardExtension->T1.State = T1_RESYNCH_REQUEST;
  1224. __leave;
  1225. }
  1226. // request the block again.
  1227. SmartcardExtension->T1.State = T1_R_BLOCK;
  1228. __leave;
  1229. }
  1230. if ((t1RecFrame.Pcb & 0xC0) == 0x80) {
  1231. // This is an R-block
  1232. UCHAR RSN = (t1RecFrame.Pcb & 0x10) >> 4;
  1233. SmartcardDebug(
  1234. DEBUG_PROTOCOL,
  1235. (TEXT("%s!SmartcardT1Reply: R(%d) <-\n"),
  1236. DRIVER_NAME,
  1237. RSN)
  1238. );
  1239. if (RSN != SmartcardExtension->T1.SSN &&
  1240. SmartcardExtension->T1.MoreData) {
  1241. // The ICC has acked the last block
  1242. SmartcardExtension->T1.Resend = 0;
  1243. SmartcardExtension->T1.BytesSent += SmartcardExtension->T1.InfBytesSent;
  1244. SmartcardExtension->T1.BytesToSend -= SmartcardExtension->T1.InfBytesSent;
  1245. SmartcardExtension->T1.SSN ^= 1;
  1246. SmartcardExtension->T1.State = T1_I_BLOCK;
  1247. __leave;
  1248. }
  1249. //
  1250. // We have an error condition...
  1251. //
  1252. ASSERT(t1RecFrame.Pcb & 0x0f);
  1253. if ((t1RecFrame.Pcb & 0x02) &&
  1254. SmartcardExtension->T1.State == T1_IFS_REQUEST) {
  1255. //
  1256. // The card does not support ifs request, so
  1257. // we stop sending this and continue with a data block
  1258. // (the card is NOT ISO conform)
  1259. //
  1260. SmartcardDebug(
  1261. DEBUG_ERROR,
  1262. (TEXT("%s!SmartcardT1Reply: Card does not support IFS REQUEST\n"),
  1263. DRIVER_NAME)
  1264. );
  1265. SmartcardExtension->T1.State = T1_I_BLOCK;
  1266. __leave;
  1267. }
  1268. // We have to resend the last block
  1269. SmartcardDebug(
  1270. DEBUG_ERROR,
  1271. (TEXT("%s!SmartcardT1Reply: Card reports error\n"),
  1272. DRIVER_NAME)
  1273. );
  1274. if (SmartcardExtension->T1.Resend++ == T1_MAX_RETRIES) {
  1275. SmartcardExtension->T1.Resend = 0;
  1276. if (SmartcardExtension->T1.OriginalState == 0) {
  1277. // Save current state
  1278. SmartcardExtension->T1.OriginalState =
  1279. SmartcardExtension->T1.State;
  1280. }
  1281. // Try to resynchronize
  1282. SmartcardExtension->T1.State = T1_RESYNCH_REQUEST;
  1283. }
  1284. __leave;
  1285. }
  1286. //
  1287. // This is an S-block
  1288. //
  1289. switch (t1RecFrame.Pcb) {
  1290. case T1_IFS_REQUEST:
  1291. SmartcardDebug(
  1292. DEBUG_PROTOCOL,
  1293. (TEXT("%s!SmartcardT1Reply: T1_IFSC_REQUEST\n"),
  1294. DRIVER_NAME)
  1295. );
  1296. // The smart card wants to exend the IFS - size
  1297. SmartcardExtension->T1.IFSC =
  1298. SmartcardExtension->SmartcardReply.Buffer[3];
  1299. // Save current state
  1300. ASSERT(SmartcardExtension->T1.OriginalState == 0);
  1301. SmartcardExtension->T1.OriginalState =
  1302. SmartcardExtension->T1.State;
  1303. SmartcardExtension->T1.State = T1_IFS_RESPONSE;
  1304. break;
  1305. case T1_ABORT_REQUEST:
  1306. SmartcardDebug(
  1307. DEBUG_PROTOCOL,
  1308. (TEXT("%s!SmartcardT1Reply: T1_ABORT_REQUEST\n"),
  1309. DRIVER_NAME)
  1310. );
  1311. SmartcardExtension->T1.State = T1_ABORT_RESPONSE;
  1312. break;
  1313. case T1_WTX_REQUEST:
  1314. SmartcardDebug(
  1315. DEBUG_PROTOCOL,
  1316. (TEXT("%s!SmartcardT1Reply: T1_WTX_REQUEST\n"),
  1317. DRIVER_NAME)
  1318. );
  1319. // Smart card needs longer wait time
  1320. SmartcardExtension->T1.Wtx =
  1321. SmartcardExtension->SmartcardReply.Buffer[3];
  1322. // Save current state
  1323. ASSERT(SmartcardExtension->T1.OriginalState == 0 ||
  1324. SmartcardExtension->T1.OriginalState == T1_WTX_RESPONSE);
  1325. SmartcardExtension->T1.OriginalState =
  1326. SmartcardExtension->T1.State;
  1327. SmartcardExtension->T1.State = T1_WTX_RESPONSE;
  1328. break;
  1329. case T1_VPP_ERROR:
  1330. SmartcardDebug(
  1331. DEBUG_ERROR,
  1332. (TEXT("%s!SmartcardT1Reply: T1_VPP_ERROR\n"),
  1333. DRIVER_NAME)
  1334. );
  1335. status = STATUS_DEVICE_POWER_FAILURE;
  1336. break;
  1337. default:
  1338. ASSERTMSG(
  1339. TEXT("SmartcardT1Reply: Invalid Pcb "),
  1340. FALSE
  1341. );
  1342. status = STATUS_DEVICE_PROTOCOL_ERROR;
  1343. break;
  1344. }
  1345. }
  1346. finally {
  1347. #if DEBUG
  1348. if (packetOk && chksumOk) {
  1349. DumpT1Block(
  1350. SmartcardExtension->SmartcardReply.Buffer,
  1351. SmartcardExtension->CardCapabilities.T1.EDC
  1352. );
  1353. }
  1354. #endif
  1355. if (SmartcardExtension->T1.State == T1_RESYNCH_REQUEST &&
  1356. SmartcardExtension->T1.Resynch++ == T1_MAX_RETRIES) {
  1357. SmartcardDebug(
  1358. DEBUG_ERROR,
  1359. (TEXT("%s!SmartcardT1Reply: Too many errors! Aborting...\n"),
  1360. DRIVER_NAME)
  1361. );
  1362. status = STATUS_DEVICE_PROTOCOL_ERROR;
  1363. }
  1364. if (status != STATUS_MORE_PROCESSING_REQUIRED) {
  1365. if (SmartcardExtension->T1.OriginalState == T1_IFS_REQUEST) {
  1366. SmartcardExtension->T1.State = T1_IFS_REQUEST;
  1367. } else {
  1368. SmartcardExtension->T1.State = T1_START;
  1369. }
  1370. if (SmartcardExtension->T1.ReplyData) {
  1371. // free the reply data buffer
  1372. #ifdef SMCLIB_VXD
  1373. _HeapFree(SmartcardExtension->T1.ReplyData, 0);
  1374. #elif defined(SMCLIB_CE)
  1375. LocalFree(SmartcardExtension->T1.ReplyData);
  1376. #else
  1377. ExFreePool(SmartcardExtension->T1.ReplyData);
  1378. #endif
  1379. SmartcardExtension->T1.ReplyData = NULL;
  1380. }
  1381. SmartcardExtension->T1.OriginalState = 0;
  1382. SmartcardExtension->T1.NAD = 0;
  1383. }
  1384. }
  1385. return status;
  1386. }
  1387. #if DEBUG
  1388. #pragma optimize( "", on )
  1389. #endif