1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
| using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace SimpleSmartcardDemo
{
class Program
{
static void Main(string[] args)
{
if (SmartcardManager.EstablishContext())
{
//enumerating existing groups of readers
ArrayList readerGroups = SmartcardManager.ListReaderGroups();
if (readerGroups.Count != 0)
{
Console.WriteLine("Groups of readers:");
foreach (object group in readerGroups)
{
Console.WriteLine("\t{0}",
group.ToString());
}
Console.WriteLine();
}
//enumerating available readers
ArrayList readers = SmartcardManager.ListReaders();
if (readers.Count == 0)
{
Console.WriteLine("No readers found.");
}
else
{
Console.WriteLine("Readers found:");
foreach (object reader in readers)
{
Console.WriteLine("\t{0}", reader.ToString());
if (SmartcardManager.EstablishConnexion(reader.ToString()))
{
Console.WriteLine("\tEstablishConnexion {0}", reader.ToString());
if (SmartcardManager.BeginTransaction())
{
Console.WriteLine("\tBeginTransaction {0}", reader.ToString());
if (SmartcardManager.Transmit())
Console.WriteLine("\tTransmit {0}", SmartcardManager._error);
if (SmartcardManager.EndTransaction())
Console.WriteLine("\tEndTransaction {0}", reader.ToString());
}
if (SmartcardManager.ReleaseConnexion())
Console.WriteLine("\tReleaseConnexion {0}", reader.ToString());
}
}
}
SmartcardManager.ReleaseContext();
}
Console.Write("\nPress any key...");
Console.ReadKey();
}
}
public enum ResourceManagerContext
{
User = 0,
System = 2
}
public static class SmartcardManager
{
private static IntPtr _context;
private static IntPtr pCardHandle;
private static uint byActiveprotocol;
public static string _error = string.Empty;
public static bool EstablishContext()
{
ReleaseContext();
uint result = SCardEstablishContext(ResourceManagerContext.System,IntPtr.Zero, IntPtr.Zero, ref _context);
return (result == 0);
}
public static bool EstablishConnexion(string szReader)
{
// 3 param : dwShareMode (SCARD_SHARE_SHARED, SCARD_SHARE_EXCLUSIVE, SCARD_SHARE_DIRECT)
// This application is allocating the reader for its private use, and will be controlling it directly. No other applications are allowed access to it.
// 4 param : dwPreferredProtocols (SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, 0)
// T=0 protocol: An asynchronous, character-oriented half-duplex transmission protocol.
// T=1 protocol: An asynchronous, block-oriented half-duplex transmission protocol.
// 5 param : pCardHandle : A handle that identifies the connection to the smart card in the designated reader.
uint result = SCardConnect(_context, szReader, 2, (0x00000001), out pCardHandle, out byActiveprotocol);
return (result == 0);
// (0x00000001 | 0x00000002)
}
// The function waits for the completion of all other transactions before it begins.
// After the transaction starts, all other applications are blocked from accessing the smart card while the transaction is in progress.
public static bool BeginTransaction()
{
uint result = SCardBeginTransaction(SmartcardManager.pCardHandle);
return (result == 0);
}
public static bool EndTransaction()
{
// SCARD_LEAVE_CARD : No action occurs (0x0000)
uint result = SCardEndTransaction(SmartcardManager.pCardHandle, (0x0000));
return (result == 0);
}
public static bool ReleaseConnexion()
{
// SCARD_LEAVE_CARD : No action occurs (0x0000)
uint result = SCardEndTransaction(SmartcardManager.pCardHandle, (0x0000));
return (result == 0);
// Error : The specified reader is not currently available for use
}
public static void ReleaseContext()
{
if (_context != IntPtr.Zero)
{
SCardReleaseContext(_context);
_context = IntPtr.Zero;
}
}
public static ArrayList ListReaders()
{
int bufsize = 0;
//first call returns required buffer size
SCardListReaders(_context, null, null, ref bufsize);
String buffer = new String((char)0, bufsize);
//retrieving list of connected readers
uint result = SCardListReaders(_context, null, buffer, ref bufsize);
string[] readers = buffer.Split(new char[] { (char)0 }, StringSplitOptions.RemoveEmptyEntries);
return new ArrayList(readers);
}
public static ArrayList ListReaderGroups()
{
int bufsize = 0;
//first call returns required buffer size
SCardListReaderGroups(_context, null, ref bufsize);
string buffer = new string((char)0, bufsize);
//retrieving list of existing groups of readers
uint result = SCardListReaderGroups(_context, buffer, ref bufsize);
string[] groups = buffer.Split(new char[] { (char)0 }, StringSplitOptions.RemoveEmptyEntries);
return new ArrayList(groups);
}
public static bool Transmit()
{
// hCardHandle was set by a previous call to SCardConnect.
// A pointer to the protocol header structure for the instruction :
//The PCI info sent to the smart card,
//I get the address of this PCI from "Winscard.dll",
//and method "GetPciT0()" is defined bellow.
IntPtr pioSendPci = GetPciT0();
// A pointer to the actual data to be written to the card
byte[] pbsendBuffer = SmartcardManager.GetSendBuffer();
// The length, in bytes, of the pbSendBuffer parameter
uint pbsendBufLen = (uint)pbsendBuffer.Length;
// Pointer to the protocol header structure for the instruction, followed by a buffer in which to receive any returned protocol control information (PCI) specific to the protocol in use. This parameter can be NULL if no PCI is returned.
SCARD_IO_REQUEST pioRecvPci = new SCARD_IO_REQUEST(0, 0);
// Pointer to any data returned from the card
byte[] pbRecvBuffer = new byte[255];
// Supplies the length, in bytes, of the pbRecvBuffer parameter and receives the actual number of bytes received from the smart card.
uint pcbRecvLength = 255;
uint result = SCardTransmit(pCardHandle, pioSendPci, pbsendBuffer, pbsendBufLen, pioRecvPci, pbRecvBuffer, pcbRecvLength);
return (result == 0);
}
private static byte[] GetSendBuffer()
{
// APDU
// Get the firmware (0x0A)
/*
string cla = "FF"; // the instruction class (The T=0 instruction class)
string ins = "00"; // the instruction code (An instruction code in the T=0 instruction class)
string p1 = "48"; // parameter to the instruction (Reference codes that complete the instruction code)
string p2 = "00"; // parameter to the instruction (Reference codes that complete the instruction code)
string lc = "00"; // size of I/O transfer (The number of data bytes to be transmitted during the command, per ISO 7816-4, Section 8.2.1)
string body = "";
*/
// Get data (0x02)
string cla = "FF"; // the instruction class (The T=0 instruction class)
string ins = "CA"; // the instruction code (An instruction code in the T=0 instruction class)
string p1 = "00"; // parameter to the instruction (Reference codes that complete the instruction code)
string p2 = "00"; // parameter to the instruction (Reference codes that complete the instruction code)
string lc = "00"; // size of I/O transfer (The number of data bytes to be transmitted during the command, per ISO 7816-4, Section 8.2.1)
string body = "";
// Turn on green on RED and GREEN color LEDs (0x02)
/*
string cla = "FF"; // the instruction class (The T=0 instruction class)
string ins = "00"; // the instruction code (An instruction code in the T=0 instruction class)
string p1 = "40"; // parameter to the instruction (Reference codes that complete the instruction code)
string p2 = "0F"; // parameter to the instruction (Reference codes that complete the instruction code)
string lc = "04"; // size of I/O transfer (The number of data bytes to be transmitted during the command, per ISO 7816-4, Section 8.2.1)
string body = "00000000";
*/
// Get the current setting of the contactless interface (0x02)
/*
string cla = "FF"; // the instruction class (The T=0 instruction class)
string ins = "00"; // the instruction code (An instruction code in the T=0 instruction class)
string p1 = "00"; // parameter to the instruction (Reference codes that complete the instruction code)
string p2 = "00"; // parameter to the instruction (Reference codes that complete the instruction code)
string lc = "02"; // size of I/O transfer (The number of data bytes to be transmitted during the command, per ISO 7816-4, Section 8.2.1)
string body = "D404";
*/
string script = String.Format("{0}{1}{2}{3}{4}{5}", cla, ins, p1, p2,lc, body);
byte[] buffer = new byte[script.Length / 2];
for (int i = 0; i < script.Length; i = i + 2)
{
string temp = script.Substring(i, 2);
buffer[i / 2] = byte.Parse(temp, System.Globalization.NumberStyles.HexNumber);
}
return buffer;
}
//
// Private/Internal Types
//
[StructLayout(LayoutKind.Sequential)]
public struct SCARD_IO_REQUEST
{
public SCARD_IO_REQUEST(int protocol, int length)
{
this.protocol = protocol;
this.pciLength = length;
}
public int protocol;
public int pciLength;
}
//Get the address of Pci from "Winscard.dll".
static public IntPtr GetPciT0()
{
IntPtr handle = LoadLibrary("Winscard.dll");
IntPtr pci = GetProcAddress(handle, "g_rgSCardT0Pci");
FreeLibrary(handle);
return pci;
}
// Prototypes :
/*
* 1 - SCardEstablishContext
* 2 - SCardListReaders
* 3 - SCardConnect
* 4 - SCardBeginTransaction
* 5 - SCardTransmit
* 6 - SCardEndTransaction
* 7 - SCardDisconnect
*/
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static internal extern uint SCardEstablishContext(ResourceManagerContext scope, IntPtr reserved1, IntPtr reserved2, ref IntPtr context);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static internal extern uint SCardReleaseContext(IntPtr context);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static internal extern uint SCardListReaderGroups(IntPtr context, string groups, ref int size);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static internal extern uint SCardListReaders(IntPtr context, string groups, string readers, ref int size);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static extern uint SCardConnect(IntPtr hContext, string szReader, uint dwShareMode, uint dwPreferredProtocols, out IntPtr phCard, out uint pdwActiveProtocol);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static extern uint SCardBeginTransaction(IntPtr hCard);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static extern uint SCardEndTransaction(IntPtr hCard, uint dwDisposition);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static extern uint SCardDisconnect(IntPtr hCard, uint dwDisposition);
[DllImport("winscard.dll", CharSet = CharSet.Unicode)]
static extern uint SCardTransmit(IntPtr hCard, IntPtr sendPci, byte[] sendBuffer, uint sbLength, [In, Out] SCARD_IO_REQUEST recvPci, [Out] byte[] pbRecvBuffer, [In, Out] uint rbLength);
//
//
//
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string fileName);
[DllImport("kernel32.dll")]
private extern static void FreeLibrary(IntPtr handle);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr handle, string procName);
}
} |
Partager