예제 #1
0
        /// <inheritdoc />
        public ICardHandle Connect(string readerName, SCardShareMode mode, SCardProtocol preferredProtocol)
        {
            ThrowOnInvalidContext();

            var handle = new CardHandle(_api, this);

            handle.Connect(readerName, mode, preferredProtocol);
            return(handle);
        }
예제 #2
0
        protected override void EstablishContext()
        {
            A.CallTo(() => CardHandle.Reconnect(A <SCardShareMode> .Ignored, A <SCardProtocol> .Ignored,
                                                A <SCardReaderDisposition> .Ignored))
            .Invokes(call => {
                A.CallTo(() => CardHandle.Mode).Returns(call.Arguments.Get <SCardShareMode>(0));
                A.CallTo(() => CardHandle.Protocol).Returns(call.Arguments.Get <SCardProtocol>(1));
            });

            _oldReaderName = Sut.Name;
            _isConnected   = Sut.IsConnected;
        }
예제 #3
0
        public void It_should_throw(string readerName, Type expectedException)
        {
            var sut = new CardHandle(_context);

            try {
                sut.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any);
            } catch (Exception exception) {
                exception.Should().BeOfType(expectedException);
                return;
            }

            throw new Exception($"Expected to throw {expectedException.Name} but did not!");
        }
예제 #4
0
 private void disconnectCard()
 {
     try
     {
         CardHandle ch = _terminalManager.Cards[_currentTerminalName];
         ch.CardTerminal.Disconnect(SCardDisposition.EjectCard);
         ResetData();
         //Console.WriteLine("Odłączono kartę");
         _terminalManager.StopPolling();
     }
     catch (Exception exception)
     {
         //Console.WriteLine("Nie udało się odłączyć karty. Wyjmij kartę z czytnika.");
     }
 }
예제 #5
0
        protected override void EstablishContext()
        {
            A.CallTo(() => _context.Handle).Returns((IntPtr)1);
            A.CallTo(() => _context.IsValid()).Returns(true);

            // let the request exit with INVALID_HANDLE
            IntPtr        handle;
            SCardProtocol protocol;

            A.CallTo(() => _api.Connect(A <IntPtr> ._, A <string> ._, A <SCardShareMode> ._, A <SCardProtocol> ._, out handle,
                                        out protocol))
            .WithAnyArguments()
            .Returns(SCardError.InvalidHandle);

            _sut = new CardHandle(_api, _context);
        }
예제 #6
0
        protected override void EstablishContext()
        {
            A.CallTo(() => _context.Handle).Returns((IntPtr)1);
            A.CallTo(() => _context.IsValid()).Returns(true);

            IntPtr        handle;
            SCardProtocol protocol;

            A.CallTo(() => _api.Connect(A <IntPtr> ._, A <string> ._, A <SCardShareMode> ._, A <SCardProtocol> ._, out handle,
                                        out protocol))
            .WithAnyArguments()
            .Returns(SCardError.Success)
            .AssignsOutAndRefParametersLazily(_ => new object[] { (IntPtr)123, SCardProtocol.T1 });

            _sut = new CardHandle(_api, _context);
        }
예제 #7
0
        protected override void EstablishContext()
        {
            A.CallTo(() => _context.Handle).Returns((IntPtr)1);
            A.CallTo(() => _context.IsValid()).Returns(true);

            IntPtr        handle;
            SCardProtocol protocol;

            A.CallTo(() => _api.Connect(A <IntPtr> ._, A <string> ._, A <SCardShareMode> ._, A <SCardProtocol> ._, out handle,
                                        out protocol))
            .WithAnyArguments()
            .Returns(SCardError.Success)
            .AssignsOutAndRefParametersLazily(_ => new object[] { (IntPtr)123, SCardProtocol.T1 });

            protocol = default(SCardProtocol);
            A.CallTo(() => _api.Reconnect((IntPtr)123, SCardShareMode.Direct, SCardProtocol.Any,
                                          SCardReaderDisposition.Reset, out protocol))
            .Returns(SCardError.Success)
            .AssignsOutAndRefParametersLazily(_ => new object[] { SCardProtocol.T15 });

            _sut = new CardHandle(_api, _context);
            _sut.Connect("MyReader", SCardShareMode.Shared, SCardProtocol.Any);
        }
