Beispiel #1
0
 public SCardReaderList(uint Scope, string Groups)
 {
     _scope            = Scope;
     _groups           = Groups;
     _reader_names     = SCARD.GetReaderList(Scope, Groups);
     _auto_update_list = true;
 }
 public bool Write(byte address, CardBuffer buffer)
 {
     _last_error = SCARD.MifUlC_Write4(hCard, address, buffer.GetBytes());
     if (_last_error != 0)
     {
         return(false);
     }
     return(true);
 }
 public bool Authenticate(CardBuffer key)
 {
     _last_error = SCARD.MifUlC_Authenticate(hCard, key.GetBytes());
     if (_last_error != 0)
     {
         return(false);
     }
     return(true);
 }
 public bool ChangeKey(CardBuffer key)
 {
     _last_error = SCARD.MifUlC_ChangeKey(hCard, key.GetBytes());
     if (_last_error != 0)
     {
         return(false);
     }
     return(true);
 }
 public CardBuffer Read(byte address)
 {
     byte[] buffer = new byte[16];
     _last_error = SCARD.MifUlC_Read(hCard, address, buffer);
     if (_last_error != 0)
     {
         return(null);
     }
     return(new CardBuffer(buffer));
 }
Beispiel #6
0
        private void Instanciate(uint Scope, string ReaderName)
        {
            uint rc;

            rc = SCARD.EstablishContext(Scope, IntPtr.Zero, IntPtr.Zero, ref _hContext);
            if (rc != SCARD.S_SUCCESS)
            {
                _hContext   = IntPtr.Zero;
                _last_error = rc;
            }

            _reader_name = ReaderName;
        }
Beispiel #7
0
        /**m* SCardChannel/Transmit
         *
         * NAME
         *   SCardChannel.Transmit()
         *
         * SYNOPSIS
         *   bool  Transmit()
         *   RAPDU Transmit(CAPDU capdu)
         *   bool  Transmit(CAPDU capdu, out RAPDU rapdu)
         *   void  Transmit(CAPDU capdu, TransmitDoneCallback callback)
         *
         * DESCRIPTION
         *   Sends a command APDU (CAPDU) to the connected card, and retrieves its response APDU (RAPDU)
         *
         * SOURCE
         *
         *   SCardChannel card = new SCardChannel( ... reader ... );
         *   if (!card.Connect( SCARD.PROTOCOL_T0|SCARD.PROTOCOL_T1 ))
         *   {
         *     // handle error
         *   }
         *
         *
         *   // Example 1
         *   // ---------
         *
         *   card.Command = new CAPDU("00 A4 00 00 02 3F 00");
         *   if (!card.Transmit())
         *   {
         *     // handle error
         *   }
         *   MessageBox.Show("Card answered: " + card.Response.AsString(" "));
         *
         *
         *   // Example 2
         *   // ---------
         *
         *   RAPDU response = card.Transmit(new CAPDU("00 A4 00 00 02 3F 00")))
         *   if (response == null)
         *   {
         *     // handle error
         *   }
         *   MessageBox.Show("Card answered: " + response.AsString(" "));
         *
         *
         *   // Example 3
         *   // ---------
         *
         *   CAPDU command  = new CAPDU("00 A4 00 00 02 3F 00");
         *   RAPDU response = new RAPDU();
         *   if (!card.Transmit(command, out response))
         *   {
         *     // handle error
         *   }
         *   MessageBox.Show("Card answered: " + response.AsString(" "));
         *
         *
         *   // Example 4
         *   // ---------
         *
         *   // In this example the Transmit is performed by a background thread
         *   // We supply a delegate so the main class (window/form) will be notified
         *   // when Transmit will return
         *
         *   delegate void OnTransmitDoneInvoker(RAPDU response);
         *
         *   void OnTransmitDone(RAPDU response)
         *   {
         *     // Ensure we're back in the context of the main thread (application's message pump)
         *     if (this.InvokeRequired)
         *     {
         *       this.BeginInvoke(new OnTransmitDoneInvoker(OnTransmitDone), response);
         *       return;
         *     }
         *
         *     if (response == null)
         *     {
         *       // handle error
         *     }
         *
         *     MessageBox.Show("Card answered: " + response.AsString(" "));
         *   }
         *
         *  card.Transmit(new CAPDU("00 A4 00 00 02 3F 00"), new SCardChannel.TransmitDoneCallback(OnTransmitDone));
         *
         *
         * SEE ALSO
         *   SCardChannel.Connect
         *   SCardChannel.Transmit
         *   SCardChannel.Command
         *   SCardChannel.Response
         *
         **/
        #region Transmit
        public virtual bool Transmit()
        {
            uint rsp_length = 32 * 1024;

            byte[] rsp_buffer = new byte[rsp_length];
            uint   rc;
            IntPtr SendPci = IntPtr.Zero;

            switch (_active_protocol)
            {
            case SCARD.PROTOCOL_T0:
                SendPci = SCARD.PCI_T0();
                break;

            case SCARD.PROTOCOL_T1:
                SendPci = SCARD.PCI_T1();
                break;

            case SCARD.PROTOCOL_RAW:
                SendPci = SCARD.PCI_RAW();
                break;

            default:
                break;
            }

            _rapdu = null;

            Trace.WriteLine("Transmit << " + _capdu.AsString());

            rc = SCARD.Transmit(_hCard,
                                SendPci,
                                _capdu.GetBytes(),
                                (uint)_capdu.Length,
                                IntPtr.Zero,             /* RecvPci is likely to remain NULL */
                                rsp_buffer,
                                ref rsp_length);

            if (rc != SCARD.S_SUCCESS)
            {
                Trace.WriteLine("Transmit : " + rc);
                _last_error = rc;
                return(false);
            }

            _rapdu = new RAPDU(rsp_buffer, (int)rsp_length);

            Trace.WriteLine("Transmit >> " + _rapdu.AsString());

            return(true);
        }
