/// <inheritdoc /> public SCardError Transmit(IntPtr sendPci, byte[] sendBuffer, SCardPCI receivePci, ref byte[] receiveBuffer) { ThrowOnInvalidCardHandle(); var ioRecvPciPtr = IntPtr.Zero; if (receivePci != null) { ioRecvPciPtr = receivePci.MemoryPtr; } var rc = Platform.Lib.Transmit( _cardHandle, sendPci, sendBuffer, ioRecvPciPtr, receiveBuffer, out var pcbRecvLength); if (rc != SCardError.Success) { return(rc); } if (receiveBuffer != null && pcbRecvLength < receiveBuffer.Length) { Array.Resize(ref receiveBuffer, pcbRecvLength); } return(rc); }
public SCardError Transmit(IntPtr pioSendPci, byte[] sendBuffer, int sendBufLength, SCardPCI ioRecvPci, byte[] recvBuffer, ref int recvBufLength) { if (cardHandle.Equals(IntPtr.Zero)) { throw new InvalidOperationException( "Reader is currently not connected or no card handle has been returned."); } IntPtr ioRecvPciPtr = IntPtr.Zero; if (ioRecvPci != null) { ioRecvPciPtr = ioRecvPci.iomem; } SCardError rc = SCardAPI.Lib.Transmit(cardHandle, pioSendPci, sendBuffer, sendBufLength, ioRecvPciPtr, recvBuffer, ref recvBufLength); return(rc); }
/// <inheritdoc /> public int Transmit(byte[] sendBuffer, byte[] receiveBuffer) { return(Transmit( sendPci: SCardPCI.GetPci(Protocol), sendBuffer: sendBuffer, receiveBuffer: receiveBuffer)); }
/// <inheritdoc /> public int Transmit(IntPtr sendPci, byte[] sendBuffer, int sendBufferLength, SCardPCI receivePci, byte[] receiveBuffer, int receiveBufferLength) { var receivePciPointer = receivePci?.MemoryPtr ?? IntPtr.Zero; return(Transmit(sendPci, sendBuffer, sendBufferLength, receivePciPointer, receiveBuffer, receiveBufferLength)); }
/// <inheritdoc /> public int Transmit(SCardPCI sendPci, byte[] sendBuffer, int sendBufferLength, byte[] receiveBuffer, int receiveBufferLength) { ThrowOnInvalidSendPci(sendPci); var sendPciMemoryPtr = sendPci.MemoryPtr; return(Transmit(sendPciMemoryPtr, sendBuffer, sendBufferLength, IntPtr.Zero, receiveBuffer, receiveBufferLength)); }
/// <inheritdoc /> public int Transmit(SCardPCI sendPci, byte[] sendBuffer, int sendBufferLength, SCardPCI receivePci, byte[] receiveBuffer, int receiveBufferLength) { ThrowOnInvalidSendPci(sendPci); var sendPciPointer = sendPci.MemoryPtr; var receivePciPointer = receivePci?.MemoryPtr ?? IntPtr.Zero; return(Transmit(sendPciPointer, sendBuffer, sendBufferLength, receivePciPointer, receiveBuffer, receiveBufferLength)); }
private static void ThrowOnInvalidSendPci(SCardPCI sendPci) { if (sendPci == null) { throw new ArgumentNullException(nameof(sendPci)); } if (sendPci.MemoryPtr == IntPtr.Zero) { throw new ArgumentException("Valid sendPci required", nameof(sendPci)); } }
/// <inheritdoc /> public SCardError Transmit(byte[] sendBuffer, int sendBufferLength, byte[] receiveBuffer, ref int receiveBufferLength) { var iorecvpci = new SCardPCI(); // will be discarded return(Transmit( SCardPCI.GetPci(ActiveProtocol), sendBuffer, sendBufferLength, iorecvpci, receiveBuffer, ref receiveBufferLength)); }
/// <inheritdoc /> public int Transmit(SCardPCI sendPci, byte[] sendBuffer, byte[] receiveBuffer) { var sendBufferLength = sendBuffer?.Length ?? 0; var receiveBufferLength = receiveBuffer?.Length ?? 0; return(Transmit( sendPci: sendPci, sendBuffer: sendBuffer, sendBufferLength: sendBufferLength, receivePci: default(SCardPCI), receiveBuffer: receiveBuffer, receiveBufferLength: receiveBufferLength)); }
public SCardError Transmit(byte[] sendBuffer, int sendBufferLength, byte[] recvBuffer, ref int recvBufferLength) { SCardPCI iorecvpci = new SCardPCI(); // will be discarded return(Transmit( SCardPCI.GetPci(activeprot), sendBuffer, sendBufferLength, iorecvpci, recvBuffer, ref recvBufferLength)); }
/// <inheritdoc /> public SCardError Transmit(SCardPCI sendPci, byte[] sendBuffer, SCardPCI receivePci, ref byte[] receiveBuffer) { if (sendPci == null) { throw new ArgumentNullException(nameof(sendPci)); } if (sendPci.MemoryPtr == IntPtr.Zero) { throw new ArgumentException("Valid sendPci required", nameof(sendPci)); } return(Transmit( sendPci.MemoryPtr, sendBuffer, receivePci, ref receiveBuffer)); }
public SCardError Transmit(SCardPCI ioSendPci, byte[] sendBuffer, SCardPCI ioRecvPci, ref byte[] recvBuffer) { if (ioSendPci == null) { throw new ArgumentNullException("ioSendPci"); } if (ioSendPci.iomem == IntPtr.Zero) { throw new ArgumentException("ioSendPci"); } return(Transmit(ioSendPci.iomem, sendBuffer, ioRecvPci, ref recvBuffer)); }
protected ResponseApdu SendAPDU(CommandApdu apdu, SCardReader reader) { var receivePci = new SCardPCI(); // IO returned protocol control information. var sendPci = SCardPCI.GetPci(reader.ActiveProtocol); var receiveBuffer = new byte[256]; var command = apdu.ToArray(); SCardError sc = reader.Transmit( sendPci, // Protocol Control Information (T0, T1 or Raw) command, // command APDU receivePci, // returning Protocol Control Information ref receiveBuffer); // data buffer if (sc != SCardError.Success) { // todo return null; } return new ResponseApdu(receiveBuffer, IsoCase.Case2Short, reader.ActiveProtocol); }
public SCardError Transmit(IntPtr pioSendPci, byte[] sendBuffer, SCardPCI ioRecvPci, ref byte[] recvBuffer) { if (cardHandle.Equals(IntPtr.Zero)) { throw new InvalidOperationException( "Reader is currently not connected or no card handle has been returned."); } int pcbRecvLength; IntPtr ioRecvPciPtr = IntPtr.Zero; if (ioRecvPci != null) { ioRecvPciPtr = ioRecvPci.iomem; } SCardError rc = SCardAPI.Lib.Transmit(cardHandle, pioSendPci, sendBuffer, ioRecvPciPtr, recvBuffer, out pcbRecvLength); if (rc == SCardError.Success) { if (recvBuffer != null && pcbRecvLength < recvBuffer.Length) { Array.Resize <byte>(ref recvBuffer, (int)pcbRecvLength); } } return(rc); }
/// <summary>Sends an APDU to the smart card that was previously connected by <see cref="M:PCSC.ISCardReader.Connect(System.String,PCSC.SCardShareMode,PCSC.SCardProtocol)" />.</summary> /// <param name="sendPci">Structure of Protocol Control Information.</param> /// <param name="sendBuffer">APDU to send to the card.</param> /// <param name="receivePci">Structure of protocol information.</param> /// <param name="receiveBuffer">Response from the card.</param> /// <returns> /// <list type="table"> /// <listheader> /// <term>Return value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.Success" /> /// </term> /// <description> Successful (SCARD_S_SUCCESS)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InsufficientBuffer" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> are too big (SCARD_E_INSUFFICIENT_BUFFER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidHandle" /> /// </term> /// <description>Invalid card handle (SCARD_E_INVALID_HANDLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidParameter" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> or <paramref name="sendPci" /> is <see langword="null" /> (SCARD_E_INVALID_PARAMETER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidValue" /> /// </term> /// <description>Invalid Protocol, reader name, etc (SCARD_E_INVALID_VALUE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NoService" /> /// </term> /// <description>The server is not runing (SCARD_E_NO_SERVICE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NotTransacted" /> /// </term> /// <description>APDU exchange not successful (SCARD_E_NOT_TRANSACTED)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ProtocolMismatch" /> /// </term> /// <description>Connect protocol is different than desired (SCARD_E_PROTO_MISMATCH)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ReaderUnavailable" /> /// </term> /// <description>The reader has been removed (SCARD_E_READER_UNAVAILABLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.CommunicationError" /> /// </term> /// <description>An internal communications error has been detected (SCARD_F_COMM_ERROR)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ResetCard" /> /// </term> /// <description>The card has been reset by another application (SCARD_W_RESET_CARD)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.RemovedCard" /> /// </term> /// <description>The card has been removed from the reader (SCARD_W_REMOVED_CARD)</description> /// </item> /// </list> /// </returns> /// <remarks> /// <para>The card responds from the APDU and stores this response in <paramref name="receiveBuffer" />. <paramref name="sendPci" /> and <paramref name="receivePci" /> are structures containing the following (implemented in <see cref="T:PCSC.SCardPCI" />): /// <example><code lang="C"> /// typedef struct { /// DWORD dwProtocol; // SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 /// DWORD cbPciLength; // Length of this structure - not used /// } SCARD_IO_REQUEST; /// </code></example> /// </para> /// <para>It is recommended to use pre-defined / built-in PCI structures by calling one of the following methods: /// <list type="bullet"> /// <item><term><see cref="M:PCSC.ISCardReader.Transmit(System.IntPtr,System.Byte[],PCSC.SCardPCI,System.Byte[]@)" /></term></item> /// <item><term><see cref="M:PCSC.ISCardReader.Transmit(System.IntPtr,System.Byte[],System.Byte[]@)" /></term></item></list></para> /// <para>This method calls the API function SCardTransmit(). The pointers to the pre-defined / built-in PCI structures are determinated with dlsym() on UNIX/Linux hosts and GetProcAddress() on Windows hosts.</para> /// </remarks> public SCardError Transmit(SCardPCI sendPci, byte[] sendBuffer, SCardPCI receivePci, ref byte[] receiveBuffer) { if (sendPci == null) { throw new ArgumentNullException("sendPci"); } if (sendPci.MemoryPtr == IntPtr.Zero) { throw new ArgumentException("sendPci"); } return Transmit( sendPci.MemoryPtr, sendBuffer, receivePci, ref receiveBuffer); }
/// <summary> /// Will try to connect to _connectedReader and read the card. /// </summary> /// <returns>Either the data from the card or the error message. Or if 'uidOnly' is true, just the UID prefixed with 'UID^' and ending with '^'</returns> public string ReadCard(bool uidOnly = false) { SCardContext context = new SCardContext(); context.Establish(SCardScope.System); SCardReader reader = new SCardReader(context); SCardError result = reader.Connect(_connectedReader, SCardShareMode.Shared, SCardProtocol.Any); if (result != SCardError.Success) { context.Dispose(); reader.Dispose(); return string.Format("No card is detected (or reader reserved by another application){0}{1}", Environment.NewLine, SCardHelper.StringifyError(result)); } string[] readerNames; SCardProtocol protocol; SCardState state; byte[] atr; result = reader.Status(out readerNames, out state, out protocol, out atr); if (result != SCardError.Success) { context.Dispose(); reader.Dispose(); return string.Format("Unable to read from card.{0}{1}", Environment.NewLine, SCardHelper.StringifyError(result)); } string message = string.Format("Card detected:{0}Protocol: {1}{0}State: {2}{0}ATR: {3}{0}", Environment.NewLine, protocol, state, BitConverter.ToString(atr ?? new byte[0])); CommandApdu apdu = new CommandApdu(IsoCase.Case2Short, reader.ActiveProtocol) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, Le = 0 }; result = reader.BeginTransaction(); if (result != SCardError.Success) { context.Dispose(); reader.Dispose(); return string.Format("Cannot start transaction.{0} {1}", Environment.NewLine, SCardHelper.StringifyError(result)); } SCardPCI recievePci = new SCardPCI(); IntPtr sendPci = SCardPCI.GetPci(reader.ActiveProtocol); byte[] recieveBuffer = new byte[256]; result = reader.Transmit(sendPci, apdu.ToArray(), recievePci, ref recieveBuffer); if (result != SCardError.Success) { context.Dispose(); reader.Dispose(); return string.Format("Cannot transmit data.{0} {1}", Environment.NewLine, SCardHelper.StringifyError(result)); } var responseApdu = new ResponseApdu(recieveBuffer, IsoCase.Case2Short, reader.ActiveProtocol); message += string.Format("SW1: {1}{0}SW2: {2}{0}", Environment.NewLine, responseApdu.SW1, responseApdu.SW2); string data = responseApdu.HasData ? BitConverter.ToString(responseApdu.GetData()) : "--"; if (uidOnly) { context.Dispose(); reader.Dispose(); return string.Format("UID^{0}^", data); } message += string.Format("UID: {0}",data); reader.EndTransaction(SCardReaderDisposition.Leave); reader.Disconnect(SCardReaderDisposition.Reset); context.Dispose(); reader.Dispose(); return message; }
private ResponseApdu _SimpleTransmit(byte[] cmdApdu, int cmdApduLength, IsoCase isoCase, SCardProtocol proto, SCardPCI recvPci, ref byte[] recvBuf, ref int recvBufLength) { SCardError sc = SCardError.UnknownError; bool cmdSent = false; do { // send Command APDU to the card sc = reader.Transmit( SCardPCI.GetPci(reader.ActiveProtocol), cmdApdu, cmdApduLength, recvPci, recvBuf, ref recvBufLength); // Do we need to resend the command APDU? if (sc == SCardError.InsufficientBuffer && recvBuf.Length < recvBufLength) { // The response buffer was too small. recvBuf = new byte[recvBufLength]; // Shall we wait until we re-send we APDU? if (_retransmitWaitTime > 0) Thread.Sleep(_retransmitWaitTime); } else cmdSent = true; } while (cmdSent == false); if (sc == SCardError.Success) { ResponseApdu respApdu = new ResponseApdu(recvBuf, recvBufLength, isoCase, proto); return respApdu; } // An error occurred, throw exception.. ThrowExceptionOnSCardError(sc); return null; }
public virtual Response Transmit(CommandApdu cmdApdu) { if (cmdApdu == null) throw new ArgumentNullException("cmdApdu"); // prepare send buffer (Check Command APDU and convert it to an byte array) byte[] sendbuf; try { sendbuf = cmdApdu.ToArray(); } catch (InvalidOperationException ex) { throw new InvalidApduException("Invalid APDU.", cmdApdu, ex); } catch (Exception ex) { throw ex; } // create Response object Response resp = new Response(); // prepare receive buffer (Response APDU) byte[] recvbuf = null; int recvbuflen = cmdApdu.ExpectedResponseLength; // expected size that shall be returned recvbuf = new byte[recvbuflen]; ResponseApdu respApdu = null; SCardPCI recvPci = new SCardPCI(); respApdu = _SimpleTransmit( sendbuf, sendbuf.Length, cmdApdu.Case, // ISO case used by the Command APDU cmdApdu.Protocol, // Protocol used by the Command APDU recvPci, ref recvbuf, ref recvbuflen); /* Check status word SW1SW2: * * 1. 0x6cxx -> Set response buffer size Le <- SW2 * 2. AND/OR 0x61xx -> More data can be read with GET RESPONSE */ // Case 1: SW1=0x6c, Previous Le/P3 not accepted -> Set le = SW2 if (respApdu.SW1 == (byte)SW1Code.ErrorP3Incorrect) { CommandApdu resendCmdApdu = (CommandApdu)cmdApdu.Clone(); if (respApdu.SW2 == 0) { resendCmdApdu.Le = 0; // 256 recvbuflen = 256 + 2; // 2 bytes for status word } else { resendCmdApdu.Le = respApdu.SW2; recvbuflen = respApdu.SW2 + 2; // 2 bytes for status word } recvbuf = new byte[recvbuflen]; recvPci = new SCardPCI(); try { sendbuf = resendCmdApdu.ToArray(); // Shall we wait until we re-send we APDU/TPDU? if (_retransmitWaitTime > 0) Thread.Sleep(_retransmitWaitTime); // send Command APDU again with new Le value respApdu = _SimpleTransmit( sendbuf, sendbuf.Length, resendCmdApdu.Case, resendCmdApdu.Protocol, recvPci, ref recvbuf, ref recvbuflen); } catch (InvalidOperationException ex) { throw new InvalidApduException("Got SW1=0x6c. Retransmission failed because of an invalid APDU.", resendCmdApdu, ex); } } // Case 2: SW1=0x61, More data available -> GET RESPONSE if (respApdu.SW1 == (byte)SW1Code.NormalDataResponse) { /* The transmission system shall issue a GET RESPONSE command APDU (or TPDU) * to the card by assigning the minimum of SW2 and Le to parameter Le (or P3)). * Le = min(Le,SW2) */ int _le = (cmdApdu.Le < respApdu.SW2) ? cmdApdu.Le : respApdu.SW2; do { // add the last ResponseAPDU to the Response object resp.AddResponseApdu(respApdu); resp.AddRecvPci(recvPci); CommandApdu getResponseApdu = _constructGetResponseApdu(ref _le); if (_le == 0) recvbuflen = 256 + 2; // 2 bytes for status word else recvbuflen = _le + 2; // 2 bytes for status word recvbuf = new byte[recvbuflen]; try { sendbuf = getResponseApdu.ToArray(); // Shall we wait until we re-send we APDU/TPDU? if (_retransmitWaitTime > 0) Thread.Sleep(_retransmitWaitTime); // send Command APDU again with new Le value respApdu = _SimpleTransmit( sendbuf, sendbuf.Length, getResponseApdu.Case, getResponseApdu.Protocol, recvPci, ref recvbuf, ref recvbuflen); } catch (InvalidOperationException ex) { throw new InvalidApduException("Got SW1=0x61. Retransmission failed because of an invalid GET RESPONSE APDU.", getResponseApdu, ex); } // In case there is more data available. _le = respApdu.SW2; } while ( // More data available. respApdu.SW1 == (byte)SW1Code.NormalDataResponse || // Warning condition: data may be corrupted. Iso7816-4 7.1.5 (respApdu.SW1 == (byte)SW1Code.WarningNVDataNotChanged && respApdu.SW2 == (byte)0x81) ); } resp.AddResponseApdu(respApdu); resp.AddRecvPci(recvPci); return resp; }
/// <summary>Sends an APDU to the smart card that was previously connected by <see cref="M:PCSC.ISCardReader.Connect(System.String,PCSC.SCardShareMode,PCSC.SCardProtocol)" />. </summary> /// <param name="sendBuffer">APDU to send to the card. </param> /// <param name="sendBufferLength">The buffer size of <paramref name="sendBuffer" /> in bytes.</param> /// <param name="receiveBuffer">Response from the card.</param> /// <param name="receiveBufferLength">The buffer size of <paramref name="receiveBuffer" /> in bytes.</param> /// <returns> /// <list type="table"> /// <listheader> /// <term>Return value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.Success" /> /// </term> /// <description> Successful (SCARD_S_SUCCESS)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InsufficientBuffer" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> are too big (SCARD_E_INSUFFICIENT_BUFFER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidHandle" /> /// </term> /// <description>Invalid card handle (SCARD_E_INVALID_HANDLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidParameter" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> is <see langword="null" /> (SCARD_E_INVALID_PARAMETER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidValue" /> /// </term> /// <description>Invalid Protocol, reader name, etc (SCARD_E_INVALID_VALUE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NoService" /> /// </term> /// <description>The server is not runing (SCARD_E_NO_SERVICE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NotTransacted" /> /// </term> /// <description>APDU exchange not successful (SCARD_E_NOT_TRANSACTED)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ProtocolMismatch" /> /// </term> /// <description>Connect protocol is different than desired (SCARD_E_PROTO_MISMATCH)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ReaderUnavailable" /> /// </term> /// <description>The reader has been removed (SCARD_E_READER_UNAVAILABLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.CommunicationError" /> /// </term> /// <description>An internal communications error has been detected (SCARD_F_COMM_ERROR)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ResetCard" /> /// </term> /// <description>The card has been reset by another application (SCARD_W_RESET_CARD)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.RemovedCard" /> /// </term> /// <description>The card has been removed from the reader (SCARD_W_REMOVED_CARD)</description> /// </item> /// </list> /// </returns> /// <remarks> /// <para>The card responds from the APDU and stores this response in <paramref name="receiveBuffer" />. The buffer <paramref name="receiveBuffer" /> must be initialized. The size of the returned data will be stored in <paramref name="receiveBufferLength" />. This method will return with error code <see cref="F:PCSC.SCardError.InsufficientBuffer" /> if the buffer size of <paramref name="receiveBuffer" /> is too small for the result. If one of the parameters <paramref name="sendBufferLength" /> or <paramref name="receiveBufferLength" /> is invalid, the method will throw an <see cref="T:System.ArgumentOutOfRangeException" />.</para> /// <para>This method calls the API function SCardTransmit().</para> /// <block subset="none" type="note"> /// <para>This method will only work if the reader has been connected with one of the following protocols: /// <list type="table"> /// <listheader><term>Protocol</term><description>Description</description></listheader> /// <item><term><see cref="F:PCSC.SCardProtocol.T0" /></term><description>T=0 active protocol.</description></item> /// <item><term><see cref="F:PCSC.SCardProtocol.T1" /></term><description>T=1 active protocol.</description></item> /// <item><term><see cref="F:PCSC.SCardProtocol.Raw" /></term><description>Raw active protocol.</description></item> /// </list></para> /// </block> /// </remarks> public SCardError Transmit(byte[] sendBuffer, int sendBufferLength, byte[] receiveBuffer, ref int receiveBufferLength) { var iorecvpci = new SCardPCI(); // will be discarded return Transmit( SCardPCI.GetPci(ActiveProtocol), sendBuffer, sendBufferLength, iorecvpci, receiveBuffer, ref receiveBufferLength); }
public SCardError Transmit(IntPtr pioSendPci, byte[] sendBuffer, SCardPCI ioRecvPci, ref byte[] recvBuffer) { if (cardHandle.Equals(IntPtr.Zero)) throw new InvalidOperationException( "Reader is currently not connected or no card handle has been returned."); int pcbRecvLength; IntPtr ioRecvPciPtr = IntPtr.Zero; if (ioRecvPci != null) ioRecvPciPtr = ioRecvPci.iomem; SCardError rc = SCardAPI.Lib.Transmit(cardHandle, pioSendPci, sendBuffer, ioRecvPciPtr, recvBuffer, out pcbRecvLength); if (rc == SCardError.Success) { if (recvBuffer != null && pcbRecvLength < recvBuffer.Length) Array.Resize<byte>(ref recvBuffer, (int)pcbRecvLength); } return rc; }
public SCardError Transmit(SCardPCI ioSendPci, byte[] sendBuffer, SCardPCI ioRecvPci, ref byte[] recvBuffer) { if (ioSendPci == null) throw new ArgumentNullException("ioSendPci"); if (ioSendPci.iomem == IntPtr.Zero) throw new ArgumentException("ioSendPci"); return Transmit(ioSendPci.iomem, sendBuffer, ioRecvPci, ref recvBuffer); }
/// <summary>Sends an APDU to the smart card that was previously connected by <see cref="M:PCSC.ISCardReader.Connect(System.String,PCSC.SCardShareMode,PCSC.SCardProtocol)" />. </summary> /// <param name="sendPci">A pointer to a pre-defined Structure of Protocol Control Information. You can use one of the following: /// <list type="table"><listheader><term>Protocol Control Information</term><description>Description</description></listheader><item><term><see cref="P:PCSC.SCardPCI.T0" /></term><description>Pre-defined T=0 PCI structure. (SCARD_PCI_T0)</description></item><item><term><see cref="P:PCSC.SCardPCI.T1" /></term><description>Pre-defined T=1 PCI structure. (SCARD_PCI_T1)</description></item><item><term><see cref="P:PCSC.SCardPCI.Raw" /></term><description>Pre-defined RAW PCI structure. (SCARD_PCI_RAW)</description></item></list></param> /// <param name="sendBuffer">APDU to send to the card. </param> /// <param name="sendBufferLength">The buffer size of <paramref name="sendBuffer" /> in bytes.</param> /// <param name="receivePci">Structure of protocol information. </param> /// <param name="receiveBuffer">Response from the card.</param> /// <param name="receiveBufferLength">The buffer size of <paramref name="receiveBuffer" /> in bytes.</param> /// <returns> /// <list type="table"> /// <listheader> /// <term>Return value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.Success" /> /// </term> /// <description> Successful (SCARD_S_SUCCESS)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InsufficientBuffer" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> are too big (SCARD_E_INSUFFICIENT_BUFFER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidHandle" /> /// </term> /// <description>Invalid card handle (SCARD_E_INVALID_HANDLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidParameter" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> or <paramref name="sendPci" /> is <see langword="null" /> (SCARD_E_INVALID_PARAMETER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidValue" /> /// </term> /// <description>Invalid Protocol, reader name, etc (SCARD_E_INVALID_VALUE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NoService" /> /// </term> /// <description>The server is not runing (SCARD_E_NO_SERVICE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NotTransacted" /> /// </term> /// <description>APDU exchange not successful (SCARD_E_NOT_TRANSACTED)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ProtocolMismatch" /> /// </term> /// <description>Connect protocol is different than desired (SCARD_E_PROTO_MISMATCH)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ReaderUnavailable" /> /// </term> /// <description>The reader has been removed (SCARD_E_READER_UNAVAILABLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.CommunicationError" /> /// </term> /// <description>An internal communications error has been detected (SCARD_F_COMM_ERROR)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ResetCard" /> /// </term> /// <description>The card has been reset by another application (SCARD_W_RESET_CARD)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.RemovedCard" /> /// </term> /// <description>The card has been removed from the reader (SCARD_W_REMOVED_CARD)</description> /// </item> /// </list> /// </returns> /// <remarks> /// <para>The card responds from the APDU and stores this response in <paramref name="receiveBuffer" />. The size of the returned data will be stored in <paramref name="receiveBufferLength" />. This method will return with error code <see cref="F:PCSC.SCardError.InsufficientBuffer" /> if the buffer size of <paramref name="receiveBuffer" /> is too small for the result. If one of the parameters <paramref name="sendBufferLength" /> or <paramref name="receiveBufferLength" /> is invalid, the method will throw an <see cref="T:System.ArgumentOutOfRangeException" />.</para> /// <para>This method calls the API function SCardTransmit(). The pointers to the pre-defined / built-in PCI structures are determinated with dlsym() on UNIX/Linux hosts and GetProcAddress() on Windows hosts.</para> /// </remarks> public SCardError Transmit(IntPtr sendPci, byte[] sendBuffer, int sendBufferLength, SCardPCI receivePci, byte[] receiveBuffer, ref int receiveBufferLength) { ThrowOnInvalidCardHandle(); var ioRecvPciPtr = IntPtr.Zero; if (receivePci != null) { ioRecvPciPtr = receivePci.MemoryPtr; } return Platform.Lib.Transmit( _cardHandle, sendPci, sendBuffer, sendBufferLength, ioRecvPciPtr, receiveBuffer, ref receiveBufferLength); }
/// <inheritdoc /> public SCardError Transmit(IntPtr sendPci, byte[] sendBuffer, int sendBufferLength, SCardPCI receivePci, byte[] receiveBuffer, ref int receiveBufferLength) { ThrowOnInvalidCardHandle(); var ioRecvPciPtr = IntPtr.Zero; if (receivePci != null) { ioRecvPciPtr = receivePci.MemoryPtr; } return(Platform.Lib.Transmit( _cardHandle, sendPci, sendBuffer, sendBufferLength, ioRecvPciPtr, receiveBuffer, ref receiveBufferLength)); }
static void Main(string[] args) { SCardContext ctx = new SCardContext(); ctx.Establish(SCardScope.System); string[] readernames = ctx.GetReaders(); if (readernames == null || readernames.Length < 1) throw new Exception("You need at least one reader in order to run this example."); // Show available readers. Console.WriteLine("Available readers: "); for (int i = 0; i < readernames.Length; i++) Console.WriteLine("[" + i + "] " + readernames[i]); int num = 0; if (readernames.Length > 1) { // Ask the user which one to choose. Console.Write("Which reader is an RFID reader? "); string relin = Console.ReadLine(); if (!(int.TryParse(relin, out num)) || num < 0 || num > readernames.Length) { Console.WriteLine("An invalid number has been entered. Exiting."); return; } } string readername = readernames[num]; SCardReader RFIDReader = new SCardReader(ctx); SCardError rc = RFIDReader.Connect( readername, SCardShareMode.Shared, SCardProtocol.Any); if (rc != SCardError.Success) { Console.WriteLine("Unable to connect to RFID card / chip. Error: " + SCardHelper.StringifyError(rc)); return; } // prepare APDU byte[] ucByteSend = new byte[] { 0xFF, // the instruction class 0xCA, // the instruction code 0x00, // parameter to the instruction 0x00, // parameter to the instruction 0x00 // size of I/O transfer }; byte[] ucByteReceive = new byte[10]; Console.Out.WriteLine("Retrieving the UID .... "); rc = RFIDReader.BeginTransaction(); if (rc != SCardError.Success) throw new Exception("Could not begin transaction."); SCardPCI ioreq = new SCardPCI(); /* creates an empty object (null). * IO returned protocol control information. */ IntPtr sendPci = SCardPCI.GetPci(RFIDReader.ActiveProtocol); rc = RFIDReader.Transmit( sendPci, /* Protocol control information, T0, T1 and Raw * are global defined protocol header structures. */ ucByteSend, /* the actual data to be written to the card */ ioreq, /* The returned protocol control information */ ref ucByteReceive); if (rc == SCardError.Success) { Console.Write("Uid: "); for (int i = 0; i < (ucByteReceive.Length); i++) Console.Write("{0:X2} ", ucByteReceive[i]); Console.WriteLine(""); } else { Console.WriteLine("Error: " + SCardHelper.StringifyError(rc)); } RFIDReader.EndTransaction(SCardReaderDisposition.Leave); RFIDReader.Disconnect(SCardReaderDisposition.Reset); return; }
/// <summary>Sends an APDU to the smart card that was previously connected by <see cref="M:PCSC.ISCardReader.Connect(System.String,PCSC.SCardShareMode,PCSC.SCardProtocol)" />. </summary> /// <param name="sendPci">A pointer to a pre-defined Structure of Protocol Control Information. You can use one of the following: /// <list type="table"><listheader><term>Protocol Control Information</term><description>Description</description></listheader><item><term><see cref="P:PCSC.SCardPCI.T0" /></term><description>Pre-defined T=0 PCI structure. (SCARD_PCI_T0)</description></item><item><term><see cref="P:PCSC.SCardPCI.T1" /></term><description>Pre-defined T=1 PCI structure. (SCARD_PCI_T1)</description></item><item><term><see cref="P:PCSC.SCardPCI.Raw" /></term><description>Pre-defined RAW PCI structure. (SCARD_PCI_RAW)</description></item></list></param> /// <param name="sendBuffer">APDU to send to the card. </param> /// <param name="receivePci">Structure of protocol information. </param> /// <param name="receiveBuffer">Response from the card. </param> /// <returns> /// <list type="table"> /// <listheader> /// <term>Return value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.Success" /> /// </term> /// <description> Successful (SCARD_S_SUCCESS)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InsufficientBuffer" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> are too big (SCARD_E_INSUFFICIENT_BUFFER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidHandle" /> /// </term> /// <description>Invalid card handle (SCARD_E_INVALID_HANDLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidParameter" /> /// </term> /// <description> /// <paramref name="sendBuffer" /> or <paramref name="receiveBuffer" /> or <paramref name="sendPci" /> is <see langword="null" /> (SCARD_E_INVALID_PARAMETER)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.InvalidValue" /> /// </term> /// <description>Invalid Protocol, reader name, etc (SCARD_E_INVALID_VALUE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NoService" /> /// </term> /// <description>The server is not runing (SCARD_E_NO_SERVICE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.NotTransacted" /> /// </term> /// <description>APDU exchange not successful (SCARD_E_NOT_TRANSACTED)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ProtocolMismatch" /> /// </term> /// <description>Connect protocol is different than desired (SCARD_E_PROTO_MISMATCH)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ReaderUnavailable" /> /// </term> /// <description>The reader has been removed (SCARD_E_READER_UNAVAILABLE)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.CommunicationError" /> /// </term> /// <description>An internal communications error has been detected (SCARD_F_COMM_ERROR)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.ResetCard" /> /// </term> /// <description>The card has been reset by another application (SCARD_W_RESET_CARD)</description> /// </item> /// <item> /// <term> /// <see cref="F:PCSC.SCardError.RemovedCard" /> /// </term> /// <description>The card has been removed from the reader (SCARD_W_REMOVED_CARD)</description> /// </item> /// </list> /// </returns> /// <remarks> /// <para>The card responds from the APDU and stores this response in <paramref name="receiveBuffer" />. <paramref name="receivePci" /> is a structure containing the following (implemented in <see cref="T:PCSC.SCardPCI" />): /// <example><code lang="C"> /// typedef struct { /// DWORD dwProtocol; // SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 /// DWORD cbPciLength; // Length of this structure - not used /// } SCARD_IO_REQUEST; /// </code></example> /// </para> /// <para>This method calls the API function SCardTransmit(). The pointers to the pre-defined / built-in PCI structures are determinated with dlsym() on UNIX/Linux hosts and GetProcAddress() on Windows hosts.</para> /// <example> /// <code lang="C#"> /// // Create a new PC/SC context. /// var ctx = new SCardContext(); /// ctx.Establish(SCardScope.System); /// /// // Connect to the reader /// var rfidReader = new SCardReader(ctx); /// SCardError rc = rfidReader.Connect( /// "OMNIKEY CardMan 5x21 00 01", /// SCardShareMode.Shared, /// SCardProtocol.T1); /// /// if (rc != SCardError.Success) { /// Console.WriteLine("Unable to connect to RFID card / chip. Error: " + SCardHelper.StringifyError(rc)); /// return; /// } /// /// // prepare APDU /// byte[] ucByteSend = new byte[] /// { /// 0xFF, // the instruction class /// 0xCA, // the instruction code /// 0x00, // parameter to the instruction /// 0x00, // parameter to the instruction /// 0x00 // size of I/O transfer /// }; /// /// rc = rfidReader.BeginTransaction(); /// if (rc != SCardError.Success) { /// throw new Exception("Could not begin transaction."); /// } /// /// Console.Out.WriteLine("Retrieving the UID .... "); /// /// SCardPCI ioreq = new SCardPCI(); // IO returned protocol control information. /// byte[] ucByteReceive = new byte[10]; /// rc = rfidReader.Transmit( /// SCardPCI.T1,// Protocol control information, T0, T1 and Raw /// // are global defined protocol header structures. /// ucByteSend, // the actual data to be written to the card /// ioreq, // The returned protocol control information /// ref ucByteReceive); /// /// if (rc == SCardError.Success) { /// Console.WriteLine("Uid: {0}", BitConverter.ToString(ucByteReceive)); /// } else { /// Console.WriteLine("Error: " + SCardHelper.StringifyError(rc)); /// } /// /// rfidReader.EndTransaction(SCardReaderDisposition.Leave); /// rfidReader.Disconnect(SCardReaderDisposition.Reset); /// ctx.Release() /// </code> /// </example> /// </remarks> public SCardError Transmit(IntPtr sendPci, byte[] sendBuffer, SCardPCI receivePci, ref byte[] receiveBuffer) { ThrowOnInvalidCardHandle(); int pcbRecvLength; var ioRecvPciPtr = IntPtr.Zero; if (receivePci != null) { ioRecvPciPtr = receivePci.MemoryPtr; } var rc = Platform.Lib.Transmit( _cardHandle, sendPci, sendBuffer, ioRecvPciPtr, receiveBuffer, out pcbRecvLength); if (rc != SCardError.Success) { return rc; } if (receiveBuffer != null && pcbRecvLength < receiveBuffer.Length) { Array.Resize(ref receiveBuffer, pcbRecvLength); } return rc; }
public static void Main() { using (var context = new SCardContext()) { context.Establish(SCardScope.System); var readerNames = context.GetReaders(); if (readerNames == null || readerNames.Length < 1) { Console.WriteLine("You need at least one reader in order to run this example."); Console.ReadKey(); return; } var readerName = ChooseRfidReader(readerNames); if (readerName == null) { return; } using (var rfidReader = new SCardReader(context)) { var sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any); if (sc != SCardError.Success) { Console.WriteLine("Could not connect to reader {0}:\n{1}", readerName, SCardHelper.StringifyError(sc)); Console.ReadKey(); return; } var apdu = new CommandApdu(IsoCase.Case2Short, rfidReader.ActiveProtocol) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, Le = 0 // We don't know the ID tag size }; sc = rfidReader.BeginTransaction(); if (sc != SCardError.Success) { Console.WriteLine("Could not begin transaction."); Console.ReadKey(); return; } Console.WriteLine("Retrieving the UID .... "); var receivePci = new SCardPCI(); // IO returned protocol control information. var sendPci = SCardPCI.GetPci(rfidReader.ActiveProtocol); var receiveBuffer = new byte[256]; var command = apdu.ToArray(); sc = rfidReader.Transmit( sendPci, // Protocol Control Information (T0, T1 or Raw) command, // command APDU receivePci, // returning Protocol Control Information ref receiveBuffer); // data buffer if (sc != SCardError.Success) { Console.WriteLine("Error: " + SCardHelper.StringifyError(sc)); } var responseApdu = new ResponseApdu(receiveBuffer, IsoCase.Case2Short, rfidReader.ActiveProtocol); Console.Write("SW1: {0:X2}, SW2: {1:X2}\nUid: {2}", responseApdu.SW1, responseApdu.SW2, responseApdu.HasData ? BitConverter.ToString(responseApdu.GetData()) : "No uid received"); rfidReader.EndTransaction(SCardReaderDisposition.Leave); rfidReader.Disconnect(SCardReaderDisposition.Reset); Console.ReadKey(); } } }
public SCardError Transmit(IntPtr pioSendPci, byte[] sendBuffer, int sendBufLength, SCardPCI ioRecvPci, byte[] recvBuffer, ref int recvBufLength) { if (cardHandle.Equals(IntPtr.Zero)) throw new InvalidOperationException( "Reader is currently not connected or no card handle has been returned."); IntPtr ioRecvPciPtr = IntPtr.Zero; if (ioRecvPci != null) ioRecvPciPtr = ioRecvPci.iomem; SCardError rc = SCardAPI.Lib.Transmit(cardHandle, pioSendPci, sendBuffer, sendBufLength, ioRecvPciPtr, recvBuffer, ref recvBufLength); return rc; }
/// <summary> /// Retrieves the UID of a card that is currently connected to the given /// reader. /// </summary> /// <param name="readername"></param> /// <exception cref="Exception">Could not begin transaction.</exception> private byte[] UidFromConnectedCard( string readername ) { SCardReader rfidReader = new SCardReader( Context ); SCardError resultCode = rfidReader.Connect( readername, SCardShareMode.Shared, SCardProtocol.Any ); if( resultCode != SCardError.Success ) { throw new Exception( "Unable to connect to RFID card / chip. Error: " + SCardHelper.StringifyError( resultCode ) ); } // prepare APDU byte[] payload = new byte[] { 0xFF, // the instruction class 0xCA, // the instruction code 0x00, // parameter to the instruction 0x00, // parameter to the instruction 0x00 // size of I/O transfer }; byte[] receiveBuffer = new byte[10]; resultCode = rfidReader.BeginTransaction(); if( resultCode != SCardError.Success ) { throw new Exception( "Could not begin transaction." ); } SCardPCI ioreq = new SCardPCI(); IntPtr protocolControlInformation = SCardPCI.GetPci( rfidReader.ActiveProtocol ); resultCode = rfidReader.Transmit( protocolControlInformation, payload, ioreq, ref receiveBuffer ); if( resultCode != SCardError.Success ) { Log.Error( SCardHelper.StringifyError( resultCode ) ); receiveBuffer = null; } rfidReader.EndTransaction( SCardReaderDisposition.Leave ); rfidReader.Disconnect( SCardReaderDisposition.Reset ); return receiveBuffer; }
public SCardError Transmit(byte[] sendBuffer, int sendBufferLength, byte[] recvBuffer, ref int recvBufferLength) { SCardPCI iorecvpci = new SCardPCI(); // will be discarded return Transmit( SCardPCI.GetPci(activeprot), sendBuffer, sendBufferLength, iorecvpci, recvBuffer, ref recvBufferLength); }
public string ReadSmartCard() { using (var context = new SCardContext()) { context.Establish(SCardScope.System); string readerName = null; try { string[] readerNames = context.GetReaders(); readerName = readerNames[0]; } catch(Exception ex) { return "error"; } if (readerName == null) { return "error"; } using (var rfidReader = new SCardReader(context)) { var sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any); if (sc != SCardError.Success) { return "error";//"Could not connect to reader {0}:\n{1}"; } var apdu = new CommandApdu(IsoCase.Case2Short, rfidReader.ActiveProtocol) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, Le = 0 // We don't know the ID tag size }; sc = rfidReader.BeginTransaction(); if (sc != SCardError.Success) { return "none";// "Could not begin transaction."; } var receivePci = new SCardPCI(); // IO returned protocol control information. var sendPci = SCardPCI.GetPci(rfidReader.ActiveProtocol); var receiveBuffer = new byte[256]; var command = apdu.ToArray(); sc = rfidReader.Transmit( sendPci, // Protocol Control Information (T0, T1 or Raw) command, // command APDU receivePci, // returning Protocol Control Information ref receiveBuffer); // data buffer if (sc != SCardError.Success) { return "none";//SCardHelper.StringifyError(sc); } var responseApdu = new ResponseApdu(receiveBuffer, IsoCase.Case2Short, rfidReader.ActiveProtocol); rfidReader.EndTransaction(SCardReaderDisposition.Leave); rfidReader.Disconnect(SCardReaderDisposition.Reset); int id = responseApdu.HasData ? BitConverter.ToInt32(responseApdu.GetData(),0) : -1; //int id = responseApdu.HasData ? System.Text.Encoding.UTF8.GetString(responseApdu.GetData()) : "none"; if (id < 0) id = id * (-1); return id.ToString(); } } return "none"; }