예제 #8
0
 public void Should_the_card_handle_be_disconnected()
 {
     A.CallTo(() => CardHandle.Disconnect(SCardReaderDisposition.Eject))
     .MustHaveHappened(Repeated.Exactly.Once);
 }
예제 #9
0
 protected override void EstablishContext()
 {
     A.CallTo(() => CardHandle.Disconnect(A <SCardReaderDisposition> .Ignored))
     .Invokes(_ => A.CallTo(() => CardHandle.IsConnected).Returns(false));
 }
예제 #10
0
 public void Should_it_reconnect_the_card_handle()
 {
     A.CallTo(() => CardHandle.Reconnect(A <SCardShareMode> .Ignored, A <SCardProtocol> .Ignored,
                                         A <SCardReaderDisposition> .Ignored))
     .MustHaveHappened();
 }
예제 #11
0
 protected override void EstablishContext()
 {
     A.CallTo(() => _context.Handle).Returns(IntPtr.Zero);
     _sut = new CardHandle(_context);
 }
예제 #12
0
        public CardHelper(CardHandle aCard)
        {
            if (aCard == null)
            {
                throw new ArgumentNullException("invalid card handle");
            }
            m_aCard = aCard;
            CardPcscPart3 pcscPart3Info = new CardPcscPart3(aCard.GetATR());

            if (pcscPart3Info.isValid)
            {
                m_isContactless = pcscPart3Info.isContactless;
                m_cardInfo     += "PC/SC 2.01 compliant ATR detected\n";
                m_cardInfo     += "interface:  ";
                if (m_isContactless == true)
                {
                    m_cardInfo += "contactless\n";
                }
                else
                {
                    m_cardInfo += "contact\n";
                }
                m_cardInfo += "protocol:  " + pcscPart3Info.CardProtocol + "\n";
                m_cardInfo += "card type: " + pcscPart3Info.CardName + "\n";
            }
            else
            {
                //m_cardInfo += "ATR is not PC/SC 2.01 part 3 compliant\n";
                //m_cardInfo += "processor card or proprietary storage card\n";
            }



            // at this time we know: it is NOT a contactless or contact storage card as defined in PC/SC part 3
            // Let's try to find out more by analyzing the reader name. We may get lucky. Note though, that there is
            // no clean, standards-based way to determine the card interface this way.

            if (m_isContactless == false)
            {
                if (aCard.Slot.CardTerminalName.Contains("OMNIKEY") &&
                    aCard.Slot.CardTerminalName.Contains("CL"))
                {
                    if (aCard.Slot.CardTerminalName.Contains("5x25"))
                    {
                        m_isProxViaATR = true;
                        m_cardInfo    += "125 KHz PROX via ATR historical bytes\n";
                    }
                    else
                    {
                        m_isContactless = true;
                        m_cardInfo     += "contactless based on reader name\n";
                    }
                }
            }

            if (m_isContactless == false)
            {
                if (aCard.Slot.CardTerminalName.ToUpper().Contains("CONTACTLESS") == true) // SCM readers contain this string
                {
                    m_isContactless = true;
                    m_cardInfo     += "contactless based on reader name\n";
                }
            }

            if (m_isContactless == false && m_isProxViaATR == false)
            {
                // we could start an analysis based onm an ATR mask here
                m_cardInfo += "unknown card interface (fall back)\n";
            }

            // let us know if you are using a reader that could be handled here
            // [email protected]
            m_cardInfo += "end of card info ";
        }