Beispiel #8
0
        private void UpdateState()
        {
            uint rc;

            IntPtr hContext = IntPtr.Zero;

            _reader_state = SCARD.STATE_UNAWARE;
            _card_atr     = null;

            rc =
                SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref hContext);
            if (rc != SCARD.S_SUCCESS)
            {
                _last_error = rc;
                return;
            }

            SCARD.READERSTATE[] states = new SCARD.READERSTATE[1];

            states[0]                = new SCARD.READERSTATE();
            states[0].szReader       = _reader_name;
            states[0].pvUserData     = IntPtr.Zero;
            states[0].dwCurrentState = 0;
            states[0].dwEventState   = 0;
            states[0].cbAtr          = 0;
            states[0].rgbAtr         = null;

            try
            {
                rc = SCARD.GetStatusChange(hContext, 0, states, 1);
            }
            catch (ThreadInterruptedException)
            {
                rc = SCARD.E_CANCELLED;
            }

            if (rc != SCARD.S_SUCCESS)
            {
                SCARD.ReleaseContext(hContext);
                return;
            }

            SCARD.ReleaseContext(hContext);

            _reader_state = states[0].dwEventState;

            if ((_reader_state & SCARD.STATE_PRESENT) != 0)
            {
                _card_atr = new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr);
            }
        }
Beispiel #9
0
        public static string[] GetReaderList(uint Scope, string Groups)
        {
            IntPtr hContext = IntPtr.Zero;
            uint   rc;

            rc = SCARD.EstablishContext(Scope, IntPtr.Zero, IntPtr.Zero, ref hContext);
            if (rc != SCARD.S_SUCCESS)
            {
                return(null);
            }

            string[] readers = GetReaderList(hContext, Groups);

            SCARD.ReleaseContext(hContext);

            return(readers);
        }
