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.

312 lines
7.5 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation 1999
  3. Module Name:
  4. Proto_T0
  5. Abstract:
  6. This module provides the mapping from an APDU to a T=0 TPDU.
  7. Author:
  8. Doug Barlow (dbarlow) 6/28/1999
  9. Notes:
  10. ?Notes?
  11. --*/
  12. #ifndef WIN32_LEAN_AND_MEAN
  13. #define WIN32_LEAN_AND_MEAN
  14. #endif
  15. #include "stdafx.h"
  16. #include "Conversion.h"
  17. /*++
  18. ApduToTpdu_T0:
  19. This routine takes an APDU, converts it to a T=0 TPDU, and performs the
  20. exchange to the specified card.
  21. Arguments:
  22. hCard supplies a handle to the card to be used in the exchange.
  23. pbPciRqst supplies the PCI Request structure
  24. cbPciRqst supplies the length of pbPciRqst, in bytes
  25. pbApdu supplies the APDU to be sent to the card.
  26. cbApdu supplies the length of the APDU in pbApdu.
  27. dwFlags supplies any special flags used to modify the operation.
  28. bfPciRsp receives the response PCI.
  29. bfReply receives the response from the card.
  30. Return Value:
  31. None
  32. Throws:
  33. Errors are thrown as HRESULT status codes.
  34. Remarks:
  35. ?Remarks?
  36. Author:
  37. Doug Barlow (dbarlow) 6/28/1999
  38. --*/
  39. #undef __SUBROUTINE__
  40. #define __SUBROUTINE__ TEXT("ApduToTpdu_T0")
  41. void
  42. ApduToTpdu_T0(
  43. IN SCARDHANDLE hCard,
  44. IN const SCARD_IO_REQUEST *pPciRqst,
  45. IN LPCBYTE pbApdu,
  46. IN DWORD cbApdu,
  47. IN DWORD dwFlags,
  48. OUT CBuffer bfPciRsp,
  49. OUT CBuffer &bfReply,
  50. IN LPCBYTE pbAltCla)
  51. {
  52. LONG lSts;
  53. DWORD dwLen, dwXmitFlags;
  54. WORD wLen, wLc, wLe, wSts;
  55. CBuffer bfXmit(264), bfRecv(264);
  56. BYTE rgb[4];
  57. BYTE b;
  58. LPCBYTE pbData;
  59. //
  60. // Prepare for conversion.
  61. //
  62. bfReply.Reset();
  63. bfPciRsp.Set((LPCBYTE)pPciRqst, pPciRqst->cbPciLength);
  64. ParseRequest(
  65. pbApdu,
  66. cbApdu,
  67. NULL,
  68. NULL,
  69. NULL,
  70. NULL,
  71. &pbData,
  72. &wLc,
  73. &wLe,
  74. &dwXmitFlags);
  75. //
  76. // Send the data.
  77. //
  78. if (0 == wLc)
  79. {
  80. //
  81. // Le goes into P3
  82. //
  83. bfXmit.Set(pbApdu, 4); // CLA, INS, P1, P2
  84. if (0 == (dwXmitFlags & APDU_MAXIMUM_LE))
  85. wLen = __min(255, wLe);
  86. else
  87. wLen = 0;
  88. b = LeastSignificantByte(wLen);
  89. bfXmit.Append(&b, 1);
  90. dwLen = bfRecv.Space();
  91. lSts = SCardTransmit(
  92. hCard,
  93. pPciRqst,
  94. bfXmit.Access(),
  95. bfXmit.Length(),
  96. (LPSCARD_IO_REQUEST)bfPciRsp.Access(),
  97. bfRecv.Access(),
  98. &dwLen);
  99. if (SCARD_S_SUCCESS != lSts)
  100. throw (HRESULT)HRESULT_FROM_WIN32(lSts);
  101. bfRecv.Resize(dwLen, TRUE);
  102. if (2 > dwLen)
  103. {
  104. bfReply.Set(bfRecv.Access(), bfRecv.Length());
  105. goto EndProtocol;
  106. }
  107. ASSERT(0x10000 > dwLen);
  108. wLe -= (WORD)(dwLen - 2);
  109. wSts = NetToLocal(bfRecv.Access(dwLen - 2));
  110. }
  111. else if (256 > wLc)
  112. {
  113. //
  114. // Send the data in the short form.
  115. //
  116. bfXmit.Set(pbApdu, 4); // CLA, INS, P1, P2
  117. b = LeastSignificantByte(wLc);
  118. bfXmit.Append(&b, 1);
  119. bfXmit.Append(pbData, wLc);
  120. dwLen = bfRecv.Space();
  121. lSts = SCardTransmit(
  122. hCard,
  123. pPciRqst,
  124. bfXmit.Access(),
  125. bfXmit.Length(),
  126. (LPSCARD_IO_REQUEST)bfPciRsp.Access(),
  127. bfRecv.Access(),
  128. &dwLen);
  129. if (SCARD_S_SUCCESS != lSts)
  130. throw (HRESULT)HRESULT_FROM_WIN32(lSts);
  131. bfRecv.Resize(dwLen, TRUE);
  132. if (2 > dwLen)
  133. {
  134. bfReply.Set(bfRecv.Access(), bfRecv.Length());
  135. goto EndProtocol;
  136. }
  137. wSts = NetToLocal(bfRecv.Access(dwLen - 2));
  138. }
  139. else
  140. {
  141. WORD wSent;
  142. //
  143. // Send the data in the enveloped form.
  144. //
  145. rgb[0] = (NULL != pbAltCla) ? *pbAltCla : *pbApdu; // CLA
  146. rgb[1] = 0xc2; // envelope INS
  147. rgb[2] = 0; // P1
  148. rgb[3] = 0; // P2
  149. wSent = 0;
  150. while (wLc > wSent)
  151. {
  152. wLen = __min(255, wLc - wSent);
  153. bfXmit.Set(rgb, 4);
  154. bfXmit.Append(&pbData[wSent], wLen);
  155. b = LeastSignificantByte(wLen);
  156. bfXmit.Append(&b, 1);
  157. wSent -= wLen;
  158. dwLen = bfRecv.Space();
  159. lSts = SCardTransmit(
  160. hCard,
  161. pPciRqst,
  162. bfXmit.Access(),
  163. bfXmit.Length(),
  164. (LPSCARD_IO_REQUEST)bfPciRsp.Access(),
  165. bfRecv.Access(),
  166. &dwLen);
  167. if (SCARD_S_SUCCESS != lSts)
  168. throw (HRESULT)HRESULT_FROM_WIN32(lSts);
  169. bfRecv.Resize(dwLen, TRUE);
  170. if (2 != dwLen)
  171. {
  172. bfReply.Set(bfRecv.Access(), bfRecv.Length());
  173. goto EndProtocol;
  174. }
  175. wSts = NetToLocal(bfRecv.Access());
  176. if ((wSent < wLc) && (0x9000 != wSts))
  177. {
  178. bfReply.Set(bfRecv.Access(), bfRecv.Length());
  179. goto EndProtocol;
  180. }
  181. }
  182. }
  183. //
  184. // At this point, the first received buffer is in bfRecv. What do we
  185. // have to do to bring in any more data?
  186. //
  187. rgb[0] = (NULL != pbAltCla) ? *pbAltCla : *pbApdu; // CLA
  188. rgb[1] = 0xc0; // Get Response INS
  189. rgb[2] = 0; // P1
  190. rgb[3] = 0; // P2
  191. for (;;)
  192. {
  193. ASSERT(2 <= bfRecv.Length());
  194. BYTE bSw1 = *bfRecv.Access(bfRecv.Length() - 2);
  195. BYTE bSw2 = *bfRecv.Access(bfRecv.Length() - 1);
  196. switch (bSw1)
  197. {
  198. case 0x6c: // Wrong length
  199. wLe = bSw2;
  200. break;
  201. case 0x61: // More data
  202. bfReply.Append(bfRecv.Access(), bfRecv.Length() - 2);
  203. if (0 == wLe)
  204. wLe = bSw2;
  205. else
  206. wLe = __min(wLe, bSw2);
  207. break;
  208. case 0x90: // Success?
  209. if (((0 == wLe) && (0 == (APDU_MAXIMUM_LE & dwFlags)))
  210. || (0x00 != bSw2))
  211. {
  212. bfReply.Append(bfRecv.Access(), bfRecv.Length());
  213. goto EndProtocol;
  214. }
  215. if (2 < bfRecv.Length()) // Shouldn't be
  216. bfReply.Append(bfRecv.Access(), bfRecv.Length() - 2);
  217. break;
  218. default: // We're done.
  219. bfReply.Append(bfRecv.Access(), bfRecv.Length());
  220. goto EndProtocol;
  221. }
  222. //
  223. // We need to request additional data.
  224. //
  225. bfXmit.Set(rgb, 4);
  226. b = LeastSignificantByte(wLe);
  227. bfXmit.Append(&b, 1);
  228. dwLen = bfRecv.Space();
  229. lSts = SCardTransmit(
  230. hCard,
  231. pPciRqst,
  232. bfXmit.Access(),
  233. bfXmit.Length(),
  234. (LPSCARD_IO_REQUEST)bfPciRsp.Access(),
  235. bfRecv.Access(),
  236. &dwLen);
  237. if (SCARD_S_SUCCESS != lSts)
  238. throw (HRESULT)HRESULT_FROM_WIN32(lSts);
  239. bfRecv.Resize(dwLen, TRUE);
  240. wLe -= b;
  241. }
  242. EndProtocol:
  243. //
  244. // We've completed the protocol exchange. The data is ready to be
  245. // returned to the caller.
  246. //
  247. return;
  248. }