예제 #13
0
        /// <summary>
        /// Łączy z kartą
        /// </summary>
        /// <param name="force">Wymuszenie zresetowania karty</param>
        /// <returns>Nr ATR karty</returns>
        public ByteArray ConnectCard(bool force = false)
        {
            if (CardHandle != null)
            {
                if (CardHandle.IsValid && !force)
                {
                    return(new ByteArray(CardHandle.ATR));
                }
                else
                {
                    CardHandle.Dispose();
                    CardHandle = null;
                }
            }

            int tryCounter = 5;

            do
            {
                try
                {
                    CardHandle = CardTerminalManager.Singleton.AcquireCard(TerminalName);
                }
                catch (System.Runtime.InteropServices.COMException comException)
                {
                    CardHandle = null;
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Message: " + comException.Message + ", HResult: " + comException.ErrorCode + ")");
                    }
                }
                catch (SCardException scException)
                {
                    CardHandle = null;
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Kod: " + scException.ResponseCode + ").", scException);
                    }
                }
                catch (Exception terminalException)
                {
                    CardHandle = null;
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU.", terminalException);
                    }
                }
                finally
                {
                    if (CardHandle == null)
                    {
                        tryCounter--;
                        if (tryCounter == 0)
                        {
                            throw new Exception("Nie znaleziono karty w czytniku.");
                        }
                    }
                }
                if (CardHandle != null)
                {
                    return(new ByteArray(CardHandle.ATR));
                }
                Thread.Sleep(1000);
            } while (true);
        }
예제 #14
0
        /// <summary>
        /// Wysyła do karty polecenie APDU
        /// </summary>
        /// <param name="command">Polecenie APDU</param>
        /// <param name="checkSuccessful">Ma sprawdzać, czy odpowiedź jest poprawna (90 00)</param>
        /// <exception cref="APDUException"></exception>
        /// <returns>Odpowiedź na polecenie APDU</returns>
        public ByteArray SendCommand(ByteArray command, bool checkSuccessful = true)
        {
            ConnectCard(false);

            CardCommandAPDU apdu = null;

            if (command.Length == 4)
            {
                apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3]);
            }
            else if (command.Length == 5)
            {
                apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], command[4]);
            }
            else if (command.Length > 5)
            {
                ByteArray data   = command.Extract(5, command[4]);
                int       length = 5 + command[4];
                if (length == command.Length)
                {
                    apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], data.ByteData);
                }
                else
                {
                    apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], data.ByteData, command[command.Length - 1]);
                }
            }

            if (apdu == null)
            {
                throw new Exception("Nieprawidłowa komenda APDU: " + command);
            }

            int tryCounter            = 5;
            CardResponseAPDU response = null;

            do
            {
                try
                {
                    Logger.Log("[Encoder] -> " + command);
                    response = CardHandle.SendCommand(apdu);
                    break;
                }
                catch (System.Runtime.InteropServices.COMException comException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Message: " + comException.Message + ", HResult: " + comException.ErrorCode + ")");
                    }
                }
                catch (SCardException scException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Kod: " + scException.ResponseCode + ").", scException);
                    }
                }
                catch (Exception terminalException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU.", terminalException);
                    }
                }
            } while (true);

            ByteArray result = new ByteArray(response.GenerateBytes());

            Logger.Log("[Encoder] <- " + result);

            if (checkSuccessful && !response.IsSuccessful && !response.IsWarning)
            {
                throw new APDUException("Błąd wykonywania komendy APDU", command, new ByteArray(response.GenerateBytes()), response.SW1, response.SW2);
            }

            return(result);
        }