Beispiel #10
0
        public virtual byte[] Control(byte[] cctrl)
        {
            byte[] rctrl = new byte[280];
            uint   rl    = 0;
            uint   rc;

            Trace.WriteLine("Control << " + (new CardBuffer(cctrl)).AsString());

            rc = SCARD.Control(_hCard,
                               SCARD.IOCTL_CSB6_PCSC_ESCAPE,
                               cctrl,
                               (uint)cctrl.Length,
                               rctrl,
                               280,
                               ref rl);

            if (rc == 1)
            {
                rc = SCARD.Control(_hCard,
                                   SCARD.IOCTL_MS_CCID_ESCAPE,
                                   cctrl,
                                   (uint)cctrl.Length,
                                   rctrl,
                                   280,
                                   ref rl);
            }

            if (rc != SCARD.S_SUCCESS)
            {
                Trace.WriteLine("Control: " + rc);
                _last_error = rc;
                rctrl       = null;
                return(null);
            }

            byte[] r = new byte[rl];
            for (int i = 0; i < rl; i++)
            {
                r[i] = rctrl[i];
            }

            Trace.WriteLine("Control >> " + (new CardBuffer(r)).AsString());

            return(r);
        }
        /**m* SCardReaderList/StopMonitor
         *
         * NAME
         *   SCardReaderList.StopMonitor()
         *
         * DESCRIPTION
         *   Stop the background thread previously launched by SCardReaderList.StartMonitor().
         *
         **/
        public void StopMonitor()
        {
            _status_change_callback = null;
            _status_change_running  = false;

            if (_status_change_thread != null)
            {
                if (_status_change_context != IntPtr.Zero)
                {
                    SCARD.Cancel(_status_change_context);
                }
                else
                {
                    _status_change_thread.Interrupt();
                }
                _status_change_thread.Join();
                _status_change_thread = null;
            }
        }
Beispiel #12
0
        /**m* SCardChannel/Reconnect
         *
         * NAME
         *   SCardChannel.Reconnect()
         *
         * SYNOPSIS
         *   bool Reconnect()
         *   bool Reconnect(uint disposition)
         *
         * DESCRIPTION
         *   Re-open the connection channel to the smartcard
         *
         * INPUTS
         *   The disposition parameter must take one of the following values:
         *   - SCARD.EJECT_CARD
         *   - SCARD.UNPOWER_CARD
         *   - SCARD.RESET_CARD
         *   - SCARD.LEAVE_CARD
         *   If this parameter is omitted, it defaults to SCARD.RESET_CARD
         *
         * OUTPUT
         *   Returns true if the connection has been successfully re-established.
         *   Returns false if not. See LastError for details.
         *
         * SEE ALSO
         *   SCardChannel.Connect
         *   SCardChannel.Disconnect
         *
         **/

        public virtual bool Reconnect(uint disposition)
        {
            uint rc;

            if (!Connected)
            {
                return(false);
            }

            rc =
                SCARD.Reconnect(_hCard, _share_mode, _want_protocols, disposition, ref _active_protocol);
            if (rc != SCARD.S_SUCCESS)
            {
                _hCard      = IntPtr.Zero;
                _last_error = rc;
                return(false);
            }

            UpdateState();
            return(true);
        }
Beispiel #13
0
        /**m* SCardChannel/Disconnect
         *
         * NAME
         *   SCardChannel.Disconnect()
         *
         * SYNOPSIS
         *   bool Disconnect()
         *   bool Disconnect(uint disposition)
         *
         * DESCRIPTION
         *   Close the connection channel
         *
         * INPUTS
         *   The disposition parameter must take one of the following values:
         *   - SCARD.EJECT_CARD
         *   - SCARD.UNPOWER_CARD
         *   - SCARD.RESET_CARD
         *   - SCARD.LEAVE_CARD
         *   If this parameter is omitted, it defaults to SCARD.RESET_CARD
         *
         * SEE ALSO
         *   SCardChannel.Connect
         *
         **/

        public virtual bool Disconnect(uint disposition)
        {
            uint rc;

            Trace.WriteLine("Disconnect, disposition=" + disposition);

            rc = SCARD.Disconnect(_hCard, disposition);
            if (rc != SCARD.S_SUCCESS)
            {
                _last_error = rc;
            }

            _hCard = IntPtr.Zero;

            if (rc != SCARD.S_SUCCESS)
            {
                return(false);
            }

            return(true);
        }
