/// <summary>
        ///  Wraps the PCSC function
        ///  LONG SCardConnect(
        ///		IN SCARDCONTEXT hContext,
        ///		IN LPCTSTR szReader,
        ///		IN DWORD dwShareMode,
        ///		IN DWORD dwPreferredProtocols,
        ///		OUT LPSCARDHANDLE phCard,
        ///		OUT LPDWORD pdwActiveProtocol
        ///	);
        /// </summary>
        /// <param name="Reader"></param>
        /// <param name="ShareMode"></param>
        /// <param name="PreferredProtocols"></param>
        public override void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols)
        {
            EstablishContext(SCOPE.User);

            IntPtr hCard     = Marshal.AllocHGlobal(Marshal.SizeOf(cardHandle));
            IntPtr pProtocol = Marshal.AllocHGlobal(Marshal.SizeOf(protocol));

            lastError = PCSC.SCardConnect(context,
                                          Reader,
                                          (uint)ShareMode,
                                          (uint)PreferredProtocols,
                                          hCard,
                                          pProtocol);

            if (lastError != 0)
            {
                Marshal.FreeHGlobal(hCard);
                Marshal.FreeHGlobal(pProtocol);
                ThrowSmartcardException("SCardConnect", lastError);
            }

            cardHandle = Marshal.ReadIntPtr(hCard);
            protocol   = (uint)Marshal.ReadInt32(pProtocol);

            Marshal.FreeHGlobal(hCard);
            Marshal.FreeHGlobal(pProtocol);
        }
 /// <summary>
 /// Wraps the PCSC function
 /// LONG SCardEndTransaction(
 ///     SCARDHANDLE hCard,
 ///     DWORD dwDisposition
 /// );
 /// </summary>
 /// <param name="Disposition">A value from DISCONNECT enum</param>
 public override void EndTransaction(DISCONNECT Disposition)
 {
     if (PCSC.SCardIsValidContext(context) == PCSC.SCARD_S_SUCCESS)
     {
         lastError = PCSC.SCardEndTransaction(cardHandle, (UInt32)Disposition);
         ThrowSmartcardException("SCardEndTransaction", lastError);
     }
 }
 /// <summary>
 /// Wraps the PSCS function
 /// LONG SCardBeginTransaction(
 ///     SCARDHANDLE hCard
 //  );
 /// </summary>
 public override void BeginTransaction()
 {
     if (PCSC.SCardIsValidContext(context) == PCSC.SCARD_S_SUCCESS)
     {
         lastError = PCSC.SCardBeginTransaction(cardHandle);
         ThrowSmartcardException("SCardBeginTransaction", lastError);
     }
 }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardReleaseContext(
        ///		IN SCARDCONTEXT hContext
        ///	);
        /// </summary>
        public void ReleaseContext()
        {
            if (PCSC.SCardIsValidContext(context) == PCSC.SCARD_S_SUCCESS)
            {
                lastError = PCSC.SCardReleaseContext(context);
                ThrowSmartcardException("SCardReleaseContext", lastError);

                context = IntPtr.Zero;
            }
        }
Пример #5
0
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardReleaseContext(
        ///		IN SCARDCONTEXT hContext
        ///	);
        /// </summary>
        private static void ReleaseContext(IntPtr hContext)
        {
            if (PCSC.SCardIsValidContext(hContext) == PCSC.SCARD_S_SUCCESS)
            {
                int lastError = PCSC.SCardReleaseContext(hContext);
                ThrowSmartcardException("SCardReleaseContext", lastError);

                //Marshal.FreeHGlobal(hContext);
                hContext = IntPtr.Zero;
            }
        }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardTransmit(
        ///		SCARDHANDLE hCard,
        ///		LPCSCARD_I0_REQUEST pioSendPci,
        ///		LPCBYTE pbSendBuffer,
        ///		DWORD cbSendLength,
        ///		LPSCARD_IO_REQUEST pioRecvPci,
        ///		LPBYTE pbRecvBuffer,
        ///		LPDWORD pcbRecvLength
        ///	);
        /// </summary>
        /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
        /// <returns>An APDUResponse object with the response from the card</returns>
        public override APDUResponse Transmit(APDUCommand ApduCmd)
        {
            // Must verify that it works with all type of cards
            uint outputLength = (ApduCmd.Le == 0)
                ? APDUResponse.MAX_LENGHT
                :(ApduCmd.Le + APDUResponse.SW_LENGTH);

            byte[] ApduBuffer   = null;
            byte[] ApduResponse = new byte[outputLength];

            PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request();
            ioRequest.Protocol  = protocol;
            ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest);

            // Build the command APDU
            if (ApduCmd.Data == null)
            {
                ApduBuffer    = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well
                ApduBuffer[4] = (byte)ApduCmd.Le;
            }
            else
            {
                int apduBufferLengh = (ApduCmd.Class == 0x90)
                    ? APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length + 1
                    : APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length;

                ApduBuffer = new byte[apduBufferLengh];
                Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length);
                ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
                if (ApduCmd.Class == 0x90)
                {
                    ApduBuffer[apduBufferLengh - 1] = 0;
                }
            }

            ApduBuffer[0] = ApduCmd.Class;
            ApduBuffer[1] = ApduCmd.Ins;
            ApduBuffer[2] = ApduCmd.P1;
            ApduBuffer[3] = ApduCmd.P2;

            lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength);
            ThrowSmartcardException("SCardTransmit", lastError);

            byte[] responseData = new byte[outputLength];
            Buffer.BlockCopy(ApduResponse, 0, responseData, 0, (int)outputLength);
            string apduString = string.Format("APDU Buffer[{0}] => Response[{1}]", ByteArray.ToString(ApduBuffer), ByteArray.ToString(responseData));

            apduTrace.Add(apduString);
            Trace.WriteLine(apduString);

            return(new APDUResponse(responseData));
        }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardEstablishContext(
        ///		IN DWORD dwScope,
        ///		IN LPCVOID pvReserved1,
        ///		IN LPCVOID pvReserved2,
        ///		OUT LPSCARDCONTEXT phContext
        ///	);
        /// </summary>
        /// <param name="Scope"></param>
        public void EstablishContext(SCOPE Scope)
        {
            IntPtr hContext = Marshal.AllocHGlobal(Marshal.SizeOf(context));

            lastError = PCSC.SCardEstablishContext((uint)Scope, IntPtr.Zero, IntPtr.Zero, hContext);
            if (lastError != 0)
            {
                Marshal.FreeHGlobal(hContext);
                ThrowSmartcardException("SCardEstablishContext", lastError);
            }

            context = Marshal.ReadIntPtr(hContext);

            Marshal.FreeHGlobal(hContext);
        }
        /// <summary>
        /// Gets the attributes of the card
        /// </summary>
        /// <param name="AttribId">Identifier for the Attribute to get</param>
        /// <returns>Attribute content</returns>
        public override byte[] GetAttribute(UInt32 AttribId)
        {
            byte[] attr    = null;
            UInt32 attrLen = 0;

            lastError = PCSC.SCardGetAttrib(cardHandle, AttribId, attr, out attrLen);
            ThrowSmartcardException("SCardGetAttr", lastError);

            if (attrLen != 0)
            {
                attr      = new byte[attrLen];
                lastError = PCSC.SCardGetAttrib(cardHandle, AttribId, attr, out attrLen);
                ThrowSmartcardException("SCardGetAttr", lastError);
            }

            return(attr);
        }
        /// <summary>
        /// Wraps the PCSC function
        ///	LONG SCardDisconnect(
        ///		IN SCARDHANDLE hCard,
        ///		IN DWORD dwDisposition
        ///	);
        /// </summary>
        /// <param name="Disposition"></param>
        public override void Disconnect(DISCONNECT Disposition)
        {
            if (PCSC.SCardIsValidContext(context) == PCSC.SCARD_S_SUCCESS)
            {
                lastError  = PCSC.SCardDisconnect(cardHandle, (uint)Disposition);
                cardHandle = IntPtr.Zero;

                try
                {
                    ThrowSmartcardException("SCardDisconnect", lastError);
                }
                finally
                {
                    ReleaseContext();
                }
            }
        }
Пример #10
0
        public virtual ControlResponse Control(IntPtr cardHandle, ControlCommand controlCmd)
        {
            int recvBufferLength = 255;
            int recvdLength      = recvBufferLength;

            byte[] recvData = new byte[recvBufferLength];

            uint dwControlCode = BitConverter.ToUInt32(controlCmd.ControlCode, 0);

            PCSC.SCardControl(cardHandle, dwControlCode, controlCmd.ControlData, controlCmd.ControlData.Length, recvData, recvBufferLength, ref recvdLength);

            byte[] responseData = new byte[recvdLength];
            Buffer.BlockCopy(recvData, 0, responseData, 0, recvdLength);
            ControlResponse controlResponse = new ControlResponse(responseData);

            return(controlResponse);
        }
Пример #11
0
        public virtual ControlResponse Control(IntPtr cardHandle, ControlCommand controlCmd)
        {
            int recvBufferLength = 255;
            int recvdLength      = recvBufferLength;

            byte[] recvData = new byte[recvBufferLength];

            uint dwControlCode = BitConverter.ToUInt32(ByteArray.ReverseBuffer(controlCmd.ControlCode), 0);
            int  error         = PCSC.SCardControl(cardHandle, dwControlCode, controlCmd.ControlData, controlCmd.ControlData.Length, recvData, recvBufferLength, ref recvdLength);

            ThrowSmartcardException("SCardControl", error);

            byte[] responseData = new byte[recvdLength];
            Buffer.BlockCopy(recvData, 0, responseData, 0, recvdLength);
            ControlResponse controlResponse = new ControlResponse(responseData);

            return(controlResponse);
        }
Пример #12
0
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardEstablishContext(
        ///		IN DWORD dwScope,
        ///		IN LPCVOID pvReserved1,
        ///		IN LPCVOID pvReserved2,
        ///		OUT LPSCARDCONTEXT phContext
        ///	);
        /// </summary>
        /// <param name="Scope"></param>
        private static IntPtr EstablishContext(SCOPE Scope)
        {
            int    lastError   = PCSC.SCARD_S_SUCCESS;
            IntPtr hContextRet = IntPtr.Zero;
            IntPtr hContext    = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));

            lastError = PCSC.SCardEstablishContext((uint)Scope, IntPtr.Zero, IntPtr.Zero, hContext);
            if (lastError != 0)
            {
                Marshal.FreeHGlobal(hContext);
                ThrowSmartcardException("SCardEstablishContext", lastError);
            }

            hContextRet = Marshal.ReadIntPtr(hContext);
            Marshal.FreeHGlobal(hContext);

            return(hContextRet);
        }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardTransmit(
        ///		SCARDHANDLE hCard,
        ///		LPCSCARD_I0_REQUEST pioSendPci,
        ///		LPCBYTE pbSendBuffer,
        ///		DWORD cbSendLength,
        ///		LPSCARD_IO_REQUEST pioRecvPci,
        ///		LPBYTE pbRecvBuffer,
        ///		LPDWORD pcbRecvLength
        ///	);
        /// </summary>
        /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
        /// <returns>An APDUResponse object with the response from the card</returns>
        public override APDUResponse Transmit(APDUCommand ApduCmd)
        {
            // Must verify that it works with all type of cards
            uint outputLength = (ApduCmd.Le == 0)
                ? APDUResponse.MAX_LENGHT
                : (ApduCmd.Le + APDUResponse.SW_LENGTH);

            byte[] ApduBuffer   = null;
            byte[] ApduResponse = new byte[outputLength];

            PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request();
            ioRequest.Protocol  = protocol;
            ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest);

            // Build the command APDU
            if (ApduCmd.Data == null)
            {
                ApduBuffer    = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well
                ApduBuffer[4] = (byte)ApduCmd.Le;
            }
            else
            {
                ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
                Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length);
                ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
            }

            ApduBuffer[0] = ApduCmd.Class;
            ApduBuffer[1] = ApduCmd.Ins;
            ApduBuffer[2] = ApduCmd.P1;
            ApduBuffer[3] = ApduCmd.P2;

            lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength);
            ThrowSmartcardException("SCardTransmit", lastError);

            byte[] ApduData = new byte[outputLength];
            Buffer.BlockCopy(ApduResponse, 0, ApduData, 0, (int)outputLength);

            return(new APDUResponse(ApduData));
        }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardListReaders(SCARDCONTEXT hContext,
        ///		LPCTSTR mszGroups,
        ///		LPTSTR mszReaders,
        ///		LPDWORD pcchReaders
        ///	);
        /// </summary>
        /// <returns>A string array of the readers</returns>
        public override string[]       ListReaders()
        {
            EstablishContext(SCOPE.User);

            string[] sListReaders  = null;
            UInt32   pchReaders    = 0;
            IntPtr   szListReaders = IntPtr.Zero;

            lastError = PCSC.SCardListReaders(context, null, szListReaders, out pchReaders);
            if (lastError == 0)
            {
                szListReaders = Marshal.AllocHGlobal((int)pchReaders);
                lastError     = PCSC.SCardListReaders(context, null, szListReaders, out pchReaders);
                if (lastError == 0)
                {
                    char[] caReadersData = new char[pchReaders];
                    int    nbReaders     = 0;
                    for (int nI = 0; nI < pchReaders; nI++)
                    {
                        caReadersData[nI] = (char)Marshal.ReadByte(szListReaders, nI);

                        if (caReadersData[nI] == 0)
                        {
                            nbReaders++;
                        }
                    }

                    // Remove last 0
                    --nbReaders;

                    if (nbReaders != 0)
                    {
                        sListReaders = new string[nbReaders];
                        char[] caReader = new char[pchReaders];
                        int    nIdx     = 0;
                        int    nIdy     = 0;
                        int    nIdz     = 0;
                        // Get the nJ string from the multi-string

                        while (nIdx < pchReaders - 1)
                        {
                            caReader[nIdy] = caReadersData[nIdx];
                            if (caReader[nIdy] == 0)
                            {
                                sListReaders[nIdz] = new string(caReader, 0, nIdy);
                                ++nIdz;
                                nIdy     = 0;
                                caReader = new char[pchReaders];
                            }
                            else
                            {
                                ++nIdy;
                            }

                            ++nIdx;
                        }
                    }
                }

                Marshal.FreeHGlobal(szListReaders);
            }

            ReleaseContext();

            ThrowSmartcardException("SCardListReaders", lastError);

            return(sListReaders);
        }
        /// <summary>
        /// This function must implement a card detection mechanism.
        ///
        /// When card insertion is detected, it must call the method CardInserted()
        /// When card removal is detected, it must call the method CardRemoved()
        ///
        /// </summary>
        protected override void RunCardDetection(string reader)
        {
            bool   bFirstLoop = true;
            IntPtr hContext   = IntPtr.Zero;  // Local context
            IntPtr phContext;

            phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));

            if (PCSC.SCardEstablishContext((uint)SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) == 0)
            {
                hContext = Marshal.ReadIntPtr(phContext);
                Marshal.FreeHGlobal(phContext);

                UInt32 nbReaders = 1;
                PCSC.SCard_ReaderState[] readerState = new PCSC.SCard_ReaderState[nbReaders];

                readerState[0].CurrentState = (UInt32)PCSC.CARD_STATE.UNAWARE;
                readerState[0].Reader       = reader;

                UInt32 eventState;
                UInt32 currentState = readerState[0].CurrentState;

                // Card detection loop
                do
                {
                    if (PCSC.SCardGetStatusChange(hContext, WAIT_TIME
                                                  , readerState, nbReaders) == 0)
                    {
                        eventState   = readerState[0].EventState;
                        currentState = readerState[0].CurrentState;

                        if (bFirstLoop)
                        {
                            // Check if a card is already inserted
                            if ((eventState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT)
                            {
                                CardInserted(reader);
                            }
                        }
                        else if (((eventState & (uint)PCSC.CARD_STATE.CHANGED) == (uint)PCSC.CARD_STATE.CHANGED) && !bFirstLoop)
                        {
                            // State has changed
                            if ((eventState & (uint)PCSC.CARD_STATE.EMPTY) == (uint)PCSC.CARD_STATE.EMPTY)
                            {
                                // There is no card, card has been removed -> Fire CardRemoved event
                                CardRemoved((string)reader);
                            }

                            if (((eventState & (uint)PCSC.CARD_STATE.PRESENT) == (uint)PCSC.CARD_STATE.PRESENT) &&
                                ((eventState & (uint)PCSC.CARD_STATE.PRESENT) != (currentState & (uint)PCSC.CARD_STATE.PRESENT)))
                            {
                                // There is a card in the reader -> Fire CardInserted event
                                CardInserted(reader);
                            }

                            if ((eventState & (uint)PCSC.CARD_STATE.ATRMATCH) == (uint)PCSC.CARD_STATE.ATRMATCH)
                            {
                                // There is a card in the reader and it matches the ATR we were expecting-> Fire CardInserted event
                                CardInserted(reader);
                            }
                        }

                        // The current stateis now the event state
                        readerState[0].CurrentState = eventState;

                        bFirstLoop = false;
                    }

                    Thread.SpinWait(50000);

                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }while (true);    // Exit on request
            }
            else
            {
                Marshal.FreeHGlobal(phContext);
                throw new Exception("PC/SC error");
            }

            PCSC.SCardReleaseContext(hContext);
            cancellationToken.ThrowIfCancellationRequested();
        }