예제 #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="aCardSlot"></param>

        public void AnalyzeCard(CardTerminalSlot aCardSlot)
        {
            // Acquire any processor card (T=0 or T=1) that may be present in the given card
            // terminal slot
            string readerName = aCardSlot.CardTerminalName;

            CardActivationResult nActivationResult;

            DisplayText("Reader Name: " + readerName);

            //aCardSlot.CardTerminal.Config
            CardHandle aCard = aCardSlot.AcquireCard((CardTypes.T0 | CardTypes.T1), out nActivationResult);

            if (nActivationResult != CardActivationResult.Success)
            {
                Debug.Assert(aCard == null);

                switch (nActivationResult)
                {
                case CardActivationResult.NoCard:
                    m_aPromptLabel.Text = readerName + ": Please insert card ...";
                    break;

                case CardActivationResult.UnresponsiveCard:
                    m_aPromptLabel.Text = readerName + ": Unresponsive card.";
                    break;

                case CardActivationResult.InUse:
                    m_aPromptLabel.Text = readerName + ": Card in use";
                    break;

                default:
                    m_aPromptLabel.Text = readerName + ": Can't power up card!";
                    break;
                }
                return;
            }
            m_aPromptLabel.Text = aCardSlot.CardTerminalName + ": Found card";
            DisplayText("Found card in reader " + aCardSlot.CardTerminalName);
            DisplayReaderProperties(aCardSlot);

            aCardSlot.BeginTransaction();

            try

            // We are doing a few things here that any card system should support.
            // Note that the CardHandle represents the combination of card terminal and
            // powered-up card.
            {
                // =========================== ATR DETECTION ======================================
                // Every card accessed through PC/SC must return an Answer To Reset (ATR).
                // So let's see what we've got here.
                byte[] atr = aCard.GetATR();
                if (atr.Length == 0)
                {
                    throw new Exception("Invalid ATR");
                }
                DisplayText("ATR: " + CardHex.FromByteArray(atr, 0, atr.Length));
                // ================================================================================

                // Go a little deeper: is this a contact or contactless card system we are dealing with?
                CardHelper cardHelper = new CardHelper(aCard);
                DisplayText(cardHelper.cardInfo);
                if (cardHelper.isContactless)
                {
                    // =========================== APDU EXCHANGE ==================================
                    // Now we can try to get a unique identifier (UID). Any contactless card with a
                    // PC/C 2.01 compliant card reader should be able to generate a UID. But never mind,
                    // even if this fails it still shows how to create a command APDU with our SmartCardAPI
                    // frameqwork and get a response APDU back from a card.
                    //
                    // Known issues:
                    // SendCommand with CLA=0xFF can cause an exception with some smart card systems,
                    // triggered by an "Unknown Error" (-2146435025) on PC/SC level.
                    // Therefore this code should only be run if we are accessing a contactless reader
                    // interface that is PC/SC 2.01 compliant
                    // ============================================================================
                    byte             CL_CLA         = 0xFF;
                    byte             CL_INS_GET_UID = 0xCA;
                    byte             P1             = 0;
                    byte             P2             = 0;
                    CardCommandAPDU  aCmdAPDU       = new CardCommandAPDU(CL_CLA, CL_INS_GET_UID, P1, P2, 256);
                    CardResponseAPDU aRespAPDU;
                    aRespAPDU = aCard.SendCommand(aCmdAPDU);
                    if (!aRespAPDU.IsSuccessful)
                    {
                        DisplayText("WARNING: can't get a UID - this might be a contact card.");
                    }
                    else
                    {
                        byte[] uidWithSw12 = aRespAPDU.GenerateBytes();
                        if (uidWithSw12.Length < 2)
                        {
                            throw new Exception("Invalid UID");
                        }
                        var uid = CardHex.FromByteArray(uidWithSw12, 0, uidWithSw12.Length - 2);
                        DisplayText("UID: " + uid);

                        if (uid.Length > 0)
                        {
                            _reader.SendRFID(uid);
                        }
                    }
                }
                aCardSlot.EndTransaction();
            }
            catch (Exception x)
            {
                Trace.WriteLine(x.ToString());
                DisplayText(x.ToString());
                m_aPromptLabel.Text = "Card access error";
            }
            finally
            {
                aCard.Dispose(); // release card handle
            }
        }