Beispiel #14
0
        /**m* SCardChannel/Connect
         *
         * NAME
         *   SCardChannel.Connect()
         *
         * SYNOPSIS
         *   bool Connect()
         *
         * DESCRIPTION
         *   Open the connection channel to the smartcard (according to the specified Protocol, default is either T=0 or T=1)
         *
         * OUTPUT
         *   Returns true if the connection has been successfully established.
         *   Returns false if not. See LastError for details.
         *
         * SEE ALSO
         *   SCardChannel.CardPresent
         *   SCardChannel.CardAtr
         *   SCardChannel.Protocol
         *   SCardChannel.Transmit
         *
         **/

        public virtual bool Connect()
        {
            uint rc;

            if (Connected)
            {
                return(false);
            }

            Trace.WriteLine("Connect to '" + _reader_name + "', share=" + _share_mode + ", protocol=" + _want_protocols);

            rc = SCARD.Connect(_hContext, _reader_name, _share_mode, _want_protocols, ref _hCard, ref _active_protocol);
            if (rc != SCARD.S_SUCCESS)
            {
                Trace.WriteLine(String.Format("Connect error {0:X08} ({0})", rc));
                _hCard      = IntPtr.Zero;
                _last_error = rc;
                return(false);
            }

            UpdateState();
            return(true);
        }
Beispiel #15
0
        public static string[] GetReaderList(IntPtr hContext, string Groups)
        {
            int    i, j = 0;
            string s = "";
            uint   rc;
            uint   readers_size  = 0;
            int    readers_count = 0;

            rc = SCARD.ListReaders(hContext, Groups, null, ref readers_size);
            if (rc != SCARD.S_SUCCESS)
            {
                return(null);
            }

            string readers_str = new string(' ', (int)readers_size);

            rc = SCARD.ListReaders(hContext, Groups, readers_str, ref readers_size);
            if (rc != SCARD.S_SUCCESS)
            {
                return(null);
            }

            for (i = 0; i < readers_size; i++)
            {
                if (readers_str[i] == '\0')
                {
                    if (i > 0)
                    {
                        readers_count++;
                    }
                    if (readers_str[i + 1] == '\0')
                    {
                        break;
                    }
                }
            }

            string[] readers = new string[readers_count];

            if (readers_count > 0)
            {
                for (i = 0; i < readers_size; i++)
                {
                    if (readers_str[i] == '\0')
                    {
                        readers[j++] = s;
                        if (readers_str[i + 1] == '\0')
                        {
                            break;
                        }
                        s = "";
                    }
                    else
                    {
                        s = s + readers_str[i];
                    }
                }
            }

            return(readers);
        }
 private void InitList()
 {
     _reader_names = SCARD.GetReaderList(_scope, _groups);
 }
        private void StatusChangeMonitor()
        {
            try
            {
                _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context);
                if (_last_error != SCARD.S_SUCCESS)
                {
                    _status_change_callback(null, 0, null);
                    return;
                }

                uint global_notification_state = SCARD.STATE_UNAWARE;

                while (_status_change_running)
                {
                    if (_status_change_context == IntPtr.Zero)
                    {
                        _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context);
                        if (_last_error != SCARD.S_SUCCESS)
                        {
                            _status_change_callback(null, 0, null);
                            return;
                        }
                    }

                    /* Construct the list of readers we'll have to monitor */
                    /* --------------------------------------------------- */
                    bool global_notification_fired = false;
                    int  monitor_count             = 0;

                    if (_auto_update_list)
                    {
                        if (_reader_names != null)
                        {
                            monitor_count = _reader_names.Length;
                            if (monitor_count > 10)
                            {
                                Trace.WriteLine("PC/SC: not able to monitor more than 10 readers (Windows limitation)");
                                monitor_count = 10;
                            }
                        }
                        monitor_count += 1;
                    }
                    else
                    {
                        if (_reader_names == null)
                        {
                            SCARD.ReleaseContext(_status_change_context);
                            _status_change_context = IntPtr.Zero;
                            _status_change_callback(null, 0, null);
                            return;
                        }
                        monitor_count = _reader_names.Length;
                        if (monitor_count > 10)
                        {
                            Trace.WriteLine("PC/SC: not able to monitor more than 10 readers (Windows limitation)");
                            monitor_count = 10;
                        }
                    }

                    SCARD.READERSTATE[] states = new SCARD.READERSTATE[monitor_count];

                    for (int i = 0; i < states.Length; i++)
                    {
                        states[i] = new SCARD.READERSTATE();
                        if (_auto_update_list && (i == 0))
                        {
                            /* Magic string to be notified of reader arrival/removal */
                            states[i].szReader       = "\\\\?PNP?\\NOTIFICATION";
                            states[i].dwCurrentState = global_notification_state;
                        }
                        else
                        {
                            /* Reader name */
                            states[i].szReader       = _reader_names[i - 1];
                            states[i].dwCurrentState = SCARD.STATE_UNAWARE;
                        }
                        states[i].dwEventState = 0;
                        states[i].cbAtr        = 0;
                        states[i].rgbAtr       = null;
                        states[i].pvUserData   = IntPtr.Zero;
                    }

                    /* Now wait for an event */
                    /* --------------------- */

                    while (_status_change_running && !global_notification_fired)
                    {
                        uint rc = SCARD.GetStatusChange(_status_change_context, 250, states, (uint)states.Length);

                        if ((rc == SCARD.E_SERVICE_STOPPED) || (rc == SCARD.E_NO_SERVICE))
                        {
                            Trace.WriteLine("PC/SC: no service");
                            SCARD.ReleaseContext(_status_change_context);
                            _status_change_context = IntPtr.Zero;
                            continue;
                        }

                        if (!_status_change_running)
                        {
                            break;
                        }

                        if (rc == SCARD.E_TIMEOUT)
                        {
                            continue;
                        }

                        if (rc != SCARD.S_SUCCESS)
                        {
                            Trace.WriteLine("PC/SC: monitor failed with error " + rc);

                            _last_error = rc;
                            /* Broadcast a message saying we have a problem! */
                            for (int i = 0; i < states.Length; i++)
                            {
                                states[i].dwEventState = 0 | SCARD.STATE_CHANGED;
                            }
                        }

                        for (int i = 0; i < states.Length; i++)
                        {
                            if ((states[i].dwEventState & SCARD.STATE_CHANGED) != 0)
                            {
                                /* This reader has fired an event */
                                /* ------------------------------ */

                                if (_auto_update_list && (i == 0))
                                {
                                    /* Not a reader but \\\\?PNP?\\NOTIFICATION */
                                    /* ---------------------------------------- */

                                    Trace.WriteLine("PC/SC: the list of readers has changed");

                                    global_notification_fired = true;
                                    global_notification_state = states[0].dwEventState;

                                    SCARD.ReleaseContext(_status_change_context);
                                    _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context);
                                    if (_last_error != SCARD.S_SUCCESS)
                                    {
                                        _status_change_callback(null, 0, null);
                                        return;
                                    }

                                    /* Refresh the list of readers */
                                    _reader_names = SCARD.GetReaderList(_status_change_context, _groups);

                                    /* Notify the application that the list of readers has changed */
                                    try
                                    {
                                        _status_change_callback(null, global_notification_state & ~SCARD.STATE_CHANGED, null);
                                    }
                                    catch {}
                                }
                                else
                                {
                                    /* This is a reader */
                                    /* ---------------- */

                                    Trace.WriteLine("PC/SC: status of reader " + states[i].szReader + " has changed");

                                    states[i].dwCurrentState = states[i].dwEventState;
                                    if ((states[i].dwCurrentState & SCARD.STATE_IGNORE) != 0)
                                    {
                                        states[i].dwCurrentState = SCARD.STATE_UNAVAILABLE;
                                    }

                                    CardBuffer card_atr = null;

                                    /* Is there a card involved ? */
                                    if ((states[i].dwEventState & SCARD.STATE_PRESENT) != 0)
                                    {
                                        try
                                        {
                                            card_atr = new CardBuffer(states[i].rgbAtr, (int)states[i].cbAtr);
                                        }
                                        catch {}
                                    }

                                    try
                                    {
                                        _status_change_callback(states[i].szReader, states[i].dwEventState & ~SCARD.STATE_CHANGED, card_atr);
                                    }
                                    catch {}
                                }
                            }
                        }
                    }
                }

                SCARD.ReleaseContext(_status_change_context);
                _status_change_context = IntPtr.Zero;
            }
            catch (ThreadInterruptedException) { }             /* Hide Interrupt */
        }
Beispiel #18
0
        protected virtual void StatusChangeMonitor()
        {
            uint rc;

            IntPtr hContext = IntPtr.Zero;

            _reader_state = SCARD.STATE_UNAWARE;
            _card_atr     = null;

            rc =
                SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref hContext);
            if (rc != SCARD.S_SUCCESS)
            {
                return;
            }

            SCARD.READERSTATE[] states = new SCARD.READERSTATE[1];

            states[0]                = new SCARD.READERSTATE();
            states[0].szReader       = _reader_name;
            states[0].pvUserData     = IntPtr.Zero;
            states[0].dwCurrentState = 0;
            states[0].dwEventState   = 0;
            states[0].cbAtr          = 0;
            states[0].rgbAtr         = null;

            while (_status_change_running)
            {
                try {
                    rc = SCARD.GetStatusChange(hContext, 1000, states, 1);
                } catch (ThreadInterruptedException) {
                    break;
                }

                if (!_status_change_running)
                {
                    break;
                }

                if (rc == SCARD.E_TIMEOUT)
                {
                    continue;
                }

                if (rc != SCARD.S_SUCCESS)
                {
                    _last_error = rc;

                    SCARD.ReleaseContext(hContext);
                    if (_status_change_callback != null)
                    {
                        _status_change_callback(0, null);
                    }
                    break;
                }

                if ((states[0].dwEventState & SCARD.STATE_CHANGED) != 0)
                {
                    states[0].dwCurrentState = states[0].dwEventState;

                    if (_status_change_callback != null)
                    {
                        CardBuffer card_atr = null;

                        if ((states[0].dwEventState & SCARD.STATE_PRESENT) != 0)
                        {
                            card_atr =
                                new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr);
                        }

                        _status_change_callback(states[0].dwEventState & ~SCARD.
                                                STATE_CHANGED, card_atr);
                    }
                }
            }

            SCARD.ReleaseContext(hContext);
        }
 public SCardMifareUltraLightC(SCardChannel card_channel)
 {
     hCard       = card_channel.hCard;
     _last_error = SCARD.MifUlC_AttachLibrary(hCard);
 }
Beispiel #20
0
        protected virtual void UpdateState()
        {
            uint rc;

            _reader_state = SCARD.STATE_UNAWARE;
            _card_atr     = null;

            if (Connected)
            {
                byte[] atr_buffer = new byte[36];
                uint   atr_length = 36;

                uint dummy = 0;

                rc =
                    SCARD.Status(_hCard, IntPtr.Zero, ref dummy,
                                 ref _reader_state, ref _active_protocol, atr_buffer,
                                 ref atr_length);
                if (rc != SCARD.S_SUCCESS)
                {
                    _last_error = rc;
                    return;
                }

                _card_atr = new CardBuffer(atr_buffer, (int)atr_length);
            }
            else
            {
                SCARD.READERSTATE[] states = new SCARD.READERSTATE[1];

                states[0]                = new SCARD.READERSTATE();
                states[0].szReader       = _reader_name;
                states[0].pvUserData     = IntPtr.Zero;
                states[0].dwCurrentState = 0;
                states[0].dwEventState   = 0;
                states[0].cbAtr          = 0;
                states[0].rgbAtr         = null;

                try
                {
                    rc = SCARD.GetStatusChange(_hContext, 0, states, 1);
                }
                catch (ThreadInterruptedException)
                {
                    rc = SCARD.E_CANCELLED;
                }

                if (rc != SCARD.S_SUCCESS)
                {
                    _last_error = rc;
                    return;
                }

                _reader_state = states[0].dwEventState;

                if ((_reader_state & SCARD.STATE_PRESENT) != 0)
                {
                    _card_atr = new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr);
                }
            }
        }
Beispiel #21
0
 public SCardReaderList()
 {
     _reader_names     = SCARD.GetReaderList();
     _auto_update_list = true;
 }