././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6948292 pyscard-2.2.1/0000755000076500000240000000000014740753203012757 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1731935918.0 pyscard-2.2.1/ACKS0000644000076500000240000000116514716637256013442 0ustar00rousseaustaffAcknowledgements ---------------- This list is sorted in alphabetical order, and is probably incomplete. I'd like to thank everybody who contributed in any way, with code, bug reports, and comments. -jda Jarle Bauck Hamar Antonio Aranda Frank Aune Michel Beziat Peter Bittner Mark Bokil Mattias Brändström Dave Cahill Eduardo Castellanos Norman Denayer Stefan Droege Luc Duche Jonathan Giannuzzi Kevin Griffin Nodir Gulyamov Max Hausch Merrick Heley Yong David Huang Valdur Kana Kristiine Adam Laurie Kurt McKee Elouan Petereau Henryk Plotz Chris Post Michael Roehner Ludovic Rousseau David Wagner Harald Welte Alex Willmer ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693285.0 pyscard-2.2.1/ChangeLog0000644000076500000240000003331414740753045014541 0ustar00rousseaustaff2.2.1 (January 2025) ==================== - patches from Ludovic Rousseau * waitforcardevent(): do not miss events between 2 calls * Use Windows locale to decode Unicode text * ACKS: add missing contributors - patches from Kurt McKee * Test, fix, and simplify ATR parsing 2.2.0 (October 2024) ==================== - patches from Ludovic Rousseau * PCSCCardRequest: - handle KeyboardInterrupt in waitforcard() & waitforcardevent() - use a local PC/SC context to avoid locks * smartcard.util.padd(): do NOT modify the input parameter * CardMonitoring: a timeout exception IS expected * Fix pydoctor documentation * wx: fix module and examples * Minor changes - patches from Kurt McKee * Remove Python 2 conditional code * Eliminate Windows Vista and Windows 7 conditionals * Test and improve the synchronization code * Test and update the `Observer.py` code * Remove `ClassLoader.py` * Migrate a `src/` layout * Migrate test/* from unittest to pytest * Add missing GSM 03.38 symbols for decoding * Support only Python 3.9 and higher * Remove the Python 2.x-only Pyro dependency * Migrate CI to use the official Coveralls action * Standardize local and CI testing to use tox * Build wheels in CI for all supported Python versions * Build the docs as a part of the test suite * Begin to add type annotations to the package * Deprecate the `HexListToBinString`, `BinStringToHexList`, `hl2bs`, and `bs2hl` utility functions * Support "64" as an ATR baud rate adjustment integer (ISO 7816-3 2006) 2.1.1 (September 2024) ====================== * Fix a regression introduced in 2.1.0 2.1.0 (September 2024) ====================== * PCSCCardRequest: fix active polling (was a 0.1 sec loop) * Fix use of undefined variable 'hresult' in exceptions * Fix print() use in pyscard user’s guide * Fix deprecation warnings * Minor changes 2.0.10 (June 2024) ================== * add 'swig' in pyproject.toml build requires * CardMonitoringThread(): do not catch unexpected exceptions 2.0.9 (April 2024) ================== * fix a bug with CardRequestTimeoutException introduced in 2.0.8 * Minor changes 2.0.8 (march 2024) ================== * Make CardMonitor() thread safe on Python 3.12 * Add hresult value in exceptions * Improve documentation * Check swig is installed on build * Remove use of imp module for wx (GUI) * Makefile: modernize use of setup.py * Minor changes 2.0.7 (March 2023) ================== * do not include the generated HTML documentation in the archive 2.0.6 (March 2023) ================== * handle SCARD_E_NO_SERVICE on Windows (on last reader removal) * add support of MSYS2/mingw environment on Windows * improve documentation * minor changes 2.0.5 (September 2022) ====================== * New version just because I failed the previous upload to https://pypi.org/ 2.0.4 (August 2022) ================== * Fix a problem on PCSCCardConnection.disconnect * Add support of BaseSCardException(hresult) format * Do not use deprecated distutils anymore 2.0.3 (March 2022) ================== * PCSCExceptions: include error code in the message * getReaderNames(): fix Windows 10 issue when the last reader is disconnected 2.0.2 (September 2021) ====================== * Fix an issue in ReaderMonitor() that failed to enumerate readers on macOS * getReaderNames(): handle SCARD_E_SERVICE_STOPPED on Windows generated on last reader removal * Restrict MAX_BUFFER_SIZE_EXTENDED to 65535 and fix an issue on Lenovo laptops with NXP NFC readers * SmartcardException: display a positive PCSC error code 2.0.1 (June 2021) ================= * Add .reconnect() method to high-level API * Handle removal of the last reader on Windows * Fix support of macOS Big Sur * Use Python3 by default * Handle bogus ACS ACR122U PICC reader 2.0.0 (September 2020) ====================== * SCardStatus(): Fix a crash in case of PC/SC error * toASCIIString(): replace non-ASCII char by '.' * remove i386 (32-bits) support on macOS 1.9.9 (August 2019) =================== * Makefile: use twine to upload to pypi.python.org * test: fix Exception test on 32-bits CPU * test: correctly handle macOS versions older than 10.10 1.9.8 (March 2019) ================== * SmartcardException: store the PC/SC return code in hresult * CardMonitoring: stop the looping only if PCSC exited * setup: support build on OpenBSD, and other BSD * Fix Windows 10 SCARD_E_SERVICE_STOPPED from SCardListReaders() * Minor documentation improvements 1.9.7 (June 2018) ================= * Modify CardMonitoring's deleteObserver method to cleanly remove threads * Python 3: fix smartcard/Synchronization.py * Python 3: Fix SCardGetErrorMessage() on Windows * PCSCPart10: add parseFeatureRequest(), parseTlvProperties() * Fix PEP8 warnings * Minor documentation improvements 1.9.6 (August 2017) =================== * include test/__init__.py in the archive tarball. "make test" now works. That fixes build using Python 3.6 1.9.5 (Feb 2017) ================ * SCardGetStatusChange(): fix a memory leak with Python 3 * SCardTransmit(): use SCARD_PCI_RAW for undefined protocol * Improve epydoc documentation 1.9.4 (May 2016) ================ * Fix installation using pip and easy_install * Avoid El Capitan SCardGetAttrib bug * CardConnection: Add context management * PCSCCardConnection: raise NoCardException if SCARD_E_NO_SMARTCARD * Stop CardMonitor monitor thread after traceback print. * minor improvements 1.9.3 (March 2016) ================== * Fix SCardControl() on Windows 7 * Fix installation using pip and easy_install 1.9.2 (February 2016) ===================== * Fix toBytes regression * Fix installation using pip * improve pydoc documentation * user-guide.rst: use real sample codes * minor improvements 1.9.1 (September 2015) ====================== * Create a new version so that the upload to Pypi does _not_ contain the swig generated files. 1.9.0 (August 2015) =================== * add Python3 support (Python2 is still supported) * fix a lot of pylint warnings * smartcard/test/* replace deprecated assert calls * add tox support and coverage reports, run test suite on Travis * add Travis CI support to automatically build on Unix * add AppVeyor support to automatically build on Windows * minor bugs fixed * Big thank you to Alex Willmer for his work on pyscard 1.7.0 (June 2015) =========== * PCSCCardConnection: Fix a problem with mode=SCARD_SHARE_DIRECT * add support of cygwin as a build platform * Fix a problem with Windows Remote Desktop * Switch from distutils to setuptools * dropped support for Python 2.5 and earlier (Alex Willmer) * dropped support for OS X 10.5 (Leopard) and earlier (Alex Willmer) * minor bugs fixed 1.6.16 (December 2014) =================== * added support for windows 64bit amd64 (Jean-Daniel Aussel) * support python "new" classes (derive classes from object) (Ludovic Rousseau from chrysn feature request ID 3110077) * fixed Reader.__eq__() (Ludovic Rousseau from Bernard Paulus bug ID 3418113) * fixed extended APDU transmit buffer too short by 2 (Jean-Daniel Aussel from bugs ID 2914636 and 3106761) * make Card and Reader objects hashable (Jean-Daniel Aussel from Hans-Peter Jansen feature request and patch) * convert the user guide to python-Sphinx 1.6.12 (August 2010) =================== * comply with PEP 8 (Ludovic Rousseau) * comply with PEP 352 (Jean-Daniel Aussel) * support of pcsclite 1.6 and deprecated LPSCARD_READERSTATE_A (Ludovic Rousseau) * support of py2exe scripts for wxWindows examples (Jean-Daniel Aussel) * partial support of remote pcsc readers with pyro (Jean-Daniel Aussel) 1.6.10 (May 2010) =================== * connect() has a new disposition parameter that is passed to SCardDisconnect (Ludovic Rousseau) * fixed winscard_init() bad initialization causing problems in multithreaded environment (Ludovic Rousseau) * Use MAX_BUFFER_SIZE_EXTENDED (64k) instead of 1024 for SCardControl and SCardTransmit (Ludovic Rousseau, reported by Lukasz Drygiel) * call winscard_init() to load the library only in the %init section instead of in each wrapped function (Ludovic Rousseau) * for Snow Leopard, do not pass -framework PCSC to the compiler (Martin Paljak) * reformatting to meet pep8 (Style Guide for Python Code) guidelines (Ludovic Rousseau) * rename FEATURE_MCT_READERDIRECT in FEATURE_MCT_READER_DIRECT to be conform with PCSC v2 part 10 ch. 2.3 (Ludovic Rousseau) * added missing CARD_E_NO_READERS_AVAILABLE (Kjell Tore Fossbakk) * added support of x86_64 on Mac OS X Snow Leopard (Jakob Schlyter) * ATR can be passed in input in the reader state list (Benoit Allard) * clear state changed bit in waitforcard/waitforcardevent upon time-out or reader removal (Jean-Daniel Aussel) * removed clearing of states and ATR content upon SCardGetStatusChange() error (Benoit Allard); handling is now moved up in python framework (Jean-Daniel Aussel) 1.6.8 (July 2009) ================= * fixed SCARD_ERROR types to match correct types on linux and Mac OS X (Ludovic Rousseau) * store g_rgSCard* references as void* (Ludovic Rousseau) * modified Mac OS X build to locate PCSC headers using -framework option (Ludovic Rousseau) * added contrib root directory and parseATR as first contribution (Ludovic Rousseau) * updated a few samples to support SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 instead of just SCARD_PROTOCOL_T0 (Ludovic Rousseau) * added SCARD_E_NO_READERS_AVAILABLE definition (Ludovic Rousseau) * added simpleAPDU.py, a simple script to send a couple of APDUs (Ludovic Rousseau) * added support for Snow Leopard 10.6 (Ludovic Rousseau) * redefined error codes to be non-Windows or -linux specifics (Ludovic Rousseau) * added definitions of SCARD_ATTR_xxx values for Mac OS X (Jean-Daniel Aussel) * delay SCardEstablishContext call until needed instead of login, to allow use of utility classes such as toHexString, even when the PCSC resource manager or pcscd daemon is not started (Ludovic Rousseau) * added javascript code for Piwik web analytics to documentation pages (Jean-Daniel Aussel) * update sourceforge logo pages to latest sourceforge standard (Jean-Daniel Aussel) * fixed ATR parsing logics (Ludovic Rousseau) * added control() method to CardConnection() (Ludovic Rousseau) * added mode argument to connect() method of CardConnection (Ludovic Rousseau) * added PCSC v2 feature management (Ludovic Rousseau) 1.6.7 ===== * better thread support and clean-up in ReaderMonitoringThread (Frank Aune) * fixed issue on Mac OS X Leopard with dlsym loading of bad SCardControl function (Mattias Brändström) * supported build of documentation files on linux and removed unresolved doc links (Ludovic Rousseau) 1.6.6 ===== * added support for Mac OS X Leopard 1.6.5 ===== * added sample_MonitorCardsAndTransmit.py sample to illustrate how to transmit apdu to a card notified by the card monitor * added support for SCardControl (Ludovic Rousseau) * added support for Max OS X Tiger (Ludovic Rousseau/Jean-Daniel Aussel) (Leopard not supported) * added debian package directory (Ludovice Rousseau) * support for python 2.3, 2.4 and 2.5 distutils * automated insertion of sourceforge logo in html pages generated by epydoc * fixed documentation generation to include examples 1.6.4 ===== * handled several issues reported by Michael Roehner concerning waitforcard() not detecting card in reader/card USB stick; changed the waitforcard() and waitforcardevent() to poll every 100ms for new readers and cards in these readers * following issue reported by Jarle Bauck Hamar, added samples on how to perform exclusive card connection or protect transmit() from being interrupted by another thread or process * fixed ATR parsing error for optional interface bytes reported by Jarle Bauck Hamar 1.6.3 ===== * better handling of protocol selection with associated test cases and added getATR_T1 example (issue reported by Adam Laurie for T=1 cards, and request from Yong David Huang for Omnikey CM5321 RFID that failed with T0|T1 mask). * added handling of linux 64-bit platform and graceful exit for unsupported platform, thanks to Henryk Plötz * added support for float value timeout in CardRequest, thanks to Henryk Plötz; updated test cases and a couple of samples with float timeouts. 1.6.2 ===== * started support for Mac OS X Darwin; not yet operational * fixed issue with "'NoneType' object is not callable" exception on some clean-up routines executed from __del__ methods (CardMonitoring, ReaderMonitoring, CardConnection) * added default protocol, protocol argument to CardConnection.connect(), and get/setProtocol methods to CardConnection, PCSCCardConnection and CardConnectionDecorator 1.6.1 ===== * maintenance release: - define LPCTSTR and LPTSTR for recent releases of pcsc-lite - print formatting of userdata in SCardHelper_PrintReaderStateList - updated home page and download links to point to sourceforge.net 1.6.0 ===== * released open-source with LGPL license ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727878166.0 pyscard-2.2.1/INSTALL.md0000644000076500000240000001221314677252026014414 0ustar00rousseaustaffpyscard: smartcard library for python ===================================== https://pyscard.sourceforge.io/ Copyright 2001-2012 Gemalto Authors: - Jean-Daniel Aussel, jean-daniel.aussel@gemalto.com - Ludovic Rousseau, ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA pyscard is a python module adding smart cards support to python. It consists of the `smartcard.scard` module, an extension module wrapping Windows smart card base components (also known as PCSC) on Windows, and PCSC lite on GNU/Linux and macOS, and of the smartcard module, a python framework with objects wrapping PCSC API. Documentation ------------- All documentation is provided in the `src/smartcard/doc` directory of the source distribution. Examples are provided in the `src/smartcard/Examples` directory of the source distribution. The binary distribution does not include any documentation, tests scripts or examples. Installation ------------ The pyscard library is packaged using the standard setuptools python module. Installation on windows ----------------------- Installing on windows from the binary distribution -------------------------------------------------- Use pip: ``` pip install pyscard ``` Installing on windows from the source distribution --------------------------------------------------- 1. you will need [swig](https://www.swig.org/), and a C compiler. You can install swig using: * Install the chocolately package manager * Open a powershell as administrator mode, run ``` choco install swig ``` * Then in the same window, install pyscard by ``` pip install pyscard ``` 2. download the source distribution The source distribution is available `pyscard-1.9..tar.gz` for Windows and GNU/Linux. 3. unzip the source distribution, open a console and type the following: ``` setup.py build_ext install ``` This will build pyscard and install it in the site-packages directory of your python distribution, e.g. `c:\python312\Lib\site-packages\smartcard`. This install procedure does not install the documentation, examples or test files. Installation on GNU/Linux or macOS ---------------------------------- Installing on GNU/Linux or macOS from the source distribution ------------------------------------------------------------- 1. you will need gcc, swig (https://www.swig.org/), and pcsc-lite (https://pcsclite.apdu.fr/) 2. download the source distribution The source distribution is available as `pyscard-1.9..tar.gz`. 3. untar the source distribution 4. from a terminal with root privileges, type the following: ``` sudo python setup.py install ``` This will build pyscard and install it in the site-packages directory of your python distribution, e.g. `/usr/lib/python3.12/site-packages/smartcard`. Developer documentation, unit tests and examples ------------------------------------------------ The developer documentation is in the `src/smartcard/doc/` directory of the source distribution. Examples are located in the `src/smartcard/Examples/` directory, and the pyunit unit tests in the `src/smartcard/test/` directory. Build instructions for packagers -------------------------------- Building a binary distribution for Windows ------------------------------------------ To build a binary distribution from the source distribution, you will need a C compiler and swig (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a console: ``` python -m build ``` This will build the wheel installer with a name similar to `pyscard-2.0.5-cp311-cp311-win_amd64.whl` in the `dist/`directory. Building a binary distribution for GNU/Linux -------------------------------------------- To build a binary distribution from the source distribution, you will need gcc, swig and pcsc-lite (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a terminal: ``` python3 -m venv temp source temp/bin/activate pip3 install -r dev-requirements.txt python3 -m build ``` This will build a wheel installer with a name similar to `pyscard-2.0.7-cp310-cp310-linux_x86_64.whl` and a source code archive `pyscard-2.0.7.tar.gz` in the `dist/`directory. Building a binary distribution for macOS ---------------------------------------- To build a binary distribution from the source distribution, you will need swig and Xcode (same requirements as for installing from the source distribution). The steps are then the same as for GNU/Linux. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/LICENSE0000644000076500000240000005744714677317744014024 0ustar00rousseaustaff GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/MANIFEST.in0000644000076500000240000000203014674316735014523 0ustar00rousseaustaffinclude ACKS include ChangeLog include INSTALL.md include LICENSE include MANIFEST.in include Makefile include README.md include TODO include src/smartcard/scard/PcscDefs.i include src/smartcard/scard/PcscTypemaps.i include src/smartcard/scard/gemalto.ver include src/smartcard/scard/helpers.c include src/smartcard/scard/helpers.h include src/smartcard/scard/memlog.h include src/smartcard/scard/pcsctypes.h include src/smartcard/scard/pyscard-reader.h include src/smartcard/scard/scard.def include src/smartcard/scard/scard.i include src/smartcard/scard/scard.rc include src/smartcard/scard/winscarddll.c include src/smartcard/scard/winscarddll.h include src/smartcard/test/configcheck.py recursive-include src/smartcard/Examples *.py *.ico recursive-include src/smartcard/doc *.html *.jpg *.css *.js *.png *.txt recursive-include src/smartcard/test/framework *.txt *.py recursive-include src/smartcard/test/frameworkpcsc *.txt *.py recursive-include src/smartcard/test/scard *.txt *.py recursive-include src/smartcard/wx *.ico include test/*.py ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727888574.0 pyscard-2.2.1/Makefile0000644000076500000240000000166314677276276014450 0ustar00rousseaustaffPYTHON ?= python3 TOX ?= tox COVERAGE ?= coverage build: $(TOX) run -m build install: clean $(PYTHON) -m pip install --editable . clean: $(PYTHON) setup.py clean rm -rf build rm -f src/smartcard/scard/_scard*.so pypi: clean # files generated by swig rm -f src/smartcard/scard/scard.py rm -f src/smartcard/scard/scard_wrap.c rm -rf dist # Use the tox 'build' label to generate wheels for all Python versions. $(TOX) run -m build python3 -m twine upload dist/* test: pytest --verbose coverage: $(COVERAGE) erase $(COVERAGE) run -m pytest $(COVERAGE) combine $(COVERAGE) report $(COVERAGE) html pylint: $(PYTHON) -m pylint --errors-only smartcard ChangeLog.git: git log --stat --decorate=short > $@ .PHONY: sync-docs sync-docs: clean $(TOX) -e docs rsync \ --recursive --verbose --update --rsh=ssh --links \ build/docs/ \ ludov@web.sourceforge.net:/home/project-web/pyscard/htdocs/ .PHONY: clean build pypi test ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6944404 pyscard-2.2.1/PKG-INFO0000644000076500000240000000256014740753203014057 0ustar00rousseaustaffMetadata-Version: 2.2 Name: pyscard Version: 2.2.1 Summary: Smartcard module for Python. Home-page: https://github.com/LudovicRousseau/pyscard Download-URL: https://sourceforge.net/projects/pyscard/files/pyscard/pyscard%202.2.1/pyscard-2.2.1.tar.gz/download Author: Ludovic Rousseau Author-email: ludovic.rousseau@free.fr Platform: linux Platform: win32 Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Intended Audience :: Developers Classifier: Operating System :: Unix Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Topic :: Security Requires-Python: >=3.9 License-File: LICENSE Requires-Dist: typing_extensions; python_version == "3.9" Provides-Extra: gui Requires-Dist: wxPython; extra == "gui" Dynamic: author Dynamic: author-email Dynamic: classifier Dynamic: description Dynamic: download-url Dynamic: home-page Dynamic: platform Dynamic: provides-extra Dynamic: requires-dist Dynamic: requires-python Dynamic: summary Smartcard package for Python ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/README.md0000644000076500000240000000174514677317744014264 0ustar00rousseaustaffpyscard: smartcard library for python ===================================== [pyscard](https://pyscard.sourceforge.io/) - python smart card library - is a python module adding smart cards support to [python](https://www.python.org/). ![alt text](https://pyscard.sourceforge.io/_images/pyscard.jpg "pyscard architecture") Documentation ------------- https://pyscard.sourceforge.io/user-guide.html#pyscard-user-guide Installation ------------ Use `python3 -m pip install pyscard` See [INSTALL.md](INSTALL.md) for more details. Samples ------- - High level API samples: See https://pyscard.sourceforge.io/pyscard-framework.html#framework-samples - Low level API samples: See https://pyscard.sourceforge.io/pyscard-wrapper.html#wrapper-samples Continuous Integration status ----------------------------- Coveralls: [![Coverage Status](https://coveralls.io/repos/LudovicRousseau/pyscard/badge.svg?branch=master&service=github)](https://coveralls.io/github/LudovicRousseau/pyscard?branch=master) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727113313.0 pyscard-2.2.1/TODO0000644000076500000240000000052614674324141013453 0ustar00rousseaustaff- document construction of standalone windows application using py2exe - documentation and implementation of card services - documentation of CardConnectionDecorator; add a meaningful example (OP secure channel?) - documentation of wxPython classes; fix wxPython code on Mac OS X - more error checking chains - more unit tests May 2010 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728488499.0 pyscard-2.2.1/pyproject.toml0000644000076500000240000000071514701522063015671 0ustar00rousseaustaff[build-system] requires = ["setuptools","swig"] build-backend = "setuptools.build_meta" # isort # ----- [tool.isort] profile = "black" # pydoctor # -------- [tool.pydoctor] add-package = ["src/smartcard"] project-name = "PySCard" project-url = "https://github.com/LudovicRousseau/pyscard" html-output = "build/docs/apidocs" warnings-as-errors = true # pytest # ------ [tool.pytest.ini_options] addopts = "--color=yes" filterwarnings = [ "error", ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6949115 pyscard-2.2.1/setup.cfg0000644000076500000240000000004614740753203014600 0ustar00rousseaustaff[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693285.0 pyscard-2.2.1/setup.py0000644000076500000240000001226314740753045014501 0ustar00rousseaustaff#! /usr/bin/env python3 """Setup file for setuptools __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2007-2018 Ludovic Rousseau ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import platform import shlex import subprocess from shutil import which from sysconfig import get_platform from setuptools import Extension, setup from setuptools.command.build_py import build_py platform_include_dirs = [] platform_sources = [] platform_libraries = [] platform_extra_compile_args = [] # ['-ggdb', '-O0'] platform_extra_link_args = [] # ['-ggdb'] if platform.system() == "Windows": platform__cc_defines = [("WIN32", "100")] platform_swig_opts = ["-DWIN32"] if "mingw" not in get_platform(): platform_sources = ["src/smartcard/scard/scard.rc"] platform_libraries = ["winscard"] elif platform.system() == "Darwin": platform__cc_defines = [("PCSCLITE", "1"), ("__APPLE__", "1")] platform_swig_opts = ["-DPCSCLITE", "-D__APPLE__"] # Other (GNU/Linux, etc.) # else: platform__cc_defines = [("PCSCLITE", "1")] platform_swig_opts = ["-DPCSCLITE"] try: pkg_config_cflags = subprocess.check_output( ["pkg-config", "--cflags", "libpcsclite"] ) platform_extra_compile_args += shlex.split(pkg_config_cflags.decode()) except: platform_include_dirs = ["/usr/include/PCSC", "/usr/local/include/PCSC"] VERSION_INFO = (2, 2, 1, 0) VERSION_STR = "%i.%i.%i" % VERSION_INFO[:3] VERSION_ALT = "%i,%01i,%01i,%04i" % VERSION_INFO class BuildPyBuildExtFirst(build_py): """Workaround substitute `build_py` command for SWIG""" def run(self): if which("swig") is None: print("Install swig and try again") print("") exit(1) # Run build_ext first so that SWIG generated files are included self.run_command("build_ext") return build_py.run(self) kw = { "name": "pyscard", "version": VERSION_STR, "description": "Smartcard module for Python.", "author": "Ludovic Rousseau", "author_email": "ludovic.rousseau@free.fr", "url": "https://github.com/LudovicRousseau/pyscard", "long_description": "Smartcard package for Python", "platforms": ["linux", "win32"], "python_requires": ">=3.9", "packages": [ "smartcard", "smartcard.pcsc", "smartcard.reader", "smartcard.scard", "smartcard.sw", "smartcard.util", "smartcard.wx", ], "package_dir": {"": "src"}, "package_data": { "smartcard.wx": ["resources/*.ico"], }, "cmdclass": {"build_py": BuildPyBuildExtFirst}, # the _scard.pyd extension to build "ext_modules": [ Extension( "smartcard.scard._scard", define_macros=[ ("VER_PRODUCTVERSION", VERSION_ALT), ("VER_PRODUCTVERSION_STR", VERSION_STR), ] + platform__cc_defines, include_dirs=["src/smartcard/scard/"] + platform_include_dirs, sources=[ "src/smartcard/scard/helpers.c", "src/smartcard/scard/winscarddll.c", "src/smartcard/scard/scard.i", ] + platform_sources, libraries=platform_libraries, extra_compile_args=platform_extra_compile_args, extra_link_args=platform_extra_link_args, swig_opts=["-outdir", "src/smartcard/scard"] + platform_swig_opts, ) ], "install_requires": [ "typing_extensions; python_version=='3.9'", ], "extras_require": { "Gui": ["wxPython"], }, "classifiers": [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", "Intended Audience :: Developers", "Operating System :: Unix", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Security", ], } # FIXME Sourceforge downloads are unauthenticated, migrate to PyPI kw["download_url"] = ( "https://sourceforge.net/projects/%(name)s/files" "/%(name)s/%(name)s%%20%(version)s" "/%(name)s-%(version)s.tar.gz/download" % kw ) setup(**kw) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.5885668 pyscard-2.2.1/src/0000755000076500000240000000000014740753203013546 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6938028 pyscard-2.2.1/src/pyscard.egg-info/0000755000076500000240000000000014740753203016705 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693378.0 pyscard-2.2.1/src/pyscard.egg-info/PKG-INFO0000644000076500000240000000256014740753202020004 0ustar00rousseaustaffMetadata-Version: 2.2 Name: pyscard Version: 2.2.1 Summary: Smartcard module for Python. Home-page: https://github.com/LudovicRousseau/pyscard Download-URL: https://sourceforge.net/projects/pyscard/files/pyscard/pyscard%202.2.1/pyscard-2.2.1.tar.gz/download Author: Ludovic Rousseau Author-email: ludovic.rousseau@free.fr Platform: linux Platform: win32 Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Intended Audience :: Developers Classifier: Operating System :: Unix Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Topic :: Security Requires-Python: >=3.9 License-File: LICENSE Requires-Dist: typing_extensions; python_version == "3.9" Provides-Extra: gui Requires-Dist: wxPython; extra == "gui" Dynamic: author Dynamic: author-email Dynamic: classifier Dynamic: description Dynamic: download-url Dynamic: home-page Dynamic: platform Dynamic: provides-extra Dynamic: requires-dist Dynamic: requires-python Dynamic: summary Smartcard package for Python ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693378.0 pyscard-2.2.1/src/pyscard.egg-info/SOURCES.txt0000644000076500000240000001516714740753202020602 0ustar00rousseaustaffACKS ChangeLog INSTALL.md LICENSE MANIFEST.in Makefile README.md TODO pyproject.toml setup.py src/pyscard.egg-info/PKG-INFO src/pyscard.egg-info/SOURCES.txt src/pyscard.egg-info/dependency_links.txt src/pyscard.egg-info/requires.txt src/pyscard.egg-info/top_level.txt src/smartcard/ATR.py src/smartcard/AbstractCardRequest.py src/smartcard/Card.py src/smartcard/CardConnection.py src/smartcard/CardConnectionDecorator.py src/smartcard/CardConnectionEvent.py src/smartcard/CardConnectionObserver.py src/smartcard/CardMonitoring.py src/smartcard/CardRequest.py src/smartcard/CardService.py src/smartcard/CardType.py src/smartcard/Exceptions.py src/smartcard/ExclusiveConnectCardConnection.py src/smartcard/ExclusiveTransmitCardConnection.py src/smartcard/Observer.py src/smartcard/PassThruCardService.py src/smartcard/ReaderMonitoring.py src/smartcard/Session.py src/smartcard/Synchronization.py src/smartcard/System.py src/smartcard/__init__.py src/smartcard/guid.py src/smartcard/ulist.py src/smartcard/Examples/framework/sample_ATR.py src/smartcard/Examples/framework/sample_CardConnectionDecorator.py src/smartcard/Examples/framework/sample_ConsoleConnectionTracer.py src/smartcard/Examples/framework/sample_CustomCardType.py src/smartcard/Examples/framework/sample_CustomErrorChecker.py src/smartcard/Examples/framework/sample_ErrorChecking.py src/smartcard/Examples/framework/sample_ExclusiveCardConnection.py src/smartcard/Examples/framework/sample_MonitorCards.py src/smartcard/Examples/framework/sample_MonitorCardsAndTransmit.py src/smartcard/Examples/framework/sample_MonitorReaders.py src/smartcard/Examples/framework/sample_TransmitCardObserver.py src/smartcard/Examples/framework/sample_apduTracerInterpreter.py src/smartcard/Examples/framework/sample_toHexString.py src/smartcard/Examples/scard-api/sample_control.py src/smartcard/Examples/scard-api/sample_getATR.py src/smartcard/Examples/scard-api/sample_getAttrib.py src/smartcard/Examples/scard-api/sample_getStatusChange.py src/smartcard/Examples/scard-api/sample_listCards.py src/smartcard/Examples/scard-api/sample_listInterfaces.py src/smartcard/Examples/scard-api/sample_locateCards.py src/smartcard/Examples/scard-api/sample_pinpad.py src/smartcard/Examples/scard-api/sample_readerGroups.py src/smartcard/Examples/scard-api/sample_readers.py src/smartcard/Examples/scard-api/sample_selectDFTelecom.py src/smartcard/Examples/scard-api/sample_transaction.py src/smartcard/Examples/simple/getATR.py src/smartcard/Examples/simple/getATR_context.py src/smartcard/Examples/simple/selectDF_TELECOM.py src/smartcard/Examples/simple/simpleAPDU.py src/smartcard/Examples/wx/apdumanager/SampleAPDUManagerPanel.py src/smartcard/Examples/wx/apdumanager/apdumanager.py src/smartcard/Examples/wx/apdumanager/setup.py src/smartcard/Examples/wx/apdumanager/images/mysmartcard.ico src/smartcard/Examples/wx/cardmonitor/cardmonitor.py src/smartcard/Examples/wx/cardmonitor/setup.py src/smartcard/Examples/wx/cardmonitor/images/mysmartcard.ico src/smartcard/Examples/wx/pcscdiag/pcscdiag.py src/smartcard/Examples/wx/readerviewer/readerviewer.py src/smartcard/Examples/wx/readerviewer/setup.py src/smartcard/Examples/wx/readerviewer/images/readerviewer.ico src/smartcard/doc/images/pyscard.jpg src/smartcard/doc/images/sflogo.php.png src/smartcard/pcsc/PCSCCardConnection.py src/smartcard/pcsc/PCSCCardRequest.py src/smartcard/pcsc/PCSCContext.py src/smartcard/pcsc/PCSCExceptions.py src/smartcard/pcsc/PCSCPart10.py src/smartcard/pcsc/PCSCReader.py src/smartcard/pcsc/PCSCReaderGroups.py src/smartcard/pcsc/__init__.py src/smartcard/reader/Reader.py src/smartcard/reader/ReaderFactory.py src/smartcard/reader/ReaderGroups.py src/smartcard/reader/__init__.py src/smartcard/scard/PcscDefs.i src/smartcard/scard/PcscTypemaps.i src/smartcard/scard/__init__.py src/smartcard/scard/gemalto.ver src/smartcard/scard/helpers.c src/smartcard/scard/helpers.h src/smartcard/scard/memlog.h src/smartcard/scard/pcsctypes.h src/smartcard/scard/pyscard-reader.h src/smartcard/scard/scard.def src/smartcard/scard/scard.i src/smartcard/scard/scard.rc src/smartcard/scard/winscarddll.c src/smartcard/scard/winscarddll.h src/smartcard/sw/ErrorChecker.py src/smartcard/sw/ErrorCheckingChain.py src/smartcard/sw/ISO7816_4ErrorChecker.py src/smartcard/sw/ISO7816_4_SW1ErrorChecker.py src/smartcard/sw/ISO7816_8ErrorChecker.py src/smartcard/sw/ISO7816_9ErrorChecker.py src/smartcard/sw/SWExceptions.py src/smartcard/sw/__init__.py src/smartcard/sw/op21_ErrorChecker.py src/smartcard/test/configcheck.py src/smartcard/test/framework/readme.txt src/smartcard/test/framework/testcase_ATR.py src/smartcard/test/framework/testcase_CAtr.py src/smartcard/test/framework/testcase_Card.py src/smartcard/test/framework/testcase_CardConnection.py src/smartcard/test/framework/testcase_CardMonitor.py src/smartcard/test/framework/testcase_CardRequest.py src/smartcard/test/framework/testcase_CardService.py src/smartcard/test/framework/testcase_CardType.py src/smartcard/test/framework/testcase_ErrorChecking.py src/smartcard/test/framework/testcase_ExclusiveCardConnection.py src/smartcard/test/framework/testcase_readergroups.py src/smartcard/test/framework/testcase_readermonitor.py src/smartcard/test/framework/testcase_readermonitorstress.py src/smartcard/test/framework/testcase_readers.py src/smartcard/test/framework/testcase_ulist.py src/smartcard/test/framework/testcase_utils.py src/smartcard/test/framework/testsuite_framework.py src/smartcard/test/frameworkpcsc/readme.txt src/smartcard/test/frameworkpcsc/testcase_pcscreadergroups.py src/smartcard/test/frameworkpcsc/testsuite_frameworkpcsc.py src/smartcard/test/scard/readme.txt src/smartcard/test/scard/testcase_getatr.py src/smartcard/test/scard/testcase_getattrib.py src/smartcard/test/scard/testcase_geterrormessage.py src/smartcard/test/scard/testcase_listcards.py src/smartcard/test/scard/testcase_locatecards.py src/smartcard/test/scard/testcase_readergroups.py src/smartcard/test/scard/testcase_returncodes.py src/smartcard/test/scard/testcase_transaction.py src/smartcard/test/scard/testsuite_scard.py src/smartcard/util/__init__.py src/smartcard/wx/APDUHexValidator.py src/smartcard/wx/APDUTracerPanel.py src/smartcard/wx/CardAndReaderTreePanel.py src/smartcard/wx/ReaderToolbar.py src/smartcard/wx/SimpleSCardApp.py src/smartcard/wx/SimpleSCardAppEventObserver.py src/smartcard/wx/SimpleSCardAppFrame.py src/smartcard/wx/__init__.py src/smartcard/wx/resources/reader.ico src/smartcard/wx/resources/smartcard.ico test/conftest.py test/test_ATR.py test/test_Exceptions.py test/test_PCSC.py test/test_PCSCExceptions.py test/test_SCardGetErrorMessage.py test/test_guid.py test/test_observer.py test/test_readergroups.py test/test_synchronization.py test/test_ulist.py test/test_util.py././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693378.0 pyscard-2.2.1/src/pyscard.egg-info/dependency_links.txt0000644000076500000240000000000114740753202022752 0ustar00rousseaustaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693378.0 pyscard-2.2.1/src/pyscard.egg-info/requires.txt0000644000076500000240000000007614740753202021307 0ustar00rousseaustaff [:python_version == "3.9"] typing_extensions [Gui] wxPython ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736693378.0 pyscard-2.2.1/src/pyscard.egg-info/top_level.txt0000644000076500000240000000001214740753202021427 0ustar00rousseaustaffsmartcard ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6146176 pyscard-2.2.1/src/smartcard/0000755000076500000240000000000014740753203015526 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729456542.0 pyscard-2.2.1/src/smartcard/ATR.py0000644000076500000240000002441114705264636016540 0ustar00rousseaustaff"""ATR class managing some of the Answer To Reset content. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from __future__ import annotations import functools import operator import warnings from smartcard.Exceptions import SmartcardException class ATR: """Parse and represent Answer to Reset sequences. Answer to Reset sequences are defined in ISO 7816-3, section 8. """ clockrateconversion: list[int | str] = [ 372, 372, 558, 744, 1116, 1488, 1860, "RFU", "RFU", 512, 768, 1024, 1536, 2048, "RFU", "RFU", ] bitratefactor: list[int | str] = [ "RFU", 1, 2, 4, 8, 16, 32, 64, 12, 20, "RFU", "RFU", "RFU", "RFU", "RFU", "RFU", ] currenttable: list[int | str] = [25, 50, 100, "RFU"] def __init__(self, atr: list[int]) -> None: """Parse ATR and initialize members: - TS: initial character - T0: format character - TA[n], TB[n], TC[n], TD[n], for n=0,1,...: protocol parameters @note: protocol parameters indices start at 0, e.g. TA[0], TA[1] correspond to the ISO standard TA1, TA2 parameters - historicalBytes: the ATR T1, T2, ..., TK historical bytes - TCK: checksum byte (only for protocols different from T=0) - FI: clock rate conversion factor - DI: voltage adjustment factor - PI1: programming voltage factor - II: maximum programming current factor - N: extra guard time """ if len(atr) < 2: raise SmartcardException(f"ATR sequences must be at least 2 bytes long") if atr[0] not in {0x3B, 0x3F}: raise SmartcardException(f"invalid TS 0x{atr[0]:02x}") self.atr = atr # initial character self.TS = self.atr[0] # format character self.T0 = self.atr[1] # count of historical bytes self.K = self.T0 & 0x0F # initialize optional characters lists self.TA: list[None | int] = [] self.TB: list[None | int] = [] self.TC: list[None | int] = [] self.TD: list[None | int] = [] self.Y: list[int] = [] td: None | int = self.T0 offset = 1 while td is not None: self.Y.append(td >> 4 & 0x0F) self.TA += [None] self.TB += [None] self.TC += [None] self.TD += [None] if self.Y[-1] & 0x01: # TA offset += 1 self.TA[-1] = self.atr[offset] if self.Y[-1] & 0x02: # TB offset += 1 self.TB[-1] = self.atr[offset] if self.Y[-1] & 0x04: # TC offset += 1 self.TC[-1] = self.atr[offset] if self.Y[-1] & 0x08: # TD offset += 1 self.TD[-1] = self.atr[offset] td = self.TD[-1] self.interfaceBytesCount = offset - 1 # historical bytes self.historicalBytes = self.atr[offset + 1 : offset + 1 + self.K] # checksum self.TCK: int | None = None self.checksumOK: bool | None = None self.hasChecksum = len(self.atr) == offset + 1 + self.K + 1 if self.hasChecksum: self.TCK = self.atr[-1] self.checksumOK = functools.reduce(operator.xor, self.atr[1:]) == 0 # clock-rate conversion factor self.FI: int | None = None if self.TA[0] is not None: self.FI = self.TA[0] >> 4 & 0x0F # bit-rate adjustment factor self.DI: int | None = None if self.TA[0] is not None: self.DI = self.TA[0] & 0x0F # maximum programming current factor self.II: int | None = None if self.TB[0] is not None: self.II = self.TB[0] >> 5 & 0x03 # programming voltage factor self.PI1: int | None = None if self.TB[0] is not None: self.PI1 = self.TB[0] & 0x1F # extra guard time self.N = self.TC[0] @property def hasTA(self) -> list[bool]: """Deprecated. Replace usage with `ATR.TA[i] is not None`.""" warnings.warn("Replace usage with `ATR.TA[i] is not None`", DeprecationWarning) return [ta is not None for ta in self.TA] @property def hasTB(self) -> list[bool]: """Deprecated. Replace usage with `ATR.TB[i] is not None`.""" warnings.warn("Replace usage with `ATR.TB[i] is not None`", DeprecationWarning) return [tb is not None for tb in self.TB] @property def hasTC(self) -> list[bool]: """Deprecated. Replace usage with `ATR.TC[i] is not None`.""" warnings.warn("Replace usage with `ATR.TC[i] is not None`", DeprecationWarning) return [tc is not None for tc in self.TC] @property def hasTD(self) -> list[bool]: """Deprecated. Replace usage with `ATR.TD[i] is not None`.""" warnings.warn("Replace usage with `ATR.TD[i] is not None`", DeprecationWarning) return [td is not None for td in self.TD] def getChecksum(self) -> int | None: """Return the checksum of the ATR. Checksum is mandatory only for T=1.""" return self.TCK def getHistoricalBytes(self) -> list[int]: """Return historical bytes.""" return self.historicalBytes def getHistoricalBytesCount(self) -> int: """Return count of historical bytes.""" return len(self.historicalBytes) def getInterfaceBytesCount(self) -> int: """Return count of interface bytes.""" return self.interfaceBytesCount def getTA1(self) -> int | None: """Return TA1 byte.""" return self.TA[0] def getTB1(self) -> int | None: """Return TB1 byte.""" return self.TB[0] def getTC1(self) -> int | None: """Return TC1 byte.""" return self.TC[0] def getTD1(self) -> int | None: """Return TD1 byte.""" return self.TD[0] def getBitRateFactor(self) -> int | str: """Return bit rate factor.""" if self.DI is not None: return ATR.bitratefactor[self.DI] return 1 def getClockRateConversion(self) -> int | str: """Return clock rate conversion.""" if self.FI is not None: return ATR.clockrateconversion[self.FI] return 372 def getProgrammingCurrent(self) -> int | str: """Return maximum programming current.""" if self.II is not None: return ATR.currenttable[self.II] return 50 def getProgrammingVoltage(self) -> int: """Return programming voltage.""" if self.PI1 is not None: return 5 * (1 + self.PI1) return 5 def getGuardTime(self) -> int | None: """Return extra guard time.""" return self.N def getSupportedProtocols(self) -> dict[str, bool]: """Returns a dictionary of supported protocols.""" protocols: dict[str, bool] = {} for td in self.TD: if td is not None: protocols[f"T={td & 0x0F}"] = True if self.TD[0] is None: protocols["T=0"] = True return protocols def isT0Supported(self) -> bool: """Return True if T=0 is supported.""" return "T=0" in self.getSupportedProtocols() def isT1Supported(self) -> bool: """Return True if T=1 is supported.""" return "T=1" in self.getSupportedProtocols() def isT15Supported(self) -> bool: """Return True if T=15 is supported.""" return "T=15" in self.getSupportedProtocols() def render(self) -> str: """Render the ATR to a readable format.""" lines: list[str] = [] enumerated_tx_values = enumerate(zip(self.TA, self.TB, self.TC, self.TD), 1) for i, (ta, tb, tc, td) in enumerated_tx_values: if ta is not None: lines.append(f"TA{i}: {ta:x}") if tb is not None: lines.append(f"TB{i}: {tb:x}") if tc is not None: lines.append(f"TC{i}: {tc:x}") if td is not None: lines.append(f"TD{i}: {td:x}") lines.append(f"supported protocols {','.join(self.getSupportedProtocols())}") lines.append(f"T=0 supported: {self.isT0Supported()}") lines.append(f"T=1 supported: {self.isT1Supported()}") if self.getChecksum() is not None: lines.append(f"checksum: {self.getChecksum()}") lines.append(f"\tclock rate conversion factor: {self.getClockRateConversion()}") lines.append(f"\tbit rate adjustment factor: {self.getBitRateFactor()}") lines.append(f"\tmaximum programming current: {self.getProgrammingCurrent()}") lines.append(f"\tprogramming voltage: {self.getProgrammingVoltage()}") lines.append(f"\tguard time: {self.getGuardTime()}") lines.append(f"nb of interface bytes: {self.getInterfaceBytesCount()}") lines.append(f"nb of historical bytes: {self.getHistoricalBytesCount()}") return "\n".join(lines) def dump(self) -> None: """Deprecated. Replace usage with `print(ATR.render())`""" warnings.warn("Replace usage with `print(ATR.render())`", DeprecationWarning) print(self.render()) def __str__(self) -> str: """Render the ATR as a space-separated string of uppercase hexadecimal pairs.""" return bytes(self.atr).hex(" ").upper() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/AbstractCardRequest.py0000644000076500000240000000653714677317744022040 0ustar00rousseaustaff"""AbstractCardRequest class. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.System from smartcard.CardType import AnyCardType from smartcard.PassThruCardService import PassThruCardService class AbstractCardRequest: """The base class for xxxCardRequest classes. A CardRequest is used for waitForCard() invocations and specifies what kind of smart card an application is waited for.""" def __init__( self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1, ): """Construct new CardRequest. @param newcardonly: if True, request a new card; default is False, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card; default is to consider all readers @param cardType: the L{smartcard.CardType.CardType} to wait for; default is L{smartcard.CardType.AnyCardType}, i.e. the request will succeed with any card @param cardServiceClass: the specific card service class to create and bind to the card;default is to create and bind a L{smartcard.PassThruCardService} @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second; to wait forever, set timeout to None """ self.newcardonly = newcardonly self.readersAsked = readers self.cardType = cardType self.cardServiceClass = cardServiceClass self.timeout = timeout # if no CardType requested, use AnyCardType if self.cardType is None: self.cardType = AnyCardType() # if no card service requested, use pass-thru card service if self.cardServiceClass is None: self.cardServiceClass = PassThruCardService def getReaders(self): """Returns the list or readers on which to wait for cards.""" # if readers not given, use all readers if self.readersAsked is None: return smartcard.System.readers() else: return self.readersAsked def waitforcard(self): """Wait for card insertion and returns a card service.""" pass def waitforcardevent(self): """Wait for card insertion or removal.""" pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Card.py0000644000076500000240000000504214677317744016771 0ustar00rousseaustaff"""Card class. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.reader.Reader import Reader from smartcard.System import readers from smartcard.util import toHexString class Card: """Card class.""" def __init__(self, reader, atr): """Card constructor. @param reader: reader in which the card is inserted @param atr: ATR of the card""" self.reader = reader self.atr = atr def __repr__(self): """Return a string representing the Card (atr and reader concatenation).""" return toHexString(self.atr) + " / " + str(self.reader) def __eq__(self, other): """Return True if self==other (same reader and same atr). Return False otherwise.""" if isinstance(other, Card): return self.atr == other.atr and repr(self.reader) == repr(other.reader) else: return False def __ne__(self, other): """Return True if self!=other (same reader and same atr).Returns False otherwise.""" return not self.__eq__(other) def __hash__(self): """Returns a hash value for this object (str(self) is unique).""" return hash(str(self)) def createConnection(self): """Return a CardConnection to the Card object.""" readerobj = None if isinstance(self.reader, Reader): readerobj = self.reader elif type(self.reader) == str: for reader in readers(): if self.reader == str(reader): readerobj = reader if readerobj: return readerobj.createConnection() else: # raise CardConnectionException( # 'not a valid reader: ' + str(self.reader)) return None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/CardConnection.py0000644000076500000240000002142714703301034020765 0ustar00rousseaustaff"""The CardConnection abstract class manages connections with a card and apdu transmission. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionEvent import CardConnectionEvent from smartcard.Observer import Observable class CardConnection(Observable): """Card connection abstract class.""" T0_protocol = 0x00000001 """ protocol T=0 """ T1_protocol = 0x00000002 """ protocol T=1 """ RAW_protocol = 0x00010000 """ protocol RAW (direct access to the reader) """ T15_protocol = 0x00000008 """ protocol T=15 """ def __init__(self, reader): """Construct a new card connection. @param reader: name of the reader in which the smartcard to connect to is located. """ Observable.__init__(self) self.reader = reader """ reader name """ self.errorcheckingchain = None """ see L{setErrorCheckingChain} """ self.defaultprotocol = CardConnection.T0_protocol | CardConnection.T1_protocol """ see L{setProtocol} and L{getProtocol} """ def __del__(self): """Connect to card.""" pass def addSWExceptionToFilter(self, exClass): """Add a status word exception class to be filtered. @param exClass: the class to filter, e.g. L{smartcard.sw.SWExceptions.WarningProcessingException} Filtered exceptions will not be raised when encountered in the error checking chain.""" if self.errorcheckingchain is not None: self.errorcheckingchain[0].addFilterException(exClass) def addObserver(self, observer): """Add a L{CardConnection} observer.""" Observable.addObserver(self, observer) def deleteObserver(self, observer): """Remove a L{CardConnection} observer.""" Observable.deleteObserver(self, observer) def connect(self, protocol=None, mode=None, disposition=None): """Connect to card. @param protocol: a bit mask of the protocols to use, from L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, L{CardConnection.RAW_protocol}, L{CardConnection.T15_protocol} @param mode: C{smartcard.scard.SCARD_SHARE_SHARED} (default), C{smartcard.scard.SCARD_SHARE_EXCLUSIVE} or C{smartcard.scard.SCARD_SHARE_DIRECT} @param disposition: C{smartcard.scard.SCARD_LEAVE_CARD} (default), C{smartcard.scard.SCARD_RESET_CARD}, C{smartcard.scard.SCARD_UNPOWER_CARD} or C{smartcard.scard.SCARD_EJECT_CARD} """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent("connect")) def reconnect(self, protocol=None, mode=None, disposition=None): """Reconnect to card. @param protocol: a bit mask of the protocols to use, from L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, L{CardConnection.RAW_protocol}, L{CardConnection.T15_protocol} @param mode: C{smartcard.scard.SCARD_SHARE_SHARED} (default), C{smartcard.scard.SCARD_SHARE_EXCLUSIVE} or C{smartcard.scard.SCARD_SHARE_DIRECT} @param disposition: C{smartcard.scard.SCARD_LEAVE_CARD}, C{smartcard.scard.SCARD_RESET_CARD} (default), C{smartcard.scard.SCARD_UNPOWER_CARD} or C{smartcard.scard.SCARD_EJECT_CARD} """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent("reconnect")) def disconnect(self): """Disconnect from card.""" Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent("disconnect")) def getATR(self): """Return card ATR""" pass def getProtocol(self): """Return bit mask for the protocol of connection, or None if no protocol set. The return value is a bit mask of L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, L{CardConnection.RAW_protocol}, L{CardConnection.T15_protocol} """ return self.defaultprotocol def getReader(self): """Return card connection reader""" return self.reader def setErrorCheckingChain(self, errorcheckingchain): """Add an error checking chain. @param errorcheckingchain: a L{smartcard.sw.ErrorCheckingChain} object The error checking strategies in errorchecking chain will be tested with each received response APDU, and a L{smartcard.sw.SWExceptions.SWException} will be raised upon error.""" self.errorcheckingchain = errorcheckingchain def setProtocol(self, protocol): """Set protocol for card connection. @param protocol: a bit mask of L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, L{CardConnection.RAW_protocol}, L{CardConnection.T15_protocol} >>> setProtocol(CardConnection.T1_protocol | CardConnection.T0_protocol) """ self.defaultprotocol = protocol def transmit(self, command, protocol=None): """Transmit an apdu. Internally calls L{doTransmit()} class method and notify observers upon command/response APDU events. Subclasses must override the L{doTransmit()} class method. @param command: list of bytes to transmit @param protocol: the transmission protocol, from L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, or L{CardConnection.RAW_protocol} """ Observable.setChanged(self) Observable.notifyObservers( self, CardConnectionEvent("command", [command, protocol]) ) data, sw1, sw2 = self.doTransmit(command, protocol) Observable.setChanged(self) Observable.notifyObservers( self, CardConnectionEvent("response", [data, sw1, sw2]) ) if self.errorcheckingchain is not None: self.errorcheckingchain[0](data, sw1, sw2) return data, sw1, sw2 def doTransmit(self, command, protocol): """Performs the command APDU transmission. Subclasses must override this method for implementing apdu transmission.""" return [], 0, 0 def control(self, controlCode, command=None): """Send a control command and buffer. Internally calls L{doControl()} class method and notify observers upon command/response events. Subclasses must override the L{doControl()} class method. @param controlCode: command code @param command: list of bytes to transmit """ if command is None: command = [] Observable.setChanged(self) Observable.notifyObservers( self, CardConnectionEvent("command", [controlCode, command]) ) data = self.doControl(controlCode, command) Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent("response", data)) if self.errorcheckingchain is not None: self.errorcheckingchain[0](data) return data def doControl(self, controlCode, command): """Performs the command control. Subclasses must override this method for implementing control.""" return [] def getAttrib(self, attribId): """return the requested attribute @param attribId: attribute id like C{smartcard.scard.SCARD_ATTR_VENDOR_NAME} """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent("attrib", [attribId])) data = self.doGetAttrib(attribId) if self.errorcheckingchain is not None: self.errorcheckingchain[0](data) return data def doGetAttrib(self, attribId): """Performs the command get attrib. Subclasses must override this method for implementing get attrib.""" return [] def __enter__(self): """Enter the runtime context.""" return self def __exit__(self, type, value, traceback): """Exit the runtime context trying to disconnect.""" self.disconnect() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/CardConnectionDecorator.py0000644000076500000240000000657714703301034022641 0ustar00rousseaustaff"""The CardConnectionDecorator is a Decorator around the CardConnection abstract class, and allows dynamic addition of features to the CardConnection, e.g. implementing a secure channel.. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnection import CardConnection class CardConnectionDecorator(CardConnection): """Card connection decorator class.""" def __init__(self, cardConnectionComponent): """Construct a new card connection decorator. CardConnectionComponent: CardConnection component to decorate """ self.component = cardConnectionComponent def addSWExceptionToFilter(self, exClass): """call inner component addSWExceptionToFilter""" self.component.addSWExceptionToFilter(exClass) def addObserver(self, observer): """call inner component addObserver""" self.component.addObserver(observer) def deleteObserver(self, observer): """call inner component deleteObserver""" self.component.deleteObserver(observer) def connect(self, protocol=None, mode=None, disposition=None): """call inner component connect""" self.component.connect(protocol, mode, disposition) def reconnect(self, protocol=None, mode=None, disposition=None): """call inner component reconnect""" self.component.reconnect(protocol, mode, disposition) def disconnect(self): """call inner component disconnect""" self.component.disconnect() def getATR(self): """call inner component getATR""" return self.component.getATR() def getProtocol(self): """call inner component getProtocol""" return self.component.getProtocol() def getReader(self): """call inner component getReader""" return self.component.getReader() def setErrorCheckingChain(self, errorcheckingchain): """call inner component setErrorCheckingChain""" self.component.setErrorCheckingChain(errorcheckingchain) def setProtocol(self, protocol): """call inner component setProtocol""" return self.component.setProtocol(protocol) def transmit(self, command, protocol=None): """call inner component transmit""" return self.component.transmit(command, protocol) def control(self, controlCode, command=None): """call inner component control""" if command is None: command = [] return self.component.control(controlCode, command) def getAttrib(self, attribId): """call inner component getAttrib""" return self.component.getAttrib(attribId) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/CardConnectionEvent.py0000644000076500000240000000270314677317744022014 0ustar00rousseaustaff"""The CardConnectionEvent is sent to CardConnectionObserver objects when a CardConnection event occurs. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class CardConnectionEvent: """Base class for card connection events. This event is notified by CardConnection objects.""" def __init__(self, type, args=None): """ @param type: 'connect', 'reconnect', 'disconnect', 'command', 'response' @param args: None for 'connect', 'reconnect' or 'disconnect' command APDU byte list for 'command' [response data, sw1, sw2] for 'response' """ self.type = type self.args = args ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/CardConnectionObserver.py0000644000076500000240000000465214677317744022527 0ustar00rousseaustaff"""CardConnectionObserver interface. CardConnectionObserver is a base class for objects that are to be notified upon CardConnection events. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.Observer import Observer from smartcard.util import toHexString # ReaderObserver interface class CardConnectionObserver(Observer): """ CardConnectionObserver is a base class for objects that are to be notified upon L{CardConnection} events. """ def update(self, cardconnection, cardconnectionevent): """Called upon CardConnection event. @param cardconnection: the observed card connection object @param cardconnectionevent: the CardConnectionEvent sent by the connection """ pass class ConsoleCardConnectionObserver(CardConnectionObserver): def update(self, cardconnection, ccevent): if "connect" == ccevent.type: print("connecting to " + cardconnection.getReader()) elif "reconnect" == ccevent.type: print("reconnecting to " + cardconnection.getReader()) elif "disconnect" == ccevent.type: print("disconnecting from " + cardconnection.getReader()) elif "command" == ccevent.type: print("> " + toHexString(ccevent.args[0])) elif "response" == ccevent.type: if [] == ccevent.args[0]: print("< [] %02X %02X" % tuple(ccevent.args[-2:])) else: print( "< " + toHexString(ccevent.args[0]) + " " + "%02X %02X" % tuple(ccevent.args[-2:]) ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736282587.0 pyscard-2.2.1/src/smartcard/CardMonitoring.py0000644000076500000240000002021314737310733021020 0ustar00rousseaustaff"""Smart card insertion/removal monitoring classes. CardObserver is a base class for objects that are to be notified upon smart card insertion/removal. CardMonitor is a singleton object notifying registered CardObservers upon reader insertion/removal. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import traceback from threading import Event, Lock, Thread from time import sleep from smartcard.CardRequest import CardRequest from smartcard.Exceptions import CardRequestTimeoutException, SmartcardException from smartcard.Observer import Observable, Observer from smartcard.scard import SCARD_E_NO_SERVICE _START_ON_DEMAND_ = False # CardObserver interface class CardObserver(Observer): """ CardObserver is a base abstract class for objects that are to be notified upon smart card insertion / removal. """ def __init__(self): pass def update(self, observable, handlers): """Called upon smart card insertion / removal. @param observable: @param handlers: - addedcards: list of inserted smart cards causing notification - removedcards: list of removed smart cards causing notification """ pass class CardMonitor: """Class that monitors smart card insertion / removals. and notify observers note: a card monitoring thread will be running as long as the card monitor has observers, or CardMonitor.stop() is called. Do not forget to delete all your observers by calling L{deleteObserver}, or your program will run forever... Uses the singleton pattern from Thinking in Python Bruce Eckel, http://mindview.net/Books/TIPython to make sure there is only one L{CardMonitor}. """ class __CardMonitorSingleton(Observable): """The real smart card monitor class. A single instance of this class is created by the public CardMonitor class. """ def __init__(self): Observable.__init__(self) if _START_ON_DEMAND_: self.rmthread = None else: self.rmthread = CardMonitoringThread(self) def addObserver(self, observer): """Add an observer. We only start the card monitoring thread when there are observers. """ Observable.addObserver(self, observer) if _START_ON_DEMAND_: if self.countObservers() > 0 and self.rmthread is None: self.rmthread = CardMonitoringThread(self) else: observer.update(self, (self.rmthread.cards, [])) def deleteObserver(self, observer): """Remove an observer. We delete the L{CardMonitoringThread} reference when there are no more observers. """ Observable.deleteObserver(self, observer) if _START_ON_DEMAND_: if self.countObservers() == 0: if self.rmthread is not None: self.rmthread.stop() self.rmthread.join() self.rmthread = None def __str__(self): return "CardMonitor" # the singleton instance = None lock = Lock() def __init__(self): with CardMonitor.lock: if not CardMonitor.instance: CardMonitor.instance = CardMonitor.__CardMonitorSingleton() def __getattr__(self, name): return getattr(self.instance, name) class CardMonitoringThread: """Card insertion thread. This thread waits for card insertion. """ class __CardMonitoringThreadSingleton(Thread): """The real card monitoring thread class. A single instance of this class is created by the public L{CardMonitoringThread} class. """ def __init__(self, observable): Thread.__init__(self) self.observable = observable self.stopEvent = Event() self.stopEvent.clear() self.cards = [] self.daemon = True # the actual monitoring thread def run(self): """Runs until stopEvent is notified, and notify observers of all card insertion/removal. """ self.cardrequest = CardRequest(timeout=60) while self.stopEvent.is_set() != 1: try: currentcards = self.cardrequest.waitforcardevent() addedcards = [] for card in currentcards: if not self.cards.__contains__(card): addedcards.append(card) removedcards = [] for card in self.cards: if not currentcards.__contains__(card): removedcards.append(card) if addedcards != [] or removedcards != []: self.cards = currentcards self.observable.setChanged() self.observable.notifyObservers((addedcards, removedcards)) except CardRequestTimeoutException: pass except SmartcardException as exc: # FIXME Tighten the exceptions caught by this block traceback.print_exc() # Most likely raised during interpreter shutdown due # to unclean exit which failed to remove all observers. # To solve this, we set the stop event and pass the # exception to let the thread finish gracefully. if exc.hresult == SCARD_E_NO_SERVICE: self.stopEvent.set() # stop the thread by signaling stopEvent def stop(self): self.stopEvent.set() # the singleton instance = None def __init__(self, observable): if not CardMonitoringThread.instance: CardMonitoringThread.instance = ( CardMonitoringThread.__CardMonitoringThreadSingleton(observable) ) CardMonitoringThread.instance.start() def join(self, *args, **kwargs): if self.instance: self.instance.join(*args, **kwargs) CardMonitoringThread.instance = None def __getattr__(self, name): if self.instance: return getattr(self.instance, name) if __name__ == "__main__": print("insert or remove cards in the next 10 seconds") # a simple card observer that prints added/removed cards class printobserver(CardObserver): def __init__(self, obsindex): self.obsindex = obsindex def update(self, observable, handlers): addedcards, removedcards = handlers print("%d - added: %s" % (self.obsindex, str(addedcards))) print("%d - removed: %s" % (self.obsindex, str(removedcards))) class testthread(Thread): def __init__(self, obsindex): Thread.__init__(self) self.readermonitor = CardMonitor() self.obsindex = obsindex self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex) self.readermonitor.addObserver(self.observer) sleep(10) self.readermonitor.deleteObserver(self.observer) t1 = testthread(1) t2 = testthread(2) t1.start() t2.start() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/CardRequest.py0000644000076500000240000000636414677317744020352 0ustar00rousseaustaff"""Smartcard CardRequest. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.pcsc.PCSCCardRequest import PCSCCardRequest class CardRequest: """A CardRequest is used for waitForCard() invocations and specifies what kind of smart card an application is waited for. """ def __init__( self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1, ): """Construct new CardRequest. @param newcardonly: if True, request a new card default is False, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card default is to consider all readers @param cardType: the L{smartcard.CardType.CardType} to wait for; default is L{smartcard.CardType.AnyCardType}, i.e. the request will succeed with any card @param cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a L{smartcard.PassThruCardService} @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to None """ self.pcsccardrequest = PCSCCardRequest( newcardonly, readers, cardType, cardServiceClass, timeout ) def getReaders(self): """Returns the list or readers on which to wait for cards.""" return self.pcsccardrequest.getReaders() def waitforcard(self): """Wait for card insertion and returns a card service.""" return self.pcsccardrequest.waitforcard() def waitforcardevent(self): """Wait for card insertion or removal.""" return self.pcsccardrequest.waitforcardevent() if __name__ == "__main__": """Small sample illustrating the use of CardRequest.py.""" from smartcard.util import toHexString print("Insert a new card within 10 seconds") cr = CardRequest(timeout=10, newcardonly=True) cs = cr.waitforcard() cs.connection.connect() print(cs.connection.getReader() + " " + toHexString(cs.connection.getATR())) cs.connection.disconnect() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728488499.0 pyscard-2.2.1/src/smartcard/CardService.py0000644000076500000240000000437214701522063020273 0ustar00rousseaustaff"""Card service abstract class. A card service is a class providings specific smart card functionality, e.g. a GSM file system or an Open Platform loader. CardService is an abstract class from which concrete card services are derived. A concrete card service is almost always smart card operating system specific. The card service performs its specific smart card functionality by accessing the smartcard with a CardConnection. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * class CardService: """Card service abstract class.""" def __init__(self, connection, cardname=None): """Construct a new card service and bind to a smart card in a reader. @param connection: the CardConnection used to access the smart card """ self.connection = connection self.cardname = cardname def __del__(self): """Destructor. Disconnect card and destroy card service resources.""" self.connection.disconnect() @staticmethod def supports(cardname): pass if __name__ == "__main__": """Small sample illustrating the use of CardService.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.System import readers cc = readers()[0].createConnection() cs = CardService(cc) cs.connection.connect() data, sw1, sw2 = cs.connection.transmit(SELECT + DF_TELECOM) print(f"{sw1:X} {sw2:X}") cs.connection.disconnect() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/CardType.py0000644000076500000240000000715714677317744017644 0ustar00rousseaustaff"""Abstract CarType. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.Exceptions import InvalidATRMaskLengthException from smartcard.System import readers from smartcard.util import toHexString class CardType: """Abstract base class for CardTypes. Known subclasses: L{smartcard.CardType.AnyCardType} L{smartcard.CardType.ATRCardType}.""" def __init__(self): """CardType constructor.""" pass def matches(self, atr, reader=None): """Returns true if atr and card connected match the L{CardType}. @param atr: the atr to check for matching @param reader: the reader (optional); default is None The reader can be used in some subclasses to do advanced matching that require connecting to the card.""" pass class AnyCardType(CardType): """The AnyCardType matches any card.""" def __init__(self): super().__init__() def matches(self, atr, reader=None): """Always returns true, i.e. AnyCardType matches any card. @param atr: the atr to check for matching @param reader: the reader (optional); default is None""" return True class ATRCardType(CardType): """The ATRCardType defines a card from an ATR and a mask.""" def __init__(self, atr, mask=None): """ATRCardType constructor. @param atr: the ATR of the CardType @param mask: an optional mask to be applied to the ATR for L{CardType} matching default is None """ super().__init__() self.atr = list(atr) self.mask = mask if mask is None: self.maskedatr = self.atr else: if len(self.atr) != len(self.mask): raise InvalidATRMaskLengthException(toHexString(mask)) self.maskedatr = list(map(lambda x, y: x & y, self.atr, self.mask)) def matches(self, atr, reader=None): """Returns true if the atr matches the masked CardType atr. @param atr: the atr to check for matching @param reader: the reader (optional); default is None When atr is compared to the CardType ATR, matches returns true if and only if CardType.atr & CardType.mask = atr & CardType.mask, where & is the bitwise logical AND.""" if len(atr) != len(self.atr): return not True if self.mask is not None: maskedatr = list(map(lambda x, y: x & y, list(atr), self.mask)) else: maskedatr = atr return self.maskedatr == maskedatr if __name__ == "__main__": """Small sample illustrating the use of CardType.py.""" r = readers() print(r) connection = r[0].createConnection() connection.connect() atrct = ATRCardType([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) print(atrct.matches(connection.getATR())) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.5892704 pyscard-2.2.1/src/smartcard/Examples/0000755000076500000240000000000014740753203017304 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6199088 pyscard-2.2.1/src/smartcard/Examples/framework/0000755000076500000240000000000014740753203021301 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_ATR.py0000755000076500000240000000313614677317744023667 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script for the smartcard.ATR utility class. __author__ = "https://www.gemalto.com/" Copyright 2001-2009 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.ATR import ATR from smartcard.util import toHexString atr = ATR( [ 0x3B, 0x9E, 0x95, 0x80, 0x1F, 0xC3, 0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD, 0xB9, ] ) print(atr) print("historical bytes: ", toHexString(atr.getHistoricalBytes())) print("checksum: ", "0x%X" % atr.getChecksum()) print("checksum OK: ", atr.checksumOK) print("T0 supported: ", atr.isT0Supported()) print("T1 supported: ", atr.isT1Supported()) print("T15 supported: ", atr.isT15Supported()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_CardConnectionDecorator.py0000755000076500000240000000731114677317744027774 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that illustrates card connection decorators. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.util import toHexString # define two custom CardConnectionDecorator # the decorators are very simple, just to illustrate # shortly how several decorators can be added to the # card connection class SecureChannelConnection(CardConnectionDecorator): """This decorator is a mockup of secure channel connection. It merely pretends to cypher/uncypher upon apdu transmission.""" def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def cypher(self, data): """Cypher mock-up; you would include the secure channel logics here.""" print("cyphering", toHexString(data)) return data def uncypher(self, data): """Uncypher mock-up; you would include the secure channel logics here.""" print("uncyphering", toHexString(data)) return data def transmit(self, command, protocol=None): """Cypher/uncypher APDUs before transmission""" cypheredbytes = self.cypher(command) data, sw1, sw2 = CardConnectionDecorator.transmit(self, cypheredbytes, protocol) if [] != data: data = self.uncypher(data) return data, sw1, sw2 class FakeATRConnection(CardConnectionDecorator): """This decorator changes the fist byte of the ATR. This is just an example to show that decorators can be nested.""" def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def getATR(self): """Replace first BYTE of ATR by 3F""" atr = CardConnectionDecorator.getATR(self) return [0x3F] + atr[1:] # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=1.5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # attach our decorator cardservice.connection = FakeATRConnection( SecureChannelConnection(cardservice.connection) ) # connect to the card and perform a few transmits cardservice.connection.connect() print("ATR", toHexString(cardservice.connection.getATR())) apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_ConsoleConnectionTracer.py0000755000076500000240000000354714677317744030032 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that monitors card connection events. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=1.5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_CustomCardType.py0000755000076500000240000000327114677317744026147 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that demonstrates how to create a custom CardType. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardRequest import CardRequest from smartcard.CardType import CardType from smartcard.util import toHexString class DCCardType(CardType): # define our custom CardType # this card type defines direct convention card # (first atr byte equal to 0x3b) def matches(self, atr, reader=None): return atr[0] == 0x3B # request a direct convention card cardtype = DCCardType() cardrequest = CardRequest(timeout=1, cardType=cardtype) cardservice = cardrequest.waitforcard() # connect and print atr and reader cardservice.connection.connect() print(toHexString(cardservice.connection.getATR())) print(cardservice.connection.getReader()) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_CustomErrorChecker.py0000755000076500000240000000563214677317744027015 0ustar00rousseaustaff#! /usr/bin/env python3 """Sample script for APDU error checking with a custom error checker. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.sw.ErrorChecker import ErrorChecker from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.SWExceptions import SWException class MyErrorChecker(ErrorChecker): """Our custom error checker that will except if 0x61 sw1: raise SWException(data, sw1, sw2) # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] if __name__ == "__main__": print("Insert a card within 10 seconds") print("Cards without a DF_TELECOM will except") # request any card cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # our error checking chain errorchain = [] errorchain = [ErrorCheckingChain([], MyErrorChecker())] cardservice.connection.setErrorCheckingChain(errorchain) # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # send a few apdus; exceptions will occur upon errors cardservice.connection.connect() try: SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: GET_RESPONSE = [0xA0, 0xC0, 00, 00] apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) except SWException as e: print(e, f"{e.sw1:x} {e.sw2:x}") cardservice.connection.disconnect() import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_ErrorChecking.py0000755000076500000240000000605114677317744025765 0ustar00rousseaustaff#! /usr/bin/env python3 """Sample script for APDU error checking. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker from smartcard.sw.SWExceptions import SWException, WarningProcessingException # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] if __name__ == "__main__": print("Insert a card within 10 seconds") print("Cards without a DF_TELECOM will except") # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # use ISO7816-4 and ISO7816-8 error checking strategy # first check iso7816_8 errors, then iso7816_4 errors errorchain = [] errorchain = [ErrorCheckingChain(errorchain, ISO7816_9ErrorChecker())] errorchain = [ErrorCheckingChain(errorchain, ISO7816_8ErrorChecker())] errorchain = [ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker())] cardservice.connection.setErrorCheckingChain(errorchain) # filter Warning Processing Exceptions (sw1 = 0x62 or 0x63) cardservice.connection.addSWExceptionToFilter(WarningProcessingException) # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() try: apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) except SWException as e: print(str(e)) cardservice.connection.disconnect() import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_ExclusiveCardConnection.py0000755000076500000240000000472314677317744030025 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that illustrates exclusive card connection decorators. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.ExclusiveConnectCardConnection import ExclusiveConnectCardConnection from smartcard.ExclusiveTransmitCardConnection import ExclusiveTransmitCardConnection from smartcard.util import toHexString # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # attach our decorator cardservice.connection = ExclusiveTransmitCardConnection( ExclusiveConnectCardConnection(cardservice.connection) ) # connect to the card and perform a few transmits cardservice.connection.connect() print("ATR", toHexString(cardservice.connection.getATR())) try: # lock for initiating transaction cardservice.connection.lock() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) finally: # unlock connection at the end of the transaction cardservice.connection.unlock() import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_MonitorCards.py0000755000076500000240000000405114677317744025642 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that monitors smartcard insertion/removal. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from time import sleep from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import toHexString # a simple card observer that prints inserted/removed cards class PrintObserver(CardObserver): """A simple card observer that is notified when cards are inserted/removed from the system and prints the list of cards """ def update(self, observable, actions): (addedcards, removedcards) = actions for card in addedcards: print("+Inserted: ", toHexString(card.atr)) for card in removedcards: print("-Removed: ", toHexString(card.atr)) if __name__ == "__main__": print("Insert or remove a smartcard in the system.") print("This program will exit in 10 seconds") print("") cardmonitor = CardMonitor() cardobserver = PrintObserver() cardmonitor.addObserver(cardobserver) sleep(10) # don't forget to remove observer, or the # monitor will poll forever... cardmonitor.deleteObserver(cardobserver) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_MonitorCardsAndTransmit.py0000755000076500000240000000545314677317744030016 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that monitors smartcard insertion/removal and select DF_TELECOM on inserted cards __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from time import sleep from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import toHexString # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # a simple card observer that tries to select DF_TELECOM on an inserted card class selectDFTELECOMObserver(CardObserver): """A simple card observer that is notified when cards are inserted/removed from the system and prints the list of cards """ def __init__(self): self.observer = ConsoleCardConnectionObserver() def update(self, observable, actions): (addedcards, removedcards) = actions for card in addedcards: print("+Inserted: ", toHexString(card.atr)) card.connection = card.createConnection() card.connection.connect() card.connection.addObserver(self.observer) apdu = SELECT + DF_TELECOM response, sw1, sw2 = card.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = card.connection.transmit(apdu) for card in removedcards: print("-Removed: ", toHexString(card.atr)) if __name__ == "__main__": print("Insert or remove a SIM card in the system.") print("This program will exit in 60 seconds") print("") cardmonitor = CardMonitor() selectobserver = selectDFTELECOMObserver() cardmonitor.addObserver(selectobserver) sleep(60) # don't forget to remove observer, or the # monitor will poll forever... cardmonitor.deleteObserver(selectobserver) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_MonitorReaders.py0000755000076500000240000000361214677317744026175 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that monitors smartcard readers. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from time import sleep from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver class printobserver(ReaderObserver): """A simple reader observer that is notified when readers are added/removed from the system and prints the list of readers """ def update(self, observable, actions): (addedreaders, removedreaders) = actions print("Added readers", addedreaders) print("Removed readers", removedreaders) if __name__ == "__main__": print("Add or remove a smartcard reader to the system.") print("This program will exit in 10 seconds") print("") readermonitor = ReaderMonitor() readerobserver = printobserver() readermonitor.addObserver(readerobserver) sleep(10) # don't forget to remove observer, or the # monitor will poll forever... readermonitor.deleteObserver(readerobserver) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_TransmitCardObserver.py0000755000076500000240000000443714677317744027351 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that monitors card insertions, connects to cards and transmit an apdu __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from time import sleep from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import * # replace by your favourite apdu SELECT_DF_TELECOM = [0xA0, 0xA4, 0x00, 0x00, 0x02, 0x7F, 0x10] class transmitobserver(CardObserver): """A card observer that is notified when cards are inserted/removed from the system, connects to cards and SELECT DF_TELECOM""" def __init__(self): self.cards = [] def update(self, observable, actions): (addedcards, removedcards) = actions for card in addedcards: if card not in self.cards: self.cards += [card] print("+Inserted: ", toHexString(card.atr)) card.connection = card.createConnection() card.connection.connect() response, sw1, sw2 = card.connection.transmit(SELECT_DF_TELECOM) print(f"{sw1:.2x} {sw2:.2x}") for card in removedcards: print("-Removed: ", toHexString(card.atr)) if card in self.cards: self.cards.remove(card) if __name__ == "__main__": print("Insert or remove a smartcard in the system.") print("This program will exit in 100 seconds") print("") cardmonitor = CardMonitor() cardobserver = transmitobserver() cardmonitor.addObserver(cardobserver) sleep(100) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_apduTracerInterpreter.py0000755000076500000240000000600614677317744027556 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that defines a custom card connection observer. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionObserver import CardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.util import toHexString class TracerAndSELECTInterpreter(CardConnectionObserver): """This observer will interprer SELECT and GET RESPONSE bytes and replace them with a human readable string.""" def update(self, cardconnection, ccevent): if "connect" == ccevent.type: print("connecting to " + cardconnection.getReader()) elif "disconnect" == ccevent.type: print("disconnecting from " + cardconnection.getReader()) elif "command" == ccevent.type: str = toHexString(ccevent.args[0]) str = str.replace("A0 A4 00 00 02", "SELECT") str = str.replace("A0 C0 00 00", "GET RESPONSE") print(">", str) elif "response" == ccevent.type: if [] == ccevent.args[0]: print("< []", "%-2X %-2X" % tuple(ccevent.args[-2:])) else: print( "<", toHexString(ccevent.args[0]), "%-2X %-2X" % tuple(ccevent.args[-2:]), ) # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # we request any type and wait for 10s for card insertion cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # create an instance of our observer and attach to the connection observer = TracerAndSELECTInterpreter() cardservice.connection.addObserver(observer) # connect and send APDUs # the observer will trace on the console cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) else: print("no DF_TELECOM") import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/framework/sample_toHexString.py0000755000076500000240000000442014677317744025514 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script to illustrate toHexString() utility method __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.util import * print(40 * "-") data = [59, 101, 0, 0, 156, 17, 1, 1, 3] print("data = [59, 101, 0, 0, 156, 17, 1, 1, 3]") print("toHexString(data) =", toHexString(data)) print("toHexString(data, COMMA) =", toHexString(data, COMMA)) print("toHexString(data, PACK) =", toHexString(data, PACK)) print("toHexString(data, HEX) =", toHexString(data, HEX)) print("toHexString(data, HEX | COMMA) =", toHexString(data, HEX | COMMA)) print("toHexString(data, HEX | UPPERCASE) =", toHexString(data, HEX | UPPERCASE)) print( "toHexString(data, HEX | UPPERCASE | COMMA) =", toHexString(data, HEX | UPPERCASE | COMMA), ) print(40 * "-") data = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] print("data = [ 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 ]") print("toHexString(data, COMMA) =", toHexString(data, COMMA)) print("toHexString(data) =", toHexString(data)) print("toHexString(data, PACK) =", toHexString(data, PACK)) print("toHexString(data, HEX) =", toHexString(data, HEX)) print("toHexString(data, HEX | COMMA) =", toHexString(data, HEX | COMMA)) print("toHexString(data, HEX | UPPERCASE) =", toHexString(data, HEX | UPPERCASE)) print( "toHexString(data, HEX | UPPERCASE | COMMA) =", toHexString(data, HEX | UPPERCASE | COMMA), ) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1736693378.625979 pyscard-2.2.1/src/smartcard/Examples/scard-api/0000755000076500000240000000000014740753203021147 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_control.py0000755000076500000240000000773714677317744024602 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: send a Control Code to a card or reader __author__ = "Ludovic Rousseau" Copyright 2007-2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * from smartcard.util import toASCIIString, toBytes, toHexString try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) if len(readers) < 1: raise error("No smart card readers") for zreader in readers: print("Trying to Control reader:", zreader) try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 ) if hresult != SCARD_S_SUCCESS: raise error("Unable to connect: " + SCardGetErrorMessage(hresult)) print("Connected with active protocol", dwActiveProtocol) try: if "winscard" == resourceManager: # IOCTL_SMARTCARD_GET_ATTRIBUTE = SCARD_CTL_CODE(2) hresult, response = SCardControl( hcard, SCARD_CTL_CODE(2), toBytes("%.8lx" % SCARD_ATTR_VENDOR_NAME), ) if hresult != SCARD_S_SUCCESS: raise error( "SCardControl failed: " + SCardGetErrorMessage(hresult) ) print("SCARD_ATTR_VENDOR_NAME:", toASCIIString(response)) elif "pcsclite" == resourceManager: # get feature request hresult, response = SCardControl( hcard, SCARD_CTL_CODE(3400), [] ) if hresult != SCARD_S_SUCCESS: raise error( "SCardControl failed: " + SCardGetErrorMessage(hresult) ) print("CM_IOCTL_GET_FEATURE_REQUEST:", toHexString(response)) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( "Failed to disconnect: " + SCardGetErrorMessage(hresult) ) print("Disconnected") except error as message: print(error, message) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") except error as e: print(e) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_getATR.py0000755000076500000240000000627114677317744024240 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: get card ATR in first pcsc reader __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import smartcard.util from smartcard.scard import * if __name__ == "__main__": hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) if len(readers) < 1: raise Exception("No smart card readers") print("PCSC Readers:", readers) for reader in readers: print("Trying to retrieve ATR of card in", reader) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) if hresult != SCARD_S_SUCCESS: print("Unable to connect: " + SCardGetErrorMessage(hresult)) else: print("Connected with active protocol", dwActiveProtocol) try: hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: print("failed to get status: " + SCardGetErrorMessage(hresult)) print("Reader:", reader) print("State:", hex(state)) print("Protocol:", protocol) print("ATR:", smartcard.util.toHexString(atr, smartcard.util.HEX)) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: print("Failed to disconnect: " + SCardGetErrorMessage(hresult)) print("Disconnected") finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_getAttrib.py0000755000076500000240000001443614677317744025041 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: List card attributes __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import struct import sys import smartcard.util from smartcard.scard import * attributes = { SCARD_ATTR_ATR_STRING: "SCARD_ATTR_ATR_STRING", SCARD_ATTR_CHANNEL_ID: "SCARD_ATTR_CHANNEL_ID", SCARD_ATTR_CHARACTERISTICS: "SCARD_ATTR_CHARACTERISTICS", SCARD_ATTR_CURRENT_BWT: "SCARD_ATTR_CURRENT_BWT", SCARD_ATTR_CURRENT_CLK: "SCARD_ATTR_CURRENT_CLK", SCARD_ATTR_CURRENT_CWT: "SCARD_ATTR_CURRENT_CWT", SCARD_ATTR_CURRENT_D: "SCARD_ATTR_CURRENT_D", SCARD_ATTR_CURRENT_EBC_ENCODING: "SCARD_ATTR_CURRENT_EBC_ENCODING", SCARD_ATTR_CURRENT_F: "SCARD_ATTR_CURRENT_F", SCARD_ATTR_CURRENT_IFSC: "SCARD_ATTR_CURRENT_IFSC", SCARD_ATTR_CURRENT_IFSD: "SCARD_ATTR_CURRENT_IFSD", SCARD_ATTR_CURRENT_IO_STATE: "SCARD_ATTR_CURRENT_IO_STATE", SCARD_ATTR_CURRENT_N: "SCARD_ATTR_CURRENT_N", SCARD_ATTR_CURRENT_PROTOCOL_TYPE: "SCARD_ATTR_CURRENT_PROTOCOL_TYPE", SCARD_ATTR_CURRENT_W: "SCARD_ATTR_CURRENT_W", SCARD_ATTR_DEFAULT_CLK: "SCARD_ATTR_DEFAULT_CLK", SCARD_ATTR_DEFAULT_DATA_RATE: "SCARD_ATTR_DEFAULT_DATA_RATE", SCARD_ATTR_DEVICE_FRIENDLY_NAME_A: "SCARD_ATTR_DEVICE_FRIENDLY_NAME_A", SCARD_ATTR_DEVICE_FRIENDLY_NAME_W: "SCARD_ATTR_DEVICE_FRIENDLY_NAME_W", SCARD_ATTR_DEVICE_IN_USE: "SCARD_ATTR_DEVICE_IN_USE", SCARD_ATTR_DEVICE_SYSTEM_NAME_A: "SCARD_ATTR_DEVICE_SYSTEM_NAME_A", SCARD_ATTR_DEVICE_SYSTEM_NAME_W: "SCARD_ATTR_DEVICE_SYSTEM_NAME_W", SCARD_ATTR_DEVICE_UNIT: "SCARD_ATTR_DEVICE_UNIT", SCARD_ATTR_ESC_AUTHREQUEST: "SCARD_ATTR_ESC_AUTHREQUEST", SCARD_ATTR_ESC_CANCEL: "SCARD_ATTR_ESC_CANCEL", SCARD_ATTR_ESC_RESET: "SCARD_ATTR_ESC_RESET", SCARD_ATTR_EXTENDED_BWT: "SCARD_ATTR_EXTENDED_BWT", SCARD_ATTR_ICC_INTERFACE_STATUS: "SCARD_ATTR_ICC_INTERFACE_STATUS", SCARD_ATTR_ICC_PRESENCE: "SCARD_ATTR_ICC_PRESENCE", SCARD_ATTR_ICC_TYPE_PER_ATR: "SCARD_ATTR_ICC_TYPE_PER_ATR", SCARD_ATTR_MAXINPUT: "SCARD_ATTR_MAXINPUT", SCARD_ATTR_MAX_CLK: "SCARD_ATTR_MAX_CLK", SCARD_ATTR_MAX_DATA_RATE: "SCARD_ATTR_MAX_DATA_RATE", SCARD_ATTR_MAX_IFSD: "SCARD_ATTR_MAX_IFSD", SCARD_ATTR_POWER_MGMT_SUPPORT: "SCARD_ATTR_POWER_MGMT_SUPPORT", SCARD_ATTR_SUPRESS_T1_IFS_REQUEST: "SCARD_ATTR_SUPRESS_T1_IFS_REQUEST", SCARD_ATTR_USER_AUTH_INPUT_DEVICE: "SCARD_ATTR_USER_AUTH_INPUT_DEVICE", SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE: "SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE", SCARD_ATTR_VENDOR_IFD_SERIAL_NO: "SCARD_ATTR_VENDOR_IFD_SERIAL_NO", SCARD_ATTR_VENDOR_IFD_TYPE: "SCARD_ATTR_VENDOR_IFD_TYPE", SCARD_ATTR_VENDOR_IFD_VERSION: "SCARD_ATTR_VENDOR_IFD_VERSION", SCARD_ATTR_VENDOR_NAME: "SCARD_ATTR_VENDOR_NAME", } if "pcsclite" == resourceManager: extra_attributes = { SCARD_ATTR_ASYNC_PROTOCOL_TYPES: "SCARD_ATTR_ASYNC_PROTOCOL_TYPES", SCARD_ATTR_SYNC_PROTOCOL_TYPES: "SCARD_ATTR_SYNC_PROTOCOL_TYPES", } attributes.update(extra_attributes) def printAttribute(attrib, value): print("-----------------", attributes[attrib], "-----------------") print(value) print(smartcard.util.toHexString(value, smartcard.util.HEX)) print(struct.pack(*["<" + "B" * len(value)] + value)) if __name__ == "__main__": hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) if len(readers) < 1: raise error("No smart card readers") for reader in readers: print("Trying to retrieve attributes of", reader) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) if hresult != SCARD_S_SUCCESS: print(error, "Unable to connect: " + SCardGetErrorMessage(hresult)) else: print("Connected with active protocol", dwActiveProtocol) try: for i in list(attributes.keys()): hresult, attrib = SCardGetAttrib(hcard, i) if hresult == SCARD_S_SUCCESS: printAttribute(i, attrib) else: print( "-----------------", attributes[i], "-----------------" ) print("error:", SCardGetErrorMessage(hresult)) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( "Failed to disconnect: " + SCardGetErrorMessage(hresult) ) print("Disconnected") finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_getStatusChange.py0000755000076500000240000000723414677317744026203 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: Detect card insertion/removal __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.util from smartcard.scard import * srTreeATR = [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] srTreeMask = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] def printstate(state): reader, eventstate, atr = state print(reader + " " + smartcard.util.toHexString(atr, smartcard.util.HEX)) if eventstate & SCARD_STATE_ATRMATCH: print("\tCard found") if eventstate & SCARD_STATE_UNAWARE: print("\tState unware") if eventstate & SCARD_STATE_IGNORE: print("\tIgnore reader") if eventstate & SCARD_STATE_UNAVAILABLE: print("\tReader unavailable") if eventstate & SCARD_STATE_EMPTY: print("\tReader empty") if eventstate & SCARD_STATE_PRESENT: print("\tCard present in reader") if eventstate & SCARD_STATE_EXCLUSIVE: print("\tCard allocated for exclusive use by another application") if eventstate & SCARD_STATE_INUSE: print("\tCard in used by another application but can be shared") if eventstate & SCARD_STATE_MUTE: print("\tCard is mute") if eventstate & SCARD_STATE_CHANGED: print("\tState changed") if eventstate & SCARD_STATE_UNKNOWN: print("\tState unknowned") try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) readerstates = [] for i in range(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] print("----- Current reader and card states are: -------") hresult, newstates = SCardGetStatusChange(hcontext, 0, readerstates) for i in newstates: printstate(i) print("----- Please insert or remove a card ------------") hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, newstates) print("----- New reader and card states are: -----------") for i in newstates: printstate(i) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) except error as e: print(e) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_listCards.py0000755000076500000240000000610214677317744025033 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: List cards introduced in the system __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.scard import * if "winscard" == resourceManager: # Cryptoflex 8k v2 is introduced in standard Windows 2000 slbCryptoFlex8kv2ATR = [0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, card = SCardListCards(hcontext, slbCryptoFlex8kv2ATR, []) if hresult != SCARD_S_SUCCESS: raise error( "Failure to locate Schlumberger Cryptoflex 8k v2 card: " + SCardGetErrorMessage(hresult) ) print("Located by ATR:", card) hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error("Failure to list cards: " + SCardGetErrorMessage(hresult)) print("Cards:", cards) for i in cards: hresult, providerguid = SCardGetCardTypeProviderName( hcontext, i, SCARD_PROVIDER_PRIMARY ) if hresult == SCARD_S_SUCCESS: print(i, "Primary provider:", providername) hresult, providername = SCardGetCardTypeProviderName( hcontext, i, SCARD_PROVIDER_CSP ) if hresult == SCARD_S_SUCCESS: print(i, "CSP Provider:", providername) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Failed to release context: " + SCardGetErrorMessage(hresult) ) print("Released context.") except error as e: print(e) elif "pcsclite" == resourceManager: print("SCardListCards not supported by pcsc lite") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_listInterfaces.py0000755000076500000240000001040214677317744026060 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: List card interfaces __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import platform import sys import smartcard.guid from smartcard.scard import * if "winscard" == resourceManager: znewcardName = "dummy-card" znewcardATR = [ 0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22, ] znewcardMask = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] znewcardPrimGuid = smartcard.guid.strToGUID( "{128F3806-4F70-4ccf-977A-60C390664840}" ) znewcardSecGuid = smartcard.guid.strToGUID("{EB7F69EA-BA20-47d0-8C50-11CFDEB63BBE}") def main(): hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise scard.error( "Failed to establish context: " + SCardGetErrorMessage(hresult) ) print("Context established!") try: # list interfaces for a known card expectedCard = "Schlumberger Cryptoflex 8k v2" hresult, interfaces = SCardListInterfaces(hcontext, expectedCard) if hresult != SCARD_S_SUCCESS: raise scard.error( "Failed to list interfaces: " + SCardGetErrorMessage(hresult) ) print("Interfaces for ", expectedCard, ":", interfaces) # introduce a card (forget first in case it is already present) hresult = SCardForgetCardType(hcontext, znewcardName) print("Introducing card " + znewcardName) hresult = SCardIntroduceCardType( hcontext, znewcardName, znewcardPrimGuid, znewcardPrimGuid + znewcardSecGuid, znewcardATR, znewcardMask, ) if hresult != SCARD_S_SUCCESS: raise error( "Failed to introduce card type: " + SCardGetErrorMessage(hresult) ) # list card interfaces hresult, interfaces = SCardListInterfaces(hcontext, znewcardName) if hresult != SCARD_S_SUCCESS: raise error( "Failed to list interfaces: " + SCardGetErrorMessage(hresult) ) for i in interfaces: print( "Interface for " + znewcardName + " :", smartcard.guid.GUIDToStr(i) ) print("Forgetting card " + znewcardName) hresult = SCardForgetCardType(hcontext, znewcardName) if hresult != SCARD_S_SUCCESS: raise error( "Failed to remove card type: " + SCardGetErrorMessage(hresult) ) finally: hresult2 = SCardReleaseContext(hcontext) if hresult2 != SCARD_S_SUCCESS: raise error( "Failed to release context: " + SCardGetErrorMessage(hresult) ) print("Released context.") main() elif "pcsclite" == resourceManager: print("SCardListInterfaces not supported by pcsc lite") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_locateCards.py0000755000076500000240000001200214677317744025323 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: Locate cards in the system __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.scard import * if "winscard" == resourceManager: znewcardName = "dummy-card" znewcardATR = [ 0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22, ] znewcardMask = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise scard.error( "Failed to establish context: " + SCardGetErrorMessage(hresult) ) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise scard.error( "Failed to list readers: " + SCardGetErrorMessage(hresult) ) print("PCSC Readers:", readers) # introduce a card (forget first in case it is already present) hresult = SCardForgetCardType(hcontext, znewcardName) print("Introducing card " + znewcardName) hresult = SCardIntroduceCardType( hcontext, znewcardName, [], [], znewcardATR, znewcardMask ) if hresult != SCARD_S_SUCCESS: if hresult == ERROR_ALREADY_EXISTS: print("Card already exists") else: raise error( "Failed to introduce card type: " + SCardGetErrorMessage(hresult) ) hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error("Failure to list cards") print("Cards:", cards) readerstates = [] for i in range(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] print(readerstates) hresult, newstates = SCardLocateCards(hcontext, cards, readerstates) for i in newstates: reader, eventstate, atr = i print(reader, end=" ") for b in atr: print("0x%.2X" % b, end=" ") print("") if eventstate & SCARD_STATE_ATRMATCH: print("Card found") if eventstate & SCARD_STATE_UNAWARE: print("State unware") if eventstate & SCARD_STATE_IGNORE: print("Ignore reader") if eventstate & SCARD_STATE_UNAVAILABLE: print("Reader unavailable") if eventstate & SCARD_STATE_EMPTY: print("Reader empty") if eventstate & SCARD_STATE_PRESENT: print("Card present in reader") if eventstate & SCARD_STATE_EXCLUSIVE: print("Card allocated for exclusive use") if eventstate & SCARD_STATE_INUSE: print("Card in use but can be shared") if eventstate & SCARD_STATE_MUTE: print("Card is mute") if eventstate & SCARD_STATE_CHANGED: print("State changed") if eventstate & SCARD_STATE_UNKNOWN: print("State unknowned") finally: hresult = SCardForgetCardType(hcontext, znewcardName) hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Failed to release context: " + SCardGetErrorMessage(hresult) ) print("Released context.") except error as e: print(e) elif "pcsclite" == resourceManager: print("SCardLocateCards not supported by pcsc lite") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_pinpad.py0000755000076500000240000001306314677317744024362 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: send a Control Code to a card or reader __author__ = "Ludovic Rousseau" Copyright 2009-2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.pcsc.PCSCExceptions import * from smartcard.scard import * def can_do_verify_pin(hCard): FEATURE_VERIFY_PIN_DIRECT = 6 return parse_get_feature_request(hCard, FEATURE_VERIFY_PIN_DIRECT) def can_do_modify_pin(hCard): FEATURE_MODIFY_PIN_DIRECT = 7 return parse_get_feature_request(hCard, FEATURE_MODIFY_PIN_DIRECT) def parse_get_feature_request(hCard, feature): # check the reader can do a verify pin CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) hresult, response = SCardControl(hcard, CM_IOCTL_GET_FEATURE_REQUEST, []) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print(response) while len(response) > 0: tag = response[0] if feature == tag: return ( ((((response[2] << 8) + response[3]) << 8) + response[4]) << 8 ) + response[5] response = response[6:] def verifypin(hCard, control=None): if control is None: control = can_do_verify_pin(hCard) if control is None: raise Exception("Not a pinpad") command = [ 0x00, # bTimerOut 0x00, # bTimerOut2 0x82, # bmFormatString 0x04, # bmPINBlockString 0x00, # bmPINLengthFormat 0x08, 0x04, # wPINMaxExtraDigit 0x02, # bEntryValidationCondition 0x01, # bNumberMessage 0x04, 0x09, # wLangId 0x00, # bMsgIndex 0x00, 0x00, 0x00, # bTeoPrologue 13, 0, 0, 0, # ulDataLength 0x00, 0x20, 0x00, 0x00, 0x08, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, ] # abData hresult, response = SCardControl(hcard, control, command) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) return hresult, response try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise ListReadersException(hresult) print("PCSC Readers:", readers) if len(readers) < 1: raise Exception("No smart card readers") for zreader in readers: print("Trying to Control reader:", zreader) try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print("Connected with active protocol", dwActiveProtocol) try: SELECT = [ 0x00, 0xA4, 0x04, 0x00, 0x06, 0xA0, 0x00, 0x00, 0x00, 0x18, 0xFF, ] hresult, response = SCardTransmit(hcard, dwActiveProtocol, SELECT) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) cmd_verify = can_do_verify_pin(hcard) if cmd_verify: print("can do verify pin: 0x%08X" % cmd_verify) cmd_modify = can_do_modify_pin(hcard) if cmd_modify: print("can do modify pin: 0x%08X" % cmd_modify) hresult, response = verifypin(hcard, cmd_verify) print("Control:", response) except Exception as ex: print("Exception:", ex) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print("Disconnected") except BaseSCardException as ex: print("SCard Exception:", ex) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise ReleaseContextException(hresult) print("Released context.") except error as e: print(e) if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_readerGroups.py0000755000076500000240000001631114677317744025550 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: illustrate reader groups functions __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * newgroup = "MyReaderGroup" try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers in all groups:", readers) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Unable to list reader groups: " + SCardGetErrorMessage(hresult) ) print("PCSC Reader groups:", readerGroups) if "winscard" == resourceManager: hresult = SCardIntroduceReaderGroup(hcontext, newgroup) if hresult != SCARD_S_SUCCESS: raise error( "Unable to introduce reader group: " + SCardGetErrorMessage(hresult) ) dummyreader = readers[0] + " dummy" hresult = SCardIntroduceReader(hcontext, dummyreader, readers[0]) if hresult != SCARD_S_SUCCESS: raise error( "Unable to introduce reader: " + dummyreader + " : " + SCardGetErrorMessage(hresult) ) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers in all groups:", readers) hresult = SCardAddReaderToGroup(hcontext, dummyreader, newgroup) if hresult != SCARD_S_SUCCESS: raise error( "Unable to add reader to group: " + SCardGetErrorMessage(hresult) ) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Unable to list reader groups: " + SCardGetErrorMessage(hresult) ) print("PCSC Reader groups:", readerGroups) hresult, readers = SCardListReaders(hcontext, [newgroup]) if hresult != SCARD_S_SUCCESS: raise error( "Failed to list readers in group " + newgroup + " : " + SCardGetErrorMessage(hresult) ) print("PCSC Readers in reader group", newgroup, ":", readers) hresult = SCardRemoveReaderFromGroup(hcontext, dummyreader, newgroup) if hresult != SCARD_S_SUCCESS: raise error( "Unable to remove reader from group: " + SCardGetErrorMessage(hresult) ) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Unable to list reader groups: " + SCardGetErrorMessage(hresult) ) print("PCSC Reader groups:", readerGroups) hresult = SCardForgetReaderGroup(hcontext, newgroup) if hresult != SCARD_S_SUCCESS: raise error( "Unable to forget reader group: " + SCardGetErrorMessage(hresult) ) hresult = SCardForgetReader(hcontext, dummyreader) if hresult != SCARD_S_SUCCESS: raise error("Failed to forget readers " + SCardGetErrorMessage(hresult)) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers in all groups:", readers) elif "pcsclite" == resourceManager: hresult, readers = SCardListReaders(hcontext, readerGroups) if hresult != SCARD_S_SUCCESS: raise error( "Failed to list readers in groups " + repr(readerGroups) + " : " + SCardGetErrorMessage(hresult) ) print("PCSC Readers in reader group", readerGroups, ":", readers) hresult = SCardIntroduceReaderGroup(hcontext, newgroup) if hresult != SCARD_E_UNSUPPORTED_FEATURE: raise error( "Was expecting an error instead of: " + SCardGetErrorMessage(hresult) ) dummyreader = readers[0] + " dummy" hresult = SCardAddReaderToGroup(hcontext, dummyreader, newgroup) if hresult != SCARD_E_UNSUPPORTED_FEATURE: raise error( "Was expecting an error instead of: " + SCardGetErrorMessage(hresult) ) dummyreader = readers[0] + " dummy" hresult = SCardIntroduceReader(hcontext, dummyreader, readers[0]) if hresult != SCARD_E_UNSUPPORTED_FEATURE: raise error( "Was expecting an error instead of: " + SCardGetErrorMessage(hresult) ) hresult = SCardRemoveReaderFromGroup(hcontext, dummyreader, newgroup) if hresult != SCARD_E_UNSUPPORTED_FEATURE: raise error( "Was expecting an error instead of: " + SCardGetErrorMessage(hresult) ) hresult = SCardForgetReaderGroup(hcontext, newgroup) if hresult != SCARD_E_UNSUPPORTED_FEATURE: raise error( "Was expecting an error instead of: " + SCardGetErrorMessage(hresult) ) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) except error as e: print(e) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_readers.py0000755000076500000240000000416514677317744024537 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: List PCSC readers __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( "Unable to list reader groups: " + SCardGetErrorMessage(hresult) ) print("PCSC Reader groups:", readerGroups) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) except error as e: print(e) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_selectDFTelecom.py0000755000076500000240000001012014677317744026100 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: Select DF_TELECOM on a SIM card __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import smartcard.util from smartcard.scard import * SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] GET_RESPONSE = [0xA0, 0xC0, 0x00, 0x00] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context : " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) if len(readers) < 1: raise error("No smart card readers") for zreader in readers: print("Trying to select DF_TELECOM of card in", zreader) try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) if hresult != SCARD_S_SUCCESS: raise error("Unable to connect: " + SCardGetErrorMessage(hresult)) print("Connected with active protocol", dwActiveProtocol) try: hresult, response = SCardTransmit( hcard, dwActiveProtocol, SELECT + DF_TELECOM ) if hresult != SCARD_S_SUCCESS: raise error( "Failed to transmit: " + SCardGetErrorMessage(hresult) ) print( "Selected DF_TELECOM: " + smartcard.util.toHexString(response, smartcard.util.HEX) ) hresult, response = SCardTransmit( hcard, dwActiveProtocol, GET_RESPONSE + [response[1]] ) if hresult != SCARD_S_SUCCESS: raise error( "Failed to transmit: " + SCardGetErrorMessage(hresult) ) print( "GET_RESPONSE after SELECT DF_TELECOM: " + smartcard.util.toHexString(response, smartcard.util.HEX) ) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( "Failed to disconnect: " + SCardGetErrorMessage(hresult) ) print("Disconnected") except error as message: print(error, message) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("Failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") except error as e: print(e) if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/scard-api/sample_transaction.py0000755000076500000240000001003714677317744025432 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample for python PCSC wrapper module: perform a simple transaction __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) print("Context established!") try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error("Failed to list readers: " + SCardGetErrorMessage(hresult)) print("PCSC Readers:", readers) if len(readers) < 1: raise error("No smart card readers") for zreader in readers: print("Trying to perform transaction on card in", zreader) try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) if hresult != SCARD_S_SUCCESS: raise error("unable to connect: " + SCardGetErrorMessage(hresult)) print("Connected with active protocol", dwActiveProtocol) try: hresult = SCardBeginTransaction(hcard) if hresult != SCARD_S_SUCCESS: raise error( "failed to begin transaction: " + SCardGetErrorMessage(hresult) ) print("Beginning transaction") hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: raise error( "failed to get status: " + SCardGetErrorMessage(hresult) ) print("ATR:", end=" ") for i in range(len(atr)): print("0x%.2X" % atr[i], end=" ") print("") finally: hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) if hresult != SCARD_S_SUCCESS: raise error( "failed to end transaction: " + SCardGetErrorMessage(hresult) ) print("Transaction ended") hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( "failed to disconnect: " + SCardGetErrorMessage(hresult) ) print("Disconnected") except error as message: print(error, message) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error("failed to release context: " + SCardGetErrorMessage(hresult)) print("Released context.") except error as e: print(e) import sys if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6281674 pyscard-2.2.1/src/smartcard/Examples/simple/0000755000076500000240000000000014740753203020575 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/simple/getATR.py0000755000076500000240000000272414677317744022324 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that displays the ATR of inserted cards. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.Exceptions import NoCardException from smartcard.System import readers from smartcard.util import toHexString for reader in readers(): try: connection = reader.createConnection() connection.connect() print(reader, toHexString(connection.getATR())) except NoCardException: print(reader, "no card inserted") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/simple/getATR_context.py0000755000076500000240000000313714677317744024067 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that displays the ATR of inserted cards. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.Exceptions import NoCardException from smartcard.System import readers from smartcard.util import toHexString # Use a connection context # the connection object is automatically destroyed at the end of with block for reader in readers(): with reader.createConnection() as connection: try: connection.connect() print(reader, toHexString(connection.getATR())) except NoCardException: print(reader, "no card inserted") # sleep(5) if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/simple/selectDF_TELECOM.py0000755000076500000240000000450114677317744024032 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script that tries to select the DF_TELECOM on all inserted cards. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.Exceptions import CardRequestTimeoutException # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() try: # request card insertion print("insert a card (SIM card if possible) within 10s") cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) # there is a DF_TELECOM if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) else: print("no DF_TELECOM") except CardRequestTimeoutException: print("time-out: no card inserted during last 10s") if "win32" == sys.platform: print("press Enter to continue") sys.stdin.read(1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/simple/simpleAPDU.py0000755000076500000240000000312214677317744023132 0ustar00rousseaustaff#! /usr/bin/env python3 """ Sample script to send 2 APDU __author__ = "Ludovic Rousseau" Copyright 2009 Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys from smartcard.System import readers # define the APDUs used in this script SELECT_APPLET = [0x00, 0xA4, 0x04, 0x00, 0x06, 0xA0, 0x00, 0x00, 0x00, 0x18, 0xFF] GET_TIME = [0x80, 0x38, 0x00, 0xA0] if __name__ == "__main__": # get all the available readers r = readers() print("Available readers: ", r) # by default we use the first reader i = 0 if len(sys.argv) > 1: i = int(sys.argv[1]) print("Using: %s" % r[i]) connection = r[i].createConnection() connection.connect() data, sw1, sw2 = connection.transmit(SELECT_APPLET) print(f"Select Applet: {sw1:02X} {sw2:02X}") data, sw1, sw2 = connection.transmit(GET_TIME) print(f"Get Time: {sw1:02X} {sw2:02X}") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.5902126 pyscard-2.2.1/src/smartcard/Examples/wx/0000755000076500000240000000000014740753203017742 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6302247 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/0000755000076500000240000000000014740753203022226 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/SampleAPDUManagerPanel.py0000755000076500000240000002054414677317744026775 0ustar00rousseaustaff#! /usr/bin/env python3 """ Simple panel that defines a dialog to send APDUs to a card. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import wx from smartcard.util import toBytes, toHexString from smartcard.wx.APDUHexValidator import APDUHexValidator from smartcard.wx.SimpleSCardAppEventObserver import SimpleSCardAppEventObserver [ ID_TEXT_COMMAND, ID_TEXTCTRL_COMMAND, ID_TEXT_RESPONSE, ID_TEXTCTRL_RESPONSE, ID_TEXT_SW, ID_TEXT_SW1, ID_TEXTCTRL_SW1, ID_TEXT_SW2, ID_TEXTCTRL_SW2, ID_CARDSTATE, ID_TRANSMIT, ] = [wx.NewId() for x in range(11)] class SampleAPDUManagerPanel(wx.Panel, SimpleSCardAppEventObserver): """A simple panel that displays activated cards and readers and can send APDU to a connected card.""" def __init__(self, parent): wx.Panel.__init__(self, parent, -1) SimpleSCardAppEventObserver.__init__(self) self.layoutControls() self.Bind(wx.EVT_BUTTON, self.OnTransmit, self.transmitbutton) # callbacks from SimpleSCardAppEventObserver interface def OnActivateCard(self, card): """Called when a card is activated by double-clicking on the card or reader tree control or toolbar. In this sample, we just connect to the card on the first activation.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel("Activated card: " + repr(card)) self.transmitbutton.Enable() def OnActivateReader(self, reader): """Called when a reader is activated by double-clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateReader(self, reader) self.feedbacktext.SetLabel("Activated reader: " + repr(reader)) self.transmitbutton.Disable() def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel("Deactivated card: " + repr(card)) self.transmitbutton.Disable() def OnDeselectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel("Deselected card: " + repr(card)) self.transmitbutton.Disable() def OnSelectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel("Selected card: " + repr(card)) if hasattr(self.selectedcard, "connection"): self.transmitbutton.Enable() def OnSelectReader(self, reader): """Called when a reader is selected by clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectReader(self, reader) self.feedbacktext.SetLabel("Selected reader: " + repr(reader)) self.transmitbutton.Disable() # callbacks def OnTransmit(self, event): if hasattr(self.selectedcard, "connection"): apdu = self.commandtextctrl.GetValue() data, sw1, sw2 = self.selectedcard.connection.transmit(toBytes(apdu)) self.SW1textctrl.SetValue("%x" % sw1) self.SW2textctrl.SetValue("%x" % sw2) self.responsetextctrl.SetValue(toHexString(data + [sw1, sw2])) event.Skip() def layoutControls(self): # create controls statictextCommand = wx.StaticText( self, ID_TEXT_COMMAND, "Command", wx.DefaultPosition, wx.DefaultSize, 0 ) self.commandtextctrl = wx.TextCtrl( self, ID_TEXTCTRL_COMMAND, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE, validator=APDUHexValidator(), ) statictextResponse = wx.StaticText( self, ID_TEXT_RESPONSE, "Response", wx.DefaultPosition, wx.DefaultSize, 0 ) self.responsetextctrl = wx.TextCtrl( self, ID_TEXTCTRL_RESPONSE, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY, ) statictextStatusWords = wx.StaticText( self, ID_TEXT_SW, "Status Words", wx.DefaultPosition, wx.DefaultSize, 0 ) statictextSW1 = wx.StaticText( self, ID_TEXT_SW1, "SW1", wx.DefaultPosition, wx.DefaultSize, 0 ) self.SW1textctrl = wx.TextCtrl( self, ID_TEXTCTRL_SW1, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_READONLY, ) statictextSW2 = wx.StaticText( self, ID_TEXT_SW2, "SW2", wx.DefaultPosition, wx.DefaultSize, 0 ) self.SW2textctrl = wx.TextCtrl( self, ID_TEXTCTRL_SW2, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_READONLY, ) self.feedbacktext = wx.StaticText( self, ID_CARDSTATE, "", wx.DefaultPosition, wx.DefaultSize, 0 ) # layout controls boxsizerCommand = wx.BoxSizer(wx.HORIZONTAL) boxsizerCommand.Add(statictextCommand, 1, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerCommand.Add(self.commandtextctrl, 5, wx.EXPAND | wx.ALL, 5) boxsizerResponse = wx.BoxSizer(wx.HORIZONTAL) boxsizerResponse.Add(statictextResponse, 1, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerResponse.Add(self.responsetextctrl, 5, wx.EXPAND | wx.ALL, 5) boxsizerSW = wx.BoxSizer(wx.HORIZONTAL) boxsizerSW.Add(statictextSW1, 0, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerSW.Add(self.SW1textctrl, 0, wx.EXPAND | wx.ALL, 5) boxsizerSW.Add(statictextSW2, 0, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerSW.Add(self.SW2textctrl, 0, wx.EXPAND | wx.ALL, 5) item11 = wx.BoxSizer(wx.HORIZONTAL) item11.Add(statictextStatusWords, 0, wx.ALIGN_CENTER | wx.ALL, 5) item11.Add(boxsizerSW, 0, wx.EXPAND | wx.ALL, 5) boxsizerResponseAndSW = wx.BoxSizer(wx.VERTICAL) boxsizerResponseAndSW.Add(boxsizerResponse, 0, wx.EXPAND | wx.ALL, 5) boxsizerResponseAndSW.Add(item11, 0, wx.EXPAND | wx.ALL, 5) staticboxAPDU = wx.StaticBox(self, -1, "APDU") boxsizerAPDU = wx.StaticBoxSizer(staticboxAPDU, wx.VERTICAL) boxsizerAPDU.Add(boxsizerCommand, 1, wx.EXPAND | wx.ALL, 5) boxsizerAPDU.Add(boxsizerResponseAndSW, 4, wx.EXPAND | wx.ALL, 5) staticboxEvents = wx.StaticBox(self, -1, "Card/Reader Events") boxsizerEvents = wx.StaticBoxSizer(staticboxEvents, wx.HORIZONTAL) boxsizerEvents.Add(self.feedbacktext, 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerboxTransmitButton = wx.BoxSizer(wx.HORIZONTAL) sizerboxTransmitButton.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.transmitbutton = wx.Button( self, ID_TRANSMIT, "Transmit", wx.DefaultPosition, wx.DefaultSize, 0 ) self.transmitbutton.Disable() sizerboxTransmitButton.Add(self.transmitbutton, 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerboxTransmitButton.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerPanel = wx.BoxSizer(wx.VERTICAL) sizerPanel.Add(boxsizerAPDU, 3, wx.EXPAND | wx.ALL, 5) sizerPanel.Add(boxsizerEvents, 1, wx.EXPAND | wx.ALL, 5) sizerPanel.Add(sizerboxTransmitButton, 1, wx.EXPAND | wx.ALL, 5) self.SetSizer(sizerPanel) self.SetAutoLayout(True) sizerPanel.Fit(self) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/apdumanager.py0000755000076500000240000000357614677317744025121 0ustar00rousseaustaff#! /usr/bin/env python3 """ Simple application to send APDUs to a card. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os import os.path import sys from SampleAPDUManagerPanel import SampleAPDUManagerPanel from smartcard.wx.SimpleSCardApp import * def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname(sys.executable) return os.path.dirname(__file__) def main(argv): app = SimpleSCardApp( appname="A tool to send apdu to a card", apppanel=SampleAPDUManagerPanel, appstyle=TR_SMARTCARD | TR_READER | PANEL_APDUTRACER, appicon=os.path.join(module_path(), "images", "mysmartcard.ico"), size=(800, 600), ) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6306705 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/images/0000755000076500000240000000000014740753203023473 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/images/mysmartcard.ico0000644000076500000240000000047614674316735026537 0ustar00rousseaustaff(( 333s333{wwwwwws{s{swwwwsw{ww{w{swwwws{s{sww{wwws{{././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/apdumanager/setup.py0000644000076500000240000000250314677317744023757 0ustar00rousseaustaff#! /usr/bin/env python3 """ Setup script to build a standalone apdumanager.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from distutils.core import setup import py2exe from smartcard.wx import ICO_READER, ICO_SMARTCARD Mydata_files = [("images", ["images/mysmartcard.ico", ICO_SMARTCARD, ICO_READER])] setup( windows=["apdumanager.py"], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}}, ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6319087 pyscard-2.2.1/src/smartcard/Examples/wx/cardmonitor/0000755000076500000240000000000014740753203022263 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/cardmonitor/cardmonitor.py0000755000076500000240000001103614677317744025201 0ustar00rousseaustaff#! /usr/bin/env python3 """ Simple smart card monitoring application. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os.path import sys from smartcard.wx.SimpleSCardApp import * from smartcard.wx.SimpleSCardAppEventObserver import SimpleSCardAppEventObserver ID_TEXT = 10000 def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname(sys.executable) return os.path.dirname(__file__) class SamplePanel(wx.Panel, SimpleSCardAppEventObserver): """A simple panel that displays activated cards and readers. The panel implements the SimpleSCardAppEventObserver, and has a chance to react on reader and card activation/deactivation.""" def __init__(self, parent): wx.Panel.__init__(self, parent, -1) sizer = wx.FlexGridSizer(0, 3, 0, 0) sizer.AddGrowableCol(1) sizer.AddGrowableRow(1) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.feedbacktext = wx.StaticText( self, ID_TEXT, "", wx.DefaultPosition, wx.DefaultSize, 0 ) sizer.Add(self.feedbacktext, 0, wx.ALIGN_LEFT | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.SetSizer(sizer) self.SetAutoLayout(True) # callbacks from SimpleSCardAppEventObserver interface def OnActivateCard(self, card): """Called when a card is activated by double-clicking on the card or reader tree control or toolbar. In this sample, we just connect to the card on the first activation.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel("Activated card: " + repr(card)) def OnActivateReader(self, reader): """Called when a reader is activated by double-clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateReader(self, reader) self.feedbacktext.SetLabel("Activated reader: " + repr(reader)) def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel("Deactivated card: " + repr(card)) def OnSelectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel("Selected card: " + repr(card)) def OnSelectReader(self, reader): """Called when a reader is selected by clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectReader(self, reader) self.feedbacktext.SetLabel("Selected reader: " + repr(reader)) def main(argv): app = SimpleSCardApp( appname="A simple card monitoring tool", apppanel=SamplePanel, appstyle=TR_SMARTCARD | TR_READER, appicon=os.path.join(module_path(), "images", "mysmartcard.ico"), size=(800, 600), ) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6323535 pyscard-2.2.1/src/smartcard/Examples/wx/cardmonitor/images/0000755000076500000240000000000014740753203023530 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/Examples/wx/cardmonitor/images/mysmartcard.ico0000644000076500000240000000047614674316735026574 0ustar00rousseaustaff(( 333s333{wwwwwws{s{swwwwsw{ww{w{swwwws{s{sww{wwws{{././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/cardmonitor/setup.py0000644000076500000240000000250214677317744024013 0ustar00rousseaustaff#! /usr/bin/env python3 """ Setup script to build a standalone cardmonitor.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from distutils.core import setup import py2exe from smartcard.wx import ICO_READER, ICO_SMARTCARD Mydata_files = [("images", ["images/mysmartcard.ico", ICO_SMARTCARD, ICO_READER])] setup( windows=["cardmonitor.py"], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}}, ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6328113 pyscard-2.2.1/src/smartcard/Examples/wx/pcscdiag/0000755000076500000240000000000014740753203021517 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/pcscdiag/pcscdiag.py0000755000076500000240000000741214677317744023674 0ustar00rousseaustaff#! /usr/bin/env python3 """ Example wxPython application that displays readers and inserted cards ATRs. This example displays a snapshot of the readers and cards, there is no automatic refresh of the readers and cards. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.Exceptions import smartcard.System import smartcard.util # wxPython GUI modules (https://www.wxpython.org/) try: import wx except ImportError: print( "You need wxpython (https://www.wxpython.org/) " + "to run this sample from the source code!" ) print("press a key to continue") import msvcrt msvcrt.getch() import sys sys.exit() def getATR(reader): """Return the ATR of the card inserted into the reader.""" connection = reader.createConnection() atr = "" try: connection.connect() atr = smartcard.util.toHexString(connection.getATR()) connection.disconnect() except smartcard.Exceptions.NoCardException: atr = "no card inserted" return atr class pcscdiag(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, size=(600, 400)) w, h = self.GetClientSize() self.tree = wx.TreeCtrl( self, wx.NewIdRef(), wx.DefaultPosition, (w, h), wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS, ) self.InitTree() self.OnExpandAll() def InitTree(self): self.tree.AddRoot("Readers and ReaderGroups") readerNode = self.tree.AppendItem(self.tree.GetRootItem(), "Readers") for reader in smartcard.System.readers(): childReader = self.tree.AppendItem(readerNode, repr(reader)) childCard = self.tree.AppendItem(childReader, getATR(reader)) readerGroupNode = self.tree.AppendItem( self.tree.GetRootItem(), "Readers Groups" ) for readergroup in smartcard.System.readergroups(): childReaderGroup = self.tree.AppendItem(readerGroupNode, readergroup) readers = smartcard.System.readers(readergroup) for reader in readers: child = self.tree.AppendItem(childReaderGroup, repr(reader)) def OnExpandAll(self): """expand all nodes""" root = self.tree.GetRootItem() fn = self.tree.Expand self.traverse(root, fn) self.tree.Expand(root) def traverse(self, traverseroot, function, cookie=0): """recursively walk tree control""" if self.tree.ItemHasChildren(traverseroot): firstchild, cookie = self.tree.GetFirstChild(traverseroot) function(firstchild) self.traverse(firstchild, function, cookie) child = self.tree.GetNextSibling(traverseroot) if child: function(child) self.traverse(child, function, cookie) if __name__ == "__main__": app = wx.App() frame = pcscdiag(None, "Smartcard readers and reader groups") frame.Show() app.MainLoop() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6337807 pyscard-2.2.1/src/smartcard/Examples/wx/readerviewer/0000755000076500000240000000000014740753203022426 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6343026 pyscard-2.2.1/src/smartcard/Examples/wx/readerviewer/images/0000755000076500000240000000000014740753203023673 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/Examples/wx/readerviewer/images/readerviewer.ico0000644000076500000240000000047614674316735027075 0ustar00rousseaustaff(( `ff`p38`x p`xppxxppxpxxxxpxpxp @?././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/readerviewer/readerviewer.py0000755000076500000240000000341414677317744025510 0ustar00rousseaustaff#! /usr/bin/env python3 """Simple smart card reader monitoring application. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os.path import sys from smartcard.wx.SimpleSCardApp import * def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname(sys.executable) return os.path.dirname(__file__) def main(argv): app = SimpleSCardApp( appname="A simple reader monitoring tool", apppanel=None, appstyle=TR_READER, appicon=os.path.join(module_path(), "images", "readerviewer.ico"), size=(800, 600), ) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Examples/wx/readerviewer/setup.py0000644000076500000240000000250614677317744024162 0ustar00rousseaustaff#! /usr/bin/env python3 """ Setup script to build a standalone readerviewer.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from distutils.core import setup import py2exe from smartcard.wx import ICO_READER, ICO_SMARTCARD Mydata_files = [("images", ["images/readerviewer.ico", ICO_SMARTCARD, ICO_READER])] setup( windows=["readerviewer.py"], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}}, ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Exceptions.py0000644000076500000240000000713314677317744020244 0ustar00rousseaustaff"""Smartcard module exceptions. This module defines the exceptions raised by the smartcard module. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import SCardGetErrorMessage class SmartcardException(Exception): """Base class for smartcard exceptions. smartcard exceptions are generated by the smartcard module and shield scard (i.e. PCSC) exceptions raised by the scard module. """ def __init__(self, message="", hresult=-1, *args): super().__init__(message, *args) self.hresult = int(hresult) def __str__(self): text = super().__str__() if self.hresult != -1: hresult = self.hresult if hresult < 0: # convert 0x-7FEFFFE3 into 0x8010001D hresult += 0x100000000 text += f": {SCardGetErrorMessage(self.hresult)} (0x{hresult:08X})" return text class CardConnectionException(SmartcardException): """Raised when a CardConnection class method fails.""" pass class CardRequestException(SmartcardException): """Raised when a CardRequest wait fails.""" pass class CardRequestTimeoutException(SmartcardException): """Raised when a CardRequest times out.""" def __init__(self, hresult=-1, *args): SmartcardException.__init__( self, "Time-out during card request", hresult=hresult, *args ) class CardServiceException(SmartcardException): """Raised when a CardService class method fails.""" pass class CardServiceStoppedException(SmartcardException): """Raised when the CardService was stopped""" pass class CardServiceNotFoundException(SmartcardException): """Raised when the CardService is not found""" pass class InvalidATRMaskLengthException(SmartcardException): """Raised when an ATR mask does not match an ATR length.""" def __init__(self, mask): SmartcardException.__init__(self, "Invalid ATR mask length: %s" % mask) class InvalidReaderException(SmartcardException): """Raised when trying to access an invalid smartcard reader.""" def __init__(self, readername): SmartcardException.__init__(self, "Invalid reader: %s" % readername) class ListReadersException(SmartcardException): """Raised when smartcard readers cannot be listed.""" def __init__(self, hresult): SmartcardException.__init__(self, "Failed to list readers", hresult=hresult) class NoCardException(SmartcardException): """Raised when no card in is present in reader.""" def __init__(self, message, hresult): SmartcardException.__init__(self, message, hresult=hresult) class NoReadersException(SmartcardException): """Raised when the system has no smartcard reader.""" def __init__(self, *args): SmartcardException.__init__(self, "No reader found", *args) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/ExclusiveConnectCardConnection.py0000644000076500000240000000622314677317744024215 0ustar00rousseaustaff"""CardConnectionDecorator that provides exclusive use of a card. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.pcsc from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.Exceptions import CardConnectionException from smartcard.pcsc import PCSCCardConnection from smartcard.scard import ( SCARD_LEAVE_CARD, SCARD_S_SUCCESS, SCARD_SHARE_EXCLUSIVE, SCardConnect, SCardDisconnect, SCardGetErrorMessage, ) class ExclusiveConnectCardConnection(CardConnectionDecorator): """This decorator uses exclusive access to the card during connection to prevent other processes to connect to this card.""" def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def connect(self, protocol=None, mode=None, disposition=None): """Disconnect and reconnect in exclusive mode PCSCCardconnections.""" CardConnectionDecorator.connect(self, protocol, mode, disposition) component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection ): pcscprotocol = PCSCCardConnection.translateprotocolmask(protocol) if 0 == pcscprotocol: pcscprotocol = component.getProtocol() if component.hcard is not None: hresult = SCardDisconnect(component.hcard, SCARD_LEAVE_CARD) if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to disconnect: " + SCardGetErrorMessage(hresult) ) hresult, component.hcard, dwActiveProtocol = SCardConnect( component.hcontext, str(component.reader), SCARD_SHARE_EXCLUSIVE, pcscprotocol, ) if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to connect with SCARD_SHARE_EXCLUSIVE" + SCardGetErrorMessage(hresult) ) # print('reconnected exclusive') break if hasattr(component, "component"): component = component.component else: break ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/ExclusiveTransmitCardConnection.py0000644000076500000240000000664214677317744024432 0ustar00rousseaustaff"""Sample CardConnectionDecorator that provides exclusive transmit() __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.pcsc from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.Exceptions import CardConnectionException from smartcard.scard import ( SCARD_LEAVE_CARD, SCARD_S_SUCCESS, SCardBeginTransaction, SCardEndTransaction, SCardGetErrorMessage, ) class ExclusiveTransmitCardConnection(CardConnectionDecorator): """This decorator uses L{SCardBeginTransaction}/L{SCardEndTransaction} to preserve other processes of threads to access the card during transmit().""" def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def lock(self): """Lock card with L{SCardBeginTransaction}.""" component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection ): hresult = SCardBeginTransaction(component.hcard) if SCARD_S_SUCCESS != hresult: raise CardConnectionException( "Failed to lock with SCardBeginTransaction: " + SCardGetErrorMessage(hresult) ) else: # print('locked') pass break if hasattr(component, "component"): component = component.component else: break def unlock(self): """Unlock card with L{SCardEndTransaction}.""" component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection ): hresult = SCardEndTransaction(component.hcard, SCARD_LEAVE_CARD) if SCARD_S_SUCCESS != hresult: raise CardConnectionException( "Failed to unlock with SCardEndTransaction: " + SCardGetErrorMessage(hresult) ) else: # print('unlocked') pass break if hasattr(component, "component"): component = component.component else: break def transmit(self, command, protocol=None): """Gain exclusive access to card during APDU transmission for if this decorator decorates a PCSCCardConnection.""" data, sw1, sw2 = CardConnectionDecorator.transmit(self, command, protocol) return data, sw1, sw2 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729025142.0 pyscard-2.2.1/src/smartcard/Observer.py0000644000076500000240000000420514703552166017674 0ustar00rousseaustaff""" from Thinking in Python, Bruce Eckel https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Observer.html (c) Copyright 2008, Creative Commons Attribution-Share Alike 3.0. Class support for "observer" pattern. The observer class is the base class for all smartcard package observers. """ from __future__ import annotations import typing from smartcard.Synchronization import Synchronization, synchronize class Observer: def update(self, observable: Observable, arg: typing.Any) -> None: """Called when the observed object is modified. You call an Observable object's notifyObservers method to notify all the object's observers of the change.""" pass class Observable(Synchronization): def __init__(self) -> None: super().__init__() self.obs: list[Observer] = [] self.changed = 0 def addObserver(self, observer: Observer) -> None: if observer not in self.obs: self.obs.append(observer) def deleteObserver(self, observer: Observer) -> None: self.obs.remove(observer) def notifyObservers(self, arg: typing.Any = None) -> None: """If 'changed' indicates that this object has changed, notify all its observers, then call clearChanged(). Each observer has its update() called with two arguments: this observable object and the generic 'arg'.""" with self.mutex: if not self.changed: return # Make a copy of the observer list. observers = self.obs.copy() self.changed = 0 # Update observers for observer in observers: observer.update(self, arg) def deleteObservers(self) -> None: self.obs = [] def setChanged(self) -> None: self.changed = 1 def clearChanged(self) -> None: self.changed = 0 def hasChanged(self) -> int: return self.changed def countObservers(self) -> int: return len(self.obs) synchronize( Observable, "addObserver deleteObserver deleteObservers " + "setChanged clearChanged hasChanged " + "countObservers", ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728488499.0 pyscard-2.2.1/src/smartcard/PassThruCardService.py0000644000076500000240000000426514701522063021766 0ustar00rousseaustaff"""Card service abstract class. A card service is a class providings specific smart card functionality, e.g. a GSM file system or an Open Platform loader. CardService is an abstract class from which concrete card services are derived. A concrete card service is almost always smart card operating system specific __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard import CardService class PassThruCardService(CardService.CardService): """Pass-thru card service class.""" def __init__(self, connection, cardname=None): """Construct a pass-thru card service. @param connection: the CardConnection used to access the smart card """ CardService.CardService.__init__(self, connection, cardname) @staticmethod def supports(cardname): """Returns True if the cardname is supported by the card service. The PassThruCardService supports all cardnames and always returns True.""" return True if __name__ == "__main__": """Small sample illustrating the use of CardService.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.System import readers cc = readers()[0].createConnection() cs = PassThruCardService(cc) cs.connection.connect() data, sw1, sw2 = cs.connection.transmit(SELECT + DF_TELECOM) print(f"{sw1:X} {sw2:X}") cs.connection.disconnect() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/ReaderMonitoring.py0000644000076500000240000001766214677317744021403 0ustar00rousseaustaff"""Smart card reader monitoring classes. ReaderObserver is a base class for objects that are to be notified upon smartcard reader insertion/removal. ReaderMonitor is a singleton object notifying registered ReaderObservers upon reader insertion/removal. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import traceback from threading import Event, Thread from time import sleep import smartcard.System from smartcard.Observer import Observable, Observer from smartcard.Synchronization import * # ReaderObserver interface class ReaderObserver(Observer): """ ReaderObserver is a base abstract class for objects that are to be notified upon smartcard reader insertion/removal. """ def __init__(self): pass def update(self, observable, handlers): """Called upon reader insertion/removal. @param observable: @param handlers: - addedreaders: list of added readers causing notification - removedreaders: list of removed readers causing notification """ pass class ReaderMonitor(Observable): """Class that monitors reader insertion/removal. and notify observers note: a reader monitoring thread will be running as long as the reader monitor has observers, or ReaderMonitor.stop() is called. It implements the shared state design pattern, where objects of the same type all share the same state, in our case essentially the ReaderMonitoring Thread. Thanks to Frank Aune for implementing the shared state pattern logics. """ __shared_state = {} def __init__( self, startOnDemand=True, readerProc=smartcard.System.readers, period=1 ): self.__dict__ = self.__shared_state Observable.__init__(self) self.startOnDemand = startOnDemand self.readerProc = readerProc self.period = period if self.startOnDemand: self.rmthread = None else: self.rmthread = ReaderMonitoringThread(self, self.readerProc, self.period) self.rmthread.start() def addObserver(self, observer): """Add an observer.""" Observable.addObserver(self, observer) # If self.startOnDemand is True, the reader monitoring # thread only runs when there are observers. if self.startOnDemand: if 0 < self.countObservers(): if not self.rmthread: self.rmthread = ReaderMonitoringThread( self, self.readerProc, self.period ) # start reader monitoring thread in another thread to # avoid a deadlock; addObserver and notifyObservers called # in the ReaderMonitoringThread run() method are # synchronized import _thread _thread.start_new_thread(self.rmthread.start, ()) else: observer.update(self, (self.rmthread.readers, [])) def deleteObserver(self, observer): """Remove an observer.""" Observable.deleteObserver(self, observer) # If self.startOnDemand is True, the reader monitoring # thread is stopped when there are no more observers. if self.startOnDemand: if 0 == self.countObservers(): self.rmthread.stop() del self.rmthread self.rmthread = None def __str__(self): return self.__class__.__name__ synchronize( ReaderMonitor, "addObserver deleteObserver deleteObservers " + "setChanged clearChanged hasChanged " + "countObservers", ) class ReaderMonitoringThread(Thread): """Reader insertion thread. This thread polls for pcsc reader insertion, since no reader insertion event is available in pcsc. """ __shared_state = {} def __init__(self, observable, readerProc, period): self.__dict__ = self.__shared_state Thread.__init__(self) self.observable = observable self.stopEvent = Event() self.stopEvent.clear() self.readers = [] self.daemon = True self.name = "smartcard.ReaderMonitoringThread" self.readerProc = readerProc self.period = period def run(self): """Runs until stopEvent is notified, and notify observers of all reader insertion/removal. """ while not self.stopEvent.is_set(): try: # no need to monitor if no observers if 0 < self.observable.countObservers(): currentReaders = self.readerProc() addedReaders = [] removedReaders = [] if currentReaders != self.readers: for reader in currentReaders: if reader not in self.readers: addedReaders.append(reader) for reader in self.readers: if reader not in currentReaders: removedReaders.append(reader) if addedReaders or removedReaders: # Notify observers self.readers = [] for r in currentReaders: self.readers.append(r) self.observable.setChanged() self.observable.notifyObservers( (addedReaders, removedReaders) ) # wait every second on stopEvent self.stopEvent.wait(self.period) except Exception: # FIXME Tighten the exceptions caught by this block traceback.print_exc() # Most likely raised during interpreter shutdown due # to unclean exit which failed to remove all observers. # To solve this, we set the stop event and pass the # exception to let the thread finish gracefully. self.stopEvent.set() def stop(self): self.stopEvent.set() self.join() if __name__ == "__main__": print("insert or remove readers in the next 20 seconds") # a simple reader observer that prints added/removed readers class printobserver(ReaderObserver): def __init__(self, obsindex): self.obsindex = obsindex def update(self, observable, handlers): addedreaders, removedreaders = handlers print("%d - added: " % self.obsindex, addedreaders) print("%d - removed: " % self.obsindex, removedreaders) class testthread(Thread): def __init__(self, obsindex): Thread.__init__(self) self.readermonitor = ReaderMonitor() self.obsindex = obsindex self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex) self.readermonitor.addObserver(self.observer) sleep(20) self.readermonitor.deleteObserver(self.observer) t1 = testthread(1) t2 = testthread(2) t1.start() t2.start() t1.join() t2.join() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/Session.py0000644000076500000240000000740414677317744017547 0ustar00rousseaustaff""" Smartcard Session. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.Exceptions import InvalidReaderException, NoReadersException from smartcard.PassThruCardService import PassThruCardService from smartcard.System import readers class Session: """The Session object enables programmers to transmit APDU to smartcards. This is an example of use of the Session object: >>> import smartcard >>> reader=smartcard.listReaders() >>> s = smartcard.Session(reader[0]) >>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] >>> DF_TELECOM = [0x7F, 0x10] >>> data, sw1, sw2 = s.sendCommandAPDU(SELECT+DF_TELECOM) >>> print(data, sw1, sw2) >>> s.close() >>> print(`s`) """ def __init__(self, readerName=None, cardServiceClass=None): """Session constructor. Initializes a smart card session and connect to the card. @param readerName: reader to connect to; default is first PCSC reader @param cardServiceClass: card service to bind the session to; default is None """ # if reader name not given, select first reader if readerName is None: if len(readers()) > 0: self.reader = readers()[0] self.readerName = repr(self.reader) else: raise NoReadersException() # otherwise select reader from name else: self.readerName = readerName for reader in readers(): if readerName == str(reader): self.reader = reader self.readerName = repr(self.reader) try: self.reader except AttributeError: raise InvalidReaderException(self.readerName) # open card connection and bind PassThruCardService cc = self.reader.createConnection() self.cs = PassThruCardService(cc) self.cs.connection.connect() def close(self): """Close the smartcard session. Closing a session will disconnect from the card.""" self.cs.connection.disconnect() def sendCommandAPDU(self, command): """Send an APDU command to the connected smartcard. @param command: list of APDU bytes, e.g. [0xA0, 0xA4, 0x00, 0x00, 0x02] @return: a tuple (response, sw1, sw2) where response is the APDU response sw1, sw2 are the two status words """ response, sw1, sw2 = self.cs.connection.transmit(command) if len(response) > 2: response.append(sw1) response.append(sw2) return response, sw1, sw2 def getATR(self): """Returns the ATR of the connected card.""" return self.cs.connection.getATR() def __repr__(self): """Returns a string representation of the session.""" return "" % self.readerName if __name__ == "__main__": """Small sample illustrating the use of Session.py.""" pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/Synchronization.py0000644000076500000240000000306314703301034021271 0ustar00rousseaustaff""" from Thinking in Python, Bruce Eckel https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Observer.html (c) Copyright 2008, Creative Commons Attribution-Share Alike 3.0. Simple emulation of Java's 'synchronized' keyword, from Peter Norvig. """ from __future__ import annotations import functools import sys import threading from collections.abc import Iterable from typing import Any, Callable, Protocol, TypeVar if sys.version_info >= (3, 10): from typing import ParamSpec else: from typing_extensions import ParamSpec T = TypeVar("T") P = ParamSpec("P") def synchronized(method: Callable[P, T]) -> Callable[P, T]: @functools.wraps(method) def f(self: _SynchronizationProtocol, *args: Any, **kwargs: Any) -> Any: with self.mutex: return method(self, *args, **kwargs) return f def synchronize(klass: type, names: str | Iterable[str] | None = None) -> None: """Synchronize methods in the given class. Only synchronize the methods whose names are given, or all methods if names=None.""" if isinstance(names, str): names = names.split() for name, val in list(klass.__dict__.items()): if callable(val) and name != "__init__" and (names is None or name in names): setattr(klass, name, synchronized(val)) class _SynchronizationProtocol(Protocol): mutex: threading.Lock | threading.RLock class Synchronization(_SynchronizationProtocol): # You can create your own self.mutex, or inherit from this class: def __init__(self): self.mutex = threading.RLock() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/System.py0000644000076500000240000000372314703301034017357 0ustar00rousseaustaff"""Smartcard system utility functions and classes. Manages smartcard readers and reader groups. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.pcsc.PCSCReaderGroups import smartcard.reader.ReaderFactory def readers(groups=None): """Returns the list of smartcard readers in groups as L{smartcard.reader.Reader}. If groups is not specified, returns the list of all smartcard readers. >>> import smartcard >>> r=smartcard.readers() >>> r=smartcard.readers(['SCard$DefaultReaders', 'MyReaderGroup']) """ if groups is None: groups = [] return smartcard.reader.ReaderFactory.ReaderFactory.readers(groups) def readergroups(): """Returns the list of reader groups.""" return smartcard.pcsc.PCSCReaderGroups.PCSCReaderGroups().instance # for legacy only def listReaders(): """Returns the list of smartcard readers. Deprecated - Use L{smartcard.System.readers()} instead. """ zreaders = [] for reader in readers(): zreaders.append(str(reader)) return zreaders if __name__ == "__main__": print(readers()) print(readers(["SCard$DefaultReaders"])) print(readergroups()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/__init__.py0000644000076500000240000000214614677317744017661 0ustar00rousseaustaff"""Smartcard utility module. The smartcard utility module provides classes and functions to access smartcards and readers. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.Session import Session # for legacy only from smartcard.System import listReaders __all__ = ["listReaders", "Session"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.5905879 pyscard-2.2.1/src/smartcard/doc/0000755000076500000240000000000014740753203016273 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6365728 pyscard-2.2.1/src/smartcard/doc/images/0000755000076500000240000000000014740753203017540 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/doc/images/pyscard.jpg0000644000076500000240000006177514674316735021742 0ustar00rousseaustaffJFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( (#o!iUw-Hil`I2YjI'Ԛ__$?kUXB5@K/(/_Bh/B5@K/(/_BhaYߡG!~%E   ? ,Э(_k_Q_ e~nE/_BB5@K/+v,!~%Yߡ[Q`0 ,У  ݢ_ e~k_VX /B5@K/(/_BhaYߡG!~%E   ? ,Э(_k_Q_ e~nE/_BB5@K/+v,/ x~iΎ$Ik bI$ĤxEk'm]!Q"b(QEQEQEQEQEQEQEQE/W/t[赮:ZDTQEY!EPEPEPEPEPEPEPEPEPEPEPEPEPOQֿX:'Ek'm]!Q"X*J ( ( ( ( ( ( ( (#=p*"N`Or'AuZ#j($(((kP_k6|;I LXCl.൷ Fw9' ߑE]EqR|M"z_1: P˞޵@zֹinh1i#ӏz.MEr!Z&o3@n1 H (ɤ|o cu-Swٴo@PsEh65կJ}bINpÎU|Tx{tMP )];vcⵍe.mxDRHt*=kkVWQizI_/dK86K v,zmor/'K q ((QEQEuEtIs)GZ [WAa oTH(((((((((y?ʹȓ:EuǼ\Io֪$ڢ* ( ( 6w.mɧ(HffSr0sx#ҽ"3RZԏdŭ\Fee d#iSدAUTPTt`RҰ\QмVڼefWQE0 (Q@Q@>)GZ [WAa oW?uEtIDb((((((((((:ZQ?{U?D-jL(((((((((((((('?(_?j,?m\ S"^趮A?Q,QE%Q@Q@Q@Q@Q@Q@Q@Q@r'AuZ'y?ʹȓ:ETIEUQEQEQEQEQEQEQEQEQEQEQEQEQEdEk'm]!\QֿX:'*%((((((((( 2+*h.  h*h.  h*h.  h*h.  ku֍m+`y6 }9+yy&4vr4zj1K832:9[E0ƱƊU$&F/ xWC+{m.WKc5خJяx SCt?M]tY2R2k㭽V96~z0A(2_A<B?  k*h.OЩ& (*h.OЩ& (*h.OЩ& (*h.OЩ& (*h.OЩ& (*h.|BHLvۦ[T" BQAn~V'95ce*O%62v_z(Ǔݎgƈ#Xco6$1^͸ 7cvy/ r<#qlwއwpG"*N25j9/_.APyN=x?M4 4?C֎ǩ#Au qn承=AW 9A<B*PԴPEPEPEPEPEPEPEPEPEPEPEPEP\Y..PG8;3%z>A| NO4?EЀQ C khQ`(>xJ- P? m#+. 8 )'AӉ9&>"N5b#Ȍ E2n +u :4KۼIa3I$$W4[Î [Gc)Xyx-sx?M5(TQUz XQE ( ( ( jiv̭,-d5zuOmv#ic Td@,~.*%~)L=X{~ 37K#VU;ht6)4% r%$(5j] h袹L|weZ_Bd@ *}c$G{e*B0u;VF`csOP g 4?C3@ѴV"Hmm"t3mܤhEQEQEQEQEQEQEQEQEQEQEQEQEQEg/j/k;D^"u?@5NXUd[=p*"x{)jiO|"'m&QPPQEQEQEQEQEW/u%k^? G[kVL_P?">>!Y\cĭΦ( ( ( ( ( ( (<߂O.o$e3IbJyl?_z'k0k0oEo_ëao;9Pː:t!_E|_MxO}5E4[R{mV>kg6ƩxM &6塹`ʬFs.I5;B<'B? / k# i67qh]N$;cyoJw|gf& "6hjw{#$9GW_G!_E|_Mr#N[EvRNs3*DHl2W>fjMӴoؘ dGxFh#+/ Я/&|4f 1,I<遃GW_G!_E|_MoQ@?xO}4?_GW_G!_E|_MoW/ikC"ݶ9[U cD? hm#+-@4Oi+&YyaskGZS3{nzm )# @qw.|!?4fy&gcI+'vR.znW/'DtY~ogb>qtɠ xO}4?_Ko } Hid0EH^C I$:бE. c#+/ Я/& B<'B? / kz#+/ Я/& B<'B? / kz#+/ Я/& B<'Baiz?46db Dh_G5(zmgJӵjvt+" ]M`.FGW_G!_E|_MoQ@?xO}4?_GW_G!_E|_MoQ@?xO}4?_GW_G!_E|_MoQ@?xO}5bxsHh'x%daA A]buj 2?I^m=ctP?N2.F8´oQX쮵[4{0D#<ׁW?\Eyu|],lPY; +w sv)kzg/|GS&}a`s(/1E_:@;zZIu# dhAؓYW^E;#Tƭ^!cՕE1¯r1 zg%÷}t6:հ,.VHi$F2ܫ&(\4_j:- !|<@җR-Ʊ^iuu e$ry\^ֻj(\֊冎!jEQE ( iqo/ϓ>3ת$8B0@"GMԅ=ۓ7~G/U KM7f;y~|U! BI } `N#OQSO>FV}[zԓ5E4i%m[ޕI<ɨ9o]f%\;ݍzi=zӴWuPpv5z(Ǔ (AEPEPEPEPEPX2O}.l& _?uǏ}.?kzn~?}m(z(AEPEPEPEPX1_mj۬Oȏ6Eß K[Ճ|9`o_>zEP ((#fvk5OjUWP$y.VPGך'y??ʲ|"N` g2_5G2_5[P2_5G2_5[P2_5G2_5[P2_5ToUw$7[h^Aez/S#:(\s^mOw/@3 ry={gh/( gh/gh/( gh/gh/( gh/gh/(U/a2H@$[W?l۳Ήdۜ ~_[^&@wzEP ({w%?V`.F3zo8OC_̵?`ׅo@QE ( ( ( ( n?[VbxD}-~?U$VAWm%QG>]Zެȃ襭 (Q@Q@d?D-kZ'$?k@ͪ(Wxz.-V3g5儲xHJ>63 R'/|aewdIwH2ߌϮ}|}⹴m}RM6kXmK27yjyw{qRWqk0k[]m2êpA1ҽB(C[^&@wz5j?/h?׬_e(Q@`.F`q+.?hX7<{`m6foQE((((+?# m[u趠g' kTZ]Tޯǒ=G sv)kz|"?mX(QEQEG?{Ut[赭iOȓ:E6jonZG~nPy+Vl=^2Mi:'9< N1uf#,x}k[Y.MV[a(ͼh<> ~γX<0o3?@+*.b:ͤS%-*Oayö"Ȥ&`}oƚP<$qD}-4nY=σ `UI*9V 2>|@_z׈n#DB22 5?]LKf%C#AcFbh5[R/Vp 1ӷu4QL(E o@z4Oi(׬ D^"袊QEw#`i[Ճw#`mhXZz8kvu43NcEPޢ(QEQEQEQEV'Gqڶ?# m@OkvQz' k_A-%nz?AR`#D.E-oWϞQE(('$?kZǼY>'AuZmQE(ajyijeKܠFW#reKx3꺀wfMg+(ù)x¾.}zBVMxKy@ ySN[:NEk0ldv=z8潎V ?u?:_@Y6@!ݳ OZԲzׇӬl쥆C4x+(sţg:_źx5F!-';h:Vw%ͥOl U@$ }:(\(b ((k_ѢNXF GeM'4A EP (t_zoyCf`_8h?%oV#\PQ@((((`ۏշX1_mjx_I?կU_G ly+s|"?m sv)kz|(AEPEPsǼY>'AuZؑwɜnW1JѬtѥ[Kxn(\8gSEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%TEay,-%Ty,-%T{[^&@wzʽOXZMD4{)F3޷,-kj#,:3P(Q@`}lJެ-CG]n41qoV#g@EP ((((Oȏ6Em'Gqځ<*ROkvQz[Jȃ襭G>]Zޯ=`(QEQEQEQEQEQEQEQEQEQEQEQEQES$8T4"q`)V:71dW1A84 O żkyR;Xs Ah5s*٦W=GU<YV1L@zdPu˘-|On&p7HGtU ͝ⅺuS%@ƀ+m?Qm{o3ʬqk;P4IId0n~ʣz 84] &MBuBH9SՏ<ڢ(QEQEQEV'Gqڶ?# m@OkvQz' k_A-%nz?AR`#D.E-oWϞQE(((kJ;y4zRh)e 4 EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?EP)e 4m?~E¡& `ۏշX1_mjx_I?կU_G ly+s|"?m sv)kz|(AEPEPsǼ\焴}.OhNm;i噠RIדtsǼY>'AuZ[ebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EPebi? t EP:H'J~bi? t EPebi? t EPebi? t EPemKšæf3ں:O:xOڀ/Džr_*z<-!S (Oȏ6Em'Gqځ<*ROkvQz[Jȃ襭G>]Zޯ=`(QEQE'VOIoֵy??ʲ|"N` ڢ(QEQEQEQT]VDԵ 6.$ =uk y*\pFEKEPExPf"Ig'e#5QESdqO#g {VouO6ŊL!,py Ԣ(QEd6~%կgJ ,F u#5/uk sJecqyK(WP͸#FQ@Q@dEk'mZՓuE/Džr_*z<-!S (Oȏ6Em'Gqځ<*ROkvQz[Jȃ襭G>]Zޯ=`(QEQE'VOIoֵy??ʲ|"N` ڢ(Tm,DD,#TPx6x4h9}?V{ӯX.r@5|}|Mt$t<=zzWçXIu W}R%Wo&lm)"6m!aԎ+-|gX-ih!m/~NݲMexC^>ғL/4hld߄3`yp1^<+AH( +{TPi1ocmGzs7 |C*O>&yQ>0'rk^u>.<$t$u-;#'x=+ٖ-AېT1Ӝ5RVC0O^X.x}:DywM%[O޵1\BǮ dZÛOJ|` ḳ(1+*ЀG+CwZ,<_?xAеBm<14Ip2r;NFO[]iGu)..-iLY{f`Wh{`wzݖǩ^[d(;09`ۏշX1_mjx_I?կU_G ly+s|"?m sv)kz|(AEPEPsǼY>'AuZ֟=p*:Z3j(AEPEPEPEPEPEPEPEPEPEPEPEPEPEPY>)GZ [VdEk'm@?m\ oT(+?# m[u趠g' kTZ]Tޯǒ=G sv)kz|"?mX(QEQEG?{UxKXfYnZu-x`ۏ VAWm_V#D.E-oV?AR|Q@(((((((((((((((((((((`ۏշX1_mjx_I?կU_G ly+s|"?mw(<C6G,zm=V x5|U^G5kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~kYsWG4W_ _??dG%~k'Gqڤßҿ2?x@Qkl>pw,Ll<$VAWm_V缛Brm`'Vd췉sg++o_cvg7nݷv4 R+E #<""/ȯFY?c'hY?c'k"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;"/ȣȋy'+ѿVOAX?VOAX>C{ 9"I|<"ddt;ڷk]*+?RxԏXAx-|_,=NǢY~ (Ɠ l^V?%JƏK<7ClQXxo +c?, W4EcY4 h0i_ g`ҿ6? l@V?%JƏK<7ClQXxo +c?, W4EcY4 h0i_ g`ҿ6? l@V?%JƏK<7ClQXxo +c?, W4EcY4 h0i_ g`ҿ6? l@V?%JƏK<7ClQXxo +c?, W4EcY4 h0i_ g`ҿ6? l@V?%JƏK<7ClQXxo +c?, W4EcY4 h0i_ g`ҿ6? l@V?%JƏK<7ClQXxo +c?, W4EcY4 hÄxJƀ6(|gj5%lI(2tOG>]ZޭH ~aX?ةDaX?أ6=m?( ~OEAO>i>߱S@}}`bϬTPaX?أ6=m?( ~OEAO>i>߱S@}}`bϬTPaX?أ6=m?( ~OEAO>i>߱S@}}`bϬTPaX?أ6=m?( ~OEAO>i>߱S@}}`bϬTPaX?أ6=m?( ~OEAO>i>߱S@}}`bϬTPaX?أ6=m?+vuFpA8WAX18FqځDT1|Nb@/1|IR~h9m*݌LG>]Zެȃ襭(QEQEQEQEQEQEQEQEk4^F};V%ŕҺ]B^۪ [+d088=ğn#H:88WG[GSj:uy˨[yBqß K[Ճ|9`o_>zEjҾCIY,,S0~BLIrHkExڵ{ ;{[iRRɈ2O\ÿjso\uz1S=w&ypW^5O𷃠4gmdqMxY(Iraܜpz>'ekjRGi)jM99 .=a0|XV` &X 2v09sӃhJOu ; 1\ D^D6\,zEcw˥+jؽrcU.eoM=?[-V|s損$9N,zx;ķ^##ә eƑA018VW hʮ ESѴ16џkx2\,y^j4T]#EKOgTGu<}uG[7e٣9ȸAr+SysXt0D[8OՋ;[v́~3KmIo ty"!xz3]"[qDOl" XAϗa>UI<7O7N7 *nSF3KK]igtO*naw Ep^$6 4]6n<<{s]7|Co/ YCqnJHak^A_ ? 5=kTTSi$7 fP8>u:mGiG>Dapx\,vW|RDi]yd.:9پ x+oLvT?k|]/ǥQ^z/n|9kq>d('%G!Ӑ0yJ~(K|otb妠al>vNN,z5NPAk[j6g 9\ ~,>#jj{+m3^+;I۾9ch.ķgd$WdboT]ib)L5_kj>$Ҵ{O4{7y 6gۏ|Qp4W\x\ x8i5 #uv2ž^vp;ڭhn}- Ӗ6k-5a ?RM+IS vXX p]؅Ul9X>2mu]',2$r[YsF qNvW_0SEJ1+#/^}베`ۏշX1_mjVAWm_V#D.E-oV?AR|qڥwZT-m}g&;*gcFI 3Ɗ㬾ZY|H[_+7*ϻ<zះv5N! e,TQE=M2 F56q|ϽC}Q>&uQ,g;H]X.p1k:0HBa>Ra^kXN`ȮJU^@r یzX.qwlkvYڅw4~YpsÌc5MgB׮#7?ik>at$]3E5ݼחZZ-(v0,9RG9,K]hַ,ڎ{[8U@@߽oI'5]w;>O?y`}k8t0xkh.txd=Ő]n[a=Oei1 ;V}IK[_vÆ^EAsԼ+uu?zٌe6- A:[;i Џ_o{=:> hr̞@d'#Q:k^!ڝ< n-=c'LWuǤ@mm_( . '`c oJe-?RV }@e+?(l}*ΣXִ9muEV)VUGC$~SRoQFoGe7m: _0 fNNkaee \'2sSX_A%6VάSw7]J 3CLn|dhz߇hZ.iVN$U7mZ:͈1_갛wg?78,<ڮiecOImw"HG=1 )+{^y5{_R0g_U3$c=뿢m;C\]X>cKx9!A*I<a;_@O }8ʊv {'xuI{tmʹ S=l,_0y_1=~n]MX.pמ|;o5a&<=wݻW 1$yUЁX5&|AfHlZ+r;3]X OxxWZ H6n2q׵mE趭n?[P' kTZ]Tޯǒ=G sv)kz|"?mX(QEQEQEQEQEQEQE_ o7JZ4/]Һ ۤp\g63a̚pm]$2 g޽Vk:Mim*yM8&+i~1\$6IJWYMDHXUDPUFL(AEPEPEPEPEPEPEPX1_mj۬Oȏ6Eß K[xCVms-"ӭ)/cVF*AlM'CF7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7M'CF?7 / "z4h0 Ѣ/*7?# mL4h0>zDKa:Gw3;lOjVAWm} k_A-%n}^sWa?dF:>M(G^&G<(tŠ((((((((((((((((((((((?UJ* u-././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/doc/images/sflogo.php.png0000644000076500000240000000552114674316735022343 0ustar00rousseaustaffPNG  IHDR}%?qgAMA  cHRMnt$m_l<XGO IDATxb`?Y glƏWL88%H2ӧO'2=rsƨ_~=E9矌1ƱK+3o߾W@; ކ$CxC0L i5L`<^xC0z 4Wb@VbЧ I@#^bfiN" wHS$ārÌdˀ9( *\`u?0S1, a``7LgM?d{eyFJ ep@w Gq @(b"i97 5(DK%L]y?B-,nޖ_vE03Ӈ ]Sa)g 1 n`Q /x?֟"DVd@?;0D6&XpT1.`ADA kx:@ >2H[RHOLF HH4| &H5!RTOZ__L@/$S4ҝc!>pKAt<98${AZW@e'XpW,RRR@ݻ% deC\h&P 0q+ k-5ul$ɯstۑ$@\ :rc + ,L6E0e@7u*v@ZxFv%ј]!H3h 0q"iL4<<Ϟsr?ؾ ^g@D1 O {!9X0I^;h&;U88T[ѵ֗u|ή[4$ fS1`p-Bq#w9oWU7ma$uiQєR*crM0HaFQ4!q5;au417[hZ*CM$*}A1ueYH 0?í7N *G-0y&/L|( 1"_,tKa `.s7M@qH2JMGnx (i$@o#E (1h&P.b&@v翫G010H2p10f`/*)h#rba$,B"J"+N<#@Cr\X÷ , , " lT¥ ;@GALAH_,#<@ p,/LYlD@l:a1wh15>^_wu% /17ï ?_3 l8Ci lUU@ p߷^pJ)< Хw& <|M; a C´Xq @ y(PD/ !jD]2afaI4) "=q{0}] ځ c8p<w@*RvyX.j2`"L `YU j&dxz&pSdT^XF 8`dd =7 'q-%IENDB`././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/guid.py0000644000076500000240000000300514677317744017045 0ustar00rousseaustaff"""smartcard.guid Utility functions to handle GUIDs as strings or list of bytes __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import uuid def strToGUID(s: str) -> list[int]: """Converts a GUID string into a list of bytes. >>> strToGUID('{AD4F1667-EA75-4124-84D4-641B3B197C65}') [103, 22, 79, 173, 117, 234, 36, 65, 132, 212, 100, 27, 59, 25, 124, 101] """ return list(uuid.UUID(s).bytes_le) def GUIDToStr(g: list[int]) -> str: """Converts a GUID sequence of bytes into a string. >>> GUIDToStr([103,22,79,173, 117,234, 36,65, ... 132, 212, 100, 27, 59, 25, 124, 101]) '{AD4F1667-EA75-4124-84D4-641B3B197C65}' """ return f"{{{uuid.UUID(bytes_le=bytes(g))}}}".upper() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6419554 pyscard-2.2.1/src/smartcard/pcsc/0000755000076500000240000000000014740753203016456 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCCardConnection.py0000644000076500000240000003052514703301034022365 0ustar00rousseaustaff"""PCSCCardConnection class manages connections thru a PCSC reader. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnection import CardConnection from smartcard.Exceptions import ( CardConnectionException, NoCardException, SmartcardException, ) from smartcard.scard import * def translateprotocolmask(protocol): """Translate L{CardConnection} protocol mask into PCSC protocol mask.""" pcscprotocol = 0 if protocol is not None: if CardConnection.T0_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T0 if CardConnection.T1_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T1 if CardConnection.RAW_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_RAW if CardConnection.T15_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T15 return pcscprotocol def translateprotocolheader(protocol): """Translate protocol into PCSC protocol header.""" pcscprotocol = 0 if protocol is not None: if CardConnection.T0_protocol == protocol: pcscprotocol = SCARD_PCI_T0 if CardConnection.T1_protocol == protocol: pcscprotocol = SCARD_PCI_T1 if CardConnection.RAW_protocol == protocol: pcscprotocol = SCARD_PCI_RAW return pcscprotocol dictProtocolHeader = {SCARD_PCI_T0: "T0", SCARD_PCI_T1: "T1", SCARD_PCI_RAW: "RAW"} dictProtocol = { SCARD_PROTOCOL_T0: "T0", SCARD_PROTOCOL_T1: "T1", SCARD_PROTOCOL_RAW: "RAW", SCARD_PROTOCOL_T15: "T15", SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1: "T0 or T1", } class PCSCCardConnection(CardConnection): """PCSCCard connection class. Handles connection with a card thru a PCSC reader.""" def __init__(self, reader): """Construct a new PCSC card connection. @param reader: the reader in which the smartcard to connect to is located. """ CardConnection.__init__(self, reader) self.hcard = None hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to establish context : " + SCardGetErrorMessage(hresult), hresult=hresult, ) def __del__(self): """Destructor. Clean PCSC connection resources.""" # race condition: module CardConnection # can disappear before __del__ is called self.disconnect() hresult = SCardReleaseContext(self.hcontext) if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_INVALID_VALUE: raise CardConnectionException( "Failed to release context: " + SCardGetErrorMessage(hresult), hresult=hresult, ) CardConnection.__del__(self) def connect(self, protocol=None, mode=None, disposition=None): """Connect to the card. If protocol is not specified, connect with the default connection protocol. If mode is not specified, connect with C{smartcard.scard.SCARD_SHARE_SHARED}.""" CardConnection.connect(self, protocol) pcscprotocol = translateprotocolmask(protocol) if 0 == pcscprotocol: pcscprotocol = self.getProtocol() if mode is None: mode = SCARD_SHARE_SHARED # store the way to dispose the card if disposition is None: disposition = SCARD_UNPOWER_CARD self.disposition = disposition hresult, self.hcard, dwActiveProtocol = SCardConnect( self.hcontext, str(self.reader), mode, pcscprotocol ) if hresult != SCARD_S_SUCCESS: self.hcard = None if hresult in (SCARD_W_REMOVED_CARD, SCARD_E_NO_SMARTCARD): raise NoCardException("Unable to connect", hresult=hresult) else: raise CardConnectionException( "Unable to connect with protocol: " + dictProtocol[pcscprotocol] + ". " + SCardGetErrorMessage(hresult), hresult=hresult, ) protocol = 0 if dwActiveProtocol == SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1: # special case for T0 | T1 # this happens when mode=SCARD_SHARE_DIRECT and no protocol is # then negotiated with the card protocol = CardConnection.T0_protocol | CardConnection.T1_protocol else: for p in dictProtocol: if p == dwActiveProtocol: protocol = eval("CardConnection.%s_protocol" % dictProtocol[p]) PCSCCardConnection.setProtocol(self, protocol) def reconnect(self, protocol=None, mode=None, disposition=None): """Reconnect to the card. If protocol is not specified, connect with the default connection protocol. If mode is not specified, connect with C{smartcard.scard.SCARD_SHARE_SHARED}. If disposition is not specified, do a warm reset (C{smartcard.scard.SCARD_RESET_CARD})""" CardConnection.reconnect(self, protocol) if self.hcard is None: raise CardConnectionException("Card not connected") pcscprotocol = translateprotocolmask(protocol) if 0 == pcscprotocol: pcscprotocol = self.getProtocol() if mode is None: mode = SCARD_SHARE_SHARED # store the way to dispose the card if disposition is None: disposition = SCARD_RESET_CARD self.disposition = disposition hresult, dwActiveProtocol = SCardReconnect( self.hcard, mode, pcscprotocol, self.disposition ) if hresult != SCARD_S_SUCCESS: self.hcard = None if hresult in (SCARD_W_REMOVED_CARD, SCARD_E_NO_SMARTCARD): raise NoCardException("Unable to reconnect", hresult=hresult) else: raise CardConnectionException( "Unable to reconnect with protocol: " + dictProtocol[pcscprotocol] + ". " + SCardGetErrorMessage(hresult), hresult=hresult, ) protocol = 0 if dwActiveProtocol == SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1: # special case for T0 | T1 # this happens when mode=SCARD_SHARE_DIRECT and no protocol is # then negotiated with the card protocol = CardConnection.T0_protocol | CardConnection.T1_protocol else: for p in dictProtocol: if p == dwActiveProtocol: protocol = eval("CardConnection.%s_protocol" % dictProtocol[p]) PCSCCardConnection.setProtocol(self, protocol) def disconnect(self): """Disconnect from the card.""" # when __del__() is invoked in response to a module being deleted, # e.g., when execution of the program is done, other globals referenced # by the __del__() method may already have been deleted. # this causes CardConnection.disconnect to except with a TypeError try: CardConnection.disconnect(self) except TypeError: pass if self.hcard is not None: hresult = SCardDisconnect(self.hcard, self.disposition) self.hcard = None if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to disconnect: " + SCardGetErrorMessage(hresult), hresult=hresult, ) def getATR(self): """Return card ATR""" CardConnection.getATR(self) if self.hcard is None: raise CardConnectionException("Card not connected") hresult, reader, state, protocol, atr = SCardStatus(self.hcard) if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to get status: " + SCardGetErrorMessage(hresult), hresult=hresult, ) return atr def doTransmit(self, command, protocol=None): """Transmit an apdu to the card and return response apdu. @param command: command apdu to transmit (list of bytes) @param protocol: the transmission protocol, from L{CardConnection.T0_protocol}, L{CardConnection.T1_protocol}, or L{CardConnection.RAW_protocol} @return: a tuple (response, sw1, sw2) where - response are the response bytes excluding status words - sw1 is status word 1, e.g. 0x90 - sw2 is status word 2, e.g. 0x1A """ if protocol is None: protocol = self.getProtocol() CardConnection.doTransmit(self, command, protocol) pcscprotocolheader = translateprotocolheader(protocol) if 0 == pcscprotocolheader: raise CardConnectionException( "Invalid protocol in transmit: must be " + "CardConnection.T0_protocol, " + "CardConnection.T1_protocol, or " + "CardConnection.RAW_protocol" ) if self.hcard is None: raise CardConnectionException("Card not connected") hresult, response = SCardTransmit(self.hcard, pcscprotocolheader, command) if hresult != SCARD_S_SUCCESS: raise CardConnectionException( "Failed to transmit with protocol " + dictProtocolHeader[pcscprotocolheader] + ". " + SCardGetErrorMessage(hresult), hresult=hresult, ) if len(response) < 2: raise CardConnectionException( "Card returned no valid response", hresult=hresult ) sw1 = (response[-2] + 256) % 256 sw2 = (response[-1] + 256) % 256 data = [(x + 256) % 256 for x in response[:-2]] return list(data), sw1, sw2 def doControl(self, controlCode, command=None): """Transmit a control command to the reader and return response. @param controlCode: control command @param command: command data to transmit (list of bytes) @return: response are the response bytes (if any) """ if command is None: command = [] CardConnection.doControl(self, controlCode, command) hresult, response = SCardControl(self.hcard, controlCode, command) if hresult != SCARD_S_SUCCESS: raise SmartcardException( "Failed to control " + SCardGetErrorMessage(hresult), hresult=hresult ) data = [(x + 256) % 256 for x in response] return list(data) def doGetAttrib(self, attribId): """get an attribute @param attribId: Identifier for the attribute to get @return: response are the attribute byte array """ CardConnection.doGetAttrib(self, attribId) hresult, response = SCardGetAttrib(self.hcard, attribId) if hresult != SCARD_S_SUCCESS: raise SmartcardException( "Failed to getAttrib " + SCardGetErrorMessage(hresult), hresult=hresult ) return response if __name__ == "__main__": """Small sample illustrating the use of CardConnection.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.pcsc.PCSCPart10 import CM_IOCTL_GET_FEATURE_REQUEST from smartcard.pcsc.PCSCReader import PCSCReader cc = PCSCReader.readers()[0].createConnection() cc.connect() print("%r %x %x" % cc.transmit(SELECT + DF_TELECOM)) print(cc.control(CM_IOCTL_GET_FEATURE_REQUEST, [])) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736282587.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCCardRequest.py0000644000076500000240000004203014737310733021725 0ustar00rousseaustaff"""PCSC Smartcard request. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import threading from datetime import datetime from smartcard import Card from smartcard.AbstractCardRequest import AbstractCardRequest from smartcard.Exceptions import ( CardRequestException, CardRequestTimeoutException, ListReadersException, ) from smartcard.pcsc.PCSCExceptions import ( EstablishContextException, ReleaseContextException, ) from smartcard.pcsc.PCSCReader import PCSCReader from smartcard.scard import * class PCSCCardRequest(AbstractCardRequest): """PCSC CardRequest class.""" def __init__( self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1, ): """Construct new PCSCCardRequest. @param newcardonly: if C{True}, request a new card. default is C{False}, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card default is to consider all readers @param cardType: the L{CardType} class to wait for; default is L{AnyCardType}, i.e. the request will returns with new or already inserted cards @param cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a L{PassThruCardService} @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to C{None} """ AbstractCardRequest.__init__( self, newcardonly, readers, cardType, cardServiceClass, timeout ) # if timeout is None, translate to scard.INFINITE if self.timeout is None: self.timeout = INFINITE # otherwise, from seconds to milliseconds else: self.timeout = int(self.timeout * 1000) hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) self.evt = threading.Event() self.hresult = SCARD_S_SUCCESS self.readerstates = {} self.newstates = [] self.timeout_init = self.timeout def __del__(self): hresult = SCardReleaseContext(self.hcontext) if hresult != SCARD_S_SUCCESS: raise ReleaseContextException(hresult) self.hcontext = -1 def getReaderNames(self): """Returns the list of PCSC readers on which to wait for cards.""" # get inserted readers hresult, pcscreaders = SCardListReaders(self.hcontext, []) # renew the context in case PC/SC was stopped # this happens on Windows when the last reader is disconnected if hresult in (SCARD_E_SERVICE_STOPPED, SCARD_E_NO_SERVICE): hresult = SCardReleaseContext(self.hcontext) if hresult != SCARD_S_SUCCESS: raise ReleaseContextException(hresult) hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) hresult, pcscreaders = SCardListReaders(self.hcontext, []) if SCARD_E_NO_READERS_AVAILABLE == hresult: return [] if SCARD_S_SUCCESS != hresult: raise ListReadersException(hresult) readers = [] # if no readers asked, use all inserted readers if self.readersAsked is None: readers = pcscreaders # otherwise use only the asked readers that are inserted else: for reader in self.readersAsked: if not isinstance(reader, str): reader = str(reader) if reader in pcscreaders: readers = readers + [reader] return readers # thread waiting for a change # the main thread will handle a possible KeyboardInterrupt def getStatusChange(self): self.hresult, self.newstates = SCardGetStatusChange( self.hcontext, self.timeout, list(self.readerstates.values()) ) self.evt.set() def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() # add PnP special reader readernames.append("\\\\?PnP?\\Notification") for reader in readernames: if reader not in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values()) ) else: hresult = SCARD_S_SUCCESS newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise exception on error if ( SCARD_S_SUCCESS != hresult and SCARD_E_TIMEOUT != hresult and SCARD_E_UNKNOWN_READER != hresult ): raise CardRequestException( "Failed to SCardGetStatusChange " + SCardGetErrorMessage(hresult), hresult=hresult, ) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports("dummy"): cardfound = True return self.cardServiceClass(reader.createConnection()) startDate = datetime.now() self.timeout = self.timeout_init while not cardfound: # create a dictionary entry for new readers readernames = self.getReaderNames() if self.readersAsked is None: # add PnP special reader readernames.append("\\\\?PnP?\\Notification") for reader in readernames: if reader not in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in list(readerstates.keys()): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion self.readerstates = readerstates waitThread = threading.Thread(target=self.getStatusChange) waitThread.start() # the main thread handles a possible KeyboardInterrupt try: waitThread.join() except KeyboardInterrupt: hresult = SCardCancel(self.hcontext) if hresult != SCARD_S_SUCCESS: raise CardRequestException( "Failed to SCardCancel " + SCardGetErrorMessage(hresult), hresult=hresult, ) # wait for the thread to finish in case of KeyboardInterrupt self.evt.wait(timeout=None) # get values set in the getStatusChange thread hresult = self.hresult newstates = self.newstates # compute remaining timeout if self.timeout != INFINITE: delta = datetime.now() - startDate self.timeout -= int(delta.total_seconds() * 1000) if self.timeout < 0: self.timeout = 0 # time-out if hresult in (SCARD_E_TIMEOUT, SCARD_E_CANCELLED): raise CardRequestTimeoutException(hresult=hresult) # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # this happens on Windows when the last reader is disconnected elif hresult in (SCARD_E_SYSTEM_CANCELLED, SCARD_E_NO_SERVICE): pass # some error happened elif SCARD_S_SUCCESS != hresult: raise CardRequestException( "Failed to get status change " + SCardGetErrorMessage(hresult), hresult=hresult, ) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and eventstate & ( SCARD_STATE_CHANGED | SCARD_STATE_PRESENT ): eventstate = eventstate & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if ( self.newcardonly and eventstate & SCARD_STATE_PRESENT and eventstate & SCARD_STATE_CHANGED ) or (not self.newcardonly and eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports("dummy"): cardfound = True return self.cardServiceClass(reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) def waitforcardevent(self): """Wait for card insertion or removal.""" AbstractCardRequest.waitforcardevent(self) presentcards = [] startDate = datetime.now() eventfound = False self.timeout = self.timeout_init previous_readernames = self.getReaderNames() while not eventfound: # get states from previous run readerstates = self.readerstates # reinitialize at each iteration just in case a new reader appeared _readernames = self.getReaderNames() readernames = _readernames if self.readersAsked is None: # add PnP special reader readernames.append("\\\\?PnP?\\Notification") # first call? if len(readerstates) == 0: # init for reader in readernames: # create a dictionary entry for new readers readerstates[reader] = (reader, SCARD_STATE_UNAWARE) hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values()) ) # check if a new reader with a card has just been connected for reader in _readernames: # is the reader a new one? if reader not in readerstates: # create a dictionary entry for new reader readerstates[reader] = (reader, SCARD_STATE_UNAWARE) hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values()) ) # added reader is the last one (index is -1) _, state, _ = newstates[-1] if state & SCARD_STATE_PRESENT: eventfound = True # check if a reader has been removed to_remove = [] for reader in readerstates: if reader not in readernames: _, state = readerstates[reader] # was the card present? if state & SCARD_STATE_PRESENT: eventfound = True to_remove.append(reader) if to_remove: for reader in to_remove: # remove reader del readerstates[reader] # get newstates with new reader list hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values()) ) if eventfound: break # update previous readers list (without PnP special reader) previous_readernames = _readernames # wait for card insertion self.readerstates = readerstates waitThread = threading.Thread(target=self.getStatusChange) waitThread.start() # the main thread handles a possible KeyboardInterrupt try: waitThread.join() except KeyboardInterrupt: hresult = SCardCancel(self.hcontext) if hresult != SCARD_S_SUCCESS: raise CardRequestException( "Failed to SCardCancel " + SCardGetErrorMessage(hresult), hresult=hresult, ) # wait for the thread to finish in case of KeyboardInterrupt self.evt.wait(timeout=None) # get values set in the getStatusChange thread hresult = self.hresult newstates = self.newstates # compute remaining timeout if self.timeout != INFINITE: delta = datetime.now() - startDate self.timeout -= int(delta.total_seconds() * 1000) if self.timeout < 0: self.timeout = 0 # time-out if hresult in (SCARD_E_TIMEOUT, SCARD_E_CANCELLED): raise CardRequestTimeoutException(hresult=hresult) # the reader was unplugged during the loop elif SCARD_E_UNKNOWN_READER == hresult: pass # this happens on Windows when the last reader is disconnected elif hresult in (SCARD_E_SYSTEM_CANCELLED, SCARD_E_NO_SERVICE): pass # some error happened elif SCARD_S_SUCCESS != hresult: raise CardRequestException( "Failed to get status change " + SCardGetErrorMessage(hresult), hresult=hresult, ) # something changed! else: for state in newstates: readername, eventstate, atr = state # ignore PnP reader if readername == "\\\\?PnP?\\Notification": continue if eventstate & SCARD_STATE_CHANGED: eventfound = True # update readerstates for next SCardGetStatusChange() call self.readerstates = {} for reader, state, atr in newstates: self.readerstates[reader] = (reader, state) # return all the cards present for state in newstates: readername, eventstate, atr = state if readername == "\\\\?PnP?\\Notification": continue if eventstate & SCARD_STATE_PRESENT: presentcards.append(Card.Card(readername, atr)) return presentcards if __name__ == "__main__": """Small sample illustrating the use of PCSCCardRequest.py.""" from smartcard.util import toHexString print("Insert a new card within 10 seconds") cr = PCSCCardRequest(timeout=10, newcardonly=True) cs = cr.waitforcard() cs.connection.connect() print(cs.connection.getReader() + " " + toHexString(cs.connection.getATR())) cs.connection.disconnect() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729430932.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCContext.py0000644000076500000240000000413514705202624021125 0ustar00rousseaustaff"""PCSC context singleton. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from threading import RLock from smartcard.pcsc.PCSCExceptions import EstablishContextException from smartcard.scard import * class PCSCContext: """Manage a singleton pcsc context handle.""" class __PCSCContextSingleton: """The actual pcsc context class as a singleton.""" def __init__(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) def getContext(self): return self.hcontext def releaseContext(self): return SCardReleaseContext(self.hcontext) # the singleton mutex = RLock() instance = None def __init__(self): with PCSCContext.mutex: if not PCSCContext.instance: self.renewContext() def __getattr__(self, name): if self.instance: return getattr(self.instance, name) @staticmethod def renewContext(): with PCSCContext.mutex: if PCSCContext.instance is not None: PCSCContext.instance.releaseContext() PCSCContext.instance = PCSCContext.__PCSCContextSingleton() return PCSCContext.instance.getContext() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCExceptions.py0000644000076500000240000000771014677317744021646 0ustar00rousseaustaff"""Smartcard module exceptions. This module defines the exceptions raised by the smartcard.pcsc modules. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # gemalto scard library import smartcard.scard class BaseSCardException(Exception): """Base class for scard (aka PCSC) exceptions. scard exceptions are raised by the scard module, i.e. low-level PCSC access to readers and cards. """ def __init__(self, hresult=-1, message="", *args): """Constructor that stores the pcsc error status.""" if not message: message = "scard exception" super().__init__(message, *args) self.message = message self.hresult = hresult def __str__(self): """Returns a string representation of the exception.""" text = super().__str__() if self.hresult != -1: hresult = self.hresult if hresult < 0: # convert 0x-7FEFFFE3 into 0x8010001D hresult += 0x100000000 text += f": {smartcard.scard.SCardGetErrorMessage(self.hresult)} (0x{hresult:08X})" return text class AddReaderToGroupException(BaseSCardException): """Raised when scard fails to add a new reader to a PCSC reader group.""" def __init__(self, hresult, readername="", groupname=""): super().__init__( message="Failed to add reader: " + readername + " to group: " + groupname, hresult=hresult, ) self.readername = readername self.groupname = groupname class EstablishContextException(BaseSCardException): """Raised when scard failed to establish context with PCSC.""" def __init__(self, hresult): super().__init__(message="Failed to establish context", hresult=hresult) class ListReadersException(BaseSCardException): """Raised when scard failed to list readers.""" def __init__(self, hresult): super().__init__(message="Failed to list readers", hresult=hresult) class IntroduceReaderException(BaseSCardException): """Raised when scard fails to introduce a new reader to PCSC.""" def __init__(self, hresult, readername=""): super().__init__( message="Failed to introduce a new reader: " + readername, hresult=hresult ) self.readername = readername class ReleaseContextException(BaseSCardException): """Raised when scard failed to release PCSC context.""" def __init__(self, hresult): super().__init__(message="Failed to release context", hresult=hresult) class RemoveReaderFromGroupException(BaseSCardException): """Raised when scard fails to remove a reader from a PCSC reader group.""" def __init__(self, hresult, readername="", groupname=""): BaseSCardException.__init__(self, hresult) self.readername = readername self.groupname = groupname super().__init__( message="Failed to remove reader: " + readername + " from group: " + groupname, hresult=hresult, ) if __name__ == "__main__": try: raise EstablishContextException(smartcard.scard.SCARD_E_NO_MEMORY) except BaseSCardException as exc: print(exc) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCPart10.py0000644000076500000240000002205714677317744020575 0ustar00rousseaustaff"""PCSCPart10: PC/SC Part 10 (pinpad) __author__ = "Ludovic Rousseau" Copyright 2009-2010 Ludovic Rosseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.scard import * # constants defined in PC/SC v2 Part 10 CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) FEATURE_VERIFY_PIN_START = 0x01 FEATURE_VERIFY_PIN_FINISH = 0x02 FEATURE_MODIFY_PIN_START = 0x03 FEATURE_MODIFY_PIN_FINISH = 0x04 FEATURE_GET_KEY_PRESSED = 0x05 FEATURE_VERIFY_PIN_DIRECT = 0x06 FEATURE_MODIFY_PIN_DIRECT = 0x07 FEATURE_MCT_READER_DIRECT = 0x08 FEATURE_MCT_UNIVERSAL = 0x09 FEATURE_IFD_PIN_PROPERTIES = 0x0A FEATURE_ABORT = 0x0B FEATURE_SET_SPE_MESSAGE = 0x0C FEATURE_VERIFY_PIN_DIRECT_APP_ID = 0x0D FEATURE_MODIFY_PIN_DIRECT_APP_ID = 0x0E FEATURE_WRITE_DISPLAY = 0x0F FEATURE_GET_KEY = 0x10 FEATURE_IFD_DISPLAY_PROPERTIES = 0x11 FEATURE_GET_TLV_PROPERTIES = 0x12 FEATURE_CCID_ESC_COMMAND = 0x13 Features = { "FEATURE_VERIFY_PIN_START": FEATURE_VERIFY_PIN_START, "FEATURE_VERIFY_PIN_FINISH": FEATURE_VERIFY_PIN_FINISH, "FEATURE_MODIFY_PIN_START": FEATURE_MODIFY_PIN_START, "FEATURE_MODIFY_PIN_FINISH": FEATURE_MODIFY_PIN_FINISH, "FEATURE_GET_KEY_PRESSED": FEATURE_GET_KEY_PRESSED, "FEATURE_VERIFY_PIN_DIRECT": FEATURE_VERIFY_PIN_DIRECT, "FEATURE_MODIFY_PIN_DIRECT": FEATURE_MODIFY_PIN_DIRECT, "FEATURE_MCT_READER_DIRECT": FEATURE_MCT_READER_DIRECT, "FEATURE_MCT_UNIVERSAL": FEATURE_MCT_UNIVERSAL, "FEATURE_IFD_PIN_PROPERTIES": FEATURE_IFD_PIN_PROPERTIES, "FEATURE_ABORT": FEATURE_ABORT, "FEATURE_SET_SPE_MESSAGE": FEATURE_SET_SPE_MESSAGE, "FEATURE_VERIFY_PIN_DIRECT_APP_ID": FEATURE_VERIFY_PIN_DIRECT_APP_ID, "FEATURE_MODIFY_PIN_DIRECT_APP_ID": FEATURE_MODIFY_PIN_DIRECT_APP_ID, "FEATURE_WRITE_DISPLAY": FEATURE_WRITE_DISPLAY, "FEATURE_GET_KEY": FEATURE_GET_KEY, "FEATURE_IFD_DISPLAY_PROPERTIES": FEATURE_IFD_DISPLAY_PROPERTIES, "FEATURE_GET_TLV_PROPERTIES": FEATURE_GET_TLV_PROPERTIES, "FEATURE_CCID_ESC_COMMAND": FEATURE_CCID_ESC_COMMAND, } # properties returned by FEATURE_GET_TLV_PROPERTIES PCSCv2_PART10_PROPERTY_wLcdLayout = 1 PCSCv2_PART10_PROPERTY_bEntryValidationCondition = 2 PCSCv2_PART10_PROPERTY_bTimeOut2 = 3 PCSCv2_PART10_PROPERTY_wLcdMaxCharacters = 4 PCSCv2_PART10_PROPERTY_wLcdMaxLines = 5 PCSCv2_PART10_PROPERTY_bMinPINSize = 6 PCSCv2_PART10_PROPERTY_bMaxPINSize = 7 PCSCv2_PART10_PROPERTY_sFirmwareID = 8 PCSCv2_PART10_PROPERTY_bPPDUSupport = 9 PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize = 10 PCSCv2_PART10_PROPERTY_wIdVendor = 11 PCSCv2_PART10_PROPERTY_wIdProduct = 12 Properties = { "PCSCv2_PART10_PROPERTY_wLcdLayout": PCSCv2_PART10_PROPERTY_wLcdLayout, "PCSCv2_PART10_PROPERTY_bEntryValidationCondition": PCSCv2_PART10_PROPERTY_bEntryValidationCondition, "PCSCv2_PART10_PROPERTY_bTimeOut2": PCSCv2_PART10_PROPERTY_bTimeOut2, "PCSCv2_PART10_PROPERTY_wLcdMaxCharacters": PCSCv2_PART10_PROPERTY_wLcdMaxCharacters, "PCSCv2_PART10_PROPERTY_wLcdMaxLines": PCSCv2_PART10_PROPERTY_wLcdMaxLines, "PCSCv2_PART10_PROPERTY_bMinPINSize": PCSCv2_PART10_PROPERTY_bMinPINSize, "PCSCv2_PART10_PROPERTY_bMaxPINSize": PCSCv2_PART10_PROPERTY_bMaxPINSize, "PCSCv2_PART10_PROPERTY_sFirmwareID": PCSCv2_PART10_PROPERTY_sFirmwareID, "PCSCv2_PART10_PROPERTY_bPPDUSupport": PCSCv2_PART10_PROPERTY_bPPDUSupport, "PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize": PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize, "PCSCv2_PART10_PROPERTY_wIdVendor": PCSCv2_PART10_PROPERTY_wIdVendor, "PCSCv2_PART10_PROPERTY_wIdProduct": PCSCv2_PART10_PROPERTY_wIdProduct, } # we already have: Features['FEATURE_x'] = FEATURE_x # we will now also have: Features[FEATURE_x] = 'FEATURE_x' for k in list(Features.keys()): Features[Features[k]] = k for k in list(Properties.keys()): Properties[Properties[k]] = k def parseFeatureRequest(response): """Get the list of Part10 features supported by the reader. @param response: result of L{CM_IOCTL_GET_FEATURE_REQUEST} command @rtype: list @return: a list of list C{[[tag1, value1], [tag2, value2]]} """ features = [] while len(response) > 0: tag = response[0] control = ( ((((response[2] << 8) + response[3]) << 8) + response[4]) << 8 ) + response[5] try: features.append([Features[tag], control]) except KeyError: pass del response[:6] return features def getFeatureRequest(cardConnection): """Get the list of Part10 features supported by the reader. @param cardConnection: L{CardConnection} object @rtype: list @return: a list of list C{[[tag1, value1], [tag2, value2]]} """ response = cardConnection.control(CM_IOCTL_GET_FEATURE_REQUEST, []) return parseFeatureRequest(response) def hasFeature(featureList, feature): """return the controlCode for a feature or None @param feature: feature to look for @param featureList: feature list as returned by L{getFeatureRequest()} @return: feature value or None """ for f in featureList: if f[0] == feature or Features[f[0]] == feature: return f[1] def getPinProperties(cardConnection, featureList=None, controlCode=None): """return the C{PIN_PROPERTIES} structure @param cardConnection: L{CardConnection} object @param featureList: feature list as returned by L{getFeatureRequest()} @param controlCode: control code for L{FEATURE_IFD_PIN_PROPERTIES} @rtype: dict @return: a dict""" if controlCode is None: if featureList is None: featureList = getFeatureRequest(cardConnection) controlCode = hasFeature(featureList, FEATURE_IFD_PIN_PROPERTIES) if controlCode is None: return {"raw": []} response = cardConnection.control(controlCode, []) d = { "raw": response, "LcdLayoutX": response[0], "LcdLayoutY": response[1], "EntryValidationCondition": response[2], "TimeOut2": response[3], } return d def getTlvProperties(cardConnection, featureList=None, controlCode=None): """return the C{GET_TLV_PROPERTIES} structure @param cardConnection: L{CardConnection} object @param featureList: feature list as returned by L{getFeatureRequest()} @param controlCode: control code for L{FEATURE_GET_TLV_PROPERTIES} @rtype: dict @return: a dict""" if controlCode is None: if featureList is None: featureList = getFeatureRequest(cardConnection) controlCode = hasFeature(featureList, FEATURE_GET_TLV_PROPERTIES) if controlCode is None: return {"raw": []} response = cardConnection.control(controlCode, []) return parseTlvProperties(response) def parseTlvProperties(response): """return the GET_TLV_PROPERTIES structure @param response: result of L{FEATURE_GET_TLV_PROPERTIES} @rtype: dict @return: a dict""" d = { "raw": response, } # create a new list to consume it tmp = list(response) while tmp: tag = tmp[0] len = tmp[1] data = tmp[2 : 2 + len] if PCSCv2_PART10_PROPERTY_sFirmwareID == tag: # convert to a string data = "".join([chr(c) for c in data]) # we now suppose the value is an integer elif 1 == len: # byte data = data[0] elif 2 == len: # 16 bits value data = data[1] * 256 + data[0] elif 4 == len: # 32 bits value data = ((data[3] * 256 + data[2]) * 256 + data[1]) * 256 + data[0] # store the value in the dictionary try: d[Properties[tag]] = data except KeyError: d["UNKNOWN"] = data del tmp[0 : 2 + len] return d if __name__ == "__main__": """Small sample illustrating the use of PCSCPart10.""" from smartcard.pcsc.PCSCReader import PCSCReader cc = PCSCReader.readers()[0].createConnection() cc.connect(mode=SCARD_SHARE_DIRECT) # print(cc.control(CM_IOCTL_GET_FEATURE_REQUEST)) features = getFeatureRequest(cc) print(features) print(hasFeature(features, FEATURE_VERIFY_PIN_START)) print(hasFeature(features, FEATURE_VERIFY_PIN_DIRECT)) properties = getPinProperties(cc) print("\nPinProperties:") for k, v in list(properties.items()): print(f" {k}: {v}") print("\nTlvProperties:") properties = getTlvProperties(cc) for k, v in list(properties.items()): print(f" {k}: {v}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCReader.py0000644000076500000240000001176414703301034020702 0ustar00rousseaustaff"""PCSCReader: concrete reader class for PCSC Readers __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.Exceptions import * from smartcard.pcsc.PCSCCardConnection import PCSCCardConnection from smartcard.pcsc.PCSCContext import PCSCContext from smartcard.pcsc.PCSCExceptions import * from smartcard.reader.Reader import Reader from smartcard.scard import * def __PCSCreaders__(hcontext, groups=None): """Returns the list of PCSC smartcard readers in PCSC group. If group is not specified, returns the list of all PCSC smartcard readers. """ if groups is None: groups = [] elif isinstance(groups, str): groups = [groups] hresult, readers = SCardListReaders(hcontext, groups) if hresult != SCARD_S_SUCCESS: if hresult == SCARD_E_NO_READERS_AVAILABLE: readers = [] elif hresult == SCARD_E_SERVICE_STOPPED: raise CardServiceStoppedException(hresult=hresult) elif hresult == SCARD_E_NO_SERVICE: raise CardServiceNotFoundException(hresult=hresult) else: raise ListReadersException(hresult) return readers class PCSCReader(Reader): """PCSC reader class.""" def __init__(self, readername): """Constructs a new PCSC reader.""" Reader.__init__(self, readername) def addtoreadergroup(self, groupname): """Add reader to a reader group.""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if SCARD_S_SUCCESS != hresult: raise EstablishContextException(hresult) try: hresult = SCardIntroduceReader(hcontext, self.name, self.name) if SCARD_S_SUCCESS != hresult and SCARD_E_DUPLICATE_READER != hresult: raise IntroduceReaderException(hresult, self.name) hresult = SCardAddReaderToGroup(hcontext, self.name, groupname) if SCARD_S_SUCCESS != hresult: raise AddReaderToGroupException(hresult, self.name, groupname) finally: hresult = SCardReleaseContext(hcontext) if SCARD_S_SUCCESS != hresult: raise ReleaseContextException(hresult) def removefromreadergroup(self, groupname): """Remove a reader from a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if SCARD_S_SUCCESS != hresult: raise EstablishContextException(hresult) try: hresult = SCardRemoveReaderFromGroup(hcontext, self.name, groupname) if SCARD_S_SUCCESS != hresult: raise RemoveReaderFromGroupException(hresult, self.name, groupname) finally: hresult = SCardReleaseContext(hcontext) if SCARD_S_SUCCESS != hresult: raise ReleaseContextException(hresult) def createConnection(self): """Return a card connection thru PCSC reader.""" return CardConnectionDecorator(PCSCCardConnection(self.name)) class Factory: @staticmethod def create(readername): return PCSCReader(readername) @staticmethod def readers(groups=None): if groups is None: groups = [] creaders = [] hcontext = PCSCContext().getContext() try: pcsc_readers = __PCSCreaders__(hcontext, groups) except (CardServiceStoppedException, CardServiceNotFoundException): hcontext = PCSCContext.renewContext() pcsc_readers = __PCSCreaders__(hcontext, groups) for reader in pcsc_readers: creaders.append(PCSCReader.Factory.create(reader)) return creaders if __name__ == "__main__": from smartcard.util import * SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] creaders = PCSCReader.readers() for reader in creaders: try: print(reader.name) connection = reader.createConnection() connection.connect() print(toHexString(connection.getATR())) data, sw1, sw2 = connection.transmit(SELECT + DF_TELECOM) print(f"{sw1:02X} {sw2:02X}") except NoCardException: print("no card in reader") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/pcsc/PCSCReaderGroups.py0000644000076500000240000001004114677317744022116 0ustar00rousseaustaff"""PCSCReaderGroups organizes smartcard readers as groups. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.pcsc.PCSCExceptions import * from smartcard.reader.ReaderGroups import innerreadergroups, readergroups from smartcard.scard import * class pcscinnerreadergroups(innerreadergroups): """Smartcard PCSC readers groups inner class. The PCSCReaderGroups singleton manages the creation of the unique instance of this class. """ def __init__(self, initlist=None): """Constructor.""" innerreadergroups.__init__(self, initlist) self.unremovablegroups = ["SCard$DefaultReaders"] def getreadergroups(self): """Returns the list of smartcard reader groups.""" innerreadergroups.getreadergroups(self) hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) hresult, readers = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise ListReadersException(hresult) hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise ReleaseContextException(hresult) return readers def addreadergroup(self, newgroup): """Add a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if SCARD_S_SUCCESS != hresult: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) try: hresult = SCardIntroduceReaderGroup(hcontext, newgroup) if SCARD_S_SUCCESS != hresult: raise error( "Unable to introduce reader group: " + SCardGetErrorMessage(hresult) ) else: innerreadergroups.addreadergroup(self, newgroup) finally: hresult = SCardReleaseContext(hcontext) if SCARD_S_SUCCESS != hresult: raise error( "Failed to release context: " + SCardGetErrorMessage(hresult) ) def removereadergroup(self, group): """Remove a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if SCARD_S_SUCCESS != hresult: raise error("Failed to establish context: " + SCardGetErrorMessage(hresult)) try: hresult = SCardForgetReaderGroup(hcontext, group) if hresult != SCARD_S_SUCCESS: raise error( "Unable to forget reader group: " + SCardGetErrorMessage(hresult) ) else: innerreadergroups.removereadergroup(self, group) finally: hresult = SCardReleaseContext(hcontext) if SCARD_S_SUCCESS != hresult: raise error( "Failed to release context: " + SCardGetErrorMessage(hresult) ) class PCSCReaderGroups(readergroups): """PCSC readers groups.""" def __init__(self, initlist=None): """Create a single instance of pcscinnerreadergroups on first call""" self.innerclazz = pcscinnerreadergroups readergroups.__init__(self, initlist) if __name__ == "__main__": print(PCSCReaderGroups().getreadergroups()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/pcsc/__init__.py0000644000076500000240000000000014674316735020570 0ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6436698 pyscard-2.2.1/src/smartcard/reader/0000755000076500000240000000000014740753203016770 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/reader/Reader.py0000644000076500000240000000400414677317744020561 0ustar00rousseaustaff"""Smart card Reader abstract class. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class Reader: """Reader abstract class. The reader class is responsible for creating connections with a card. """ def __init__(self, readername): """Constructs a new reader and store readername.""" self.name = readername def addtoreadergroup(self, groupname): """Add reader to a reader group.""" pass def removefromreadergroup(self, groupname): """Remove reader from a reader group.""" pass def createConnection(self): """Returns a card connection thru reader.""" pass def __eq__(self, other): """Returns True if self==other (same name).""" if type(other) == type(self): return self.name == other.name else: return False def __hash__(self): """Returns a hash value for this object (self.name is unique).""" return hash(self.name) def __repr__(self): """Returns card reader name string for `object` calls.""" return "'%s'" % self.name def __str__(self): """Returns card reader name string for str(object) calls.""" return self.name ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/reader/ReaderFactory.py0000644000076500000240000000407414703761333022103 0ustar00rousseaustaff"""ReaderFactory: creates smartcard readers. __author__ = "gemalto https://www.gemalto.com/" Factory pattern implementation borrowed from Thinking in Python, Bruce Eckel, http://mindview.net/Books/TIPython Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import importlib from smartcard.pcsc.PCSCReader import PCSCReader class ReaderFactory: """Class to create readers from reader type id.""" factories = {} factorymethods = [PCSCReader.readers] # A Template Method: @staticmethod def createReader(clazz: str, readername: str): """Static method to create a reader from a reader clazz. @param clazz: the reader class name @param readername: the reader name """ if clazz not in ReaderFactory.factories: module_name, _, class_name = clazz.rpartition(".") imported_module = importlib.import_module(module_name) imported_class = getattr(imported_module, class_name) ReaderFactory.factories[clazz] = imported_class.Factory() return ReaderFactory.factories[clazz].create(readername) @staticmethod def readers(groups=None): if groups is None: groups = [] zreaders = [] for fm in ReaderFactory.factorymethods: zreaders += fm(groups) return zreaders ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/reader/ReaderGroups.py0000644000076500000240000000630414677317744021766 0ustar00rousseaustaff"""ReaderGroups manages smart card reader in groups. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from smartcard.Exceptions import SmartcardException from smartcard.ulist import ulist class BadReaderGroupException(SmartcardException): """Raised when trying to add an invalid reader group.""" def __init__(self): SmartcardException.__init__(self, "Invalid reader group") class innerreadergroups(ulist): """Smartcard readers groups private class. The readergroups singleton manages the creation of the unique instance of this class. """ def __init__(self, initlist=None): """Retrieve and store list of reader groups""" if initlist is None: initlist = self.getreadergroups() or [] ulist.__init__(self, initlist) self.unremovablegroups = [] def __onadditem__(self, item): """Called when a reader group is added.""" self.addreadergroup(item) def __onremoveitem__(self, item): """Called when a reader group is added.""" self.removereadergroup(item) def __iter__(self): return ulist.__iter__(self) # # abstract methods implemented in subclasses # def getreadergroups(self): """Returns the list of smartcard reader groups.""" return [] def addreadergroup(self, newgroup): """Add a reader group""" if not isinstance(newgroup, str): raise BadReaderGroupException self += newgroup def removereadergroup(self, group): """Remove a reader group""" if not isinstance(group, str): raise BadReaderGroupException self.remove(group) def addreadertogroup(self, readername, groupname): """Add a reader to a reader group""" pass def removereaderfromgroup(self, readername, groupname): """Remove a reader from a reader group""" pass class readergroups: """ReadersGroups organizes smart card reader as groups.""" """The single instance of __readergroups""" instance = None innerclazz = innerreadergroups def __init__(self, initlist=None): """Create a single instance of innerreadergroups on first call""" if readergroups.instance is None: readergroups.instance = self.innerclazz(initlist) """All operators redirected to inner class.""" def __getattr__(self, name): return getattr(self.instance, name) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/reader/__init__.py0000644000076500000240000000000014674316735021102 0ustar00rousseaustaff././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6539009 pyscard-2.2.1/src/smartcard/scard/0000755000076500000240000000000014740753203016622 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/PcscDefs.i0000644000076500000240000003251114677317744020507 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ typedef enum { SCARD_SCOPE_USER, SCARD_SCOPE_TERMINAL, SCARD_SCOPE_SYSTEM } ScopeType ; typedef enum { SCARD_SHARE_SHARED, SCARD_SHARE_EXCLUSIVE, SCARD_SHARE_DIRECT } ShareType ; typedef enum { SCARD_LEAVE_CARD, SCARD_RESET_CARD, SCARD_UNPOWER_CARD, SCARD_EJECT_CARD } DispositionType ; typedef enum { SCARD_STATE_UNAWARE, SCARD_STATE_IGNORE, SCARD_STATE_CHANGED, SCARD_STATE_UNKNOWN, SCARD_STATE_UNAVAILABLE, SCARD_STATE_EMPTY, SCARD_STATE_PRESENT, SCARD_STATE_ATRMATCH, SCARD_STATE_EXCLUSIVE, SCARD_STATE_INUSE, SCARD_STATE_MUTE } StateType ; // SCARD_STATE_UNPOWERED is not defined on Windows and old Mac OS X %constant unsigned long SCARD_STATE_UNPOWERED = 0x0400 ; // protocols #ifdef WIN32 typedef enum { SCARD_PROTOCOL_UNDEFINED, SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_Tx, SCARD_PROTOCOL_DEFAULT, SCARD_PROTOCOL_OPTIMAL } ProtocolType ; // define pcsc lite constants for winscard %constant unsigned long SCARD_PROTOCOL_UNSET = SCARD_PROTOCOL_UNDEFINED ; %constant unsigned long SCARD_PROTOCOL_ANY = SCARD_PROTOCOL_Tx ; %constant unsigned long SCARD_PROTOCOL_T15 = 0x00000008 ; #endif #ifdef PCSCLITE #ifdef __APPLE__ typedef enum { SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_ANY } ProtocolType ; %constant unsigned long SCARD_PROTOCOL_UNSET = SCARD_PROTOCOL_ANY ; %constant unsigned long SCARD_PROTOCOL_T15 = 0x00000008 ; %constant unsigned long SCARD_PROTOCOL_UNDEFINED = 0 ; %constant unsigned long SCARD_PROTOCOL_OPTIMAL = SCARD_PROTOCOL_ANY ; #else //__APPLE__ typedef enum { SCARD_PROTOCOL_UNSET, SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_T15, SCARD_PROTOCOL_ANY } ProtocolType ; %constant unsigned long SCARD_PROTOCOL_UNDEFINED = SCARD_PROTOCOL_UNSET ; %constant unsigned long SCARD_PROTOCOL_OPTIMAL = SCARD_PROTOCOL_UNSET ; #endif //!__APPLE__ // define winscard constants for pcsc lite %constant unsigned long SCARD_PROTOCOL_Tx = SCARD_PROTOCOL_ANY ; %constant unsigned long SCARD_PROTOCOL_DEFAULT = SCARD_PROTOCOL_ANY ; #endif //PCSCLITE %constant unsigned long SCARD_PCI_T0 = 0x01 ; %constant unsigned long SCARD_PCI_T1 = 0x02 ; %constant unsigned long SCARD_PCI_RAW = 0x04 ; #ifdef WIN32 typedef enum { SCARD_PROVIDER_PRIMARY, SCARD_PROVIDER_CSP } ProviderType ; typedef enum { SCARD_ATTR_VENDOR_NAME, SCARD_ATTR_VENDOR_IFD_TYPE, SCARD_ATTR_VENDOR_IFD_VERSION, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, SCARD_ATTR_CHANNEL_ID, SCARD_ATTR_DEFAULT_CLK, SCARD_ATTR_MAX_CLK, SCARD_ATTR_DEFAULT_DATA_RATE, SCARD_ATTR_MAX_DATA_RATE, SCARD_ATTR_MAX_IFSD, SCARD_ATTR_POWER_MGMT_SUPPORT, SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE, SCARD_ATTR_USER_AUTH_INPUT_DEVICE, SCARD_ATTR_CHARACTERISTICS, SCARD_ATTR_CURRENT_PROTOCOL_TYPE, SCARD_ATTR_CURRENT_CLK, SCARD_ATTR_CURRENT_F, SCARD_ATTR_CURRENT_D, SCARD_ATTR_CURRENT_N, SCARD_ATTR_CURRENT_W, SCARD_ATTR_CURRENT_IFSC, SCARD_ATTR_CURRENT_IFSD, SCARD_ATTR_CURRENT_BWT, SCARD_ATTR_CURRENT_CWT, SCARD_ATTR_CURRENT_EBC_ENCODING, SCARD_ATTR_EXTENDED_BWT, SCARD_ATTR_ICC_PRESENCE, SCARD_ATTR_ICC_INTERFACE_STATUS, SCARD_ATTR_CURRENT_IO_STATE, SCARD_ATTR_ATR_STRING, SCARD_ATTR_ICC_TYPE_PER_ATR, SCARD_ATTR_ESC_RESET, SCARD_ATTR_ESC_CANCEL, SCARD_ATTR_ESC_AUTHREQUEST, SCARD_ATTR_MAXINPUT, SCARD_ATTR_DEVICE_UNIT, SCARD_ATTR_DEVICE_IN_USE, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, SCARD_ATTR_DEVICE_SYSTEM_NAME_A, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, SCARD_ATTR_DEVICE_SYSTEM_NAME_W, SCARD_ATTR_SUPRESS_T1_IFS_REQUEST } AttributeType ; typedef enum { // from winerror.h ERROR_ALREADY_EXISTS } ErrorTypeWin32Only; #endif // WIN32 #ifdef PCSCLITE typedef enum { SCARD_ATTR_VENDOR_NAME , SCARD_ATTR_VENDOR_IFD_TYPE , SCARD_ATTR_VENDOR_IFD_VERSION , SCARD_ATTR_VENDOR_IFD_SERIAL_NO , SCARD_ATTR_CHANNEL_ID , SCARD_ATTR_ASYNC_PROTOCOL_TYPES , SCARD_ATTR_DEFAULT_CLK , SCARD_ATTR_MAX_CLK , SCARD_ATTR_DEFAULT_DATA_RATE , SCARD_ATTR_MAX_DATA_RATE , SCARD_ATTR_MAX_IFSD , SCARD_ATTR_SYNC_PROTOCOL_TYPES , SCARD_ATTR_POWER_MGMT_SUPPORT , SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE , SCARD_ATTR_USER_AUTH_INPUT_DEVICE , SCARD_ATTR_CHARACTERISTICS , SCARD_ATTR_CURRENT_PROTOCOL_TYPE , SCARD_ATTR_CURRENT_CLK , SCARD_ATTR_CURRENT_F , SCARD_ATTR_CURRENT_D , SCARD_ATTR_CURRENT_N , SCARD_ATTR_CURRENT_W , SCARD_ATTR_CURRENT_IFSC , SCARD_ATTR_CURRENT_IFSD , SCARD_ATTR_CURRENT_BWT , SCARD_ATTR_CURRENT_CWT , SCARD_ATTR_CURRENT_EBC_ENCODING , SCARD_ATTR_EXTENDED_BWT , SCARD_ATTR_ICC_PRESENCE , SCARD_ATTR_ICC_INTERFACE_STATUS , SCARD_ATTR_CURRENT_IO_STATE , SCARD_ATTR_ATR_STRING , SCARD_ATTR_ICC_TYPE_PER_ATR , SCARD_ATTR_ESC_RESET , SCARD_ATTR_ESC_CANCEL , SCARD_ATTR_ESC_AUTHREQUEST , SCARD_ATTR_MAXINPUT , SCARD_ATTR_DEVICE_UNIT , SCARD_ATTR_DEVICE_IN_USE , SCARD_ATTR_DEVICE_FRIENDLY_NAME_A , SCARD_ATTR_DEVICE_SYSTEM_NAME_A , SCARD_ATTR_DEVICE_FRIENDLY_NAME_W , SCARD_ATTR_DEVICE_SYSTEM_NAME_W , SCARD_ATTR_SUPRESS_T1_IFS_REQUEST } AttributeType ; %constant unsigned long SCARD_ATTR_DEVICE_FRIENDLY_NAME = SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ; %constant unsigned long SCARD_ATTR_DEVICE_SYSTEM_NAME = SCARD_ATTR_DEVICE_SYSTEM_NAME_A ; #endif //PCSCLITE /* int and unsigned long are different on 64-bits systems */ #ifdef __APPLE__ #define TYPE int #else #define TYPE long #endif %constant TYPE SCARD_S_SUCCESS = SCARD_S_SUCCESS ; %constant TYPE SCARD_F_INTERNAL_ERROR = SCARD_F_INTERNAL_ERROR ; %constant TYPE SCARD_E_CANCELLED = SCARD_E_CANCELLED ; %constant TYPE SCARD_E_INVALID_HANDLE = SCARD_E_INVALID_HANDLE ; %constant TYPE SCARD_E_INVALID_PARAMETER = SCARD_E_INVALID_PARAMETER ; %constant TYPE SCARD_E_INVALID_TARGET = SCARD_E_INVALID_TARGET ; %constant TYPE SCARD_E_NO_MEMORY = SCARD_E_NO_MEMORY ; %constant TYPE SCARD_F_WAITED_TOO_LONG = SCARD_F_WAITED_TOO_LONG ; %constant TYPE SCARD_E_INSUFFICIENT_BUFFER = SCARD_E_INSUFFICIENT_BUFFER ; %constant TYPE SCARD_E_UNKNOWN_READER = SCARD_E_UNKNOWN_READER ; %constant TYPE SCARD_E_TIMEOUT = SCARD_E_TIMEOUT ; %constant TYPE SCARD_E_SHARING_VIOLATION = SCARD_E_SHARING_VIOLATION ; %constant TYPE SCARD_E_NO_SMARTCARD = SCARD_E_NO_SMARTCARD ; %constant TYPE SCARD_E_UNKNOWN_CARD = SCARD_E_UNKNOWN_CARD ; %constant TYPE SCARD_E_CANT_DISPOSE = SCARD_E_CANT_DISPOSE ; %constant TYPE SCARD_E_PROTO_MISMATCH = SCARD_E_PROTO_MISMATCH ; %constant TYPE SCARD_E_NOT_READY = SCARD_E_NOT_READY ; %constant TYPE SCARD_E_INVALID_VALUE = SCARD_E_INVALID_VALUE ; %constant TYPE SCARD_E_SYSTEM_CANCELLED = SCARD_E_SYSTEM_CANCELLED ; %constant TYPE SCARD_F_COMM_ERROR = SCARD_F_COMM_ERROR ; %constant TYPE SCARD_F_UNKNOWN_ERROR = SCARD_F_UNKNOWN_ERROR ; %constant TYPE SCARD_E_INVALID_ATR = SCARD_E_INVALID_ATR ; %constant TYPE SCARD_E_NOT_TRANSACTED = SCARD_E_NOT_TRANSACTED ; %constant TYPE SCARD_E_READER_UNAVAILABLE = SCARD_E_READER_UNAVAILABLE ; %constant TYPE SCARD_E_PCI_TOO_SMALL = SCARD_E_PCI_TOO_SMALL ; %constant TYPE SCARD_E_READER_UNSUPPORTED = SCARD_E_READER_UNSUPPORTED ; %constant TYPE SCARD_E_DUPLICATE_READER = SCARD_E_DUPLICATE_READER ; %constant TYPE SCARD_E_CARD_UNSUPPORTED = SCARD_E_CARD_UNSUPPORTED ; %constant TYPE SCARD_E_NO_SERVICE = SCARD_E_NO_SERVICE ; %constant TYPE SCARD_E_SERVICE_STOPPED = SCARD_E_SERVICE_STOPPED ; #ifdef SCARD_E_NO_READERS_AVAILABLE %constant TYPE SCARD_E_NO_READERS_AVAILABLE = SCARD_E_NO_READERS_AVAILABLE ; #else %constant TYPE SCARD_E_NO_READERS_AVAILABLE = 0x8010002E ; #endif %constant TYPE SCARD_E_UNSUPPORTED_FEATURE = SCARD_E_UNSUPPORTED_FEATURE ; %constant TYPE SCARD_W_UNSUPPORTED_CARD = SCARD_W_UNSUPPORTED_CARD ; %constant TYPE SCARD_W_UNRESPONSIVE_CARD = SCARD_W_UNRESPONSIVE_CARD ; %constant TYPE SCARD_W_UNPOWERED_CARD = SCARD_W_UNPOWERED_CARD ; %constant TYPE SCARD_W_RESET_CARD = SCARD_W_RESET_CARD ; %constant TYPE SCARD_W_REMOVED_CARD = SCARD_W_REMOVED_CARD ; #ifdef SCARD_W_SECURITY_VIOLATION /* introduced in pcsc-lite > 1.5.2 */ %constant TYPE SCARD_W_SECURITY_VIOLATION = SCARD_W_SECURITY_VIOLATION ; %constant TYPE SCARD_W_WRONG_CHV = SCARD_W_WRONG_CHV ; %constant TYPE SCARD_W_CHV_BLOCKED = SCARD_W_CHV_BLOCKED ; %constant TYPE SCARD_W_EOF = SCARD_W_EOF ; %constant TYPE SCARD_W_CANCELLED_BY_USER = SCARD_W_CANCELLED_BY_USER ; %constant TYPE SCARD_W_CARD_NOT_AUTHENTICATED = SCARD_W_CARD_NOT_AUTHENTICATED ; %constant TYPE SCARD_E_UNEXPECTED = SCARD_E_UNEXPECTED ; %constant TYPE SCARD_E_ICC_INSTALLATION = SCARD_E_ICC_INSTALLATION ; %constant TYPE SCARD_E_ICC_CREATEORDER = SCARD_E_ICC_CREATEORDER ; %constant TYPE SCARD_E_DIR_NOT_FOUND = SCARD_E_DIR_NOT_FOUND ; %constant TYPE SCARD_E_FILE_NOT_FOUND = SCARD_E_FILE_NOT_FOUND ; %constant TYPE SCARD_E_NO_DIR = SCARD_E_NO_DIR ; %constant TYPE SCARD_E_NO_FILE = SCARD_E_NO_FILE ; %constant TYPE SCARD_E_NO_ACCESS = SCARD_E_NO_ACCESS ; %constant TYPE SCARD_E_WRITE_TOO_MANY = SCARD_E_WRITE_TOO_MANY ; %constant TYPE SCARD_E_BAD_SEEK = SCARD_E_BAD_SEEK ; %constant TYPE SCARD_E_INVALID_CHV = SCARD_E_INVALID_CHV ; %constant TYPE SCARD_E_UNKNOWN_RES_MNG = SCARD_E_UNKNOWN_RES_MNG ; %constant TYPE SCARD_E_NO_SUCH_CERTIFICATE = SCARD_E_NO_SUCH_CERTIFICATE ; %constant TYPE SCARD_E_CERTIFICATE_UNAVAILABLE = SCARD_E_CERTIFICATE_UNAVAILABLE ; %constant TYPE SCARD_E_COMM_DATA_LOST = SCARD_E_COMM_DATA_LOST ; %constant TYPE SCARD_E_NO_KEY_CONTAINER = SCARD_E_NO_KEY_CONTAINER ; %constant TYPE SCARD_E_SERVER_TOO_BUSY = SCARD_E_SERVER_TOO_BUSY ; #else %constant TYPE SCARD_W_SECURITY_VIOLATION = 0x8010006A ; %constant TYPE SCARD_W_WRONG_CHV = 0x8010006B ; %constant TYPE SCARD_W_CHV_BLOCKED = 0x8010006C ; %constant TYPE SCARD_W_EOF = 0x8010006D ; %constant TYPE SCARD_W_CANCELLED_BY_USER = 0x8010006E ; %constant TYPE SCARD_W_CARD_NOT_AUTHENTICATED = 0x8010006F ; %constant TYPE SCARD_E_UNEXPECTED = 0x8010001F ; %constant TYPE SCARD_E_ICC_INSTALLATION = 0x80100020 ; %constant TYPE SCARD_E_ICC_CREATEORDER = 0x80100021 ; %constant TYPE SCARD_E_DIR_NOT_FOUND = 0x80100023 ; %constant TYPE SCARD_E_FILE_NOT_FOUND = 0x80100024 ; %constant TYPE SCARD_E_NO_DIR = 0x80100025 ; %constant TYPE SCARD_E_NO_FILE = 0x80100026 ; %constant TYPE SCARD_E_NO_ACCESS = 0x80100027 ; %constant TYPE SCARD_E_WRITE_TOO_MANY = 0x80100028 ; %constant TYPE SCARD_E_BAD_SEEK = 0x80100029 ; %constant TYPE SCARD_E_INVALID_CHV = 0x8010002A ; %constant TYPE SCARD_E_UNKNOWN_RES_MNG = 0x8010002B ; %constant TYPE SCARD_E_NO_SUCH_CERTIFICATE = 0x8010002C ; %constant TYPE SCARD_E_CERTIFICATE_UNAVAILABLE = 0x8010002D ; %constant TYPE SCARD_E_COMM_DATA_LOST = 0x8010002F ; %constant TYPE SCARD_E_NO_KEY_CONTAINER = 0x80100030 ; %constant TYPE SCARD_E_SERVER_TOO_BUSY = 0x80100031 ; #endif #ifdef WIN32 typedef enum { ERROR_INVALID_HANDLE } Win32ErrorType ; #endif //WIN32 #ifdef PCSCLITE %constant unsigned long INVALID_HANDLE = SCARD_E_INVALID_HANDLE ; #endif //PCSCLITE // this error code is defined outside the enum, since it is available // on winscard only (e.g. not in pcsc lite) %constant unsigned long SCARD_P_SHUTDOWN = 0x80100018 ; // Infinite timeout %constant unsigned long INFINITE = 0x7FFFFFFF ; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/PcscTypemaps.i0000644000076500000240000003463314674316735021433 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ // Tell SWIG to wrap all the wrappers with Python's thread macros %exception { Py_BEGIN_ALLOW_THREADS; $function Py_END_ALLOW_THREADS; } /*============================================================================== // // support for list of BYTEs, aka BYTELIST // ==============================================================================*/ #ifdef SWIG(python) #endif %typemap(in,numinputs=0) BYTELIST *OUTPUT(BYTELIST temp) { $1 = &temp; $1->ab = NULL; $1->bAllocated=FALSE; } // builds a byte list from a Python list %typemap(in) BYTELIST* INPUT(BYTELIST*) { $1 = SCardHelper_PyByteListToBYTELIST( $input ); if (NULL == $1) goto fail; } // release bytelist arg %typemap(freearg) BYTELIST* { if(NULL!=$1) { if(NULL!=$1->ab) { mem_Free( $1->ab ); } if($1->bAllocated==TRUE) { mem_Free( $1 ); } } } // builds a Python list from a byte list %typemap(argout) BYTELIST *OUTPUT { SCardHelper_AppendByteListToPyObject( $1, &$result ); } // other names for BYTELIST as INPUT parameter %apply BYTELIST* INPUT { BYTELIST* ATR }; %apply BYTELIST* INPUT { BYTELIST* ATTRIBUTESIN }; %apply BYTELIST* INPUT { BYTELIST* MASK }; %apply BYTELIST* INPUT { BYTELIST* APDUCOMMAND }; %apply BYTELIST* INPUT { BYTELIST* INBUFFER }; // other names for BYTELIST as OUTPUT parameter %apply BYTELIST* OUTPUT { BYTELIST* ATROUT }; %apply BYTELIST* OUTPUT { BYTELIST* ATTRIBUTES }; %apply BYTELIST* OUTPUT { BYTELIST* APDURESPONSE }; %apply BYTELIST* OUTPUT { BYTELIST* OUTBUFFER }; /*============================================================================== // // support for ERRORSTRING // ==============================================================================*/ // on win32, the ERRORSTRING is allocated and // must be free'd with Local Free // release ERRORSTRING OUTPUT argument. // on pcsc-lite, the error string is not allocated, // i.e. nothing to do. %typemap(ret) ERRORSTRING { #ifdef WIN32 if(NULL!=$1) { HLOCAL hlocal = LocalFree( $1 ); if(NULL!=hlocal) { fprintf( stderr, "Failed to free error message string!\n" ); } } #endif // WIN32 } // builds a Python string from a STRING %typemap(out) ERRORSTRING { SCardHelper_OutErrorStringAsPyObject( $1, &$result ); } /*============================================================================== // // support for GUIDLIST // ==============================================================================*/ %typemap(in,numinputs=0) GUIDLIST *OUTPUT(GUIDLIST temp) { $1 = &temp; $1->bAllocated=FALSE; } // release GUIDLIST INPUT argument // for input arg, GUIDLIST was allocated from the heap // i.e. $1 has to be freed %typemap(freearg) GUIDLIST* INPUT { if(NULL!=$1) { if(NULL!=$1->aguid) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->aguid ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->aguid ); } } mem_Free( $1 ); } } // release GUIDLIST OUTPUT argument // for output arg, GUIDLIST was not allocated // from the heap, but from the stack // i.e. $1 must not be freed %typemap(freearg) GUIDLIST* OUTPUT { if(NULL!=$1) { if(NULL!=$1->aguid) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->aguid ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->aguid ); } } } } // builds a win32 string list from a Python list %typemap(in) GUIDLIST* INPUT(GUIDLIST*) { $1 = SCardHelper_PyGuidListToGUIDLIST( $input ); if (NULL == $1) goto fail; } // builds a Python list from a GUID list %typemap(argout) GUIDLIST *OUTPUT { SCardHelper_AppendGuidListToPyObject( $1, &$result ); } // other names for GUIDLIST as INPUT parameter %apply GUIDLIST* INPUT { GUIDLIST* PRIMARYPROVIDER }; %apply GUIDLIST* INPUT { GUIDLIST* PROVIDERLIST }; // other names for GUIDLIST as OUTPUT parameter %apply GUIDLIST* OUTPUT { GUIDLIST* GUIDINTERFACES }; /*============================================================================== // // support for READERSTATELIST* // ==============================================================================*/ %typemap(in,numinputs=0) READERSTATELIST *OUTPUT(READERSTATELIST temp) { $1 = &temp; } // release READERSTATELIST INPUT/OUTPUT argument // for input arg, READERSTATELIST was allocated from the heap // i.e. $1 has to be freed %typemap(freearg) READERSTATELIST* BOTH { if(NULL!=$1) { int i; for(i=0; i<$1->cRStates; i++ ) { if($1->aszReaderNames[i]) { mem_Free( $1->aszReaderNames[i] ); } } if(NULL!=$1->ars) { mem_Free( $1->ars ); } if(NULL!=$1->aszReaderNames) { mem_Free( $1->aszReaderNames ); } mem_Free( $1 ); } } // release READERSTATELIST OUTPUT argument // for output arg, READERSTATELIST was not allocated // from the heap, but from the stack // i.e. $1 must not be freed %typemap(freearg) READERSTATELIST* OUTPUT { if(NULL!=$1) { int i; for(i=0; i<$1->cRStates; i++ ) { if($1->aszReaderNames[i]) { mem_Free( $1->aszReaderNames[i] ); } } if(NULL!=$1->ars) { mem_Free( $1->ars ); } if(NULL!=$1->aszReaderNames) { mem_Free( $1->aszReaderNames ); } } } // builds a READERSTATE list string list from a Python list %typemap(in) READERSTATELIST *prsl(READERSTATELIST*) { $1 = SCardHelper_PyReaderStateListToREADERSTATELIST( $input ); if (NULL == $1) goto fail; } // builds a Python list from a win32 string list %typemap(argout) READERSTATELIST *prsl { SCardHelper_AppendReaderStateListToPyObject( $1, &$result ); } // reader state list as input and output //%typemap(in) READERSTATELIST *BOTH = READERSTATELIST *prsl; //%typemap(argout) READERSTATELIST *BOTH = READERSTATELIST *prsl; // other names for READERSTATELIST as input/output parameter %apply READERSTATELIST *BOTH {READERSTATELIST* prsl}; /*============================================================================== // // support for SCARDCONTEXT // ==============================================================================*/ %typemap(in,numinputs=0) SCARDCONTEXT *OUTPUT(SCARDCONTEXT temp) { $1 = &temp; } %typemap(in) SCARDCONTEXT hcontext(SCARDCONTEXT) { $1 = SCardHelper_PyScardContextToSCARDCONTEXT( $input ); if (0 == $1) goto fail; } %typemap(argout) SCARDCONTEXT *OUTPUT { SCardHelper_AppendSCardContextToPyObject( *$1, &$result ); } // different names for SCARDCONTEXT OUTPUT parameters %apply SCARDCONTEXT* OUTPUT { SCARDCONTEXT* phcontext }; /*============================================================================== // // support for SCARDDWORDARG // ==============================================================================*/ %typemap(in,numinputs=0) SCARDDWORDARG *OUTPUT(SCARDDWORDARG temp) { $1 = &temp; } %typemap(in) SCARDDWORDARG INPUT(SCARDDWORDARG) { $1 = SCardHelper_PySCardDwordArgToSCARDDWORDARG( $input ); if ((SCARDDWORDARG)-1 == $1) goto fail; } %typemap(argout) SCARDDWORDARG* OUTPUT { SCardHelper_AppendSCardDwordArgToPyObject( *$1, &$result ); } // different names for SCARDWORDARG INPUT parameters %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwProviderId }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwShareMode }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwPreferredProtocols }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwDisposition }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwScope }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwAttrId }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwTimeout }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwInitialization }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwControlCode }; // different names for SCARDWORDARG OUTPUT parameters %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwActiveProtocol }; %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwProtocol }; %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwState }; /*============================================================================== // // support for SCARDHANDLE // ==============================================================================*/ %typemap(in,numinputs=0) SCARDHANDLE *OUTPUT(SCARDHANDLE temp) { $1 = &temp; } %typemap(in) SCARDHANDLE hcard(SCARDHANDLE) { $1 = SCardHelper_PyScardHandleToSCARDHANDLE( $input ); if (0 == $1) goto fail; } %typemap(argout) SCARDHANDLE* OUTPUT { SCardHelper_AppendSCardHandleToPyObject( *$1, &$result ); } // different names for SCARDHANDLE OUTPUT parameters %apply SCARDHANDLE* OUTPUT { SCARDHANDLE* phcard }; /*============================================================================== // // support for SCARDRETCODE // ==============================================================================*/ %typemap(out) SCARDRETCODE { $result = PyLong_FromLong((long)$1); } /*============================================================================== // // support for STRING // ==============================================================================*/ // release STRING INPUT argument. // string is allocated in SCardHelper_PyStringToString // string->sz is always allocated %typemap(freearg) STRING* INPUT { if(NULL!=$1) { if(NULL!=$1->sz) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->sz ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->sz ); } $1->sz=NULL; } mem_Free( $1 ); } } // release STRING OUTPUT argument. // string is not allocated // string->sz is always allocated %typemap(freearg) STRING* OUTPUT { if(NULL!=$1) { if(NULL!=$1->sz) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->sz ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->sz ); } $1->sz=NULL; } } } // force the argument to be ignored %typemap(in,numinputs=0) STRING *OUTPUT(STRING temp) { $1 = &temp; $1->bAllocated=FALSE; } // builds a string from a Python string %typemap(in) STRING *INPUT( STRING ) { $1 = SCardHelper_PyStringToString( $input ); if (NULL == $1) goto fail; } // builds a Python string from a STRING %typemap(argout) STRING *OUTPUT { SCardHelper_AppendStringToPyObject( $1, &$result ); } // other names for STRING as output parameter %apply STRING* OUTPUT { PROVIDERNAME_t* pszProviderName }; %apply STRING* OUTPUT { STRING* pszReaderNameOut }; /*============================================================================== // // support for STRINGLIST // SCardxxx API stores multi-strings as a concatenation // of strings terminated by a null, e.g. // item0\0item2\0lastitem\0\0 // ==============================================================================*/ // for OUTPUT STRINGLIST, free the allocated buffer // for winscard, the buffer is automatically allocated and // has to be freed by SCardFreeMemory. // for pcsclite, the buffer is allocated with mem_Malloc and // has to be freed by mem_Free. %typemap(freearg) STRINGLIST* { if(NULL!=$1) { if(NULL!=$1->ac) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->ac ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "Failed to SCardFreeMemory!\n" ); } } else { if( NULL!=$1->ac ) { mem_Free( $1->ac ); } } } if($1->bAllocated==TRUE) { mem_Free( $1 ); } } } %typemap(in,numinputs=0) STRINGLIST *OUTPUT(STRINGLIST temp) { $1 = &temp; $1->bAllocated=FALSE; } // builds a win32 string list from a Python list %typemap(in) STRINGLIST* INPUT(STRINGLIST*) { $1 = SCardHelper_PyStringListToStringList( $input ); if (NULL == $1) goto fail; } // builds a Python list from a win32 string list %typemap(argout) STRINGLIST *OUTPUT { SCardHelper_AppendStringListToPyObject( $1, &$result ); } // other names for STRINGLIST as input parameter %apply STRINGLIST* INPUT { STRINGLIST* CARDSTOLOCATE }; %apply STRINGLIST* INPUT { STRINGLIST* psl }; %apply STRINGLIST* INPUT { STRINGLIST* READERGROUPSIN }; // other names for STRINGLIST as output parameter %apply STRINGLIST* OUTPUT { STRINGLIST* MATCHINGCARDS }; %apply STRINGLIST* OUTPUT { STRINGLIST* READERSFOUND }; %apply STRINGLIST* OUTPUT { STRINGLIST* READERGROUPSOUT }; %apply STRINGLIST* OUTPUT { STRINGLIST* pszReaderName }; //#endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/__init__.py0000644000076500000240000000004414674316735020744 0ustar00rousseaustafffrom smartcard.scard.scard import * ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/gemalto.ver0000644000076500000240000000674614674316735021020 0ustar00rousseaustaff#ifndef VER_COMPANYNAME_STR #define VER_COMPANYNAME_STR "gemalto\0" #endif #ifndef VER_LEGALCOPYRIGHT_YEARS #define VER_LEGALCOPYRIGHT_YEARS "2001-2012" #endif #ifndef VER_LEGALCOPYRIGHT_STR #define VER_LEGALCOPYRIGHT_STR "Copyright \251 gemalto" VER_LEGALCOPYRIGHT_YEARS #endif #ifndef VER_PRODUCTNAME_STR #define VER_PRODUCTNAME_STR "Smart Cards Software Development Tools" #endif /* VER_PRODUCTVERSION and VER_PRODUCTVERSION_STR are provided by setup.py */ #ifndef VER_FILEVERSION #define VER_FILEVERSION VER_PRODUCTVERSION #endif #ifndef VER_FILEFLAGSMASK #define VER_FILEFLAGSMASK (VS_FF_DEBUG | VS_FF_PRERELEASE) #endif #ifndef VER_FILEFLAGS #ifdef DEBUG #define VER_FILEFLAGS (VS_FF_DEBUG) #else #define VER_FILEFLAGS (0) #endif #endif #ifndef VER_FILEOS #ifdef WIN32 #define VER_FILEOS VOS_NT_WINDOWS32 #else #define VER_FILEOS VOS_DOS_WINDOWS16 #endif #endif #ifndef VER_FILEVERSION_STR #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR #endif #ifndef VER_ORIGINALFILENAME_STR #define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR #endif #define EXPORT_TAG #ifdef RC_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_PRODUCTVERSION FILEFLAGSMASK VER_FILEFLAGSMASK FILEFLAGS VER_FILEFLAGS FILEOS VER_FILEOS FILETYPE VER_FILETYPE FILESUBTYPE VER_FILESUBTYPE BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END BLOCK "040c04b0" /* LANG_FRENCH/SUBLANG_FRENCH */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END #ifdef VER_ANSICP /* Some apps are hard coded to look for ANSI CP. */ BLOCK "040904E4" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Ansi CP */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END #endif END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 0x04B0 END END #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1736282587.0 pyscard-2.2.1/src/smartcard/scard/helpers.c0000644000076500000240000010321114737310733020431 0ustar00rousseaustaff/*=========================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ===========================================================================*/ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #else #include #endif #include #include #include "pcsctypes.h" #include "helpers.h" #include "memlog.h" extern PyObject* PyExc_SCardError; #ifdef PCSCLITE #define FALSE (0==1) #define TRUE (1==1) #define lstrlen strlen #endif // PCSCLITE #if PY_MAJOR_VERSION >= 3 #define PyInt_Check(x) PyLong_Check(x) #define PyInt_AsLong(x) PyLong_AsLong(x) #define PyInt_FromLong(x) PyLong_FromLong(x) #define PyString_Check(name) PyUnicode_Check(name) #define PyString_FromString(x) PyUnicode_FromString(x) #define PyString_AsString(str) PyBytes_AsString(str) #endif /**=======================================================================**/ static int _IsAReaderState( PyObject* o) /*=========================================================================== ===========================================================================*/ { PyObject* o2; // expecting at least 2 items: reader name and current state if( (PyTuple_Size(o)!=2) && (PyTuple_Size(o)!=3) ) { PyErr_SetString( PyExc_TypeError, "Expecting two or three items in tuple." ); return 0; } o2 = PyTuple_GetItem(o, 0); if(!PyString_Check(o2)) { PyErr_SetString( PyExc_TypeError, "Expected a string as reader name." ); return 0; } o2 = PyTuple_GetItem(o, 1); if(!PyInt_Check(o2) && !PyLong_Check(o2) ) { PyErr_SetString( PyExc_TypeError, "Expected an Int as second tuple item." ); return 0; } if(PyTuple_Size(o)==3) { o2 = PyTuple_GetItem(o, 2); if(!PyList_Check(o2)) { PyErr_SetString( PyExc_TypeError, "Expected a list as third tuple item." ); return 0; } } return 1; } /**=======================================================================**/ static int _ReaderStateFromTuple( PyObject* o, READERSTATELIST* prl, unsigned int x ) /*=========================================================================== ===========================================================================*/ { char* psz; PyObject* o2; #if PY_MAJOR_VERSION >= 3 PyObject* temp_bytes; #endif // first tuple item is reader name o2=PyTuple_GetItem(o, 0); #if PY_MAJOR_VERSION >= 3 // Convert the readername from string (unicode) to bytes (ascii) temp_bytes = PyUnicode_AsEncodedString(o2, "ASCII", "strict"); // Owned reference if (temp_bytes != NULL) { psz = PyBytes_AsString(temp_bytes); // Borrowed pointer if (NULL == psz) return 0; } else return 0; #else psz = PyString_AsString(o2); #endif prl->aszReaderNames[x] = mem_Malloc(strlen(psz)+1); if (!prl->aszReaderNames[x]) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); return 0; } prl->ars[x].szReader = prl->aszReaderNames[x]; strcpy( prl->aszReaderNames[x], psz ); #if PY_MAJOR_VERSION >= 3 Py_DECREF(temp_bytes); #endif // second tuple item is current state o2=PyTuple_GetItem(o, 1); prl->ars[x].dwCurrentState = (SCARDDWORDARG)PyInt_AsLong(o2); // third tuple item is the ATR (optionally) if(PyTuple_Size(o)==3) { BYTELIST* ATR = mem_Malloc(sizeof(BYTELIST)); if( !ATR ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); return 0; } o2 = PyTuple_GetItem(o, 2); ATR = SCardHelper_PyByteListToBYTELIST(o2); memcpy(prl->ars[x].rgbAtr, ATR->ab, ATR->cBytes); prl->ars[x].cbAtr = ATR->cBytes; mem_Free(ATR); } return 1; } /**========================================================================== BYTELIST Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendByteListToPyObject( BYTELIST* source, PyObject** ptarget ) /*=========================================================================== builds a Python list from a byte list ===========================================================================*/ { PyObject* oByteList; // create byte list... if( (NULL!=source) && (NULL!=source->ab) ) { unsigned int i; oByteList = PyList_New( source->cBytes ); for(i=0; icBytes; i++) { PyObject* pyby; pyby = Py_BuildValue( "b", source->ab[i] ); PyList_SetItem( oByteList, i, pyby ); } } else { oByteList = PyList_New( 0 ); } // append list to target if( !*ptarget ) { *ptarget = oByteList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oByteList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oByteList); Py_XDECREF(oByteList); } } /**=======================================================================**/ BYTELIST* SCardHelper_PyByteListToBYTELIST(PyObject* source) /*=========================================================================== build a Python byte list from a BYTELIST ===========================================================================*/ { Py_ssize_t cBytes, x; BYTELIST* pbl; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cBytes = PyList_Size(source); for( x=0; x0) { pbl->ab = mem_Malloc( cBytes*sizeof(unsigned char) ); if( !pbl->ab ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( pbl ); return NULL; } } else { pbl->ab=NULL; } pbl->bAllocated=TRUE; pbl->cBytes=(SCARDDWORDARG)cBytes; for( x=0; xab[x] = (unsigned char)PyInt_AsLong(o); } return (BYTELIST*)pbl; } /**=======================================================================**/ void SCardHelper_PrintByteList( BYTELIST* apsz ) /*=========================================================================== dump a byte list ===========================================================================*/ { unsigned long i; for(i=0; icBytes; i++) { printf("0x%.2X ", apsz->ab[i] ); } printf("\n"); } /**========================================================================== ERRORSTRING Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_OutErrorStringAsPyObject( ERRORSTRING source, PyObject** ptarget ) /*=========================================================================== Builds a Python string from an ERRORSTRING ===========================================================================*/ { PyObject* pystr; if( NULL!=source ) { #if (PY_MAJOR_VERSION >= 3) && defined(WIN32) pystr = PyUnicode_DecodeLocale(source, NULL); #else pystr = PyString_FromString( source ); #endif *ptarget = pystr; } else { *ptarget = Py_None; Py_INCREF(Py_None); } } /**========================================================================== GUIDLIST Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendGuidListToPyObject( GUIDLIST* source, PyObject** ptarget ) /*=========================================================================== build a Python GUID list from a C GUID list ===========================================================================*/ { PyObject* oByte; PyObject* oGuildItem; PyObject* oGuidList; unsigned char* pc; unsigned int i, j; // create GUID list... for(;;) { if (source!=NULL) { // create GUID list oGuidList = PyList_New( source->cGuids ); if(NULL==oGuidList) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate GUID list" ); break; } for( i=0; icGuids; i++) { oGuildItem=PyList_New( sizeof(GUID) ); if(NULL==oGuildItem) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate GUID item list" ); break; } pc=(unsigned char*)&source->aguid[i]; for (j=0; jbAllocated=TRUE; pgl->cGuids=(unsigned long)cGuids; pgl->hcontext=(unsigned long)NULL; // allocate GUIDs in GUID list if (cGuids>0) { pgl->aguid = mem_Malloc( cGuids*sizeof(GUID) ); if( NULL==pgl->aguid ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( pgl ); return NULL; } } else { pgl->aguid=NULL; } // fill individual GUIDs /* for( iGuid=0; iGuidxaguid+iGuid*sizeof(GUID); for( x=0; xaguid; for( x=0; xcGuids; i++) { unsigned char* pc=(unsigned char*)&apsz->aguid[i]; for (j=0; jcRStates ); for( i=0; icRStates; i++ ) { PyObject* oReader; PyObject* oEventState; PyObject* oAtr; PyObject* oByte; SCARDDWORDARG j; // reader, event state, atr PyObject* ot = PyTuple_New( 3 ); oReader = PyString_FromString( source->ars[i].szReader ); oEventState = PyInt_FromLong( (SCARDDWORDARG)source->ars[i].dwEventState ); // ATR visibly not initialised if ( source->ars[i].cbAtr > SCARD_ATR_LENGTH) source->ars[i].cbAtr = 0; oAtr = PyList_New( source->ars[i].cbAtr ); for(j=0; jars[i].cbAtr; j++) { oByte = PyInt_FromLong( source->ars[i].rgbAtr[j] ); PyList_SetItem( oAtr, j, oByte ); } PyTuple_SetItem( ot, 0, oReader ); PyTuple_SetItem( ot, 1, oEventState ); PyTuple_SetItem( ot, 2, oAtr ); PyList_SetItem( oRStateList, i, ot ); } } else { oRStateList = PyList_New( 0 ); } if( !*ptarget ) { *ptarget = oRStateList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oRStateList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oRStateList); Py_XDECREF(oRStateList); } } /**=======================================================================**/ READERSTATELIST* SCardHelper_PyReaderStateListToREADERSTATELIST(PyObject* source) /*=========================================================================== build a READERSTATELIST from a Python list of reader states ===========================================================================*/ { SCARDDWORDARG cRStates, x; READERSTATELIST* prl; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cRStates = (SCARDDWORDARG)PyList_Size(source); for( x=0; xcRStates = cRStates; prl->ars = mem_Malloc( cRStates*sizeof(SCARD_READERSTATE) ); if (!prl->ars) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( prl ); return NULL; } /* zeroise SCARD_READERSTATE to work with remote desktop */ memset(prl->ars, 0, cRStates*sizeof(SCARD_READERSTATE) ); prl->aszReaderNames = mem_Malloc( cRStates*sizeof(char*) ); if (!prl->aszReaderNames) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( prl->ars ); mem_Free( prl ); return NULL; } for( x=0; xaszReaderNames[x] ); } mem_Free( prl->ars ); mem_Free( prl ); return NULL; } } return (READERSTATELIST*)prl; } /**========================================================================== SCARDCONTEXT Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendSCardContextToPyObject( SCARDCONTEXT source, PyObject** ptarget ) /*=========================================================================== builds a Python SCARDCONTEXT from a C SCARDCONTEXT ===========================================================================*/ { PyObject* oScardContext; // create SCARDCONTEXT #ifdef PCSCLITE oScardContext = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardContext = PyLong_FromVoidPtr( (void*)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardContext; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardContext; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardContext); Py_XDECREF(oScardContext); } } /**=======================================================================**/ SCARDCONTEXT SCardHelper_PyScardContextToSCARDCONTEXT(PyObject* source) /*=========================================================================== build a SCARDCONTEXT from a python SCARDCONTEXT ===========================================================================*/ { SCARDCONTEXT scRet=0; // sanity check // do we have a python long? if (!PyLong_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a python long as SCARDCONTEXT." ); return 0; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsVoidPtr( source ); #endif // PCSCLITE return scRet; } /**========================================================================== SCARDHANDLE Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendSCardHandleToPyObject( SCARDHANDLE source, PyObject** ptarget ) /*=========================================================================== builds a Python SCARDHANDLE from a C SCARDHANDLE ===========================================================================*/ { PyObject* oScardHandle; // create SCARDHANDLE #ifdef PCSCLITE oScardHandle = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardHandle = PyLong_FromVoidPtr( (void*)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardHandle; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardHandle; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardHandle); Py_XDECREF(oScardHandle); } } /**=======================================================================**/ SCARDCONTEXT SCardHelper_PyScardHandleToSCARDHANDLE(PyObject* source) /*=========================================================================== build a SCARDHANDLE from a python SCARDHANDLE ===========================================================================*/ { SCARDHANDLE scRet=0; // sanity check // do we have a python long? if (!PyLong_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a python long as SCARDHANDLE." ); return 0; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsVoidPtr( source ); #endif // PCSCLITE return scRet; } /**========================================================================== SCARDDWORDARG Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendSCardDwordArgToPyObject( SCARDDWORDARG source, PyObject** ptarget ) /*=========================================================================== builds a Python SCARDDWORDARG from a C SCARDDWORDARG ===========================================================================*/ { PyObject* oScardDword; // create SCARDDWORDARG #ifdef PCSCLITE oScardDword = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardDword = PyLong_FromUnsignedLong( (unsigned long)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardDword; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardDword; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardDword); Py_XDECREF(oScardDword); } } /**=======================================================================**/ SCARDDWORDARG SCardHelper_PySCardDwordArgToSCARDDWORDARG(PyObject* source) /*=========================================================================== build a SCARDDWORDARG from a python SCARDDWORDARG ===========================================================================*/ { SCARDDWORDARG scRet=0; // sanity check // do we have a python long or int? if( !PyLong_Check(source) && !PyInt_Check(source) ) { PyErr_SetString( PyExc_TypeError, "Expected a python integer or long." ); return -1; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsUnsignedLong( source ); #endif // PCSCLITE return scRet; } /**========================================================================== STRING Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendStringToPyObject( STRING* source, PyObject** ptarget ) /*=========================================================================== Builds a Python string from a STRING ===========================================================================*/ { PyObject* pystr; if(NULL!=source) { if(NULL!=source->sz) { pystr = PyString_FromString( source->sz ); } else { pystr = Py_None; Py_INCREF(Py_None); } if( !*ptarget ) { *ptarget = pystr; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = pystr; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append( *ptarget, pystr ); Py_XDECREF( pystr ); } } else { if( !*ptarget ) { *ptarget = Py_None; Py_INCREF(Py_None); } } } /**=======================================================================**/ STRING* SCardHelper_PyStringToString( PyObject* source ) /*=========================================================================== Build a STRING from a Python string; the string is allocated and will have to be freed externally to the wrapper ===========================================================================*/ { size_t ulLength; STRING* pstr=NULL; for(;;) { // sanity check if( !PyString_Check( source ) ) { PyErr_SetString( PyExc_TypeError, "Expected a string." ); break; } pstr=(STRING*)mem_Malloc( sizeof(STRING) ); if(NULL==pstr) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate STRING" ); break; } ulLength=strlen( PyString_AsString(source)) + 1 ; pstr->sz=(char*)mem_Malloc( ulLength ); if(NULL==pstr->sz) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate STRING buffer" ); break; } strcpy( pstr->sz, PyString_AsString( source ) ); break; } return pstr; } /**=======================================================================**/ void SCardHelper_PrintString( STRING* str ) /*=========================================================================== dump a string list ===========================================================================*/ { if(NULL!=str) { char* p=str->sz; if( NULL!=p) { printf("%s ", p ); } } } /**========================================================================== STRINGLIST Helpers ===========================================================================*/ /**=======================================================================**/ void SCardHelper_AppendStringListToPyObject( STRINGLIST* source, PyObject** ptarget ) /*=========================================================================== builds a Python list from a STRINGLIST; the multi-string list in the STRINGLIST is stored as series of null-terminated strings terminated by a null, e.g. item0\0item2\0lastitem\0\0) ===========================================================================*/ { unsigned int cStr; char* p=source->ac; PyObject* oStrList; //PyObject* o; // count STRs in STRINGLIST list if( NULL!=p ) { unsigned int i; for( i=0, cStr=0; ; i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { cStr++; } else { break; } } } else { cStr=0; } // create STR list... if( NULL!=p ) { unsigned int i, j; oStrList = PyList_New( cStr ); for( i=0, j=0; ; j++, i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { PyObject* pystr; pystr = PyString_FromString( p+i ); PyList_SetItem( oStrList, j, pystr ); } else { break; } } } else { oStrList = PyList_New( cStr ); } if( !*ptarget ) { *ptarget = oStrList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oStrList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oStrList); Py_XDECREF(oStrList); } } /**=======================================================================**/ STRINGLIST* SCardHelper_PyStringListToStringList(PyObject* source) /*=========================================================================== build a Python string list from a STRINGLIST ===========================================================================*/ { Py_ssize_t cStrings, cChars, x; STRINGLIST* psl; char* p; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cStrings = PyList_Size(source); for( x=0, cChars=0; x= 3 cChars += PyUnicode_GET_LENGTH(o) + 1 ; #else cChars += strlen( PyString_AsString(o)) + 1 ; #endif } cChars += 1; psl=mem_Malloc(sizeof(STRINGLIST)); if(!psl) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); return NULL; } psl->bAllocated=TRUE; psl->hcontext = 0; if ( cChars>1 ) { psl->ac = mem_Malloc( cChars*sizeof(char) ); if (!psl->ac) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( psl ); return NULL; } for( x=0, p=psl->ac; x= 3 // Convert the group name from string (unicode) to bytes (ascii) PyObject * temp_bytes = PyUnicode_AsEncodedString(o, "ASCII", "strict"); // Owned reference if (temp_bytes != NULL) { char * psz = PyBytes_AsString(temp_bytes); // Borrowed pointer if (NULL == psz) return 0; strcpy(p, psz); Py_DECREF(temp_bytes); } #else strcpy( p, PyString_AsString(o) ); #endif p += strlen( p ) + 1; } strcpy( p, "\0" ); } else { psl->ac=NULL; } return (STRINGLIST*)psl; } /**=======================================================================**/ void SCardHelper_PrintStringList( STRINGLIST* sl ) /*=========================================================================== dump a string list ===========================================================================*/ { char* p=(char*)sl->ac; unsigned int i; for( i=0; ; i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { printf("%s ", p+i ); } else { printf("\n" ); break; } } } #ifdef WIN32 /**=======================================================================**/ BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) /*=========================================================================== Initialize and clean-up memory logging on process attach and detach ===========================================================================*/ { switch(fdwReason) { case DLL_PROCESS_ATTACH: if (!mem_Init()) { fprintf( stderr, "Failed to initialize memory logging services!\n" ); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (!mem_CleanUp()) { fprintf( stderr, "Failed to cleanup memory logging services!\n" ); } break; } return TRUE; return 1; } #endif // WIN32 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/helpers.h0000644000076500000240000000720614677317744020461 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ================================================================================ ==============================================================================*/ typedef struct { int bAllocated; unsigned char* ab; SCARDDWORDARG cBytes; } BYTELIST ; typedef char* ERRORSTRING; #ifdef PCSCLITE typedef struct { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[ 8 ]; } GUID; #endif typedef struct { int bAllocated; GUID* aguid; unsigned long cGuids; SCARDCONTEXT hcontext; } GUIDLIST ; typedef struct { SCARD_READERSTATE* ars; char** aszReaderNames; int cRStates; } READERSTATELIST ; typedef struct { int bAllocated; SCARDCONTEXT hcontext; char* sz; } STRING; typedef struct { int bAllocated; SCARDCONTEXT hcontext; char* ac; } STRINGLIST ; /**============================================================================= F U N C T I O N P R O T O T Y P E S ==============================================================================*/ // BYTELIST helpers void SCardHelper_AppendByteListToPyObject( BYTELIST* source, PyObject** ptarget ); BYTELIST* SCardHelper_PyByteListToBYTELIST(PyObject* source); void SCardHelper_PrintByteList( BYTELIST* apsz ); // ERRORSTRING helpers void SCardHelper_OutErrorStringAsPyObject( ERRORSTRING source, PyObject** ptarget ); // GUIDLIST helpers void SCardHelper_AppendGuidListToPyObject( GUIDLIST* source, PyObject** ptarget ); GUIDLIST* SCardHelper_PyGuidListToGUIDLIST(PyObject* source); void SCardHelper_PrintGuidList( GUIDLIST* apsz ); // READERSTATELIST helpers void SCardHelper_AppendReaderStateListToPyObject( READERSTATELIST* source, PyObject** ptarget ); READERSTATELIST* SCardHelper_PyReaderStateListToREADERSTATELIST(PyObject* source); // SCARDCONTEXT helpers void SCardHelper_AppendSCardContextToPyObject( SCARDCONTEXT source, PyObject** ptarget ); SCARDCONTEXT SCardHelper_PyScardContextToSCARDCONTEXT( PyObject* source ); // SCARDHANDLE helpers void SCardHelper_AppendSCardHandleToPyObject( SCARDHANDLE source, PyObject** ptarget ); SCARDHANDLE SCardHelper_PyScardHandleToSCARDHANDLE( PyObject* source ); // SCARDDWORDARG helpers void SCardHelper_AppendSCardDwordArgToPyObject( SCARDDWORDARG source, PyObject** ptarget ); SCARDDWORDARG SCardHelper_PySCardDwordArgToSCARDDWORDARG( PyObject* source ); // STRING helpers void SCardHelper_AppendStringToPyObject( STRING* source, PyObject** ptarget ); STRING* SCardHelper_PyStringToString( PyObject* source ); void SCardHelper_PrintString( STRING* str ); // STRINGLIST helpers void SCardHelper_AppendStringListToPyObject( STRINGLIST* source, PyObject** ptarget ); STRINGLIST* SCardHelper_PyStringListToStringList(PyObject* source); void SCardHelper_PrintStringList( STRINGLIST* apsz ); ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/memlog.h0000644000076500000240000000403214674316735020265 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ #ifndef __MEMLOG_H__ #define __MEMLOG_H__ #ifdef __cplusplus extern "C" { #endif // __cplusplus // // define __ENABLE_MEMLOG__ and write your own version // of mem_XXX functions to enable memory logging; this // is useful to track memory leaks when fiddling with // the swig typemaps. #ifdef __ENABLE_MEMLOG__ int mem_CleanUp( void ); void __cdecl mem_Free( void* pv ); void mem_HeapCheck( void ); int mem_Init( void ); void* __cdecl mem_Malloc( size_t ulSize ); void* __cdecl mem_MallocWithCaller( size_t ulSize, void* pvCaller ); void mem_HeapPrint( void ); // // defaults to free/malloc // #else // !__ENABLE_MEMLOG__ #define mem_CleanUp() (1) #define mem_Free free #define mem_HeapCheck() #define mem_Init() (1) #define mem_Malloc malloc #define mem_MallocWithCaller( x, y ) malloc( x ) #define mem_HeapPrint() #endif // __ENABLE_MEMLOG__ #ifdef __cplusplus } #endif // __cplusplus #endif // __MEMLOG_H__ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/pcsctypes.h0000644000076500000240000000266114674316735021030 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ================================================================================ ==============================================================================*/ #ifndef __PCSCTYPES_H__ #define __PCSCTYPES_H__ #ifdef PCSCLITE #ifdef __APPLE__ typedef uint32_t SCARDDWORDARG; typedef int32_t SCARDRETCODE; #else //!__APPLE__ typedef unsigned long SCARDDWORDARG; typedef long SCARDRETCODE; #endif #else // !PCSCLITE typedef unsigned long SCARDDWORDARG; typedef long SCARDRETCODE; #endif #endif //__PCSCTYPES_H__ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/pyscard-reader.h0000644000076500000240000001335514677317744021726 0ustar00rousseaustaff/*============================================================================== This file contains SCARD_ATTR attributes definitions taken from reader.h, in MUSCLE SmartCard Development ( https://muscle.apdu.fr/ ). It allows to build pyscard on Mac OS X without any dependency on the muscle source code. Indeed, default Mac OS X does not contain reader.h as part of the PCSC.framework. Copyright (C) 1999-2005 David Corcoran Copyright (C) 1999-2009 Ludovic Rousseau The licence of reader.h pcsc-lite is 3-clauses BSD and can be relicenced in LGPL v2+ for pyscard. This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) #define SCARD_CLASS_VENDOR_INFO 1 #define SCARD_CLASS_COMMUNICATIONS 2 #define SCARD_CLASS_PROTOCOL 3 #define SCARD_CLASS_POWER_MGMT 4 #define SCARD_CLASS_SECURITY 5 #define SCARD_CLASS_MECHANICAL 6 #define SCARD_CLASS_VENDOR_DEFINED 7 #define SCARD_CLASS_IFD_PROTOCOL 8 #define SCARD_CLASS_ICC_STATE 9 #define SCARD_CLASS_SYSTEM 0x7fff #define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) #define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) #define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) #define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) #define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) #define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) #define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) #define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) #define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) #define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) #define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) #define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) #define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) #define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) #define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) #define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) #define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) #define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) #define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) #define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) #define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) #define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) #define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) #define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) #define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) #define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) #define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) #define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) #define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) #define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) #define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) #define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) #define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) #define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) #define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) #define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) #define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) #define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) #define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004) #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) #define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006) #define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) #ifdef UNICODE #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W #else #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/scard.def0000644000076500000240000000016314677317744020415 0ustar00rousseaustaffLIBRARY "_scard.pyd" DESCRIPTION 'Python PCSC scard module Dynamic Link Library' EXPORTS init_scard ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/scard/scard.i0000644000076500000240000022516214703034261020073 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ %define DOCSTRING "The smartcard.scard module is a simple wrapper on top of the C language PCSC SCardXXX API. The smartcard.scard module is the lower layer of the pyscard framework that provides a higher level interface. You should avoid using the L{smartcard.scard} package directly, and use the pyscard directly because: - smartcard.scard being a C wrapper, the code tends to look like C code written in python syntax - the smartcard package provides higher level abstractions (e.g. L{CardType}, L{CardConnection}), and makes programming easier since it is totally written in Python You can still use the smartcard.scard package if you want to write your own framework, or if you want to perform quick-and-dirty port of C language programs using SCardXXX calls, or if there are features of SCardXXX API that you want to use and that are not available in the pyscard library. Introduction The smartcard.scard module is a Python wrapper around PCSC smart card base services. On Windows, the wrapper is performed around the smart card base components winscard library. On linux and OS X, the wrapper is performed around the PCSC-lite library. The smartcard.scard module provides mapping for the following API functions, depending on the Operating System:: =============================== ======= ======= Function Windows Linux OS X =============================== ======= ======= GetOpenCardName SCardAddReaderToGroup Y SCardBeginTransaction Y Y SCardCancel Y Y SCardConnect Y Y SCardControl Y Y SCardDisconnect Y Y SCardEndTransaction Y Y SCardEstablishContext Y Y SCardForgetCardType Y SCardForgetReader Y SCardForgetReaderGroup Y SCardFreeMemory SCardGetAttrib Y Y SCardGetCardTypeProviderName Y SCardGetErrorMessage Y Y SCardGetProviderId SCardGetStatusChange Y Y SCardIntroduceCardType Y SCardIntroduceReader Y SCardIntroduceReaderGroup Y SCardIsValidContext Y Y SCardListCards Y SCardListInterfaces Y SCardListReaderGroups Y Y SCardListReaders Y Y SCardLocateCards Y SCardReconnect Y Y SCardReleaseContext Y Y SCardRemoveReaderFromGroup Y SCardSetAttrib Y Y SCardSetCartTypeProviderName SCardStatus Y Y SCardTransmit Y Y SCardUIDlgSelectCard =============================== ======= ======= Comments, bug reports, improvements welcome. ------------------------------------------------------------------------------- Copyright 2001-2012 gemalto @Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com @Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA " %enddef %module(docstring=DOCSTRING, package="smartcard.scard") scard %feature("autodoc", "1"); %{ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #else #include #endif #ifdef PCSCLITE #ifdef __APPLE__ #include "pyscard-reader.h" #ifndef SCARD_CTL_CODE #define SCARD_CTL_CODE(code) (0x42000000 + (code)) #endif #else #include #endif // undefined on older releases #ifndef MAX_BUFFER_SIZE_EXTENDED #define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) #endif #else // !PCSCLITE // SCARD_CTL_CODE defined in WinSmCrd.h included by Win32 winscard.h // MAX_BUFFER_SIZE_EXTENDED is pcsc-lite specific // Issues on Lenovo laptop with NXP reader for higher values // See https://github.com/LudovicRousseau/pyscard/issues/100 #define MAX_BUFFER_SIZE_EXTENDED 65535 #endif //PCSCLITE #include "pcsctypes.h" #include "helpers.h" #include "memlog.h" #include "winscarddll.h" typedef STRING PROVIDERNAME_t; %} %include typemaps.i %include PcscTypemaps.i %{ // // these functions are only available on win32 PCSC // #ifdef WIN32 /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return (mySCardAddReaderToGroupA)( hcontext, szReaderName, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetCardType(SCARDCONTEXT hcontext, char* pszCardName) { return (mySCardForgetCardTypeA)(hcontext, pszCardName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName) { return (mySCardForgetReaderA)(hcontext, szReaderName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return (mySCardForgetReaderGroupA)(hcontext, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* pszCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* psl) { long lRetCode; unsigned long cchProviderName=SCARD_AUTOALLOCATE; // autoallocate memory; will be freed on output typemap psl->hcontext=hcontext; psl->sz=NULL; lRetCode=(mySCardGetCardTypeProviderNameA)( hcontext, pszCardName, dwProviderId, (LPTSTR)&psl->sz, &cchProviderName); return lRetCode; }; /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceCardType( SCARDCONTEXT hcontext, char* pszCardName, GUIDLIST* pguidPrimaryProvider, GUIDLIST* rgguidInterfaces, BYTELIST* pbAtr, BYTELIST* pbAtrMask ) { return (mySCardIntroduceCardTypeA)( hcontext, pszCardName, pguidPrimaryProvider ? pguidPrimaryProvider->aguid : NULL, rgguidInterfaces ? rgguidInterfaces->aguid : NULL, rgguidInterfaces ? rgguidInterfaces->cGuids : 0, pbAtr->ab, pbAtrMask->ab, pbAtr->cBytes); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName) { return (mySCardIntroduceReaderA)(hcontext, szReaderName, szDeviceName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return (mySCardIntroduceReaderGroupA)(hcontext, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ListCards(SCARDCONTEXT hcontext, BYTELIST* pbl, GUIDLIST* guidlist, STRINGLIST* pmszCards) { // autoallocate memory; will be freed on output typemap unsigned long cchCards=SCARD_AUTOALLOCATE; pmszCards->ac=NULL; pmszCards->hcontext=hcontext; //SCardHelper_PrintByteList(pbl); return (mySCardListCardsA)( hcontext, pbl->ab, (NULL==guidlist) ? NULL : guidlist->aguid, (NULL==guidlist) ? 0 : guidlist->cGuids, (LPTSTR)&pmszCards->ac, &cchCards); }; /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ListInterfaces( SCARDCONTEXT hcontext, char* pszCard, GUIDLIST* pgl ) { long lRetCode; pgl->cGuids = SCARD_AUTOALLOCATE; pgl->hcontext = hcontext; pgl->aguid = NULL; lRetCode = (mySCardListInterfacesA)(hcontext, pszCard, (LPGUID)&pgl->aguid, &pgl->cGuids); if (lRetCode!=SCARD_S_SUCCESS) { pgl->cGuids=0; } return lRetCode; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* mszCards, READERSTATELIST* prl ) { LPCSTR pcstr=(0==strlen((LPCTSTR)mszCards->ac)) ? NULL : (LPCTSTR)mszCards->ac; return (mySCardLocateCardsA)( hcontext, pcstr, prl->ars, prl->cRStates); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return (mySCardRemoveReaderFromGroupA)( hcontext, szReaderName, szGroupName); } #else /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName) { return SCARD_E_UNSUPPORTED_FEATURE; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return SCARD_E_UNSUPPORTED_FEATURE; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return SCARD_E_UNSUPPORTED_FEATURE; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return SCARD_E_UNSUPPORTED_FEATURE; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return SCARD_E_UNSUPPORTED_FEATURE; } #endif // WIN32 /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _IsValidContext(SCARDCONTEXT hcontext) { return (mySCardIsValidContext)(hcontext); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* pbl) { long lRetCode; pbl->cBytes = 65535; pbl->ab = NULL; lRetCode = (mySCardGetAttrib)(hcard, dwAttrId, pbl->ab, &pbl->cBytes); if ((lRetCode!=SCARD_S_SUCCESS) || (pbl->cBytes<1)) { return lRetCode; } pbl->ab = (unsigned char*)mem_Malloc(pbl->cBytes*sizeof(unsigned char)); if (pbl->ab==NULL) { return SCARD_E_NO_MEMORY; } lRetCode = (mySCardGetAttrib)(hcard, dwAttrId, pbl->ab, &pbl->cBytes); return lRetCode; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* pbl) { long lRetCode; lRetCode = (mySCardSetAttrib)(hcard, dwAttrId, pbl->ab, pbl->cBytes); return lRetCode; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Control( SCARDHANDLE hcard, SCARDDWORDARG controlCode, BYTELIST* pblSendBuffer, BYTELIST* pblRecvBuffer ) { SCARDRETCODE lRet; pblRecvBuffer->ab = (unsigned char*)mem_Malloc(MAX_BUFFER_SIZE_EXTENDED*sizeof(unsigned char)); pblRecvBuffer->cBytes = MAX_BUFFER_SIZE_EXTENDED; lRet = (mySCardControl)( hcard, controlCode, pblSendBuffer->ab, pblSendBuffer->cBytes, pblRecvBuffer->ab, pblRecvBuffer->cBytes, &pblRecvBuffer->cBytes); return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _BeginTransaction(SCARDHANDLE hcard) { return (mySCardBeginTransaction)(hcard); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Cancel(SCARDCONTEXT hcontext) { return (mySCardCancel)(hcontext); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Connect( SCARDCONTEXT hcontext, char* szReader, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, LPSCARDHANDLE phCard, SCARDDWORDARG* pdwActiveProtocol ) { SCARDRETCODE lRet; lRet = (mySCardConnectA)( hcontext, (LPCTSTR)szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol); return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition) { return (mySCardDisconnect)(hcard, dwDisposition); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition) { return (mySCardEndTransaction)(hcard, dwDisposition); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phContext) { return (mySCardEstablishContext)(dwScope, NULL, NULL, phContext); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl) { SCARDRETCODE hresult; int i; // bad reader state list if (NULL==prsl) { return SCARD_E_INVALID_PARAMETER; } // remove changed bit for(i=0; icRStates; i++) { // remove changed bit prsl->ars[i].dwCurrentState = prsl->ars[i].dwCurrentState & (0xFFFFFFFF ^ SCARD_STATE_CHANGED); } hresult = (mySCardGetStatusChangeA)(hcontext, dwTimeout, prsl->ars, prsl->cRStates); //printf("\n%.8lx\n", hresult); //for(i=0; icRStates; i++) //{ // printf("%s %.8lx %.8lx\n", prsl->ars[i].szReader, prsl->ars[i].dwCurrentState, prsl->ars[i].dwEventState); //} return hresult; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* pmszGroups, STRINGLIST* pmszReaders) { LPCTSTR mszGroups; SCARDDWORDARG cchReaders; LONG lRetCode; if (pmszGroups) { mszGroups=pmszGroups->ac; } else { mszGroups=NULL; } #ifdef NOAUTOALLOCATE // autoallocate memory; will be freed on output typemap cchReaders=SCARD_AUTOALLOCATE; pmszReaders->ac=NULL; pmszReaders->hcontext=hcontext; return (mySCardListReadersA)(hcontext, mszGroups, (LPTSTR)&pmszReaders->ac, &cchReaders); #endif //AUTOALLOCATE // no autoallocate on pcsc-lite; do a first call to get length // then allocate memory and do a final call #ifndef NOAUTOALLOCATE // set hcontext to 0 so that mem_Free will // be called instead of SCardFreeMemory pmszReaders->hcontext=0; pmszReaders->ac=NULL; cchReaders=0; lRetCode = (mySCardListReadersA)(hcontext, mszGroups, NULL, &cchReaders); if (SCARD_S_SUCCESS!=lRetCode) { return lRetCode; } if (0==cchReaders) { return SCARD_S_SUCCESS; } pmszReaders->ac=mem_Malloc(cchReaders*sizeof(char)); if (NULL==pmszReaders->ac) { return SCARD_E_NO_MEMORY; } return (mySCardListReadersA)(hcontext, mszGroups, (LPTSTR)pmszReaders->ac, &cchReaders); #endif // !NOAUTOALLOCATE } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* pmszReaderGroups) { DWORD cchReaderGroups; LONG lRetCode; #ifdef NOAUTOALLOCATE cchReaderGroups = SCARD_AUTOALLOCATE; pmszReaderGroups->ac=NULL; pmszReaderGroups->hcontext=hcontext; return (mySCardListReaderGroupsA)(hcontext, (LPTSTR)&pmszReaderGroups->ac, &cchReaderGroups); #endif // NOAUTOALLOCATE // no autoallocate on pcsc-lite; do a first call to get length // then allocate memory and do a final call #ifndef NOAUTOALLOCATE // set hcontext to 0 so that mem_Free will // be called instead of SCardFreeMemory pmszReaderGroups->hcontext=0; cchReaderGroups = 0; pmszReaderGroups->ac=NULL; lRetCode = (mySCardListReaderGroupsA)(hcontext, (LPTSTR)pmszReaderGroups->ac, &cchReaderGroups); if (SCARD_S_SUCCESS!=lRetCode) { return lRetCode; } if (0==cchReaderGroups) { return SCARD_S_SUCCESS; } pmszReaderGroups->ac=mem_Malloc(cchReaderGroups*sizeof(char)); if (NULL==pmszReaderGroups->ac) { return SCARD_E_NO_MEMORY; } return (mySCardListReaderGroupsA)(hcontext, (LPTSTR)pmszReaderGroups->ac, &cchReaderGroups); #endif // !NOAUTOALLOCATE }; /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ) { return (mySCardReconnect)( hcard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ReleaseContext(SCARDCONTEXT hcontext) { SCARDRETCODE lRet; lRet = (mySCardReleaseContext)(hcontext); return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Status( SCARDHANDLE hcard, STRING* pszReaderName, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* pbl ) { long lRetCode; SCARDDWORDARG dwReaderLen=256; SCARDDWORDARG dwAtrLen=36; for(;;) { pbl->ab = (unsigned char*)mem_Malloc(dwAtrLen*sizeof(unsigned char)); if (pbl->ab == NULL) { lRetCode=SCARD_E_NO_MEMORY; break; } pbl->cBytes = dwAtrLen; pszReaderName->sz = mem_Malloc(dwReaderLen*sizeof(char)); pszReaderName->hcontext = 0; if (NULL == pszReaderName->sz) { lRetCode=SCARD_E_NO_MEMORY; break; } pszReaderName->sz[0] = '\0'; lRetCode = (mySCardStatusA)( hcard, (LPTSTR)pszReaderName->sz, &dwReaderLen, pdwState, pdwProtocol, pbl->ab, &pbl->cBytes); break; } return lRetCode; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* pblSendBuffer, BYTELIST* pblRecvBuffer ) { PSCARD_IO_REQUEST piorequest=NULL; long ret; pblRecvBuffer->ab = (unsigned char*)mem_Malloc(MAX_BUFFER_SIZE_EXTENDED*sizeof(unsigned char)); pblRecvBuffer->cBytes = MAX_BUFFER_SIZE_EXTENDED; // keep in sync with redefinition in PcscDefs.i switch(pioSendPci) { case SCARD_PROTOCOL_T0: piorequest = myg_prgSCardT0Pci; break; case SCARD_PROTOCOL_T1: piorequest = myg_prgSCardT1Pci; break; case SCARD_PROTOCOL_RAW: case SCARD_PROTOCOL_UNDEFINED: piorequest = myg_prgSCardRawPci; break; default: return SCARD_E_INVALID_PARAMETER; } ret = (mySCardTransmit)( hcard, piorequest, pblSendBuffer->ab, pblSendBuffer->cBytes, NULL, pblRecvBuffer->ab, &pblRecvBuffer->cBytes); return ret; } /////////////////////////////////////////////////////////////////////////////// static long _SCARD_CTL_CODE(long code) { return SCARD_CTL_CODE(code); } /////////////////////////////////////////////////////////////////////////////// static ERRORSTRING _GetErrorMessage(long lErrCode) { #ifdef WIN32 #define _NO_SERVICE_MSG "The Smart card resource manager is not running." DWORD dwRetCode; LPVOID ppszError; dwRetCode=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, lErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ppszError, 0, NULL); if (0L==dwRetCode) { ppszError=NULL; if (SCARD_E_NO_SERVICE==lErrCode) { ppszError=(LPVOID)LocalAlloc(LPTR, sizeof(_NO_SERVICE_MSG)+1); if (NULL!=ppszError) { strncpy(ppszError, _NO_SERVICE_MSG, sizeof(_NO_SERVICE_MSG)+1); } } } return ppszError; #endif // WIN32 #ifdef PCSCLITE return myPcscStringifyError(lErrCode); #endif // PCSCLITE } %} // // a few documentation typemaps // %typemap(doc, name="hcard", type="") (SCARDHANDLE hcard) "hcard: card handle return from SCardConnect()"; %typemap(doc, name="hcard", type="") (SCARDHANDLE* phcard) "hcard: on output, a card handle"; %typemap(doc, name="hcontext", type="") (SCARDCONTEXT hcontext) "hcontext: context handle return from SCardEstablishContext()"; %typemap(doc, name="hcontext", type="") (SCARDCONTEXT* phcontext) "hcontext: on output, a valid context handle if successful"; %typemap(doc, name="readerstatelist", type="tuple[]") (READERSTATELIST *prsl) "readerstatelist: in input/output, a list of reader state tuple (readername, state, atr)"; %typemap(doc, name="groupname", type="") (char* szGroupName) "groupname: card reader group name"; %typemap(doc, name="readername", type="") (char* szReaderName) "readername: card reader name"; %typemap(doc, name="cardname", type="") (char* szCardName) "cardname: friendly name of a card"; %typemap(doc, name="devicename", type="") (char* szDeviceName) "devicename: card reader device name"; %typemap(doc, name="providername", type="") (PROVIDERNAME_t* pszProviderName) "providername: on output, provider name"; %typemap(doc, name="readername", type="") (STRING* pszReaderNameOut) "readername: on output, reader name"; %typemap(doc, name="apducommand", type="byte[]") (BYTELIST* APDUCOMMAND) "apducommand: list of APDU bytes to transmit"; %typemap(doc, name="apduresponse", type="byte[]") (BYTELIST* APDURESPONSE) "apduresponse: on output, the list of APDU response bytes"; %typemap(doc, name="atr", type="byte[]") (BYTELIST* ATR) "atr: card ATR"; %typemap(doc, name="atr", type="byte[]") (BYTELIST* ATROUT) "atr: on output, the card ATR"; %typemap(doc, name="attributes", type="byte[]") (BYTELIST* ATTRIBUTES) "attributes: on output, a list of attributes"; %typemap(doc, name="mask", type="byte[]") (BYTELIST* MASK) "mask: mask to apply to card ATR"; %typemap(doc, name="inbuffer", type="byte[]") (BYTELIST* INBUFFER) "inbuffer: list of bytes to send with the control code"; %typemap(doc, name="outbuffer", type="byte[]") (BYTELIST* OUTBUFFER) "outbuffer: on output, the bytes returned by execution of the control code"; %typemap(doc, name="primaryprovider", type="GUID") (GUIDLIST* PRIMARYPROVIDER) "primaryprovidername: GUID of the smart card primary service provider"; %typemap(doc, name="providerlist", type="GUID[]") (GUIDLIST* PROVIDERLIST) "providerlist: list of GUIDs of interfaces supported by smart card"; %typemap(doc, name="interfaces", type="GUID[]") (GUIDLIST* GUIDINTERFACES) "interfaces: on output, a list of GUIDs of the interfaces supported by the smart card"; %typemap(doc, name="cards", type="") (STRINGLIST* CARDSTOLOCATE) "cards: a list of cards to locate"; %typemap(doc, name="matchingcards", type="[]") (STRINGLIST* MATCHINGCARDS) "matchingcards: on output, a list of matching cards"; %typemap(doc, name="readergroups", type="[]") (STRINGLIST* READERGROUPSIN) "readergroups: a list of reader groups to search for readers"; %typemap(doc, name="readergroups", type="[]") (STRINGLIST* READERGROUPSOUT) "readergroups: on output, the list of reader groups"; %typemap(doc, name="readers", type="[]") (STRINGLIST* READERSFOUND) "matchingcards: on output, a list of readers found"; %typemap(doc, name="readername", type="") (STRINGLIST* pszReaderName) "readername: on output, the name of the reader in which the card is inserted"; %typemap(doc, name="dwActiveProtocol", type="") (SCARDDWORDARG* pdwActiveProtocol) "dwActiveProtocol: on output, active protocol of card connection"; %typemap(doc, name="dwState", type="") (SCARDDWORDARG* pdwState) "dwState: on output, current state of the smart card"; %typemap(doc, name="dwProtocol", type="") (SCARDDWORDARG* pdwProtocol) "dwProtocol: on output, the current protocol"; %typemap(doc, name="dwScope", type="") (SCARDDWORDARG dwScope) "dwScope: context scope"; %typemap(doc, name="dwProviderId", type="") (SCARDDWORDARG dwProviderId) "dwProviderId: provider type, SCARD_PROVIDER_PRIMARY or SCARD_PROVIDER_CSP"; %typemap(doc, name="dwPreferredProtocols", type="") (SCARDDWORDARG dwPreferredProtocols) "dwPreferredProtocols: preferred protocols"; %typemap(doc, name="dwShareMode", type="") (SCARDDWORDARG dwShareMode) "dwShareMode: share mode"; %typemap(doc, name="dwDisposition", type="") (SCARDDWORDARG dwDisposition) "dwDisposition: card disposition on return"; %typemap(doc, name="dwAttrId", type="") (SCARDDWORDARG dwAttrId) "dwAttrId: value of attribute to get"; %typemap(doc, name="dwTimeout", type="") (SCARDDWORDARG dwTimeout) "dwTimeout: timeout value, INFINITE for infinite time-out"; %typemap(doc, name="dwInitialization", type="") (SCARDDWORDARG dwInitialization) "dwInitialization: the type of initialization that should be performed on the card"; %typemap(doc, name="dwControlCode", type="") (SCARDDWORDARG dwControlCode) "dwControlCode: the control code to send"; // // these functions are only available on win32 PCSC // but a fake function is provided on Unix // /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ADDREADERTOGROUP " adds a reader to a reader group Windows only, not supported by PCSC lite wrapper. example: >>> from smartcard.scard import * >>> ... establish context ... >>> newgroup = 'SCard$MyOwnGroup' >>> reader = 'SchlumbergerSema Reflex USB v.2 0' >>> readeralias = 'SchlumbergerSema Reflex USB v.2 0 alias' >>> hresult = SCardIntroduceReader(hcontext, readeralias, reader]) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to introduce reader: ' + >>> SCardGetErrorMessage(hresult)) >>> >>> hresult = SCardAddReaderToGroup(hcontext, readeralias, newgroup) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to add reader to group: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_ADDREADERTOGROUP; %rename(SCardAddReaderToGroup) _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); SCARDRETCODE _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCEREADER " Introduces a reader to the smart card subsystem. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... >>> dummyreader = readers[0] + ' dummy' >>> hresult = SCardIntroduceReader(hcontext, dummyreader, readers[0]) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to introduce reader: ' + dummyreader + ' : ' >>> + SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_INTRODUCEREADER; %rename(SCardIntroduceReader) _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName); SCARDRETCODE _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCEREADERGROUP " Introduces a reader group to the smart card subsystem. However, the reader group is not created until the group is specified when adding a reader to the smart card database. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> hresult = SCardIntroduceReaderGroup(hcontext, 'SCard$MyOwnGroup') >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to introduce reader group: ' + >>> SCardGetErrorMessage(hresult)) >>> hresult = SCardAddReaderToGroup(hcontext, 'SchlumbergerSema Reflex USB v.2 0', 'SCard$MyOwnGroup') >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to add reader to group: ' + >>> SCardGetErrorMessage(hresult)) " %enddef %feature("docstring") DOCSTRING_INTRODUCEREADERGROUP; %rename(SCardIntroduceReaderGroup) _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); SCARDRETCODE _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETREADERGROUP " Removes a previously introduced smart card reader group from the smart card subsystem. Although this function automatically clears all readers from the group, it does not affect the existence of the individual readers in the database. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... establish context ... >>> ... >>> hresult = SCardForgetReaderGroup(hcontext, newgroup) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to forget reader group: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_FORGETREADERGROUP; %rename(SCardForgetReaderGroup) _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); SCARDRETCODE _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); // // these functions are only available on win32 PCSC // /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_REMOVEREADERFROMGROUP " Removes a reader from an existing reader group. This function has no affect on the reader. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> hresult = SCardRemoveReaderFromGroup(hcontext, 'SchlumbergerSema Reflex USB v.2 0', 'SCard$MyOwnGroup') >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Unable to remove reader from group: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_REMOVEREADERFROMGROUP; %rename(SCardRemoveReaderFromGroup) _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); SCARDRETCODE _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); #ifdef WIN32 /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETCARDTYPE " removes an introduced smart card from the smart card subsystem. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... establish context ... >>> hresult = SCardForgetCardType(hcontext, 'myCardName') >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failed to remove card type: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_FORGETCARDTYPE; %rename(SCardForgetCardType) _ForgetCardType(SCARDCONTEXT hcontext, char* szCardName); SCARDRETCODE _ForgetCardType(SCARDCONTEXT hcontext, char* szCardName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETREADER " Removes a previously introduced smart card reader from the smart card subsystem. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... establish context ... >>> ... >>> hresult = SCardForgetReader(hcontext, dummyreader) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failed to forget readers ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_FORGETREADER; %rename(SCardForgetReader) _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName); SCARDRETCODE _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETCARDTYPEPROVIDERNAME " Returns the name of the module (dynamic link library) containing the provider for a given card name and provider type. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... establish context ... >>> hresult, cards = SCardListCards(hcontext, [], []) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failure to list cards: ' + >>> SCardGetErrorMessage(hresult)) >>> for i in cards: >>> hresult, providername = SCardGetCardTypeProviderName(hcontext, i, SCARD_PROVIDER_PRIMARY) >>> if hresult == SCARD_S_SUCCESS: >>> print(providername) >>> hresult, providername = SCardGetCardTypeProviderName(hcontext, i, SCARD_PROVIDER_CSP) >>> if hresult == SCARD_S_SUCCESS: >>> print(providername) ... " %enddef %feature("docstring") DOCSTRING_GETCARDTYPEPROVIDERNAME; %rename(SCardGetCardTypeProviderName) _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* szCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* pszProviderName ); SCARDRETCODE _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* szCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* pszProviderName ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCECARDTYPE " Introduces a smart card to the smart card subsystem (for the active user) by adding it to the smart card database. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... >>> znewcardName = 'dummy-card' >>> znewcardATR = [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] >>> znewcardMask = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] >>> znewcardPrimGuid = smartcard.guid.strToGUID('{128F3806-4F70-4ccf-977A-60C390664840}') >>> znewcardSecGuid = smartcard.guid.strToGUID('{EB7F69EA-BA20-47d0-8C50-11CFDEB63BBE}') >>> ... >>> hresult = SCardIntroduceCardType(hcontext, znewcardName, >>> znewcardPrimGuid, znewcardPrimGuid + znewcardSecGuid, >>> znewcardATR, znewcardMask) >>> >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failed to introduce card type: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_INTRODUCECARDTYPE; %rename(SCardIntroduceCardType) _IntroduceCardType( SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* PRIMARYPROVIDER, GUIDLIST* PROVIDERLIST, BYTELIST* ATR, BYTELIST* MASK ); SCARDRETCODE _IntroduceCardType( SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* PRIMARYPROVIDER, GUIDLIST* PROVIDERLIST, BYTELIST* ATR, BYTELIST* MASK ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTINTERFACES " Provides a list of interfaces supplied by a given card. The caller supplies the name of a smart card previously introduced to the subsystem, and receives the list of interfaces supported by the card Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> hresult, interfaces = SCardListInterfaces(hcontext, 'Schlumberger Cryptoflex 8k v2') >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failed to list interfaces: ' + >>> SCardGetErrorMessage(hresult)) ... " %enddef %feature("docstring") DOCSTRING_LISTINTERFACES; %rename(SCardListInterfaces) _ListInterfaces(SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* GUIDINTERFACES); SCARDRETCODE _ListInterfaces(SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* GUIDINTERFACES); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTCARDS " Searches the smart card database and provides a list of named cards previously introduced to the system by the user. The caller specifies an ATR string, a set of interface identifiers (GUIDs), or both. If both an ATR string and an identifier array are supplied, the cards returned will match the ATR string supplied and support the interfaces specified. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> ... >>> slbCryptoFlex8kv2ATR = [ 0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00 ] >>> hresult, card = SCardListCards(hcontext, slbCryptoFlex8kv2ATR, []) >>> if hresult ! =SCARD_S_SUCCESS: >>> raise error('Failure to locate Schlumberger Cryptoflex 8k v2 card: ' + >>> SCardGetErrorMessage(hresult)) >>> hresult, cards = SCardListCards(hcontext, [], []) >>> if hresult != SCARD_S_SUCCESS: >>> raise error('Failure to list cards: ' + >>> SCardGetErrorMessage(hresult)) >>> print('Cards: ', cards) ... " %enddef %feature("docstring") DOCSTRING_LISTCARDS; %rename (SCardListCards) _ListCards( SCARDCONTEXT hcontext, BYTELIST* ATR, GUIDLIST* PROVIDERLIST, STRINGLIST* MATCHINGCARDS); SCARDRETCODE _ListCards( SCARDCONTEXT hcontext, BYTELIST* ATR, GUIDLIST* PROVIDERLIST, STRINGLIST* MATCHINGCARDS); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LOCATECARDS " Searches the readers listed in the readerstate parameter for a card with an ATR string that matches one of the card names specified in mszCards, returning immediately with the result. Windows only, not supported by PCSC lite wrapper. >>> from smartcard.scard import * >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> hresult, readers = SCardListReaders(hcontext, []) >>> readerstates = [] >>> cards = ['Schlumberger Cryptoflex 4k', 'Schlumberger Cryptoflex 8k', 'Schlumberger Cryptoflex 8k v2'] >>> for i in xrange(len(readers)): >>> readerstates += [(readers[i], SCARD_STATE_UNAWARE)] >>> hresult, newstates = SCardLocateCards(hcontext, cards, readerstates) >>> for i in newstates: >>> reader, eventstate, atr = i >>> print(reader,) >>> for b in atr: >>> print('0x%.2X' % b, end='') >>> print("") >>> if eventstate & SCARD_STATE_ATRMATCH: >>> print('Card found') >>> if eventstate & SCARD_STATE_EMPTY: >>> print('Reader empty') >>> if eventstate & SCARD_STATE_PRESENT: >>> print('Card present in reader') ... " %enddef %feature("docstring") DOCSTRING_LOCATECARDS; %rename(SCardLocateCards) _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* CARDSTOLOCATE, READERSTATELIST *prsl); SCARDRETCODE _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* CARDSTOLOCATE, READERSTATELIST *prsl); #endif // WIN32 /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ISVALIDCONTEXT " This function determines whether a smart card context handle is still valid. After a smart card context handle has been set by L{SCardEstablishContext()}, it may become not valid if the resource manager service has been shut down. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # valid context? >>> hresult = SCardIsValidContext(hcontext) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_ISVALIDCONTEXT; %rename(SCardIsValidContext) _IsValidContext(SCARDCONTEXT hcontext); SCARDRETCODE _IsValidContext(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETATTRIB " This function get an attribute from the IFD Handler. The possible attributes are:: ======================================== ======= ======= Attribute Windows PCSC lite ======================================== ======= ======= SCARD_ATTR_ASYNC_PROTOCOL_TYPES Y SCARD_ATTR_ATR_STRING Y Y SCARD_ATTR_CHANNEL_ID Y Y SCARD_ATTR_CHARACTERISTICS Y Y SCARD_ATTR_CURRENT_BWT Y Y SCARD_ATTR_CURRENT_CLK Y Y SCARD_ATTR_CURRENT_CWT Y Y SCARD_ATTR_CURRENT_D Y Y SCARD_ATTR_CURRENT_EBC_ENCODING Y Y SCARD_ATTR_CURRENT_F Y Y SCARD_ATTR_CURRENT_IFSC Y Y SCARD_ATTR_CURRENT_IFSD Y Y SCARD_ATTR_CURRENT_IO_STATE Y Y SCARD_ATTR_CURRENT_N Y Y SCARD_ATTR_CURRENT_PROTOCOL_TYPE Y Y SCARD_ATTR_CURRENT_W Y Y SCARD_ATTR_DEFAULT_CLK Y Y SCARD_ATTR_DEFAULT_DATA_RATE Y Y SCARD_ATTR_DEVICE_FRIENDLY_NAME_A Y Y SCARD_ATTR_DEVICE_FRIENDLY_NAME_W Y Y SCARD_ATTR_DEVICE_IN_USE Y Y SCARD_ATTR_DEVICE_SYSTEM_NAME_A Y Y SCARD_ATTR_DEVICE_SYSTEM_NAME_W Y Y SCARD_ATTR_DEVICE_UNIT Y Y SCARD_ATTR_ESC_AUTHREQUEST Y Y SCARD_ATTR_ESC_CANCEL Y Y SCARD_ATTR_ESC_RESET Y Y SCARD_ATTR_EXTENDED_BWT Y Y SCARD_ATTR_ICC_INTERFACE_STATUS Y Y SCARD_ATTR_ICC_PRESENCE Y Y SCARD_ATTR_ICC_TYPE_PER_ATR Y Y SCARD_ATTR_MAXINPUT Y Y SCARD_ATTR_MAX_CLK Y Y SCARD_ATTR_MAX_DATA_RATE Y Y SCARD_ATTR_MAX_IFSD Y Y SCARD_ATTR_POWER_MGMT_SUPPORT Y Y SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Y Y SCARD_ATTR_SYNC_PROTOCOL_TYPES Y SCARD_ATTR_USER_AUTH_INPUT_DEVICE Y Y SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE Y Y SCARD_ATTR_VENDOR_IFD_SERIAL_NO Y Y SCARD_ATTR_VENDOR_IFD_TYPE Y Y SCARD_ATTR_VENDOR_IFD_VERSION Y Y SCARD_ATTR_VENDOR_NAME Y Y ======================================== ======= ======= Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # get attribute >>> hresult, attrib = SCardGetAttrib(hcard, SCARD_ATTR_ATR_STRING) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> print(attrib) " %enddef %feature("docstring") DOCSTRING_GETATTRIB; %rename(SCardGetAttrib) _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTES); SCARDRETCODE _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTES); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_SETATTRIB " This function sets an attribute from the IFD Handler. Not all attributes are supported by all readers nor can they be set at all times. The possible attributes are:: ======================================== ======= ======= Attribute Windows PCSC lite ======================================== ======= ======= SCARD_ATTR_ASYNC_PROTOCOL_TYPES Y SCARD_ATTR_ATR_STRING Y Y SCARD_ATTR_CHANNEL_ID Y Y SCARD_ATTR_CHARACTERISTICS Y Y SCARD_ATTR_CURRENT_BWT Y Y SCARD_ATTR_CURRENT_CLK Y Y SCARD_ATTR_CURRENT_CWT Y Y SCARD_ATTR_CURRENT_D Y Y SCARD_ATTR_CURRENT_EBC_ENCODING Y Y SCARD_ATTR_CURRENT_F Y Y SCARD_ATTR_CURRENT_IFSC Y Y SCARD_ATTR_CURRENT_IFSD Y Y SCARD_ATTR_CURRENT_IO_STATE Y Y SCARD_ATTR_CURRENT_N Y Y SCARD_ATTR_CURRENT_PROTOCOL_TYPE Y Y SCARD_ATTR_CURRENT_W Y Y SCARD_ATTR_DEFAULT_CLK Y Y SCARD_ATTR_DEFAULT_DATA_RATE Y Y SCARD_ATTR_DEVICE_FRIENDLY_NAME_A Y Y SCARD_ATTR_DEVICE_FRIENDLY_NAME_W Y Y SCARD_ATTR_DEVICE_IN_USE Y Y SCARD_ATTR_DEVICE_SYSTEM_NAME_A Y Y SCARD_ATTR_DEVICE_SYSTEM_NAME_W Y Y SCARD_ATTR_DEVICE_UNIT Y Y SCARD_ATTR_ESC_AUTHREQUEST Y Y SCARD_ATTR_ESC_CANCEL Y Y SCARD_ATTR_ESC_RESET Y Y SCARD_ATTR_EXTENDED_BWT Y Y SCARD_ATTR_ICC_INTERFACE_STATUS Y Y SCARD_ATTR_ICC_PRESENCE Y Y SCARD_ATTR_ICC_TYPE_PER_ATR Y Y SCARD_ATTR_MAXINPUT Y Y SCARD_ATTR_MAX_CLK Y Y SCARD_ATTR_MAX_DATA_RATE Y Y SCARD_ATTR_MAX_IFSD Y Y SCARD_ATTR_POWER_MGMT_SUPPORT Y Y SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Y Y SCARD_ATTR_SYNC_PROTOCOL_TYPES Y SCARD_ATTR_USER_AUTH_INPUT_DEVICE Y Y SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE Y Y SCARD_ATTR_VENDOR_IFD_SERIAL_NO Y Y SCARD_ATTR_VENDOR_IFD_TYPE Y Y SCARD_ATTR_VENDOR_IFD_VERSION Y Y SCARD_ATTR_VENDOR_NAME Y Y ======================================== ======= ======= Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. >>> from smartcard.scard import * >>> ... establish context and connect to card ... >>> hresult, attrib = SCardSetAttrib(hcard, SCARD_ATTR_VENDOR_NAME, ['G', 'e', 'm', 'a', 'l', 't', 'o']) >>> if hresult != SCARD_S_SUCCESS: >>> print('Failed to set attribute') >>> ... " %enddef %feature("docstring") DOCSTRING_SETATTRIB; %rename(SCardSetAttrib) _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTESIN); SCARDRETCODE _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTESIN); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CONTROL " This function sends a control command to the reader connected to by L{SCardConnect()}. It returns a result and the control response. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # control >>> CMD = [0x12, 0x34] >>> hresult, response = SCardControl(hcard, 42, CMD) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_CONTROL; %rename(SCardControl) _Control( SCARDHANDLE hcard, SCARDDWORDARG dwControlCode, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); SCARDRETCODE _Control( SCARDHANDLE hcard, SCARDDWORDARG dwControlCode, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_BEGINTRANSACTION " This function establishes a temporary exclusive access mode for doing a series of commands or transaction. You might want to use this when you are selecting a few files and then writing a large file so you can make sure that another application will not change the current file. If another application has a lock on this reader or this application is in SCARD_SHARE_EXCLUSIVE there will be no action taken. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # begin transaction >>> hresult = SCardBeginTransaction(hcard) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_BEGINTRANSACTION; %rename(SCardBeginTransaction) _BeginTransaction(SCARDHANDLE hcard); SCARDRETCODE _BeginTransaction(SCARDHANDLE hcard); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CANCEL " This function cancels all pending blocking requests on the L{SCardGetStatusChange()} function. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> ... establish context ... >>> hresult = SCardCancel(hcard) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) ..." %enddef %feature("docstring") DOCSTRING_CANCEL; %rename(SCardCancel) _Cancel(SCARDCONTEXT hcontext); SCARDRETCODE _Cancel(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CONNECT " This function establishes a connection to the friendly name of the reader specified in readername. The first connection will power up and perform a reset on the card. Value of dwShareMode: - SCARD_SHARE_SHARED This application will allow others to share the reader - SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader - SCARD_SHARE_DIRECT Direct control of the reader, even without a card SCARD_SHARE_DIRECT can be used before using L{SCardControl()} to send control commands to the reader even if a card is not present in the reader. Value of dwPreferredProtocols: - SCARD_PROTOCOL_T0 Use the T=0 protocol - SCARD_PROTOCOL_T1 Use the T=1 protocol - SCARD_PROTOCOL_RAW Use with memory type cards >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_CONNECT; %rename(SCardConnect) _Connect( SCARDCONTEXT hcontext, char* szReaderName, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDHANDLE* phcard, SCARDDWORDARG* pdwActiveProtocol ); SCARDRETCODE _Connect( SCARDCONTEXT hcontext, char* szReaderName, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDHANDLE* phcard, SCARDDWORDARG* pdwActiveProtocol ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_DISCONNECT " This function terminates a connection to the connection made through L{SCardConnect()}. Value of disposition: - SCARD_LEAVE_CARD Do nothing - SCARD_RESET_CARD Reset the card (warm reset) - SCARD_UNPOWER_CARD Unpower the card (cold reset) - SCARD_EJECT_CARD Eject the card >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # disconnect >>> hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_DISCONNECT; %rename(SCardDisconnect) _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); SCARDRETCODE _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ENDTRANSACTION " This function ends a previously begun transaction. The calling application must be the owner of the previously begun transaction or an error will occur. Value of disposition: - SCARD_LEAVE_CARD Do nothing - SCARD_RESET_CARD Reset the card - SCARD_UNPOWER_CARD Unpower the card - SCARD_EJECT_CARD Eject the card >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # begin transaction >>> hresult = SCardBeginTransaction(hcard) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # end transaction >>> hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_ENDTRANSACTION; %rename(SCardEndTransaction) _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); SCARDRETCODE _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ESTABLISHCONTEXT " This function creates a communication context to the PC/SC Resource Manager. This must be the first PC/SC function called in a PC/SC application. Value of dwScope: - SCARD_SCOPE_USER Operations performed within the scope of the User - SCARD_SCOPE_TERMINAL Not used - SCARD_SCOPE_GLOBAL Not used - SCARD_SCOPE_SYSTEM Operations performed within the scope of the system >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) " %enddef %feature("docstring") DOCSTRING_ESTABLISHCONTEXT; %rename(SCardEstablishContext) _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phcontext); SCARDRETCODE _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETSTATUSCHANGE " This function receives a structure or list of tuples containing reader states. A READERSTATE hast three fields (readername, state, atr). It then blocks for a change in state to occur on any of the OR'd values contained in the current state for a maximum blocking time of dwTimeout or forever if INFINITE is used. The new event state will be contained in state. A status change might be a card insertion or removal event, a change in ATR, etc. Value of state: - SCARD_STATE_UNAWARE The application is unaware of the current state, and would like to know. The use of this value results in an immediate return from state transition monitoring services. This is represented by all bits set to zero - SCARD_STATE_IGNORE This reader should be ignored - SCARD_STATE_CHANGED There is a difference between the state believed by the application, and the state known by the resource manager. When this bit is set, the application may assume a significant state change has occurred on this reader - SCARD_STATE_UNKNOWN The given reader name is not recognized by the resource manager. If this bit is set, then SCARD_STATE_CHANGED and SCARD_STATE_IGNORE will also be set - SCARD_STATE_UNAVAILABLE The actual state of this reader is not available. If this bit is set, then all the following bits are clear - SCARD_STATE_EMPTY There is no card in the reader. If this bit is set, all the following bits will be clear - SCARD_STATE_PRESENT There is a card in the reader - SCARD_STATE_ATRMATCH There is a card in the reader with an ATR matching one of the target cards. If this bit is set, SCARD_STATE_PRESENT will also be set. This bit is only returned on the SCardLocateCards function - SCARD_STATE_EXCLUSIVE The card in the reader is allocated for exclusive use by another application. If this bit is set, SCARD_STATE_PRESENT will also be set - SCARD_STATE_INUSE The card in the reader is in use by one or more other applications, but may be connected to in shared mode. If this bit is set, SCARD_STATE_PRESENT will also be set - SCARD_STATE_MUTE There is an unresponsive card in the reader >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # get status change >>> readerstates = [] >>> for reader in readers: >>> readerstates.append((reader, SCARD_STATE_UNAWARE)) >>> >>> hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, readerstates) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> for state in newstates: >>> reader, eventstate, atr = state >>> print(f'Reader: {reader}:', end='') >>> if eventstate & SCARD_STATE_PRESENT: >>> print(' Card present') >>> if eventstate & SCARD_STATE_EMPTY: >>> print(' Reader empty') >>> >>> print('insert or remove a card') >>> # wait for card move >>> readerstates = newstates >>> hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, readerstates) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_GETSTATUSCHANGE; %rename(SCardGetStatusChange) _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl); SCARDRETCODE _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTREADERS " This function returns a list of currently available readers on the system. A list of group can be provided in input to list readers in a given group only. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> for reader in readers: >>> print(reader) " %enddef %feature("docstring") DOCSTRING_LISTREADERS; %rename(SCardListReaders) _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSIN, STRINGLIST* READERSFOUND); SCARDRETCODE _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSIN, STRINGLIST* READERSFOUND); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTREADERGROUPS " This function returns a list of currently available reader groups on the system. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> hresult, readerGroups = SCardListReaderGroups(hcontext) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> print('PCSC Reader groups:', readerGroups) " %enddef %feature("docstring") DOCSTRING_LISTREADERGROUPS; %rename(SCardListReaderGroups) _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSOUT); SCARDRETCODE _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSOUT); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_RECONNECT " This function reestablishes a connection to a reader that was previously connected to using L{SCardConnect()}. In a multi application environment it is possible for an application to reset the card in shared mode. When this occurs any other application trying to access certain commands will be returned the value SCARD_W_RESET_CARD. When this occurs L{SCardReconnect()} must be called in order to acknowledge that the card was reset and allow it to change it's state accordingly. Value of dwShareMode: - SCARD_SHARE_SHARED This application will allow others to share the reader - SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader Value of dwPreferredProtocols: - SCARD_PROTOCOL_T0 Use the T=0 protocol - SCARD_PROTOCOL_T1 Use the T=1 protocol - SCARD_PROTOCOL_RAW Use with memory type cards dwPreferredProtocols is a bit mask of acceptable protocols for the connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you do not have a preferred protocol. Value of dwInitialization: - SCARD_LEAVE_CARD Do nothing - SCARD_RESET_CARD Reset the card (warm reset) - SCARD_UNPOWER_CARD Unpower the card (cold reset) - SCARD_EJECT_CARD Eject the card >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # reconnect >>> hresult, activeProtocol = SCardReconnect(hcard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, SCARD_RESET_CARD) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) " %enddef %feature("docstring") DOCSTRING_RECONNECT; %rename(SCardReconnect) _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ); SCARDRETCODE _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_RELEASECONTEXT " Release a PC/SC context established by L{SCardEstablishContext()}. >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # release context >>> hresult = SCardReleaseContext(hcontext) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ReleaseContextException(hresult) " %enddef %feature("docstring") DOCSTRING_RELEASECONTEXT; %rename(SCardReleaseContext) _ReleaseContext(SCARDCONTEXT hcontext); SCARDRETCODE _ReleaseContext(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_STATUS " This function returns the current status of the reader connected to by hcard. The reader friendly name is returned, as well as the state, protocol and ATR. The state is a DWORD possibly OR'd with the following values: Value of pdwState: - SCARD_ABSENT There is no card in the reader - SCARD_PRESENT There is a card in the reader, but it has not been moved into position for use - SCARD_SWALLOWED There is a card in the reader in position for use. The card is not powered - SCARD_POWERED Power is being provided to the card, but the reader driver is unaware of the mode of the card - SCARD_NEGOTIABLE The card has been reset and is awaiting PTS negotiation - SCARD_SPECIFIC The card has been reset and specific communication protocols have been established Value of pdwProtocol: - SCARD_PROTOCOL_T0 Use the T=0 protocol - SCARD_PROTOCOL_T1 Use the T=1 protocol >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> from smartcard.util import toHexString >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # status >>> hresult, reader, state, protocol, atr = SCardStatus(hcard) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> print('Reader:', reader) >>> print('State: 0x%04X' % state) >>> print('Protocol:', protocol) >>> print('ATR:', toHexString(atr)) " %enddef %feature("docstring") DOCSTRING_STATUS; %rename(SCardStatus) _Status( SCARDHANDLE hcard, STRING* pszReaderNameOut, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* ATROUT ); SCARDRETCODE _Status( SCARDHANDLE hcard, STRING* pszReaderNameOut, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* ATROUT ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_TRANSMIT " This function sends an APDU to the smart card contained in the reader connected to by L{SCardConnect()}. It returns a result and the card APDU response. Value of pioSendPci: - SCARD_PCI_T0 Pre-defined T=0 PCI structure - SCARD_PCI_T1 Pre-defined T=1 PCI structure >>> from smartcard.scard import * >>> from smartcard.pcsc import * >>> from smartcard.util import toHexString >>> >>> # establish context >>> hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.EstablishContextException(hresult) >>> >>> # list readers >>> hresult, readers = SCardListReaders(hcontext, []) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.ListReadersException(hresult) >>> >>> # connect >>> hresult, hcard, dwActiveProtocol = SCardConnect( >>> hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> >>> # transmit >>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] >>> DF_TELECOM = [0x7F, 0x10] >>> hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) >>> if hresult != SCARD_S_SUCCESS: >>> raise PCSCExceptions.BaseSCardException(hresult) >>> print(toHexString(response)) " %enddef %feature("docstring") DOCSTRING_TRANSMIT; %rename(SCardTransmit) _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* APDUCOMMAND, BYTELIST* APDURESPONSE ); SCARDRETCODE _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* APDUCOMMAND, BYTELIST* APDURESPONSE ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_SCARD_CTL_CODE " This function returns the value of a control code >>> from smartcard.scard import * >>> ... >>> CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) >>> ... " %enddef %feature("docstring") DOCSTRING_SCARD_CTL_CODE; %rename(SCARD_CTL_CODE) _SCARD_CTL_CODE(long code); long _SCARD_CTL_CODE(long code); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETERRORMESSAGE " This function return a human readable text for the given PC/SC error code. >>> from smartcard.scard import * >>> ... >>> hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) >>> if hresult != SCARD_S_SUCCESS: >>> print('Failed to transmit:', SCardGetErrorMessage(hresult)) >>> ... " %enddef %feature("docstring") DOCSTRING_GETERRORMESSAGE; %rename(SCardGetErrorMessage) _GetErrorMessage(long lErrCode); ERRORSTRING _GetErrorMessage(long lErrCode); %inline %{ %} %{ PyObject *PyExc_SCardError=NULL; %} //---------------------------------------------------------------------- // This code gets added to the module initialization function //---------------------------------------------------------------------- %init %{ PyExc_SCardError = PyErr_NewException("scard.error", NULL, NULL); if (PyExc_SCardError != NULL) PyDict_SetItemString(d, "error", PyExc_SCardError); /* load the PCSC library */ winscard_init(); %} //---------------------------------------------------------------------- // This code is added to the scard.py python module //---------------------------------------------------------------------- %pythoncode %{ error = _scard.error %} %include PcscDefs.i #ifdef PCSCLITEyy %pythoncode %{ def SCardListCards(hcontext, atr, guidlist): return (SCARD_S_SUCCESS, []) def SCardLocateCards(hcontext, cardnames, readerstates): newreaderstates=[] for state in readerstates: newreaderstates.append((state[0], state[1], [])) return (SCARD_S_SUCCESS, newreaderstates) %} #endif #ifdef PCSCLITE %constant char* resourceManager = "pcsclite" ; #ifdef __APPLE__ %constant char* resourceManagerSubType = "pcsclite-lion" ; #else // !__APPLE__ %constant char* resourceManagerSubType = "pcsclite-linux" ; #endif // __APPLE__ #endif // PCSCLITE #ifdef WIN32 %constant char* resourceManager = "winscard" ; %constant char* resourceManagerSubType = "winscard-win32" ; #endif // WIN32 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/scard.rc0000644000076500000240000000046314677317744020266 0ustar00rousseaustaff#include #define VER_FILEDESCRIPTION_STR "Python PCSC Module\0" #define VER_INTERNALNAME_STR "_scard.pyd" #define VER_ORIGINALFILENAME_STR "_scard.pyd" #define VER_FILETYPE VFT_DLL #define VER_FILESUBTYPE (0) #include "gemalto.ver" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/scard/winscarddll.c0000644000076500000240000007015014677317744021316 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ #include #ifdef __APPLE__ #include #endif #include "pcsctypes.h" #include "winscarddll.h" #ifdef PCSCLITE #include #include #endif // PCSCLITE #ifndef NULL #define NULL ((void*)0) #endif //NULL // // these functions are only available on win32 PCSC // #ifdef WIN32 WINSCARDAPI HANDLE WINAPI _defaultSCARDACCESSSTARTEDEVENT(void) { return NULL; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDADDREADERTOGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETCARDTYPEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETREADERA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETREADERGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETPROVIDERIDA( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidProviderId) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETCARDTYPEPROVIDERNAMEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, OUT LPTSTR szProvider, IN OUT SCARDDWORDARG* pcchProvider) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCECARDTYPEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN LPCGUID pguidPrimaryProvider, IN LPCGUID rgguidInterfaces, IN SCARDDWORDARG dwInterfaceCount, IN LPCBYTE pbAtr, IN LPCBYTE pbAtrMask, IN SCARDDWORDARG cbAtrLen) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCEREADERA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szDeviceName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCEREADERGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTCARDSA( IN SCARDCONTEXT hContext, IN LPCBYTE pbAtr, IN LPCGUID rgquidInterfaces, IN SCARDDWORDARG cguidInterfaceCount, OUT LPTSTR mszCards, IN OUT SCARDDWORDARG* pcchCards) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTINTERFACESA( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidInterfaces, IN OUT SCARDDWORDARG* pcguidInterfaces) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLOCATECARDSA( IN SCARDCONTEXT hContext, IN LPCSTR mszCards, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLOCATECARDSBYATRA( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN SCARDDWORDARG cAtrs, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { return SCARD_E_NO_SERVICE; } WINSCARDAPI void WINAPI _defaultSCARDRELEASESTARTEDEVENT(void) { return; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDREMOVEREADERFROMGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSETCARDTYPEPROVIDERNAMEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, IN LPCSTR szProvider) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSTATE( IN SCARDHANDLE hCard, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen) { return SCARD_E_NO_SERVICE; } SCARDACCESSSTARTEDEVENT mySCardAccessStartedEvent = _defaultSCARDACCESSSTARTEDEVENT; SCARDADDREADERTOGROUPA mySCardAddReaderToGroupA = _defaultSCARDADDREADERTOGROUPA; SCARDFORGETCARDTYPEA mySCardForgetCardTypeA = _defaultSCARDFORGETCARDTYPEA; SCARDFORGETREADERA mySCardForgetReaderA = _defaultSCARDFORGETREADERA; SCARDFORGETREADERGROUPA mySCardForgetReaderGroupA = _defaultSCARDFORGETREADERGROUPA; SCARDGETPROVIDERIDA mySCardGetProviderIdA = _defaultSCARDGETPROVIDERIDA; SCARDGETCARDTYPEPROVIDERNAMEA mySCardGetCardTypeProviderNameA = _defaultSCARDGETCARDTYPEPROVIDERNAMEA; SCARDINTRODUCECARDTYPEA mySCardIntroduceCardTypeA = _defaultSCARDINTRODUCECARDTYPEA; SCARDINTRODUCEREADERA mySCardIntroduceReaderA = _defaultSCARDINTRODUCEREADERA; SCARDINTRODUCEREADERGROUPA mySCardIntroduceReaderGroupA = _defaultSCARDINTRODUCEREADERGROUPA; SCARDLISTCARDSA mySCardListCardsA = _defaultSCARDLISTCARDSA; SCARDLISTINTERFACESA mySCardListInterfacesA = _defaultSCARDLISTINTERFACESA; SCARDLOCATECARDSA mySCardLocateCardsA = _defaultSCARDLOCATECARDSA; SCARDLOCATECARDSBYATRA mySCardLocateCardsByATRA = _defaultSCARDLOCATECARDSBYATRA; SCARDRELEASESTARTEDEVENT mySCardReleaseStartedEvent = _defaultSCARDRELEASESTARTEDEVENT; SCARDREMOVEREADERFROMGROUPA mySCardRemoveReaderFromGroupA = _defaultSCARDREMOVEREADERFROMGROUPA; SCARDSETCARDTYPEPROVIDERNAMEA mySCardSetCardTypeProviderNameA = _defaultSCARDSETCARDTYPEPROVIDERNAMEA; SCARDSTATE mySCardState = _defaultSCARDSTATE; #endif // WIN32 static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDISVALIDCONTEXT( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETATTRIB( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, OUT LPBYTE pbAttr, IN OUT SCARDDWORDARG* pcbAttrLen) { (void)hCard; (void)dwAttrId; (void)pbAttr; (void)pcbAttrLen; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSETATTRIB( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, IN LPCBYTE pbAttr, IN SCARDDWORDARG cbAttrLen) { (void)hCard; (void)dwAttrId; (void)pbAttr; (void)cbAttrLen; return SCARD_E_NO_SERVICE; } SCARDISVALIDCONTEXT mySCardIsValidContext = _defaultSCARDISVALIDCONTEXT; SCARDGETATTRIB mySCardGetAttrib = _defaultSCARDGETATTRIB; SCARDSETATTRIB mySCardSetAttrib = _defaultSCARDSETATTRIB; static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCONTROL( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwControlCode, IN LPCVOID lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT LPVOID lpOutBuffer, IN SCARDDWORDARG nOutBufferSize, OUT SCARDDWORDARG* lpBytesReturned) { (void)hCard; (void)dwControlCode; (void)lpInBuffer; (void)nInBufferSize; (void)lpOutBuffer; (void)nOutBufferSize; (void)lpBytesReturned; return SCARD_E_NO_SERVICE; } #ifdef PCSCLITE /////////////////////////////////////////////////////////////////////////////// // some pcsclite versions (e.g. on Max OS X Tiger) have no pcsc_stringify // this function was taken from pcsclite // static char* _defaultPCSCSTRINGIFYERROR( SCARDRETCODE pcscError ) { static char strError[75]; switch(pcscError ) { case SCARD_S_SUCCESS: strncpy( strError, "Command successful.", sizeof( strError ) ); break; case SCARD_E_CANCELLED: strncpy( strError, "Command cancelled.", sizeof( strError ) ); break; case SCARD_E_CANT_DISPOSE: strncpy( strError, "Cannot dispose handle.", sizeof( strError ) ); break; case SCARD_E_INSUFFICIENT_BUFFER: strncpy( strError, "Insufficient buffer.", sizeof( strError ) ); break; case SCARD_E_INVALID_ATR: strncpy( strError, "Invalid ATR.", sizeof( strError ) ); break; case SCARD_E_INVALID_HANDLE: strncpy( strError, "Invalid handle.", sizeof( strError ) ); break; case SCARD_E_INVALID_PARAMETER: strncpy( strError, "Invalid parameter given.", sizeof( strError ) ); break; case SCARD_E_INVALID_TARGET: strncpy( strError, "Invalid target given.", sizeof( strError ) ); break; case SCARD_E_INVALID_VALUE: strncpy( strError, "Invalid value given.", sizeof( strError ) ); break; case SCARD_E_NO_MEMORY: strncpy( strError, "Not enough memory.", sizeof( strError ) ); break; case SCARD_F_COMM_ERROR: strncpy( strError, "RPC transport error.", sizeof( strError ) ); break; case SCARD_F_INTERNAL_ERROR: strncpy( strError, "Internal error.", sizeof( strError ) ); break; case SCARD_F_UNKNOWN_ERROR: strncpy( strError, "Unknown error.", sizeof( strError ) ); break; case SCARD_F_WAITED_TOO_LONG: strncpy( strError, "Waited too long.", sizeof( strError ) ); break; case SCARD_E_UNKNOWN_READER: strncpy( strError, "Unknown reader specified.", sizeof( strError ) ); break; case SCARD_E_TIMEOUT: strncpy( strError, "Command timeout.", sizeof( strError ) ); break; case SCARD_E_SHARING_VIOLATION: strncpy( strError, "Sharing violation.", sizeof( strError ) ); break; case SCARD_E_NO_SMARTCARD: strncpy( strError, "No smart card inserted.", sizeof( strError ) ); break; case SCARD_E_UNKNOWN_CARD: strncpy( strError, "Unknown card.", sizeof( strError ) ); break; case SCARD_E_PROTO_MISMATCH: strncpy( strError, "Card protocol mismatch.", sizeof( strError ) ); break; case SCARD_E_NOT_READY: strncpy( strError, "Subsystem not ready.", sizeof( strError ) ); break; case SCARD_E_SYSTEM_CANCELLED: strncpy( strError, "System cancelled.", sizeof( strError ) ); break; case SCARD_E_NOT_TRANSACTED: strncpy( strError, "Transaction failed.", sizeof( strError ) ); break; case SCARD_E_READER_UNAVAILABLE: strncpy( strError, "Reader is unavailable.", sizeof( strError ) ); break; case SCARD_W_UNSUPPORTED_CARD: strncpy( strError, "Card is not supported.", sizeof( strError ) ); break; case SCARD_W_UNRESPONSIVE_CARD: strncpy( strError, "Card is unresponsive.", sizeof( strError ) ); break; case SCARD_W_UNPOWERED_CARD: strncpy( strError, "Card is unpowered.", sizeof( strError ) ); break; case SCARD_W_RESET_CARD: strncpy( strError, "Card was reset.", sizeof( strError ) ); break; case SCARD_W_REMOVED_CARD: strncpy( strError, "Card was removed.", sizeof( strError ) ); break; case SCARD_E_UNSUPPORTED_FEATURE: strncpy( strError, "Feature not supported.", sizeof( strError ) ); break; case SCARD_E_PCI_TOO_SMALL: strncpy( strError, "PCI struct too small.", sizeof( strError ) ); break; case SCARD_E_READER_UNSUPPORTED: strncpy( strError, "Reader is unsupported.", sizeof( strError ) ); break; case SCARD_E_DUPLICATE_READER: strncpy( strError, "Reader already exists.", sizeof( strError ) ); break; case SCARD_E_CARD_UNSUPPORTED: strncpy( strError, "Card is unsupported.", sizeof( strError ) ); break; case SCARD_E_NO_SERVICE: strncpy( strError, "Service not available.", sizeof( strError ) ); break; case SCARD_E_SERVICE_STOPPED: strncpy( strError, "Service was stopped.", sizeof( strError ) ); break; default: snprintf(strError, sizeof(strError)-1, "Unknown error: %ld, 0x%08lx", (long)pcscError, (long unsigned int)pcscError); }; // zero terminates string strError[sizeof(strError)-1] = '\0'; return strError; } #endif static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDBEGINTRANSACTION( IN SCARDHANDLE hCard) { (void)hCard; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCANCEL( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCONNECTA( IN SCARDCONTEXT hContext, IN LPCTSTR szReader, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT SCARDDWORDARG* pdwActiveProtocol) { (void)hContext; (void)szReader; (void)dwShareMode; (void)dwPreferredProtocols; (void)phCard; (void)pdwActiveProtocol; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDDISCONNECT( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition) { (void)hCard; (void)dwDisposition; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDENDTRANSACTION( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition) { (void)hCard; (void)dwDisposition; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDESTABLISHCONTEXT( IN SCARDDWORDARG dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext) { (void)dwScope; (void)pvReserved1; (void)pvReserved2; (void)phContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFREEMEMORY( IN SCARDCONTEXT hContext, IN LPCVOID pvMem) { (void)hContext; (void)pvMem; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETSTATUSCHANGEA( IN SCARDCONTEXT hContext, IN SCARDDWORDARG dwTimeout, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { (void)hContext; (void)dwTimeout; (void)rgReaderStates; (void)cReaders; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTREADERSA( IN SCARDCONTEXT hContext, IN LPCTSTR mszGroups, OUT LPTSTR mszReaders, IN OUT SCARDDWORDARG* pcchReaders) { (void)hContext; (void)mszGroups; (void)mszReaders; (void)pcchReaders; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTREADERGROUPSA( IN SCARDCONTEXT hContext, OUT LPTSTR mszGroups, IN OUT SCARDDWORDARG* pcchGroups) { (void)hContext; (void)mszGroups; (void)pcchGroups; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDRECONNECT( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, IN SCARDDWORDARG dwInitialization, OUT SCARDDWORDARG* pdwActiveProtocol) { (void)hCard; (void)dwShareMode; (void)dwPreferredProtocols; (void)dwInitialization; (void)pdwActiveProtocol; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDRELEASECONTEXT( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSTATUSA( IN SCARDHANDLE hCard, OUT LPTSTR szReaderName, IN OUT SCARDDWORDARG* pcchReaderLen, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen) { (void)hCard; (void)szReaderName; (void)pcchReaderLen; (void)pdwState; (void)pdwProtocol; (void)pbAtr; (void)pcbAtrLen; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDTRANSMIT( IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN SCARDDWORDARG cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT SCARDDWORDARG* pcbRecvLength) { (void)hCard; (void)pioSendPci; (void)pbSendBuffer; (void)cbSendLength; (void)pioRecvPci; (void)pbRecvBuffer; (void)pcbRecvLength; return SCARD_E_NO_SERVICE; } SCARDBEGINTRANSACTION mySCardBeginTransaction = _defaultSCARDBEGINTRANSACTION; SCARDCANCEL mySCardCancel = _defaultSCARDCANCEL; SCARDCONNECTA mySCardConnectA = _defaultSCARDCONNECTA; SCARDCONTROL mySCardControl = _defaultSCARDCONTROL; SCARDDISCONNECT mySCardDisconnect = _defaultSCARDDISCONNECT; SCARDENDTRANSACTION mySCardEndTransaction = _defaultSCARDENDTRANSACTION; SCARDESTABLISHCONTEXT mySCardEstablishContext = _defaultSCARDESTABLISHCONTEXT; SCARDFREEMEMORY mySCardFreeMemory = _defaultSCARDFREEMEMORY; SCARDGETSTATUSCHANGEA mySCardGetStatusChangeA = _defaultSCARDGETSTATUSCHANGEA; SCARDLISTREADERSA mySCardListReadersA = _defaultSCARDLISTREADERSA; SCARDLISTREADERGROUPSA mySCardListReaderGroupsA = _defaultSCARDLISTREADERGROUPSA; SCARDRECONNECT mySCardReconnect = _defaultSCARDRECONNECT; SCARDRELEASECONTEXT mySCardReleaseContext = _defaultSCARDRELEASECONTEXT; SCARDSTATUSA mySCardStatusA = _defaultSCARDSTATUSA; SCARDTRANSMIT mySCardTransmit = _defaultSCARDTRANSMIT; #ifdef PCSCLITE PCSCSTRINGIFYERROR myPcscStringifyError = _defaultPCSCSTRINGIFYERROR; #endif // PCSCLITE void * myg_prgSCardT0Pci=NULL; void * myg_prgSCardT1Pci=NULL; void * myg_prgSCardRawPci=NULL; long winscard_init(void) { static BOOL bFirstCall=TRUE; static long lRetCode=SCARD_E_NO_SERVICE; #ifdef WIN32 #define GETPROCADDRESS(type,name) my##name=(type)GetProcAddress(hinstDLL, #name ); HINSTANCE hinstDLL=NULL; if( bFirstCall ) { bFirstCall=FALSE; hinstDLL = LoadLibrary( "winscard.dll" ); if( NULL!=hinstDLL ) { lRetCode=SCARD_S_SUCCESS; GETPROCADDRESS( SCARDADDREADERTOGROUPA , SCardAddReaderToGroupA ); GETPROCADDRESS( SCARDACCESSSTARTEDEVENT , SCardAccessStartedEvent ); GETPROCADDRESS( SCARDBEGINTRANSACTION , SCardBeginTransaction ); GETPROCADDRESS( SCARDCANCEL , SCardCancel ); GETPROCADDRESS( SCARDCONNECTA , SCardConnectA ); GETPROCADDRESS( SCARDCONTROL , SCardControl ); GETPROCADDRESS( SCARDDISCONNECT , SCardDisconnect ); GETPROCADDRESS( SCARDENDTRANSACTION , SCardEndTransaction ); GETPROCADDRESS( SCARDESTABLISHCONTEXT , SCardEstablishContext ); GETPROCADDRESS( SCARDFORGETCARDTYPEA , SCardForgetCardTypeA ); GETPROCADDRESS( SCARDFORGETREADERA , SCardForgetReaderA ); GETPROCADDRESS( SCARDFORGETREADERGROUPA , SCardForgetReaderGroupA ); GETPROCADDRESS( SCARDFREEMEMORY , SCardFreeMemory ); GETPROCADDRESS( SCARDGETCARDTYPEPROVIDERNAMEA , SCardGetCardTypeProviderNameA ); GETPROCADDRESS( SCARDGETATTRIB , SCardGetAttrib ); GETPROCADDRESS( SCARDGETPROVIDERIDA , SCardGetProviderIdA ); GETPROCADDRESS( SCARDGETSTATUSCHANGEA , SCardGetStatusChangeA ); GETPROCADDRESS( SCARDINTRODUCECARDTYPEA , SCardIntroduceCardTypeA ); GETPROCADDRESS( SCARDINTRODUCEREADERA , SCardIntroduceReaderA ); GETPROCADDRESS( SCARDINTRODUCEREADERGROUPA , SCardIntroduceReaderGroupA ); GETPROCADDRESS( SCARDISVALIDCONTEXT , SCardIsValidContext ); GETPROCADDRESS( SCARDLISTCARDSA , SCardListCardsA ); GETPROCADDRESS( SCARDLISTINTERFACESA , SCardListInterfacesA ); GETPROCADDRESS( SCARDLISTREADERSA , SCardListReadersA ); GETPROCADDRESS( SCARDLISTREADERGROUPSA , SCardListReaderGroupsA ); GETPROCADDRESS( SCARDLOCATECARDSA , SCardLocateCardsA ); GETPROCADDRESS( SCARDLOCATECARDSBYATRA , SCardLocateCardsByATRA ); GETPROCADDRESS( SCARDRECONNECT , SCardReconnect ); GETPROCADDRESS( SCARDRELEASECONTEXT , SCardReleaseContext ); GETPROCADDRESS( SCARDRELEASESTARTEDEVENT , SCardReleaseStartedEvent ); GETPROCADDRESS( SCARDREMOVEREADERFROMGROUPA , SCardRemoveReaderFromGroupA ); GETPROCADDRESS( SCARDSETATTRIB , SCardSetAttrib ); GETPROCADDRESS( SCARDSETCARDTYPEPROVIDERNAMEA , SCardSetCardTypeProviderNameA ); GETPROCADDRESS( SCARDSTATE , SCardState ); GETPROCADDRESS( SCARDSTATUSA , SCardStatusA ); GETPROCADDRESS( SCARDTRANSMIT , SCardTransmit ); myg_prgSCardT0Pci = GetProcAddress( hinstDLL, "g_rgSCardT0Pci" ); myg_prgSCardT1Pci = GetProcAddress( hinstDLL, "g_rgSCardT1Pci" ); myg_prgSCardRawPci = GetProcAddress( hinstDLL, "g_rgSCardRawPci" ); } } #endif // WIN32 #ifdef PCSCLITE #define GETPROCADDRESS( type, name, realname ) my##name=(type)dlsym( handle, #realname ); \ dlsym_error = dlerror(); \ if (NULL!=dlsym_error) \ { \ printf( "Failed to load symbol for: %s, %s!\n", #realname, (char*)dlsym_error ); \ } // some functions are not available on older releases of pcsc-lite, such // as SCardIsValidContext; don't complain if they are not located #define SILENTGETPROCADDRESS( type, name, realname ) my##name=(type)dlsym( handle, #realname ); \ dlsym_error = dlerror(); void* handle=NULL; char* dlsym_error; const char *lib = NULL; #ifdef __APPLE__ lib = "/System/Library/Frameworks/PCSC.framework/PCSC"; #else lib = "libpcsclite.so.1"; #endif if( bFirstCall ) { dlerror(); handle = dlopen( lib, RTLD_NOW ); if( NULL!=handle ) { lRetCode=SCARD_S_SUCCESS; GETPROCADDRESS( SCARDBEGINTRANSACTION , SCardBeginTransaction , SCardBeginTransaction ); GETPROCADDRESS( SCARDCANCEL , SCardCancel , SCardCancel ); GETPROCADDRESS( SCARDCONNECTA , SCardConnectA , SCardConnect ); GETPROCADDRESS( SCARDDISCONNECT , SCardDisconnect , SCardDisconnect ); GETPROCADDRESS( SCARDENDTRANSACTION , SCardEndTransaction , SCardEndTransaction ); GETPROCADDRESS( SCARDESTABLISHCONTEXT , SCardEstablishContext , SCardEstablishContext ); GETPROCADDRESS( SCARDGETSTATUSCHANGEA , SCardGetStatusChangeA , SCardGetStatusChange ); GETPROCADDRESS( SCARDLISTREADERSA , SCardListReadersA , SCardListReaders ); GETPROCADDRESS( SCARDLISTREADERGROUPSA , SCardListReaderGroupsA , SCardListReaderGroups ); GETPROCADDRESS( SCARDRECONNECT , SCardReconnect , SCardReconnect ); GETPROCADDRESS( SCARDRELEASECONTEXT , SCardReleaseContext , SCardReleaseContext ); GETPROCADDRESS( SCARDSTATUSA , SCardStatusA , SCardStatus ); GETPROCADDRESS( SCARDTRANSMIT , SCardTransmit , SCardTransmit ); SILENTGETPROCADDRESS( PCSCSTRINGIFYERROR , PcscStringifyError , pcsc_stringify_error ); #ifndef __APPLE__ GETPROCADDRESS( SCARDCONTROL, SCardControl, SCardControl ); #else // !__APPLE__ GETPROCADDRESS( SCARDCONTROL, SCardControl, SCardControl132 ); #endif // __APPLE__ SILENTGETPROCADDRESS( SCARDISVALIDCONTEXT , SCardIsValidContext , SCardIsValidContext ); GETPROCADDRESS( SCARDGETATTRIB , SCardGetAttrib , SCardGetAttrib ); GETPROCADDRESS( SCARDSETATTRIB , SCardSetAttrib , SCardSetAttrib ); myg_prgSCardT0Pci = dlsym( handle, "g_rgSCardT0Pci" ); myg_prgSCardT1Pci = dlsym( handle, "g_rgSCardT1Pci" ); myg_prgSCardRawPci = dlsym( handle, "g_rgSCardRawPci" ); dlsym_error = dlerror(); if( NULL!= dlsym_error ) { printf( "Failed to load symbol address from %s: %s!", lib, (char*)dlsym_error ); } } else { dlsym_error = dlerror(); if( NULL!= dlsym_error ) { printf( "Failed to dlopen %s: %s!", lib, (dlsym_error==NULL) ? "" : (char*)dlsym_error ); } } bFirstCall=FALSE; } #endif // PCSCLITE return lRetCode; }; ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/scard/winscarddll.h0000644000076500000240000002631514674316735021323 0ustar00rousseaustaff/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================*/ #ifndef __WINSCARDDLL_H__ #define __WINSCARDDLL_H__ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #include #define LPCTSTR char* #else // !__APPLE__ #include #endif #ifdef PCSCLITE #define WINSCARDAPI #define WINAPI #define IN #define OUT #define LPSCARD_READERSTATEA SCARD_READERSTATE * #define SCARD_AUTOALLOCATE (DWORD)(-1) #ifndef FALSE #define FALSE (0==1) #endif // FALSE #ifndef TRUE #define TRUE (1==1) #endif #endif // PCSCLITE // // these functions are only available on win32 PCSC // #ifdef WIN32 typedef WINSCARDAPI HANDLE (WINAPI *SCARDACCESSSTARTEDEVENT)(void); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDADDREADERTOGROUPA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReaderName, IN LPCTSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETCARDTYPEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETREADERA)( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETREADERGROUPA)( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETCARDTYPEPROVIDERNAMEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, OUT LPTSTR szProvider, IN OUT SCARDDWORDARG* pcchProvider); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETPROVIDERIDA)( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidProviderId); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCECARDTYPEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN LPCGUID pguidPrimaryProvider, IN LPCGUID rgguidInterfaces, IN SCARDDWORDARG dwInterfaceCount, IN LPCBYTE pbAtr, IN LPCBYTE pbAtrMask, IN SCARDDWORDARG cbAtrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCEREADERA)( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szDeviceName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCEREADERGROUPA)( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTCARDSA)( IN SCARDCONTEXT hContext, IN LPCBYTE pbAtr, IN LPCGUID rgquidInterfaces, IN SCARDDWORDARG cguidInterfaceCount, OUT LPTSTR mszCards, IN OUT SCARDDWORDARG* pcchCards); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTINTERFACESA)( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidInterfaces, IN OUT SCARDDWORDARG* pcguidInterfaces); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLOCATECARDSA)( IN SCARDCONTEXT hContext, IN LPCSTR mszCards, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLOCATECARDSBYATRA)( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN SCARDDWORDARG cAtrs, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSETCARDTYPEPROVIDERNAMEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, IN LPCSTR szProvider); typedef WINSCARDAPI void (WINAPI *SCARDRELEASESTARTEDEVENT)(void); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDREMOVEREADERFROMGROUPA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReaderName, IN LPCTSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSTATE)( IN SCARDHANDLE hCard, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen); extern SCARDACCESSSTARTEDEVENT mySCardAccessStartedEvent; extern SCARDADDREADERTOGROUPA mySCardAddReaderToGroupA; extern SCARDFORGETCARDTYPEA mySCardForgetCardTypeA; extern SCARDFORGETREADERA mySCardForgetReaderA; extern SCARDFORGETREADERGROUPA mySCardForgetReaderGroupA; extern SCARDGETCARDTYPEPROVIDERNAMEA mySCardGetCardTypeProviderNameA; extern SCARDGETPROVIDERIDA mySCardGetProviderIdA; extern SCARDINTRODUCECARDTYPEA mySCardIntroduceCardTypeA; extern SCARDINTRODUCEREADERA mySCardIntroduceReaderA; extern SCARDINTRODUCEREADERGROUPA mySCardIntroduceReaderGroupA; extern SCARDLISTCARDSA mySCardListCardsA; extern SCARDLISTINTERFACESA mySCardListInterfacesA; extern SCARDLOCATECARDSA mySCardLocateCardsA; extern SCARDLOCATECARDSBYATRA mySCardLocateCardsByATRA; extern SCARDRELEASESTARTEDEVENT mySCardReleaseStartedEvent; extern SCARDREMOVEREADERFROMGROUPA mySCardRemoveReaderFromGroupA; extern SCARDSETCARDTYPEPROVIDERNAMEA mySCardSetCardTypeProviderNameA; extern SCARDSTATE mySCardState; #endif // WIN32 typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDISVALIDCONTEXT)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETATTRIB)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, OUT LPBYTE pbAttr, IN OUT SCARDDWORDARG* pcbAttrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSETATTRIB)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, IN LPCBYTE pbAttr, IN SCARDDWORDARG cbAttrLen); extern SCARDISVALIDCONTEXT mySCardIsValidContext; extern SCARDGETATTRIB mySCardGetAttrib; extern SCARDSETATTRIB mySCardSetAttrib; typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCONTROL)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwControlCode, IN LPCVOID lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT LPVOID lpOutBuffer, IN SCARDDWORDARG nOutBufferSize, OUT SCARDDWORDARG* lpBytesReturned); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDBEGINTRANSACTION)( IN SCARDHANDLE hCard); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCANCEL)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCANCELTRANSACTION)( IN SCARDHANDLE hCard); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCONNECTA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReader, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT SCARDDWORDARG* pdwActiveProtocol); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDDISCONNECT)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDENDTRANSACTION)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDESTABLISHCONTEXT)( IN SCARDDWORDARG dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFREEMEMORY)( IN SCARDCONTEXT hContext, IN LPCVOID pvMem); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETSTATUSCHANGEA)( IN SCARDCONTEXT hContext, IN SCARDDWORDARG dwTimeout, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTREADERSA)( IN SCARDCONTEXT hContext, IN LPCTSTR mszGroups, OUT LPTSTR mszReaders, IN OUT SCARDDWORDARG* pcchReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTREADERGROUPSA)( IN SCARDCONTEXT hContext, OUT LPTSTR mszGroups, IN OUT SCARDDWORDARG* pcchGroups); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDRECONNECT)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, IN SCARDDWORDARG dwInitialization, OUT SCARDDWORDARG* pdwActiveProtocol); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDRELEASECONTEXT)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSTATUSA)( IN SCARDHANDLE hCard, OUT LPTSTR szReaderName, IN OUT SCARDDWORDARG* pcchReaderLen, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDTRANSMIT)( IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN SCARDDWORDARG cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT SCARDDWORDARG* pcbRecvLength); #ifdef PCSCLITE typedef WINSCARDAPI char* (WINAPI *PCSCSTRINGIFYERROR)( IN SCARDRETCODE pcscError); extern PCSCSTRINGIFYERROR myPcscStringifyError; #endif // PCSCLITE extern SCARDBEGINTRANSACTION mySCardBeginTransaction; extern SCARDCANCEL mySCardCancel; extern SCARDCONNECTA mySCardConnectA; extern SCARDCONTROL mySCardControl; extern SCARDDISCONNECT mySCardDisconnect; extern SCARDENDTRANSACTION mySCardEndTransaction; extern SCARDESTABLISHCONTEXT mySCardEstablishContext; extern SCARDFREEMEMORY mySCardFreeMemory; extern SCARDGETSTATUSCHANGEA mySCardGetStatusChangeA; extern SCARDLISTREADERSA mySCardListReadersA; extern SCARDLISTREADERGROUPSA mySCardListReaderGroupsA; extern SCARDRECONNECT mySCardReconnect; extern SCARDRELEASECONTEXT mySCardReleaseContext; extern SCARDSTATUSA mySCardStatusA; extern SCARDTRANSMIT mySCardTransmit; extern void * myg_prgSCardT0Pci; extern void * myg_prgSCardT1Pci; extern void * myg_prgSCardRawPci; long winscard_init(void); #endif // __WINSCARDDLL_H__ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6590483 pyscard-2.2.1/src/smartcard/sw/0000755000076500000240000000000014740753203016157 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ErrorChecker.py0000644000076500000240000000336114677317744021131 0ustar00rousseaustaff"""Base class for status word error checkers. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class ErrorChecker: """Base class for status word error checking strategies. Error checking strategies are chained into an L{ErrorCheckingChain} to implement a Chain of Responsibility. Each strategy in the chain is called until an error is detected. The strategy raises a L{smartcard.sw.SWExceptions} exception when an error is detected. Implementation derived from Bruce Eckel, Thinking in Python. The L{ErrorCheckingChain} implements the Chain Of Responsibility design pattern. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. Derived classes must raise a L{smartcard.sw.SWExceptions} upon error. @param data: apdu response data @param sw1: apdu data status word 1 @param sw2: apdu data status word 2 """ pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ErrorCheckingChain.py0000644000076500000240000000667314677317744022254 0ustar00rousseaustaff"""The error checking chain is a list of status word (sw1, sw2) error check strategies. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from sys import exc_info class ErrorCheckingChain: """The error checking chain is a list of response apdu status word (sw1, sw2) error check strategies. Each strategy in the chain is called until an error is detected. A L{smartcard.sw.SWExceptions} exception is raised when an error is detected. No exception is raised if no error is detected. Implementation derived from Bruce Eckel, Thinking in Python. The L{ErrorCheckingChain} implements the Chain Of Responsibility design pattern. """ def __init__(self, chain, strategy): """constructor. Appends a strategy to the L{ErrorCheckingChain} chain.""" self.strategy = strategy self.chain = chain self.chain.append(self) self.excludes = [] def next(self): """Returns next error checking strategy.""" # Where this link is in the chain: location = self.chain.index(self) if not self.end(): return self.chain[location + 1] def addFilterException(self, exClass): """Add an exception filter to the error checking chain. @param exClass: the exception to exclude, e.g. L{smartcard.sw.SWExceptions.WarningProcessingException} A filtered exception will not be raised when the sw1,sw2 conditions that would raise the exception are met. """ self.excludes.append(exClass) if self.end(): return self.next().addFilterException(exClass) def end(self): """Returns True if this is the end of the error checking strategy chain.""" return self.chain.index(self) + 1 >= len(self.chain) def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error on the chain.""" try: self.strategy(data, sw1, sw2) except tuple(self.excludes) as exc: # The following additional filter may look redundant, it isn't. # It checks that type(exc) is *equal* to any of self.excludes, # rather than equal-or-subclass to any of self.excludes. # This maintains backward compatibility with the behaviour of # pyscard <= 1.6.16. # if exception is filtered, return for exception in self.excludes: if exception == exc_info()[0]: return # otherwise reraise exception raise # if not done, call next strategy if self.end(): return return self.next()(data, sw1, sw2) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ISO7816_4ErrorChecker.py0000644000076500000240000001534114677317744022256 0ustar00rousseaustaff"""ISO7816-4 error checking strategy. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker iso7816_4SW = { 0x62: ( smartcard.sw.SWExceptions.WarningProcessingException, { 0x00: "Response padded/ More APDU commands expected", 0x81: "Part of returned data may be corrupted", 0x82: "End of file/record reached before reading Le bytes", 0x83: "File invalidated", 0x84: "FCI not correctly formatted", 0xFF: "Correct execution, response padded", }, ), 0x63: ( smartcard.sw.SWExceptions.WarningProcessingException, { 0x00: "Authentication failed", 0x81: "File filled up by the last write", 0xC0: "PIN verification failed. 0 tries before blocking PIN", 0xC1: "PIN verification failed. 1 tries before blocking PIN", 0xC2: "PIN verification failed. 2 tries before blocking PIN", 0xC3: "PIN verification failed. 3 tries before blocking PIN", 0xC4: "PIN verification failed. 4 tries before blocking PIN", 0xC5: "PIN verification failed. 5 tries before blocking PIN", 0xC6: "PIN verification failed. 6 tries before blocking PIN", 0xC7: "PIN verification failed. 7 tries before blocking PIN", 0xC8: "PIN verification failed. 8 tries before blocking PIN", 0xC9: "PIN verification failed. 9 tries before blocking PIN", 0xCA: "PIN verification failed. 10 tries before blocking PIN", 0xCB: "PIN verification failed. 11 tries before blocking PIN", 0xCC: "PIN verification failed. 12 tries before blocking PIN", 0xCD: "PIN verification failed. 13 tries before blocking PIN", 0xCE: "PIN verification failed. 14 tries before blocking PIN", 0xCF: "PIN verification failed. 15 tries before blocking PIN", }, ), 0x64: ( smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Integrity error detected in EEPROM"}, ), 0x67: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length in Lc"}, ), 0x68: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x81: "Logical channel not supported", 0x82: "Secure messaging not supported"}, ), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x81: "Command incompatible with file structure.", 0x82: "Security status not satisfied", 0x83: "Authentication method blocked", 0x84: "Referenced data invalid", 0x85: "Conditions of use not satisfied", 0x86: "Command not allowed (no current EF)", 0x87: "Secure messaging data object missing.", 0x88: "Secure messaging data object incorrect", }, ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x80: "Incorrect parameters in the data field", 0x81: "Function not supported", 0x82: "File not found", 0x83: "Record not found", 0x84: "Not enough memory space in the file", 0x85: "Lc inconsistent with TLV structure", 0x86: "Incorrect parameters P1-P2", 0x87: "Lc is inconsistent with P1-P2", 0x88: "Referenced data not found", }, ), 0x6B: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Incorrect parameters P1-P2"}, ), 0x6D: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Instruction (INS) not supported"}, ), 0x6E: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Class (CLA) not supported"}, ), 0x6F: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Fatal error"}), } class ISO7816_4ErrorChecker(ErrorChecker): """ISO7816-4 error checking strategy. This strategy raises the following exceptions: - sw1 sw2 - 62 00 81 82 83 84 FF WarningProcessingException - 63 00 81 C0->CF WarningProcessingException - 64 00 ExecutionErrorException - 67 00 CheckingErrorException - 68 81 82 CheckingErrorException - 69 81->88 99? c1? CheckingErrorException - 6a 80->88 CheckingErrorException - 6b 00 CheckingErrorException - 6d 00 CheckingErrorException - 6e 00 CheckingErrorException - 6f 00 CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 65 any - 66 any - 6c any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 80 85 - 6b any except 00 Use another checker in the error checking chain, e.g., the ISO7816_4SW1ErrorChecker, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. Derived classes must raise a L{smartcard.sw.SWExceptions} upon error. @param data: apdu response data @param sw1: apdu data status words @param sw2: apdu data status words """ if sw1 in iso7816_4SW: exception, sw2dir = iso7816_4SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == "__main__": """Small sample illustrating the use of ISO7816_4ErrorChecker.""" ecs = ISO7816_4ErrorChecker() ecs([], 0x90, 0x00) try: ecs([], 0x6B, 0x00) except smartcard.sw.SWExceptions.CheckingErrorException as e: print(str(e) + f" {e.sw1:x} {e.sw2:x}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ISO7816_4_SW1ErrorChecker.py0000644000076500000240000000644414677317744022754 0ustar00rousseaustaff"""ISO7816-4 sw1 only error checker. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker iso7816_4SW1 = { 0x62: smartcard.sw.SWExceptions.WarningProcessingException, 0x63: smartcard.sw.SWExceptions.WarningProcessingException, 0x64: smartcard.sw.SWExceptions.ExecutionErrorException, 0x65: smartcard.sw.SWExceptions.ExecutionErrorException, 0x66: smartcard.sw.SWExceptions.SecurityRelatedException, 0x67: smartcard.sw.SWExceptions.CheckingErrorException, 0x68: smartcard.sw.SWExceptions.CheckingErrorException, 0x69: smartcard.sw.SWExceptions.CheckingErrorException, 0x6A: smartcard.sw.SWExceptions.CheckingErrorException, 0x6B: smartcard.sw.SWExceptions.CheckingErrorException, 0x6C: smartcard.sw.SWExceptions.CheckingErrorException, 0x6D: smartcard.sw.SWExceptions.CheckingErrorException, 0x6E: smartcard.sw.SWExceptions.CheckingErrorException, 0x6F: smartcard.sw.SWExceptions.CheckingErrorException, } class ISO7816_4_SW1ErrorChecker(ErrorChecker): """ISO7816-4 error checker based on status word sw1 only. This error checker raises the following exceptions: - sw1 sw2 - 62 any L{WarningProcessingException} - 63 any L{WarningProcessingException} - 64 any L{ExecutionErrorException} - 65 any L{ExecutionErrorException} - 66 any L{SecurityRelatedException} - 67 any L{CheckingErrorException} - 68 any L{CheckingErrorException} - 69 any L{CheckingErrorException} - 6a any L{CheckingErrorException} - 6b any L{CheckingErrorException} - 6c any L{CheckingErrorException} - 6d any L{CheckingErrorException} - 6e any L{CheckingErrorException} - 6f any L{CheckingErrorException} """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1: apdu data status word 1 @param sw2: apdu data status word 2 """ if sw1 in iso7816_4SW1: exception = iso7816_4SW1[sw1] raise exception(data, sw1, sw2) if __name__ == "__main__": """Small sample illustrating the use of ISO7816_4_SW1ErrorChecker.""" ecs = ISO7816_4_SW1ErrorChecker() ecs([], 0x90, 0x00) try: ecs([], 0x66, 0x80) except smartcard.sw.SWExceptions.SecurityRelatedException as e: print(str(e) + f" {e.sw1:x} {e.sw2:x}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ISO7816_8ErrorChecker.py0000644000076500000240000001260114677317744022256 0ustar00rousseaustaff"""ISO7816-8 error checker. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker iso7816_8SW = { 0x63: ( smartcard.sw.SWExceptions.WarningProcessingException, { 0x00: "Authentication failed", 0xC0: "PIN verification failed. 0 retries before blocking PIN", 0xC1: "PIN verification failed. 1 retries before blocking PIN", 0xC2: "PIN verification failed. 2 retries before blocking PIN", 0xC3: "PIN verification failed. 3 retries before blocking PIN", 0xC4: "PIN verification failed. 4 retries before blocking PIN", 0xC5: "PIN verification failed. 5 retries before blocking PIN", 0xC6: "PIN verification failed. 6 retries before blocking PIN", 0xC7: "PIN verification failed. 7 retries before blocking PIN", 0xC8: "PIN verification failed. 8 retries before blocking PIN", 0xC9: "PIN verification failed. 9 retries before blocking PIN", 0xCA: "PIN verification failed. 10 retries before blocking PIN", 0xCB: "PIN verification failed. 11 retries before blocking PIN", 0xCC: "PIN verification failed. 12 retries before blocking PIN", 0xCD: "PIN verification failed. 13 retries before blocking PIN", 0xCE: "PIN verification failed. 14 retries before blocking PIN", 0xCF: "PIN verification failed. 15 retries before blocking PIN", }, ), 0x65: ( smartcard.sw.SWExceptions.ExecutionErrorException, {0x81: "Memory failure (unsuccessful changing)"}, ), 0x66: ( smartcard.sw.SWExceptions.SecurityRelatedException, { 0x00: "The environment cannot be set or modified", 0x87: "Expected SM data objects missing", 0x88: "SM data objects incorrect", }, ), 0x67: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length (empty Lc field)"}, ), 0x68: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x83: "Final command expected", 0x84: "Command chaining not supported"}, ), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x82: "Security status not satisfied", 0x83: "Authentication method blocked", 0x84: "Referenced data invalidated", 0x85: "Conditions of use not satisfied", }, ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x81: "Function not supported", 0x82: "File not found", 0x86: "Incorrect parameters P1-P2", 0x88: "Referenced data not found", }, ), } class ISO7816_8ErrorChecker(ErrorChecker): """ISO7816-8 error checker. This error checker raises the following exceptions: - sw1 sw2 - 63 00,c0-cf L{WarningProcessingException} - 65 81 L{ExecutionErrorException} - 66 00,87,88 L{SecurityRelatedException} - 67 00 L{CheckingErrorException} - 68 82,84 L{CheckingErrorException} - 69 82,83,84,85 L{CheckingErrorException} - 6A 81,82,86,88 L{CheckingErrorException} This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 62 any - 6f any and on undefined sw2 values, e.g.: - sw1 sw2 - 66 81 82 - 67 any except 00 Use another checker in the error checking chain, e.g., the L{ISO7816_4_SW1ErrorChecker} or L{ISO7816_4ErrorChecker}, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. Derived classes must raise a L{smartcard.sw.SWExceptions} upon error. @param data: apdu response data @param sw1: apdu data status word 1 @param sw2: apdu data status word 2 """ if sw1 in iso7816_8SW: exception, sw2dir = iso7816_8SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == "__main__": """Small sample illustrating the use of ISO7816_8ErrorChecker.""" ecs = ISO7816_8ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x6A, 0x83) try: ecs([], 0x66, 0x87) except smartcard.sw.SWExceptions.SecurityRelatedException as e: print(str(e) + f" {e.sw1:x} {e.sw2:x}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/ISO7816_9ErrorChecker.py0000644000076500000240000000644214677317744022265 0ustar00rousseaustaff"""ISO7816-9 error checker. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker iso7816_9SW = { 0x62: ( smartcard.sw.SWExceptions.WarningProcessingException, {0x82: "End of file/record reached"}, ), 0x64: ( smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Execution error"}, ), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x82: "Security status not satisfied"}, ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x80: "Incorrect parameters in data field", 0x84: "Not enough memory space", 0x89: "File already exists", 0x8A: "DF name already exists", }, ), } class ISO7816_9ErrorChecker(ErrorChecker): """ISO7816-8 error checker. This error checker raises the following exceptions: - sw1 sw2 - 62 82 WarningProcessingException - 64 00 ExecutionErrorException - 69 82 CheckingErrorException - 6A 80,84,89,8A CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 63 any - 6F any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 81 83 - 64 any except 00 Use another checker in the error checking chain, e.g., the L{ISO7816_4_SW1ErrorChecker} or L{ISO7816_4ErrorChecker}, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. Derived classes must raise a L{smartcard.sw.SWExceptions} upon error. @param data: apdu response data @param sw1: apdu data status word 1 @param sw2: apdu data status word 2 """ if sw1 in iso7816_9SW: exception, sw2dir = iso7816_9SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == "__main__": """Small sample illustrating the use of ISO7816_9ErrorChecker.""" ecs = ISO7816_9ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x6A, 0x81) try: ecs([], 0x6A, 0x8A) except smartcard.sw.SWExceptions.CheckingErrorException as e: print(str(e) + f" {e.sw1:x} {e.sw2:x}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/SWExceptions.py0000644000076500000240000000533114677317744021145 0ustar00rousseaustaff"""Status Word (SW) Exceptions This module defines the exceptions raised by status word errors or warnings. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class SWException(Exception): """Base class for status word exceptions. Status word exceptions are generated when errors and warnings are detected in the sw1 and sw2 bytes of the response apdu. """ def __init__(self, data, sw1, sw2, message=""): self.message = message """response apdu data""" self.data = data """response apdu sw1""" self.sw1 = sw1 """response apdu sw2""" self.sw2 = sw2 def __str__(self): return repr("Status word exception: " + self.message + "!") class WarningProcessingException(SWException): """Raised when a warning processing is detected from sw1, sw2. Examples of warning processing exception: sw1=62 or sw=63 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__(self, data, sw1, sw2, "warning processing - " + message) class ExecutionErrorException(SWException): """Raised when an execution error is detected from sw1, sw2. Examples of execution error: sw1=64 or sw=65 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__(self, data, sw1, sw2, "execution error - " + message) class SecurityRelatedException(SWException): """Raised when a security issue is detected from sw1, sw2. Examples of security issue: sw1=66 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__(self, data, sw1, sw2, "security issue - " + message) class CheckingErrorException(SWException): """Raised when a checking error is detected from sw1, sw2. Examples of checking error: sw1=67 to 6F (ISO781604).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__(self, data, sw1, sw2, "checking error - " + message) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727878166.0 pyscard-2.2.1/src/smartcard/sw/__init__.py0000644000076500000240000000163014677252026020276 0ustar00rousseaustaff"""smartcard.sw module for status word error checking. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/sw/op21_ErrorChecker.py0000644000076500000240000001073114677317744021771 0ustar00rousseaustaff"""Open Platform 2.1 error checker. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker op21_SW = { 0x62: ( smartcard.sw.SWExceptions.WarningProcessingException, {0x83: "Card life cycle is CARD_LOCKED"}, ), 0x63: ( smartcard.sw.SWExceptions.WarningProcessingException, {0x00: "Authentication failed"}, ), 0x64: ( smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Execution error"}, ), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x81: "Memory failure"}), 0x67: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length in Lc"}, ), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x82: "Security status not satisfied", 0x85: "Conditions of use not satisfied", }, ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, { 0x80: "Incorrect values in command data", 0x81: "Function not supported", 0x82: "Application not found", 0x84: "Not enough memory space", 0x86: "Incorrect parameters P1-P2", 0x88: "Referenced data not found", }, ), 0x6D: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Instruction not supported"}, ), 0x6E: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Class not supported"}, ), 0x94: ( smartcard.sw.SWExceptions.CheckingErrorException, {0x84: "Algorithm not supported", 0x85: "Invalid key check value"}, ), } class op21_ErrorChecker(ErrorChecker): """Open platform 2.1 error checker. This error checker raises the following exceptions: - sw1 sw2 - 62 83 L{WarningProcessingException} - 63 00 L{WarningProcessingException} - 64 00 L{ExecutionErrorException} - 65 81 L{ExecutionErrorException} - 67 00 L{CheckingErrorException} - 69 82 85 L{CheckingErrorException} - 6A 80 81 82 84 86 88 L{CheckingErrorException} - 6D 00 L{CheckingErrorException} - 6E 00 L{CheckingErrorException} - 94 84 85 L{CheckingErrorException} This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 63 any - 6F any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 81 83 - 64 any except 00 Use another checker in the error checking chain to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. Derived classes must raise a L{smartcard.sw.SWExceptions} upon error. @param data: apdu response data @param sw1: apdu data status word 1 @param sw2: apdu data status word 2 """ if sw1 in op21_SW: exception, sw2dir = op21_SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == "__main__": """Small sample illustrating the use of op21_ErrorChecker.""" ecs = op21_ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x94, 0x81) try: ecs([], 0x94, 0x84) except smartcard.sw.SWExceptions.CheckingErrorException as e: print(str(e) + f"{e.sw1:x} {e.sw2:x}") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6598186 pyscard-2.2.1/src/smartcard/test/0000755000076500000240000000000014740753203016505 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938532.0 pyscard-2.2.1/src/smartcard/test/configcheck.py0000755000076500000240000000645014703301044021321 0ustar00rousseaustaff#! /usr/bin/env python3 """Generates test suite smartcard configuration from connected readers and cards. The generated configuration is store in local_config.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os.path import time from smartcard.ATR import ATR from smartcard.Exceptions import NoCardException from smartcard.System import readers def getATR(reader): """ Get card ATR """ cc = reader.createConnection() cc.connect() atr = cc.getATR() cc.disconnect() return atr def checklocalconfig(): """ Generate or regenerate local_config.py """ if os.path.isfile("local_config.py"): print("regenerating local_config.py...") else: print("local_config.py not found; generating local_config.py...") wrong_setup = False # generate local configuration with open("local_config.py", "w", encoding="utf-8") as f: f.write("from smartcard.util import toHexString\n") f.write("expectedReaders = ") expectedReaders = readers() if len(expectedReaders) < 2: print("You should use at least 2 readers.") wrong_setup = True f.write(str(expectedReaders) + "\n") expectedATRs = [] atr_ok = 0 for reader in expectedReaders: try: atr = getATR(reader) expectedATRs.append(atr) if ATR(atr).isT1Supported(): print("You should use T=0 cards") wrong_setup = True atr_ok += 1 except NoCardException: expectedATRs.append([]) if atr_ok < 2: print("You should use at least 2 cards.") wrong_setup = True f.write("expectedATRs = ") f.write(repr(expectedATRs) + "\n") f.write("expectedATRinReader = {}\n") f.write("for i in range(len(expectedReaders)):\n") f.write(" expectedATRinReader[expectedReaders[i]] = expectedATRs[i]\n") f.write("expectedReaderForATR = {}\n") f.write("for i in range(len(expectedReaders)):\n") f.write( " expectedReaderForATR[toHexString(expectedATRs[i])] = " + "expectedReaders[i]\n" ) f.write("expectedReaderGroups = ['SCard$DefaultReaders']\n") if wrong_setup: print("The readers or cards setup is invalid. Some tests WILL fail!") print("Pause for 5 seconds") time.sleep(5) if __name__ == "__main__": import sys checklocalconfig() sys.exit() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1736693378.671978 pyscard-2.2.1/src/smartcard/test/framework/0000755000076500000240000000000014740753203020502 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/framework/readme.txt0000644000076500000240000000312014677317744022513 0ustar00rousseaustaff------------------------------------------------------------------------------- This directory contains the test suite for the pyscard framework. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ------------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_ATR.py0000755000076500000240000000340614703761333023405 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for testing that we have at least two cards for the test suite. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest sys.path += [".."] try: from local_config import expectedATRs except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_ATR(unittest.TestCase): """Test ATR configuration for test suite""" def testcase_ATRconfig(self): """ATRconfig""" # we have at list 2 readers (one is the simulator), e.g. # two potential ATRs self.assertTrue(len(expectedATRs) > 1) # we have at least two non empty ATRs count = 0 for atr in expectedATRs: if atr: count += 1 self.assertTrue(count > 1) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CAtr.py0000755000076500000240000001257714703034261023612 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.ATR This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest # gemalto jython from smartcard.ATR import ATR class testcase_CAtr(unittest.TestCase): """Test APDU class and utilities""" def testcase_ATR1(self): """Usimera Classic 2.""" a = ATR( [ 0x3B, 0x9E, 0x95, 0x80, 0x1F, 0xC3, 0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD, 0xB9, ] ) historicalbytes = [ 0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD, ] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), 0xB9) self.assertTrue(a.checksumOK) self.assertTrue(a.isT0Supported()) self.assertTrue(not a.isT1Supported()) self.assertTrue(a.isT15Supported()) def testcase_ATR2(self): """Palmera Protect V2.""" a = ATR([0x3B, 0x65, 0x00, 0x00, 0x9C, 0x02, 0x02, 0x01, 0x02]) historicalbytes = [0x9C, 0x02, 0x02, 0x01, 0x02] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), None) self.assertTrue(a.isT0Supported()) self.assertTrue(not a.isT1Supported()) self.assertTrue(not a.isT15Supported()) def testcase_ATR3(self): """Simera 3.13.""" a = ATR([0x3B, 0x16, 0x18, 0x20, 0x02, 0x01, 0x00, 0x80, 0x0D]) historicalbytes = [0x20, 0x02, 0x01, 0x00, 0x80, 0x0D] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), None) self.assertTrue(a.isT0Supported()) self.assertTrue(not a.isT1Supported()) self.assertTrue(not a.isT15Supported()) def testcase_ATR4(self): """SIMRock'n Tree""" a = ATR( [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] ) historicalbytes = [0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), None) self.assertTrue(a.isT0Supported()) self.assertTrue(not a.isT1Supported()) self.assertTrue(not a.isT15Supported()) def testcase_ATR5(self): """Demo Vitale online IGEA340""" a = ATR([0x3F, 0x65, 0x25, 0x00, 0x52, 0x09, 0x6A, 0x90, 0x00]) historicalbytes = [0x52, 0x09, 0x6A, 0x90, 0x00] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), None) self.assertTrue(a.isT0Supported()) self.assertTrue(not a.isT1Supported()) self.assertTrue(not a.isT15Supported()) def testcase_ATR6(self): """Simagine 2002""" a = ATR([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) historicalbytes = [0x20, 0x02, 0x01, 0x00, 0x00, 0x0D] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), None) def testcase_ATR7(self): """Protect V3 T=1""" a = ATR( [ 0x3B, 0xE5, 0x00, 0x00, 0x81, 0x21, 0x45, 0x9C, 0x10, 0x01, 0x00, 0x80, 0x0D, ] ) historicalbytes = [0x9C, 0x10, 0x01, 0x00, 0x80] self.assertEqual(a.getHistoricalBytes(), historicalbytes) self.assertEqual(a.getChecksum(), 0x0D) self.assertTrue(not a.isT0Supported()) self.assertTrue(a.isT1Supported()) self.assertTrue(not a.isT15Supported()) self.assertTrue(a.checksumOK) self.assertTrue(a.getTB1() == 0x00) self.assertTrue(a.getTC1() == 0x00) self.assertTrue(a.getTD1() == 0x81) self.assertTrue(a.TD[2 - 1] == 0x21) # TD2 self.assertTrue(a.TB[3 - 1] == 0x45) # TB3 if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_Card.py0000755000076500000240000000767514703761333023644 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.Card This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest from smartcard.Card import Card from smartcard.Exceptions import NoCardException from smartcard.System import readers sys.path += [".."] try: from local_config import expectedATRinReader, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] class testcase_Card(unittest.TestCase): """Test case for smartcard.Card.""" def testcase_CardDictionary(self): """Create a dictionary with Card keys""" mydict = {} for reader in readers(): card = Card(reader, expectedATRinReader[reader.name]) mydict[card] = reader for card in list(mydict.keys()): self.assertTrue(str(card.reader) in expectedReaders) def testcase_Card_FromReaders(self): """Create a Card from Readers and test that the response to SELECT DF_TELECOM has two bytes.""" for reader in readers(): card = Card(reader, expectedATRinReader[reader.name]) cc = card.createConnection() if expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "9f 20": 2, "6e 0": 3} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) def testcase_Card_FromReaderStrings(self): """Create a Card from reader strings and test that the response to SELECT DF_TELECOM has two bytes.""" for reader in readers(): card = Card(str(reader), expectedATRinReader[reader.name]) cc = card.createConnection() if expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "9f 20": 2, "6e 0": 3} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) def testcase_Card_Eq_NotEq(self): """Test == and != for Cards.""" for reader in readers(): card = Card(str(reader), expectedATRinReader[reader.name]) cardcopy = Card(str(reader), expectedATRinReader[str(reader)]) self.assertEqual(True, card == cardcopy) self.assertEqual(True, not card != cardcopy) for reader in readers(): card = Card(str(reader), expectedATRinReader[reader.name]) cardcopy = Card(str(reader), [0, 0]) self.assertEqual(True, card != cardcopy) self.assertEqual(True, not card == cardcopy) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938532.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CardConnection.py0000755000076500000240000002103714703301044025635 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.CardConnection This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest sys.path += [".."] try: from local_config import expectedATRinReader except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() from smartcard.CardConnection import CardConnection from smartcard.Exceptions import CardConnectionException, NoCardException from smartcard.scard import ( SCARD_LEAVE_CARD, SCARD_RESET_CARD, SCARD_SHARE_EXCLUSIVE, SCARD_UNPOWER_CARD, ) from smartcard.System import readers SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] class testcase_CardConnection(unittest.TestCase): """Test case for CardConnection.""" def testcase_CardConnection(self): """Test with default protocols the response to SELECT DF_TELECOM.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0(self): """Test with T0 the response to SELECT DF_TELECOM.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol) response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT1inConnect(self): """Test that connecting with T1 on a T0 card fails.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: # should fail since the test card does not support T1 self.assertRaises( CardConnectionException, cc.connect, CardConnection.T1_protocol ) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT1inTransmit(self): """Test that T1 in transmit for a T0 card fails.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect() self.assertRaises( CardConnectionException, cc.transmit, SELECT + DF_TELECOM, CardConnection.T1_protocol, ) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0T1(self): """Test test with T0 | T1 the response to SELECT DF_TELECOM.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol | CardConnection.T1_protocol) response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0inTransmit(self): """Test with T0 in transmit the response to SELECT DF_TELECOM.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol) response, sw1, sw2 = cc.transmit( SELECT + DF_TELECOM, CardConnection.T0_protocol ) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0T1inTransmitMustFail(self): """Test with bad parameter in transmit the response to SELECT DF_TELECOM.""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol | CardConnection.T1_protocol) self.assertRaises( CardConnectionException, cc.transmit, SELECT + DF_TELECOM, CardConnection.T0_protocol | CardConnection.T1_protocol, ) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardReconnectProtocol(self): """Test .reconnect()""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol | CardConnection.T1_protocol) # reconnect in T=1 when a T=0 card (GPK 8K) shall fail self.assertRaises( CardConnectionException, cc.reconnect, protocol=CardConnection.T1_protocol, ) cc.disconnect() else: self.assertRaises(NoCardException, cc.connect) def testcase_CardReconnectMode(self): """Test .reconnect()""" for reader in readers(): cc = reader.createConnection() cc2 = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol | CardConnection.T1_protocol) # reconnect in exclusive mode should fail self.assertRaises( CardConnectionException, cc2.reconnect, mode=SCARD_SHARE_EXCLUSIVE ) cc.disconnect() else: self.assertRaises(NoCardException, cc.connect) def testcase_CardReconnectDisposition(self): """Test .reconnect()""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol | CardConnection.T1_protocol) cc.reconnect(disposition=SCARD_LEAVE_CARD) cc.reconnect(disposition=SCARD_RESET_CARD) cc.reconnect(disposition=SCARD_UNPOWER_CARD) cc.disconnect() else: self.assertRaises(NoCardException, cc.connect) def testcase_CardReconnectNoConnect(self): """Test .reconnect()""" for reader in readers(): cc = reader.createConnection() if expectedATRinReader[str(reader)]: # reconnect without connect first shall fail self.assertRaises(CardConnectionException, cc.reconnect) else: self.assertRaises(NoCardException, cc.connect) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CardMonitor.py0000755000076500000240000000564414703761333025206 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.CardMonitoring. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import threading import time import unittest from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import toHexString sys.path += [".."] try: from local_config import expectedATRs except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() # a simple card observer that prints inserted/removed cards class printobserver(CardObserver): """print observer""" def __init__(self, obsindex, testcase): self.obsindex = obsindex self.testcase = testcase def update(self, observable, handlers): (addedcards, removedcards) = handlers foundcards = {} self.testcase.assertEqual(removedcards, []) for card in addedcards: foundcards[toHexString(card.atr)] = 1 for atr in expectedATRs: if atr and foundcards: self.testcase.assertTrue(toHexString(atr) in foundcards) class testthread(threading.Thread): """thread""" def __init__(self, obsindex, testcase): threading.Thread.__init__(self) self.obsindex = obsindex self.testcase = testcase self.cardmonitor = CardMonitor() self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex, self.testcase) self.cardmonitor.addObserver(self.observer) time.sleep(1) self.cardmonitor.deleteObserver(self.observer) class testcase_cardmonitor(unittest.TestCase): """Test smartcard framework card monitoring classes""" def testcase_cardmonitorthread(self): """card monitor thread""" threads = [] for i in range(0, 4): t = testthread(i, self) threads.append(t) for t in threads: t.start() for t in threads: t.join() if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CardRequest.py0000755000076500000240000001155514703034261025176 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.CardRequest This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest sys.path += [".."] try: from local_config import ( expectedATRinReader, expectedATRs, expectedReaderForATR, expectedReaders, ) except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() import smartcard.System from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType, ATRCardType from smartcard.Exceptions import CardRequestTimeoutException from smartcard.PassThruCardService import PassThruCardService from smartcard.util import toHexString class testcase_CardRequest(unittest.TestCase): """Test case for CardType.""" def testcase_CardRequestATRCardType(self): """Test smartcard.AnyCardType.""" for atr in expectedATRs: if atr: ct = ATRCardType(atr) cr = CardRequest(timeout=10, cardType=ct) cs = cr.waitforcard() cs.connection.connect() self.assertEqual(atr, cs.connection.getATR()) self.assertEqual( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)] ) cs.connection.disconnect() def testcase_CardRequestAnyCardTypeInSelectedReader(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader] if atr: ct = AnyCardType() cr = CardRequest(timeout=10.6, readers=[reader], cardType=ct) cs = cr.waitforcard() cs.connection.connect() self.assertEqual(atr, cs.connection.getATR()) self.assertEqual( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)] ) def testcase_CardRequestATRCardTypeTimeout(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader][:-1] ct = ATRCardType(atr) cr = CardRequest(timeout=1, readers=[reader], cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) def testcase_CardRequestATRCardTypeTimeoutAnyReader(self): """Test smartcard.AnyCardType.""" readers = smartcard.System.readers() atr = expectedATRs[0][:-1] ct = ATRCardType(atr) cr = CardRequest(timeout=1.5, readers=readers, cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) def testcase_CardRequestAnyCardTypeAnyReaderPassThru(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader] if atr: ct = AnyCardType() cardservice = PassThruCardService cr = CardRequest( timeout=10.6, readers=[reader], cardType=ct, cardServiceClass=cardservice, ) cs = cr.waitforcard() cs.connection.connect() self.assertEqual(cs.__class__, PassThruCardService) self.assertEqual(atr, cs.connection.getATR()) self.assertEqual( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)] ) def testcase_CardRequestAnyCardTypeInSelectedReaderNewCard(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: ct = AnyCardType() cr = CardRequest(newcardonly=True, timeout=1, readers=[reader], cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CardService.py0000755000076500000240000000413714703761333025153 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.CardService This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest from smartcard.CardService import CardService from smartcard.System import readers sys.path += [".."] try: from local_config import expectedATRinReader except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_CardService(unittest.TestCase): """Test case for CardService.""" def testcase_CardService(self): """Test the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): if expectedATRinReader[reader.name]: cc = reader.createConnection() cs = CardService(cc) cs.connection.connect() response, sw1, sw2 = cs.connection.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEqual([], response) self.assertTrue(f"{sw1:x} {sw2:x}" in expectedSWs or "9f" == f"{sw1:x}") if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_CardType.py0000755000076500000240000001142314703761333024470 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.CardType This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest sys.path += [".."] try: from local_config import expectedATRinReader except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() from smartcard.CardType import AnyCardType, ATRCardType from smartcard.System import readers class testcase_CardType(unittest.TestCase): """Test case for CardType.""" def testcase_AnyCardType(self): """Test smartcard.AnyCardType.""" ct = AnyCardType() for reader in readers(): if expectedATRinReader[reader.name]: connection = reader.createConnection() connection.connect() self.assertEqual(True, ct.matches(connection.getATR())) self.assertEqual(True, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeWithoutMask(self): """Test smartcard.ATRCardType without mask.""" for reader in readers(): if expectedATRinReader[reader.name]: ct = ATRCardType(expectedATRinReader[reader.name]) connection = reader.createConnection() connection.connect() self.assertEqual(True, ct.matches(connection.getATR())) self.assertEqual(True, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeMisMatchWithoutMask(self): """Test smartcard.ATRCardType mismatch without mask.""" for reader in readers(): if expectedATRinReader[reader.name]: atr = list(expectedATRinReader[reader.name]) # change the last byte of the expected atr atr[-1] = 0xFF ct = ATRCardType(atr) connection = reader.createConnection() connection.connect() self.assertEqual(False, ct.matches(connection.getATR())) self.assertEqual(False, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeWithMask(self): """Test smartcard.ATRCardType with mask.""" for reader in readers(): if expectedATRinReader[reader.name]: mask = [0xFF for x in expectedATRinReader[reader.name]] # don't look to the last byte mask[-1] = 0x00 ct = ATRCardType(expectedATRinReader[reader.name], mask) connection = reader.createConnection() connection.connect() atr = connection.getATR() connection.disconnect() # change a bit in the last byte atr[-1] = atr[-1] ^ 0xFF self.assertEqual(True, ct.matches(atr)) self.assertEqual(True, ct.matches(atr, reader)) def testcase_ATRCardTypeWithMaskMismatch(self): """Test smartcard.ATRCardType with mask and mismatch.""" for reader in readers(): if expectedATRinReader[reader.name]: mask = [0xFF for x in expectedATRinReader[reader.name]] # don't look to the last byte mask[0] = mask[-1] = 0x00 ct = ATRCardType(expectedATRinReader[reader.name], mask) connection = reader.createConnection() connection.connect() atr = connection.getATR() connection.disconnect() # change a bit in the :-2 byte atr[-2] = atr[-2] ^ 0xFF self.assertEqual(False, ct.matches(atr)) self.assertEqual(False, ct.matches(atr, reader)) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_ErrorChecking.py0000755000076500000240000003104314703761333025502 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.sw This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest import smartcard.sw.SWExceptions from smartcard.sw.ErrorChecker import ErrorChecker from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.ISO7816_4_SW1ErrorChecker import ISO7816_4_SW1ErrorChecker from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker from smartcard.sw.op21_ErrorChecker import op21_ErrorChecker class CustomSWException(smartcard.sw.SWExceptions.SWException): """Test exception raised by TestErrorChecker.""" def __init__(self, data, sw1, sw2, message=""): smartcard.sw.SWExceptions.SWException.__init__(self, data, sw1, sw2) class TestErrorChecker(ErrorChecker): """Test error checking checker. This checker raises the following exception: sw1: 56 sw2: 55 CustomSWException sw1: 63 sw2: any WarningProcessingException """ def __call__(self, data, sw1, sw2): if 0x56 == sw1 and 0x55 == sw2: raise CustomSWException(data, sw1, sw2) if 0x63 == sw1: raise CustomSWException(data, sw1, sw2) class testcase_ErrorChecking(unittest.TestCase): """Test case for smartcard.sw.* error checking.""" def failUnlessRaises(self, excClass, callableObj, *args, **kwargs): """override of unittest.TestCase.failUnlessRaises so that we return the exception object for testing fields.""" try: callableObj(*args, **kwargs) except excClass as e: return e if hasattr(excClass, "__name__"): exc_name = excClass.__name__ else: exc_name = str(excClass) raise self.failureException(exc_name) def testcase_ISO7816_4SW1ErrorChecker(self): """Test ISO7816_4_SW1ErrorChecker.""" ecs = ISO7816_4_SW1ErrorChecker() tiso7816_4SW1 = { 0x62: smartcard.sw.SWExceptions.WarningProcessingException, 0x63: smartcard.sw.SWExceptions.WarningProcessingException, 0x64: smartcard.sw.SWExceptions.ExecutionErrorException, 0x65: smartcard.sw.SWExceptions.ExecutionErrorException, 0x66: smartcard.sw.SWExceptions.SecurityRelatedException, 0x67: smartcard.sw.SWExceptions.CheckingErrorException, 0x68: smartcard.sw.SWExceptions.CheckingErrorException, 0x69: smartcard.sw.SWExceptions.CheckingErrorException, 0x6A: smartcard.sw.SWExceptions.CheckingErrorException, 0x6B: smartcard.sw.SWExceptions.CheckingErrorException, 0x6C: smartcard.sw.SWExceptions.CheckingErrorException, 0x6D: smartcard.sw.SWExceptions.CheckingErrorException, 0x6E: smartcard.sw.SWExceptions.CheckingErrorException, 0x6F: smartcard.sw.SWExceptions.CheckingErrorException, } for sw1 in range(0x00, 0xFF + 1): exception = tiso7816_4SW1.get(sw1) for sw2 in range(0x00, 0xFF + 1): if exception is not None: with self.assertRaises(exception): ecs([], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_4ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_4ErrorChecker() tiso7816_4SW = { 0x62: ( smartcard.sw.SWExceptions.WarningProcessingException, [0x00, 0x81, 0x82, 0x83, 0x84, 0xFF], ), 0x63: ( smartcard.sw.SWExceptions.WarningProcessingException, [0x00, 0x81] + list(range(0xC0, 0xCF + 1)), ), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x00]), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, [0x81, 0x82]), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, list(range(0x81, 0x88 + 1)), ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, list(range(0x80, 0x88 + 1)), ), 0x6B: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6F: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), } exception = None for sw1 in range(0x00, 0xFF + 1): sw2range = [] if sw1 in tiso7816_4SW: exception, sw2range = tiso7816_4SW[sw1] for sw2 in range(0x00, 0xFF + 1): if sw2 in sw2range: with self.assertRaises(exception): ecs([], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_8ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_8ErrorChecker() tiso7816_8SW = { 0x63: ( smartcard.sw.SWExceptions.WarningProcessingException, [0x00] + list(range(0xC0, 0xCF + 1)), ), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x81]), 0x66: ( smartcard.sw.SWExceptions.SecurityRelatedException, [0x00, 0x87, 0x88], ), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, [0x83, 0x84]), 0x69: ( smartcard.sw.SWExceptions.CheckingErrorException, list(range(0x82, 0x85 + 1)), ), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, [0x81, 0x82, 0x86, 0x88], ), } exception = None for sw1 in range(0x00, 0xFF + 1): sw2range = [] if sw1 in tiso7816_8SW: exception, sw2range = tiso7816_8SW[sw1] for sw2 in range(0x00, 0xFF + 1): if sw2 in sw2range: with self.assertRaises(exception): ecs([], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_9ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_9ErrorChecker() tiso7816_9SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, [0x82]), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x00]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, [0x82]), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, [0x80, 0x84, 0x89, 0x8A], ), } exception = None for sw1 in range(0x00, 0xFF + 1): sw2range = [] if sw1 in tiso7816_9SW: exception, sw2range = tiso7816_9SW[sw1] for sw2 in range(0x00, 0xFF + 1): if sw2 in sw2range: with self.assertRaises(exception): ecs([], sw1, sw2) else: ecs([], sw1, sw2) def testcase_op21_ErrorChecker(self): """Test op21_ErrorChecker.""" ecs = op21_ErrorChecker() top21_SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, [0x83]), 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, [0x00]), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x00]), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x81]), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, [0x82, 0x85]), 0x6A: ( smartcard.sw.SWExceptions.CheckingErrorException, [0x80, 0x81, 0x82, 0x84, 0x86, 0x88], ), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x94: (smartcard.sw.SWExceptions.CheckingErrorException, [0x84, 0x85]), } exception = None for sw1 in range(0x00, 0xFF + 1): sw2range = [] if sw1 in top21_SW: exception, sw2range = top21_SW[sw1] for sw2 in range(0x00, 0xFF + 1): if sw2 in sw2range: with self.assertRaises(exception): ecs([], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO78164_Test_ErrorCheckingChain(self): """Test error chain with ISO7816-4 checker followed by Test checker.""" errorchain = [] errorchain = [ ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker()), ErrorCheckingChain(errorchain, TestErrorChecker()), ] # ISO7816-4 is answering first on the next, i.e # WarningProcessingException for sw2 in [0x00, 0x81] + list(range(0xC0, 0xCF + 1)): with self.assertRaises( smartcard.sw.SWExceptions.WarningProcessingException ): errorchain[0]([], 0x63, sw2) def testcase_Test_ISO78164_ErrorCheckingChain(self): """Test error chain with Test checker followed by ISO7816-4 checker.""" errorchain = [] errorchain = [ ErrorCheckingChain(errorchain, TestErrorChecker()), ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker()), ] # TestErrorChecker is answering first, i.e. CustomSWException for sw2 in [0x00, 0x81] + list(range(0xC0, 0xCF + 1)): with self.assertRaises(CustomSWException): errorchain[0]([], 0x63, sw2) def testcase_ErrorMessage(self): """Test correct exception error message.""" ecs = ISO7816_4ErrorChecker() with self.assertRaises(smartcard.sw.SWExceptions.CheckingErrorException) as e: ecs([], 0x69, 0x85) self.assertEqual( str(e), "'Status word exception: checking error - " + "Conditions of use not satisfied!'", ) with self.assertRaises(smartcard.sw.SWExceptions.CheckingErrorException) as e: ecs([], 0x6B, 0x00) self.assertEqual( str(e), "'Status word exception: checking error - " + "Incorrect parameters P1-P2!'", ) def testcase_ISO78164_Test_ErrorCheckingChain_filtering(self): """Test error chain with ISO7816-4 checker followed by Test checker.""" errorchain = [] errorchain = [ ErrorCheckingChain(errorchain, ISO7816_8ErrorChecker()), ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker()), ErrorCheckingChain(errorchain, ISO7816_4_SW1ErrorChecker()), ] # don't care about Warning Exceptions errorchain[0].addFilterException( smartcard.sw.SWExceptions.WarningProcessingException ) for sw2 in range(0x00, 0xFF): # should not raise errorchain[0]([], 0x62, sw2) errorchain[0]([], 0x63, sw2) # should raise self.assertRaises( smartcard.sw.SWExceptions.ExecutionErrorException, errorchain[0], [], 0x64, sw2, ) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_ExclusiveCardConnection.py0000755000076500000240000000760714703761333027547 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.ExclusiveTransmitCardConnection. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import random import threading import time import unittest # from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.ExclusiveTransmitCardConnection import ExclusiveTransmitCardConnection # define the apdus used in this script GET_RESPONSE = [0xA0, 0xC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] def signalEvent(evt): """A simple callback that signals an event.""" evt.set() class testthread(threading.Thread): """A test thread that repetitevely sends APDUs to a card within a transaction.""" def __init__(self, threadindex): """Connect to a card with an ExclusiveTransmitCardConnection.""" threading.Thread.__init__(self) self.threadindex = threadindex # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach our decorator cardservice.connection = ExclusiveTransmitCardConnection(cardservice.connection) # uncomment to attach the console tracer # observer=ConsoleCardConnectionObserver() # cardservice.connection.addObserver(observer) # connect to the card cardservice.connection.connect() self.cardservice = cardservice # this event will signal the end of the thread self.evtStop = threading.Event() # this timer will set the event stop event in 30s timer = threading.Timer(10, signalEvent, [self.evtStop]) timer.start() self.countTransmitted = 0 def run(self): """Transmit APDUS with a random interval to the card.""" connection = self.cardservice.connection while not self.evtStop.is_set(): try: connection.lock() apdu = SELECT + DF_TELECOM _, sw1, sw2 = connection.transmit(apdu) if 0x90 == (sw1 & 0xF0): apdu = GET_RESPONSE + [sw2] _, sw1, sw2 = connection.transmit(apdu) finally: connection.unlock() self.countTransmitted = self.countTransmitted + 1 time.sleep(float(random.uniform(1, 3)) * 0.01) class testcase_cardmonitor(unittest.TestCase): """Test smartcard framework card monitoring classes""" def testcase_cardmonitorthread(self): """card monitor thread""" threads = [] for i in range(0, 4): t = testthread(i) threads.append(t) for t in threads: t.start() for t in threads: t.join() # for t in threads: # print(f"Thread {t.threadindex}: transmitted {t.countTransmitted} apdus.") if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_readergroups.py0000755000076500000240000001247014703761333025462 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.readers.ReaderGroups This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest from smartcard.scard import resourceManager from smartcard.System import readergroups if "winscard" == resourceManager: class testcase_readergroups(unittest.TestCase): """Test smartcard framework readersgroups.""" pinpadgroup = "Pinpad$Readers" biogroup = "Biometric$Readers" def testcase_readergroup_add(self): """tests groups=groups+[newgroups]""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups = groups + [self.pinpadgroup] self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time and biometric once groups = groups + [self.biogroup, self.pinpadgroup] self.assertEqual(groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_iadd(self): """test groups+=[newgroups]""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups += [self.pinpadgroup] self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time and biometric once groups += [self.biogroup, self.pinpadgroup] self.assertEqual(groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_radd(self): """test groups=[newgroups]+groups""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group zgroups = [self.pinpadgroup] + groups self.assertEqual(groups, groupssnapshot) self.assertEqual(zgroups, groupssnapshot + [self.pinpadgroup]) self.assertTrue(isinstance(zgroups, list)) self.assertTrue(isinstance(groups, type(readergroups()))) # add pinpad a tiwce and biometric once zgroups = [self.pinpadgroup, self.biogroup, self.pinpadgroup] + groups self.assertEqual(groups, groupssnapshot) self.assertEqual( zgroups, groupssnapshot + [self.pinpadgroup, self.biogroup] ) self.assertTrue(isinstance(zgroups, list)) self.assertTrue(isinstance(groups, type(readergroups()))) def testcase_readergroup_append(self): """test groups.append(newgroups)""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups.append(self.pinpadgroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time groups.append(self.pinpadgroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add biometric once groups.append(self.biogroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_insert(self): """test groups.insert(i,newgroups)""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups.insert(0, self.pinpadgroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time groups.insert(1, self.pinpadgroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup]) # add biometric once groups.insert(1, self.biogroup) self.assertEqual(groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_readermonitor.py0000755000076500000240000000562014703761333025631 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.ReaderMonitoring This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import threading import time import unittest sys.path += [".."] try: from local_config import expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver # a simple reader observer that prints added/removed readers class printobserver(ReaderObserver): """observer""" def __init__(self, obsindex, testcase): self.obsindex = obsindex self.testcase = testcase def update(self, observable, handlers): (addedreaders, removedreaders) = handlers foundreaders = {} self.testcase.assertEqual(removedreaders, []) for reader in addedreaders: foundreaders[str(reader)] = 1 if foundreaders: for reader in expectedReaders: self.testcase.assertTrue(reader in foundreaders) class testthread(threading.Thread): """thread""" def __init__(self, obsindex, testcase): threading.Thread.__init__(self) self.obsindex = obsindex self.testcase = testcase self.readermonitor = ReaderMonitor() self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex, self.testcase) self.readermonitor.addObserver(self.observer) time.sleep(1) self.readermonitor.deleteObserver(self.observer) class testcase_readermonitor(unittest.TestCase): """Test smartcard framework reader monitoring methods""" def testcase_readermonitorthread(self): """readermonitor thread""" threads = [] for i in range(0, 4): t = testthread(i, self) threads.append(t) for t in threads: t.start() for t in threads: t.join() if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_readermonitorstress.py0000755000076500000240000001270514703761333027077 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.ReaderMonitoring This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import random import threading import time import unittest from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver PERIOD = 0.1 # stats on virtual reader insertion/removal insertedreaderstats = {} removedreaderstats = {} # the virtual list of readers mutexvreaders = threading.RLock() virtualreaders = [] def getReaders(): """Return virtual list of inserted readers. Replacement of smartcard.system.readers for testing purpose""" with mutexvreaders: currentreaders = virtualreaders readerEvent.set() return currentreaders # an event to signal test threads to end exitEvent = threading.Event() # an event to ensure only one insertion/removal between getReaders() calls readerEvent = threading.Event() readerEvent.clear() # test running time in seconds RUNNING_TIME = 15 # the count of registered observers OBS_COUNT = 100 class readerInsertionThread(threading.Thread): """Simulate reader insertion every 2 to 4 periods.""" def __init__(self): threading.Thread.__init__(self) def run(self): while not exitEvent.is_set(): time.sleep(random.uniform(2 * PERIOD, 4 * PERIOD)) readerEvent.wait() newreader = random.choice("abcdefghijklmnopqrstuvwxyz") with mutexvreaders: if newreader not in virtualreaders: virtualreaders.append(newreader) if newreader in insertedreaderstats: insertedreaderstats[newreader] += 1 else: insertedreaderstats[newreader] = 1 readerEvent.clear() class readerRemovalThread(threading.Thread): """Simulate reader removal every 5 to 6 periods.""" def __init__(self): threading.Thread.__init__(self) def run(self): while not exitEvent.is_set(): time.sleep(random.uniform(5 * PERIOD, 6 * PERIOD)) readerEvent.wait() with mutexvreaders: if virtualreaders: oldreader = random.choice(virtualreaders) virtualreaders.remove(oldreader) if oldreader in removedreaderstats: removedreaderstats[oldreader] += 1 else: removedreaderstats[oldreader] = 1 readerEvent.clear() class countobserver(ReaderObserver): """A simple reader observer that counts added/removed readers.""" def __init__(self, obsindex): self.obsindex = obsindex self.insertedreaderstats = {} self.removedreaderstats = {} self.countnotified = 0 def update(self, observable, handlers): (addedreaders, removedreaders) = handlers self.countnotified += 1 for newreader in addedreaders: if newreader in self.insertedreaderstats: self.insertedreaderstats[newreader] += 1 else: self.insertedreaderstats[newreader] = 1 for oldreader in removedreaders: if oldreader in self.removedreaderstats: self.removedreaderstats[oldreader] += 1 else: self.removedreaderstats[oldreader] = 1 class testcase_readermonitorstress(unittest.TestCase): """Test smartcard framework reader monitoring""" def testcase_readermonitorthread(self): """readermonitor thread""" # create thread that simulates reader insertion insertionthread = readerInsertionThread() # create thread that simulates reader removal removalthread = readerRemovalThread() readermonitor = ReaderMonitor(readerProc=getReaders, period=PERIOD) observers = [] for i in range(0, OBS_COUNT): observer = countobserver(i) readermonitor.addObserver(observer) observers.append(observer) # signal threads to start insertionthread.start() removalthread.start() # let reader insertion/removal threads run for a while # then signal threads to end time.sleep(RUNNING_TIME) exitEvent.set() # wait until all threads ended removalthread.join() insertionthread.join() time.sleep(2 * PERIOD) for observer in observers: self.assertEqual(observer.insertedreaderstats, insertedreaderstats) self.assertEqual(observer.removedreaderstats, removedreaderstats) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_readers.py0000755000076500000240000000724514703761333024411 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.readers. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest from smartcard import listReaders from smartcard.scard import resourceManager from smartcard.System import readergroups, readers sys.path += [".."] try: from local_config import expectedReaderGroups, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_readers(unittest.TestCase): """Test smartcard framework readers factory methods""" def testcase_enoughreaders(self): """enough readers""" self.assertTrue(len(readers()) > 1) def testcase_readers(self): """readers""" foundreaders = {} for reader in readers(): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assertTrue(reader in foundreaders) def testcase_hashreaders(self): """hash readers""" foundreaders = {} for reader in readers(): foundreaders[reader] = 1 for reader in list(foundreaders.keys()): self.assertTrue(reader in readers()) def testcase_legacyreaders(self): """legacy readers""" foundreaders = {} for reader in listReaders(): foundreaders[reader] = 1 for reader in expectedReaders: self.assertTrue(reader in foundreaders) def testcase_readers_in_readergroup(self): """readers in readergroups""" foundreaders = {} for reader in readers(["SCard$DefaultReaders"]): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assertTrue(reader in foundreaders) def testcase_readers_in_readergroup_empty(self): """readers in readergroups empty""" foundreaders = {} for reader in readers([]): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assertTrue(reader in foundreaders) if "winscard" == resourceManager: def testcase_readers_in_readergroup_nonexistent(self): """readers in readergroups nonexistent""" foundreaders = {} for reader in readers(["dummy$group"]): foundreaders[reader] = 1 for reader in expectedReaders: self.assertTrue(reader not in foundreaders) self.assertEqual(0, len(foundreaders)) def testcase_readergroups(self): """readergroups""" foundreadergroups = {} for readergroup in readergroups(): foundreadergroups[readergroup] = 1 for readergroup in expectedReaderGroups: self.assertTrue(readergroup in foundreadergroups) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729094363.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_ulist.py0000755000076500000240000001032514703761333024115 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for ulist This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest from smartcard.ulist import ulist class C(ulist): """ulist subclass""" def __onadditem__(self, item): # print('+', item) pass def __onremoveitem__(self, item): # print('-', item) pass class testcase_ulist(unittest.TestCase): """Test smartcard.ulist.""" def testcase_ulist_init(self): """tests constructor""" c = C([1, 2, 3, 3, 4, 5, 5]) self.assertEqual([1, 2, 3, 4, 5], c) c = C(["one", "two", "three", "one"]) self.assertEqual(["one", "two", "three"], c) def testcase_ulist_add(self): """tests l=l+other""" seed = [1, 2, 3] c = C(seed) self.assertEqual(seed, c) c = c + [] self.assertEqual(seed, c) c = c + 4 self.assertEqual(seed + [4], c) c = c + 4 self.assertEqual(seed + [4], c) c = c + "word" self.assertEqual(seed + [4] + ["word"], c) seed = ["one", "two", "three"] c = C(seed) self.assertEqual(seed, c) c = c + ["four", "five"] self.assertEqual(seed + ["four", "five"], c) def testcase_ulist_iadd(self): """tests l+=other""" seed = [1, 2, 3] c = C(seed) self.assertEqual(seed, c) c += [] self.assertEqual(seed, c) c += 4 self.assertEqual(seed + [4], c) c += 4 self.assertEqual(seed + [4], c) c += [4, 3, 2, 1] self.assertEqual(seed + [4], c) c += "word" self.assertEqual(seed + [4] + ["word"], c) seed = ["one", "two", "three"] c = C(seed) self.assertEqual(seed, c) c += ["four", "five"] self.assertEqual(seed + ["four", "five"], c) def testcase_ulist_radd(self): """tests l=other+l""" seed = [1, 2, 3] c = C(seed) self.assertEqual(seed, c) l = [] + c self.assertEqual(seed, l) l = [3] + c self.assertEqual(seed, c) self.assertEqual(seed, l) l = [3, 3, 4, 4] + c self.assertEqual(seed, c) self.assertEqual(seed + [4], l) l = [4] + ["word"] + c self.assertEqual(seed, c) self.assertEqual(seed + [4] + ["word"], l) def testcase_ulist_append(self): """append""" seed = [1, 2, 3] c = C(seed) c.append(4) self.assertEqual(seed + [4], c) c.append(4) self.assertEqual(seed + [4], c) c.append("word") self.assertEqual(seed + [4] + ["word"], c) def testcase_ulist_insert(self): """insert""" seed = [1, 2, 3] c = C(seed) c.insert(0, 0) self.assertEqual([0] + seed, c) c.insert(1, 0) self.assertEqual([0] + seed, c) def testcase_ulist_pop(self): """pop""" seed = [1, 2, 3] c = C(seed) c.pop() self.assertEqual(c, [1, 2]) c.pop(1) self.assertEqual(c, [1]) def testcase_ulist_remove(self): """remove""" seed = [1, 2, 3] c = C(seed) c.remove(2) self.assertEqual(c, [1, 3]) c.remove(1) self.assertEqual(c, [3]) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/framework/testcase_utils.py0000755000076500000240000001317714703034261024116 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.utils This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest from smartcard.util import ( COMMA, HEX, PACK, UPPERCASE, padd, toASCIIBytes, toASCIIString, toBytes, toGSM3_38Bytes, toHexString, ) class testcase_utils(unittest.TestCase): """Test smartcard.utils.""" def testcase_asciitostring(self): """tests ASCIIToString""" self.assertEqual( toASCIIString([0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31]), "Number 101", ) def testcase_bytesto338(self): """tests toGSM3_38Bytes""" self.assertEqual( toGSM3_38Bytes("@ùPascal"), [0x00, 0x06, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C] ) def testcase_padd(self): """tests padd""" self.assertEqual( [ 0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 16), ) self.assertEqual( [0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 9), ) self.assertEqual( [0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 8), ) self.assertEqual( [0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 10), ) def testcase_toasciibytes(self): """tests toASCIIBytes""" self.assertEqual( [0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31], toASCIIBytes("Number 101"), ) self.assertEqual(toASCIIString(toASCIIBytes("Number 101")), "Number 101") def testcase_tobytestring(self): """tests toByteString""" self.assertEqual( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B 65 00 00 9C 11 01 01 03") ) self.assertEqual( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B6500009C11010103") ) self.assertEqual( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B65 0000 9C11 010103") ) self.assertEqual( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B65 \t\t0000 \t9C11 \t0101\t03 \t\n"), ) def testcase_tohexstring(self): """tests toHexString""" self.assertEqual( "3B 65 00 00 9C 11 01 01 03", toHexString([59, 101, 0, 0, 156, 17, 1, 1, 3]) ) atr = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] self.assertEqual("3B, 65, 00, 00, 9C, 11, 01, 01, 03", toHexString(atr, COMMA)) self.assertEqual("3B6500009C11010103", toHexString(atr, PACK)) self.assertEqual( "0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03", toHexString(atr, HEX) ) self.assertEqual( "0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03", toHexString(atr, HEX | COMMA), ) self.assertEqual( "0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03", toHexString(atr, HEX | UPPERCASE), ) self.assertEqual( "0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03", toHexString(atr, HEX | UPPERCASE | COMMA), ) atr = [59, 101, 0, 0, 156, 17, 1, 1, 3] self.assertEqual("3B, 65, 00, 00, 9C, 11, 01, 01, 03", toHexString(atr, COMMA)) self.assertEqual("3B6500009C11010103", toHexString(atr, PACK)) self.assertEqual( "0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03", toHexString(atr, HEX) ) self.assertEqual( "0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03", toHexString(atr, HEX | COMMA), ) self.assertEqual( "0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03", toHexString(atr, HEX | UPPERCASE), ) self.assertEqual( "0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03", toHexString(atr, HEX | UPPERCASE | COMMA), ) def testcase_tohexstring_empty(self): """tests toHexString""" self.assertEqual("", toHexString()) self.assertEqual("", toHexString([])) def testcase_tohexstring_nobytes(self): """tests toHexString""" self.assertRaises(TypeError, toHexString, "bad input") self.assertRaises(TypeError, toHexString, ["bad", "input"]) if __name__ == "__main__": unittest.main(verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/framework/testsuite_framework.py0000755000076500000240000000366214703034261025167 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit test suite for smartcard python framework. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest # so that we can locate configcheck sys.path += [".."] import configcheck def suite(): """suite""" modules_to_test = ( "testcase_ATR", "testcase_Card", "testcase_CardConnection", "testcase_CardMonitor", "testcase_CardRequest", "testcase_CardService", "testcase_CardType", "testcase_CAtr", "testcase_ErrorChecking", "testcase_ExclusiveCardConnection", "testcase_readers", "testcase_readergroups", "testcase_readermonitor", "testcase_readermonitorstress", "testcase_ulist", "testcase_utils", ) testsuite_framework = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_framework.addTest(unittest.TestLoader().loadTestsFromModule(module)) return testsuite_framework if __name__ == "__main__": configcheck.checklocalconfig() # set verbosity=2 to get more details unittest.main(defaultTest="suite", verbosity=2) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6736631 pyscard-2.2.1/src/smartcard/test/frameworkpcsc/0000755000076500000240000000000014740753203021353 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/frameworkpcsc/readme.txt0000644000076500000240000000314114677317744023367 0ustar00rousseaustaff------------------------------------------------------------------------------- This directory contains the test suite for the pcsc part of the pyscard framework. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ------------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/frameworkpcsc/testcase_pcscreadergroups.py0000755000076500000240000001420514677317744027217 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for smartcard.pcsc.readers This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest sys.path += [".."] try: from local_config import ( expectedATRinReader, expectedATRs, expectedReaderGroups, expectedReaders, ) except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() from smartcard.pcsc.PCSCReader import PCSCReader from smartcard.pcsc.PCSCReaderGroups import PCSCReaderGroups from smartcard.scard import resourceManager if "winscard" == resourceManager: class testcase_readergroups(unittest.TestCase): """Test smartcard framework readers factory methods""" def setUp(self): groups = PCSCReaderGroups().instance groups.remove("Pinpad$Readers") groups.remove("Biometric$Readers") def testcase_add(self): """Test for groups=groups+newgroups""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups = groups + newgroup self.assertEqual(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_addlist(self): """Test for groups=groups+[newgroups]""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroups = ["Pinpad$Readers", "Biometric$Readers"] groups = groups + newgroups self.assertEqual(groups, groupssnapshot + newgroups) for group in newgroups: groups.remove(group) def testcase_iadd(self): """Test for groups+=newgroup""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups += newgroup self.assertEqual(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_iaddlist(self): """Test for groups+=[newgroups]""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroups = ["Pinpad$Readers", "Biometric$Readers"] groups += newgroups self.assertEqual(groups, groupssnapshot + newgroups) for group in newgroups: groups.remove(group) def testcase_append(self): """Test for groups.append(newgroup)""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups.append(newgroup) self.assertEqual(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_insert(self): """Test for groups.insert(newgroup)""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups.insert(0, newgroup) self.assertEqual(groups, [newgroup] + groupssnapshot) groups.remove(newgroup) def testcase_removereadergroup_pop(self): """Test for groups.pop()""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups.insert(0, newgroup) self.assertEqual(groups, [newgroup] + groupssnapshot) groups.pop(0) self.assertEqual(groups, groupssnapshot) def testcase_addreadertogroup(self): """Test for adding readers to group""" groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups.insert(0, newgroup) for r in PCSCReader.readers("SCard$DefaultReaders"): r.addtoreadergroup(newgroup) self.assertEqual( PCSCReader.readers("SCard$DefaultReaders"), PCSCReader.readers(newgroup) ) groups.pop(0) self.assertEqual([], PCSCReader.readers(newgroup)) def testcase_removereaderfromgroup(self): """Test for removing readers from group""" groups = PCSCReaderGroups().instance newgroup = "Pinpad$Readers" groups.insert(0, newgroup) for r in PCSCReader.readers("SCard$DefaultReaders"): r.addtoreadergroup(newgroup) self.assertEqual( PCSCReader.readers("SCard$DefaultReaders"), PCSCReader.readers(newgroup) ) for r in PCSCReader.readers("SCard$DefaultReaders"): r.removefromreadergroup(newgroup) self.assertEqual([], PCSCReader.readers(newgroup)) groups.pop(0) self.assertEqual([], PCSCReader.readers(newgroup)) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_readergroups) return unittest.TestSuite(suite1) else: print("These tests are for Windows only") if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/frameworkpcsc/testsuite_frameworkpcsc.py0000755000076500000240000000266614703034261026714 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit test suite for smartcard python framework over pcsc. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest # so that we can locate configcheck sys.path += [".."] import configcheck def suite(): """suite""" modules_to_test = ("testcase_pcscreadergroups",) testsuite_framework = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_framework.addTest(unittest.TestLoader().loadTestsFromModule(module)) return testsuite_framework if __name__ == "__main__": configcheck.checklocalconfig() unittest.main(defaultTest="suite", verbosity=1) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6793838 pyscard-2.2.1/src/smartcard/test/scard/0000755000076500000240000000000014740753203017601 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/readme.txt0000644000076500000240000000316514677317744021623 0ustar00rousseaustaff------------------------------------------------------------------------------- This directory contains the test suite for the smartcard.scard wrapper of the C language SCardXXX API. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ------------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_getatr.py0000755000076500000240000000576714677317744023375 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardConnect/SCardStatus/SCardDisconnect This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest from smartcard.scard import * sys.path += [".."] try: from local_config import expectedATRs, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_getATR(unittest.TestCase): """Test scard API for ATR retrieval""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def _getATR(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) self.assertEqual(hresult, 0) try: hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEqual(hresult, 0) self.assertEqual(reader, expectedReaders[r]) self.assertEqual(atr, expectedATRs[r]) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEqual(hresult, 0) def test_getATR0(self): testcase_getATR._getATR(self, 0) def test_getATR1(self): testcase_getATR._getATR(self, 1) def test_getATR2(self): testcase_getATR._getATR(self, 2) def test_getATR3(self): testcase_getATR._getATR(self, 3) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_getATR) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_getattrib.py0000755000076500000240000000754514677317744024070 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardConnect/SCardGetAttrib/SCardDisconnect. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import struct # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest from smartcard.scard import * sys.path += [".."] try: from local_config import expectedATRs, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_getAttrib(unittest.TestCase): """Test scard API for SCardGetAttrib""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def _getAttrib(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) self.assertEqual(hresult, 0) try: hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEqual(hresult, 0) self.assertEqual(reader, expectedReaders[r]) self.assertEqual(atr, expectedATRs[r]) if "SCARD_ATTR_ATR_STRING" in scard.__dict__: hresult, attrib = SCardGetAttrib(hcard, SCARD_ATTR_ATR_STRING) self.assertEqual(hresult, 0) self.assertEqual(expectedATRs[r], attrib) if "winscard" == resourceManager: hresult, attrib = SCardGetAttrib( hcard, SCARD_ATTR_DEVICE_SYSTEM_NAME_A ) self.assertEqual(hresult, 0) trimmedAttrib = attrib[:-1] self.assertEqual( expectedReaders[r], apply( struct.pack, ["<" + "B" * len(trimmedAttrib)] + trimmedAttrib, ), ) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEqual(hresult, 0) def test_getATR0(self): testcase_getAttrib._getAttrib(self, 0) def test_getATR1(self): testcase_getAttrib._getAttrib(self, 1) def test_getATR3(self): testcase_getAttrib._getAttrib(self, 2) def test_getATR4(self): testcase_getAttrib._getAttrib(self, 3) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_getAttrib) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_geterrormessage.py0000755000076500000240000000452114677317744025270 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardGetErrorMessage. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest from smartcard.scard import * class testcase_geterrormessage(unittest.TestCase): """Test scard API for ATR retrieval with SCardLocateCards""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def test_getErrorMessage(self): hresult, readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) hresult = SCardReleaseContext(pow(2, 63) >> 60) if "win32" == sys.platform: self.assertEqual( (SCARD_E_INVALID_HANDLE == hresult or ERROR_INVALID_HANDLE == hresult), True, ) else: self.assertEqual((SCARD_E_INVALID_HANDLE == hresult), True) self.assertEqual( ( SCardGetErrorMessage(hresult).rstrip() == "Invalid handle.".rstrip() or SCardGetErrorMessage(hresult).rstrip() == "The handle is invalid.".rstrip() ), True, ) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_geterrormessage) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_listcards.py0000755000076500000240000002027414677317744024065 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardIntroduceCardType/SCardListCards/SCardListInterfaces This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import platform import unittest import smartcard.guid from smartcard.scard import * if "winscard" == resourceManager: class testcase_listcards(unittest.TestCase): """Test scard API for ATR retrieval""" # setup for all unit tests: establish context and introduce # a dummy card interface def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) self.dummycardname = "dummycard" self.dummycardATR = [ 0x3B, 0x75, 0x94, 0x00, 0x00, 0x62, 0x02, 0x02, 0x01, 0x01, ] self.dummycardMask = [ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] self.dummycardguid1 = smartcard.guid.strToGUID( "{AD4F1667-EA75-4124-84D4-641B3B197C65}" ) self.dummycardguid2 = smartcard.guid.strToGUID( "{382AE95A-7C2C-449c-A179-56C6DE6FF3BC}" ) testcase_listcards.__introduceinterface(self) # teardown for all unit tests: release context and forget # dummy card interface def tearDown(self): testcase_listcards.__forgetinterface(self) hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) # introduce a dummy card interface # card ATR same as e-gate def __introduceinterface(self): hresult = SCardForgetCardType(self.hcontext, self.dummycardname) dummycardPrimaryGUID = self.dummycardguid1 dummycardGUIDS = self.dummycardguid1 + self.dummycardguid2 hresult = SCardIntroduceCardType( self.hcontext, self.dummycardname, dummycardPrimaryGUID, dummycardGUIDS, self.dummycardATR, self.dummycardMask, ) self.assertEqual(hresult, 0) # forget dummy card interface def __forgetinterface(self): hresult = SCardForgetCardType(self.hcontext, self.dummycardname) self.assertEqual(hresult, 0) # locate a known card # Cryptoflex 8k v2 is present in standard Windows 2000 def test_listcryptoflexbyatr(self): slbCryptoFlex8kv2ATR = [ 0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00, ] slbCryptoFlex8kv2Name = ["Schlumberger Cryptoflex 8K v2"] hresult, card = SCardListCards(self.hcontext, slbCryptoFlex8kv2ATR, []) self.assertEqual(hresult, 0) self.assertEqual(card, slbCryptoFlex8kv2Name) # locate dummy card by interface def test_listdummycardbyguid(self): guidstolocate = self.dummycardguid2 + self.dummycardguid1 locatedcardnames = [self.dummycardname] hresult, card = SCardListCards(self.hcontext, [], guidstolocate) self.assertEqual(hresult, 0) self.assertEqual(card, locatedcardnames) # list our dummy card interfaces and check # that they match the introduced interfaces def test_listdummycardinterfaces(self): hresult, interfaces = SCardListInterfaces(self.hcontext, self.dummycardname) self.assertEqual(hresult, 0) self.assertEqual(2, len(interfaces)) self.assertEqual(self.dummycardguid1, interfaces[0]) self.assertEqual(self.dummycardguid2, interfaces[1]) # locate all cards and interfaces in the system def test_listallcards(self): # dummycard has been introduced in the test setup and # will be removed in the test teardown. Other cards are # the cards present by default on Windows 2000 expectedCards = [ "dummycard", "GemSAFE Smart Card (8K)", "Schlumberger Cryptoflex 4K", "Schlumberger Cryptoflex 8K", "Schlumberger Cryptoflex 8K v2", ] hresult, cards = SCardListCards(self.hcontext, [], []) self.assertEqual(hresult, 0) foundCards = {} for i in range(len(cards)): foundCards[cards[i]] = 1 for i in expectedCards: self.assertTrue(i in foundCards) # dummycard has a primary provider, # other cards have no primary provider expectedPrimaryProviderResult = { "dummycard": [0, self.dummycardguid1], "GemSAFE": [2, None], "Schlumberger Cryptoflex 4k": [2, None], "Schlumberger Cryptoflex 8k": [2, None], "Schlumberger Cryptoflex 8k v2": [2, None], } for i in range(len(cards)): hresult, providername = SCardGetCardTypeProviderName( self.hcontext, cards[i], SCARD_PROVIDER_PRIMARY ) if cards[i] in expectedPrimaryProviderResult: self.assertEqual( hresult, expectedPrimaryProviderResult[cards[i]][0] ) if hresult == SCARD_S_SUCCESS: self.assertEqual( providername, smartcard.guid.GUIDToStr( expectedPrimaryProviderResult[cards[i]][1] ), ) # dummycard has no CSP, other cards have a CSP expectedProviderCSPResult = { "dummycard": [2, None], "GemSAFE": [0, "Gemplus GemSAFE Card CSP v1.0"], "Schlumberger Cryptoflex 4k": [ 0, "Schlumberger Cryptographic Service Provider", ], "Schlumberger Cryptoflex 8k": [ 0, "Schlumberger Cryptographic Service Provider", ], "Schlumberger Cryptoflex 8k v2": [ 0, "Schlumberger Cryptographic Service Provider", ], } for i in range(len(cards)): hresult, providername = SCardGetCardTypeProviderName( self.hcontext, cards[i], SCARD_PROVIDER_CSP ) if cards[i] in expectedProviderCSPResult: self.assertEqual(hresult, expectedProviderCSPResult[cards[i]][0]) self.assertEqual( providername, expectedProviderCSPResult[cards[i]][1] ) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_listcards) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_locatecards.py0000755000076500000240000001035414677317744024357 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardLocateCards. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import platform # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest from smartcard.scard import * sys.path += [".."] try: from local_config import expectedATRinReader, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_locatecards(unittest.TestCase): """Test scard API for ATR retrieval with SCardLocateCards""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def test_locateCards(self): hresult, readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) foundReaders = {} for reader in readers: foundReaders[reader] = 1 for reader in expectedReaders: self.assertTrue(reader in foundReaders) if "winscard" == resourceManager: hresult, cards = SCardListCards(self.hcontext, [], []) self.assertEqual(hresult, 0) readerstates = [] for i in range(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] hresult, newstates = SCardLocateCards(self.hcontext, cards, readerstates) self.assertEqual(hresult, 0) dictexpectedreaders = {} for reader in expectedReaders: dictexpectedreaders[reader] = 1 for reader, eventstate, atr in newstates: if reader in dictexpectedreaders and [] != expectedATRinReader[reader]: self.assertEqual(expectedATRinReader[reader], atr) self.assertTrue(eventstate & SCARD_STATE_PRESENT) self.assertTrue(eventstate & SCARD_STATE_CHANGED) # 10ms delay, so that time-out always occurs hresult, newstates = SCardGetStatusChange(self.hcontext, 10, newstates) self.assertEqual(hresult, SCARD_E_TIMEOUT) self.assertEqual( SCardGetErrorMessage(hresult), "The user-specified timeout value has expired. ", ) elif "pcsclite" == resourceManager: readerstates = [] for i in range(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] hresult, newstates = SCardGetStatusChange(self.hcontext, 0, readerstates) self.assertEqual(hresult, 0) dictexpectedreaders = {} for reader in expectedReaders: dictexpectedreaders[reader] = 1 for reader, eventstate, atr in newstates: if reader in dictexpectedreaders and [] != expectedATRinReader[reader]: self.assertEqual(expectedATRinReader[reader], atr) self.assertTrue(eventstate & SCARD_STATE_PRESENT) self.assertTrue(eventstate & SCARD_STATE_CHANGED) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_locatecards) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_readergroups.py0000755000076500000240000001072014677317744024572 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardxxx readers and readergroups methods. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest from smartcard.scard import * sys.path += [".."] try: from local_config import expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() expectedGroups = ["SCard$DefaultReaders"] class testcase_readergroups(unittest.TestCase): """Test scard reader groups API""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def test_listReaders(self): # list current readers and compare with expected list hresult, readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) for i in range(len(expectedReaders)): self.assertEqual(readers[i], expectedReaders[i]) # list current reader groups and compare with expected list hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEqual(hresult, 0) for i in range(len(expectedGroups)): self.assertEqual(readerGroups[i], expectedGroups[i]) if "winscard" == resourceManager: # add a new group newgroup = "SCard$MyOwnGroup" expectedGroups.append(newgroup) hresult = SCardIntroduceReaderGroup(self.hcontext, newgroup) self.assertEqual(hresult, 0) dummyreader = readers[0] + " alias" hresult = SCardIntroduceReader(self.hcontext, dummyreader, readers[0]) self.assertEqual(hresult, 0) hresult = SCardAddReaderToGroup(self.hcontext, dummyreader, newgroup) self.assertEqual(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEqual(hresult, 0) for i in range(len(expectedGroups)): self.assertEqual(readerGroups[i], expectedGroups[i]) # list readers in new group hresult, newreaders = SCardListReaders(self.hcontext, [newgroup]) self.assertEqual(hresult, 0) self.assertEqual(newreaders[0], dummyreader) # remove reader from new group hresult = SCardRemoveReaderFromGroup(self.hcontext, dummyreader, newgroup) self.assertEqual(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEqual(hresult, 0) expectedGroups.remove(newgroup) for i in range(len(expectedGroups)): self.assertEqual(readerGroups[i], expectedGroups[i]) hresult = SCardForgetReaderGroup(self.hcontext, newgroup) self.assertEqual(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEqual(hresult, 0) for i in range(len(expectedGroups)): self.assertEqual(readerGroups[i], expectedGroups[i]) hresult = SCardForgetReader(self.hcontext, dummyreader) self.assertEqual(hresult, 0) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_readergroups) return unittest.TestSuite(suite1) if __name__ == "__main__": # When this module is executed from the command-line, run all its tests unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_returncodes.py0000755000076500000240000000705314677317744024432 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for return codes This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2009 gemalto Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import unittest from smartcard.scard import * class testcase_returncodes(unittest.TestCase): """Test scard API for return codes""" def test_getReturnCodes(self): errors = ( SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR, SCARD_E_CANCELLED, SCARD_E_INVALID_HANDLE, SCARD_E_INVALID_PARAMETER, SCARD_E_INVALID_TARGET, SCARD_E_NO_MEMORY, SCARD_F_WAITED_TOO_LONG, SCARD_E_INSUFFICIENT_BUFFER, SCARD_E_UNKNOWN_READER, SCARD_E_TIMEOUT, SCARD_E_SHARING_VIOLATION, SCARD_E_NO_SMARTCARD, SCARD_E_UNKNOWN_CARD, SCARD_E_CANT_DISPOSE, SCARD_E_PROTO_MISMATCH, SCARD_E_NOT_READY, SCARD_E_INVALID_VALUE, SCARD_E_SYSTEM_CANCELLED, SCARD_F_COMM_ERROR, SCARD_F_UNKNOWN_ERROR, SCARD_E_INVALID_ATR, SCARD_E_NOT_TRANSACTED, SCARD_E_READER_UNAVAILABLE, SCARD_E_PCI_TOO_SMALL, SCARD_E_READER_UNSUPPORTED, SCARD_E_DUPLICATE_READER, SCARD_E_CARD_UNSUPPORTED, SCARD_E_NO_SERVICE, SCARD_E_SERVICE_STOPPED, SCARD_E_UNEXPECTED, SCARD_E_ICC_INSTALLATION, SCARD_E_ICC_CREATEORDER, SCARD_E_UNSUPPORTED_FEATURE, SCARD_E_DIR_NOT_FOUND, SCARD_E_FILE_NOT_FOUND, SCARD_E_NO_DIR, SCARD_E_NO_FILE, SCARD_E_NO_ACCESS, SCARD_E_WRITE_TOO_MANY, SCARD_E_BAD_SEEK, SCARD_E_INVALID_CHV, SCARD_E_UNKNOWN_RES_MNG, SCARD_E_NO_SUCH_CERTIFICATE, SCARD_E_CERTIFICATE_UNAVAILABLE, SCARD_E_NO_READERS_AVAILABLE, SCARD_E_COMM_DATA_LOST, SCARD_E_NO_KEY_CONTAINER, SCARD_E_SERVER_TOO_BUSY, SCARD_W_UNSUPPORTED_CARD, SCARD_W_UNRESPONSIVE_CARD, SCARD_W_UNPOWERED_CARD, SCARD_W_RESET_CARD, SCARD_W_REMOVED_CARD, SCARD_W_SECURITY_VIOLATION, SCARD_W_WRONG_CHV, SCARD_W_CHV_BLOCKED, SCARD_W_EOF, SCARD_W_CANCELLED_BY_USER, SCARD_W_CARD_NOT_AUTHENTICATED, ) # for e in errors: # print(hex((e+0x100000000) & 0xFFFFFFFF), SCardGetErrorMessage(e)) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_returncodes) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/test/scard/testcase_transaction.py0000755000076500000240000000650614677317744024424 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit tests for SCardBeginTransaction/SCardEndTransaction. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys import unittest from smartcard.scard import * sys.path += [".."] try: from local_config import expectedATRs, expectedReaders except ImportError: print("execute test suite first to generate the local_config.py file") sys.exit() class testcase_transaction(unittest.TestCase): """Test scard API for SCardBegin/EndTransaction""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEqual(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEqual(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEqual(hresult, 0) def _transaction(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ) self.assertEqual(hresult, 0) try: hresult = SCardBeginTransaction(hcard) self.assertEqual(hresult, 0) hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEqual(hresult, 0) self.assertEqual(reader, expectedReaders[r]) self.assertEqual(atr, expectedATRs[r]) hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) self.assertEqual(hresult, 0) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEqual(hresult, 0) def test_transaction_reader0(self): testcase_transaction._transaction(self, 0) def test_transaction_reader1(self): testcase_transaction._transaction(self, 1) def test_transaction_reader2(self): testcase_transaction._transaction(self, 2) def test_transaction_reader3(self): testcase_transaction._transaction(self, 3) def suite(): suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(testcase_transaction) return unittest.TestSuite(suite1) if __name__ == "__main__": unittest.main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728854193.0 pyscard-2.2.1/src/smartcard/test/scard/testsuite_scard.py0000755000076500000240000000317714703034261023366 0ustar00rousseaustaff#! /usr/bin/env python3 """Unit test suite for scard python module. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import unittest # so that we can locate configcheck sys.path += [".."] import configcheck def suite(): """suite""" modules_to_test = ( "testcase_getatr", "testcase_getattrib", "testcase_geterrormessage", "testcase_listcards", "testcase_locatecards", "testcase_readergroups", "testcase_returncodes", "testcase_transaction", ) testsuite_scard = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_scard.addTest(unittest.TestLoader().loadTestsFromModule(module)) return testsuite_scard if __name__ == "__main__": configcheck.checklocalconfig() unittest.main(defaultTest="suite", verbosity=1) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/ulist.py0000644000076500000240000000747614677317744017275 0ustar00rousseaustaff"""ulist is a subclass of list where items cannot appear twice in the list. [1,2,2,3,3,4] is a valid list, whereas in ulist we can only have [1,2,3,4]. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class ulist(list): """ulist ensures that all items are unique and provides an __onadditem__ hook to perform custom action in subclasses.""" # # override list methods # def __init__(self, initlist=None): if initlist is not None and initlist != []: list.__init__(self, [initlist[0]]) for item in initlist[1:]: if not list.__contains__(self, item): list.append(self, item) else: list.__init__(self, initlist) def __add__(self, other): newother = self.__remove_duplicates(other) self.__appendother__(newother) return self.__class__(list(self) + list(newother)) def __iadd__(self, other): newother = self.__remove_duplicates(other) self.__appendother__(newother) list.__iadd__(self, newother) return self def __radd__(self, other): newother = self.__remove_duplicates(other) return list.__add__(self, newother) def append(self, item): if not list.__contains__(self, item): list.append(self, item) self.__onadditem__(item) def insert(self, i, item): if not list.__contains__(self, item): list.insert(self, i, item) self.__onadditem__(item) def pop(self, i=-1): item = list.pop(self, i) self.__onremoveitem__(item) return item def remove(self, item): list.remove(self, item) self.__onremoveitem__(item) # # non list methods # def __remove_duplicates(self, _other): """Remove from other items already in list.""" if ( not isinstance(_other, type(self)) and not isinstance(_other, type(list)) and not isinstance(_other, list) ): other = [_other] else: other = list(_other) # remove items already in self newother = [] for i in range(0, len(other)): item = other.pop(0) if not list.__contains__(self, item): newother.append(item) # remove duplicate items in other other = [] if newother != []: other.append(newother[0]) for i in range(1, len(newother)): item = newother.pop() if not other.__contains__(item): other.append(item) return other def __appendother__(self, other): """Append other to object.""" for item in other: self.__onadditem__(item) def __onadditem__(self, item): """Called for each item added. Override in subclasses for adding custom action.""" pass def __onremoveitem__(self, item): """Called for each item removed. Override in subclasses for adding custom action.""" pass ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6798263 pyscard-2.2.1/src/smartcard/util/0000755000076500000240000000000014740753203016503 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/util/__init__.py0000644000076500000240000002064614677317744020643 0ustar00rousseaustaff"""smartcard.util package __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ from __future__ import annotations import warnings PACK = 1 HEX = 2 UPPERCASE = 4 COMMA = 8 def padd(bytelist: list[int], length: int, padding: str = "FF"): """Padds a byte list with a constant byte value (default is x0FF) @param bytelist: the byte list to padd @param length: the total length of the resulting byte list; no padding if length is smaller than the byte list length @param padding: padding value (default is 0xff) @return: the padded bytelist >>> padd([59, 101, 0, 0, 156, 17, 1, 1, 3], 16) [59, 101, 0, 0, 156, 17, 1, 1, 3, 255, 255, 255, 255, 255, 255, 255] >>> padd([59, 101, 0, 0, 156, 17, 1, 1, 3], 12, '80') [59, 101, 0, 0, 156, 17, 1, 1, 3, 128, 128, 128] >>> padd([59, 101, 0, 0, 156, 17, 1, 1, 3], 8) [59, 101, 0, 0, 156, 17, 1, 1, 3] """ return bytelist + [int(padding, 16)] * (length - len(bytelist)) def toASCIIBytes(stringtoconvert: str) -> list[int]: """Convert a string to a list of UTF-8 encoded bytes. @param stringtoconvert: the string to convert into a byte list @return: a byte list of the ASCII codes of the string characters L{toASCIIBytes()} is the reverse of L{toASCIIString()} >>> toASCIIBytes("Number 101") [78, 117, 109, 98, 101, 114, 32, 49, 48, 49] """ return list(stringtoconvert.encode("utf-8")) def toASCIIString(bytelist: list[int]) -> str: """Convert a list of integers in the range ``[32, 127]`` to a string. Integer values outside the range ``[32, 127]`` are replaced with a period. @param bytelist: list of ASCII bytes to convert into a string @return: a string from the ASCII code list L{toASCIIString()} is the reverse of L{toASCIIBytes()} >>> toASCIIString([0x4E,0x75,0x6D,0x62,0x65,0x72,0x20,0x31,0x30,0x31]) 'Number 101' >>> toASCIIString([0x01, 0x20, 0x80, 0x7E, 0xF0]) ". .~." """ return "".join(chr(c) if 32 <= c <= 127 else "." for c in bytelist) def toBytes(bytestring: str) -> list[int]: """Convert a string of hexadecimal characters to a list of integers. @param bytestring: a byte string >>> toBytes("3B 65 00 00 9C 11 01 01 03") [59, 101, 0, 0, 156, 17, 1, 1, 3] >>> toBytes("3B6500009C11010103") [59, 101, 0, 0, 156, 17, 1, 1, 3] >>> toBytes("3B6500 009C1101 0103") [59, 101, 0, 0, 156, 17, 1, 1, 3] """ try: return list(bytes.fromhex(bytestring)) except ValueError: raise TypeError("not a string representing a list of bytes") """GSM3.38 character conversion table.""" __dic_GSM_3_38__ = { "@": 0x00, # @ At symbol "£": 0x01, # £ Britain pound symbol "$": 0x02, # $ Dollar symbol "¥": 0x03, # ¥ Yen symbol "è": 0x04, # è e accent grave "é": 0x05, # é e accent aigu "ù": 0x06, # ù u accent grave "ì": 0x07, # ì i accent grave "ò": 0x08, # ò o accent grave "Ç": 0x09, # Ç C majuscule cedille "\n": 0x0A, # LF Line Feed "Ø": 0x0B, # Ø O majuscule barré "ø": 0x0C, # ø o minuscule barré "\r": 0x0D, # CR Carriage Return "Å": 0x0E, # Å Angstroem majuscule "å": 0x0F, # å Angstroem minuscule "Δ": 0x10, # Δ Greek letter delta "_": 0x11, # underscore "Φ": 0x12, # Φ Greek letter phi "Γ": 0x13, # Γ Greek letter gamma "Λ": 0x14, # Λ Greek letter lambda "Ω": 0x15, # Ω Greek letter omega "Π": 0x16, # Π Greek letter pi "Ψ": 0x17, # Ψ Greek letter psi "Σ": 0x18, # Σ Greek letter sigma "Θ": 0x19, # Θ Greek letter theta "Ξ": 0x1A, # Ξ Greek letter xi # 0x1B maps to extension table "Æ": 0x1C, # Æ majuscule ae "æ": 0x1D, # æ minuscule ae "ß": 0x1E, # ß s dur allemand "É": 0x1F, # É majuscule é " ": 0x20, "!": 0x21, '"': 0x22, # guillemet "#": 0x23, "¤": 0x24, # ¤ carré # # 0x25 ... 0x3F # % ... ? # "¡": 0x40, # ¡ point d'exclamation renversé # # 0x41 ... 0x5A # A ... Z # "Ä": 0x5B, # Ä majuscule A trema "Ö": 0x5C, # Ö majuscule O trema "Ñ": 0x5D, # Ñ majuscule N tilde espagnol "Ü": 0x5E, # Ü majuscule U trema "§": 0x5F, # § signe paragraphe "¿": 0x60, # ¿ point interrogation renversé # # 0x61 ... 0x7A # a ... z # "ä": 0x7B, # ä minuscule a trema "ö": 0x7C, # ö minuscule o trema "ñ": 0x7D, # ñ minuscule n tilde espagnol "ü": 0x7E, # ü minuscule u trema "à": 0x7F, # à a accent grave } def toGSM3_38Bytes(stringtoconvert: str | bytes) -> list[int]: """Returns a list of bytes from a string using GSM 3.38 conversion table. @param stringtoconvert: string to convert @return: a list of bytes >>> toGSM3_38Bytes("@ùPascal") [0, 6, 80, 97, 115, 99, 97, 108] """ if isinstance(stringtoconvert, bytes): stringtoconvert = stringtoconvert.decode("iso8859-1") result = [] for char in stringtoconvert: if ("%" <= char <= "?") or ("A" <= char <= "Z") or ("a" <= char <= "z"): result.append(ord(char)) else: result.append(__dic_GSM_3_38__[char]) return result def toHexString(data: list[int] | None = None, format: int = 0) -> str: """Convert a list of integers to a formatted string of hexadecimal. Integers larger than 255 will be truncated to two-byte hexadecimal pairs. @param data: a list of bytes to stringify, e.g. [59, 22, 148, 32, 2, 1, 0, 0, 13] @param format: a logical OR of - COMMA: add a comma between bytes - HEX: add the 0x chars before bytes - UPPERCASE: use 0X before bytes (need HEX) - PACK: remove blanks >>> vals = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] >>> toHexString(vals) '3B 65 00 00 9C 11 01 01 03' >>> toHexString(vals, COMMA) '3B, 65, 00, 00, 9C, 11, 01, 01, 03' >>> toHexString(vals, HEX) '0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03' >>> toHexString(vals, HEX | COMMA) '0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03' >>> toHexString(vals, PACK) '3B6500009C11010103' >>> toHexString(vals, HEX | UPPERCASE) '0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03' >>> toHexString(vals, HEX | UPPERCASE | COMMA) '0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03' """ if not (data is None or isinstance(data, list)): raise TypeError("not a list of bytes") if not data: return "" pformat = "%-0.2X" separator = "" if COMMA & format: separator = "," if not PACK & format: separator += " " if HEX & format: if UPPERCASE & format: pformat = "0X" + pformat else: pformat = "0x" + pformat return separator.join(pformat % (a & 0xFF) for a in data).rstrip() def HexListToBinString(hexlist: list[int]) -> str: """Deprecated. Use `bytes(hexlist).decode("utf-8")` or similar. >>> HexListToBinString([78, 117, 109, 98, 101, 114, 32, 49, 48, 49]) 'Number 101' """ warnings.warn( 'Use `bytes(hexlist).decode("utf-8")` or similar.', DeprecationWarning, ) return bytes(hexlist).decode("utf-8") def BinStringToHexList(binstring: str) -> list[int]: """Deprecated. Use `list(binstring.encode("utf-8"))` or similar. >>> BinStringToHexList("Number 101") [78, 117, 109, 98, 101, 114, 32, 49, 48, 49] """ warnings.warn( 'Use `list(binstring.encode("utf-8"))` or similar.', DeprecationWarning, ) return list(binstring.encode("utf-8")) hl2bs = HexListToBinString bs2hl = BinStringToHexList ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6849668 pyscard-2.2.1/src/smartcard/wx/0000755000076500000240000000000014740753203016164 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/APDUHexValidator.py0000644000076500000240000000401014677317744021614 0ustar00rousseaustaff""" A wxValidator that matches APDU in hexadecimal such as:: A4 A0 00 00 02 A4A0000002 __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import re import string import wx # a regexp to match ATRs and APDUs hexbyte = "[0-9a-fA-F]{1,2}" apduregexp = re.compile("((%s)[ ]*)*" % hexbyte) class APDUHexValidator(wx.PyValidator): """A wxValidator that matches APDU in hexadecimal such as: A4 A0 00 00 02 A4A0000002""" def __init__(self): wx.Validator.__init__(self) self.Bind(wx.EVT_CHAR, self.OnChar) def Clone(self): return APDUHexValidator() def Validate(self, win): tc = self.GetWindow() value = tc.GetValue() if not apduregexp.match(value): return False return True def OnChar(self, event): key = event.GetKeyCode() if wx.WXK_SPACE == key or chr(key) in string.hexdigits: value = event.GetEventObject().GetValue() + chr(key) if apduregexp.match(value): event.Skip() return if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: event.Skip() return if not wx.Validator.IsSilent(): wx.Bell() return ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/APDUTracerPanel.py0000644000076500000240000000524014677317744021430 0ustar00rousseaustaff"""Graphical APDU Tracer. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # wxPython GUI modules (https://www.wxpython.org/) import wx from smartcard.CardConnectionObserver import CardConnectionObserver from smartcard.util import toHexString [ wxID_APDUTEXTCTRL, ] = [wx.NewId() for x in range(1)] class APDUTracerPanel(wx.Panel, CardConnectionObserver): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) boxsizer = wx.BoxSizer(wx.HORIZONTAL) self.apdutextctrl = wx.TextCtrl( self, wxID_APDUTEXTCTRL, "", pos=wx.DefaultPosition, style=wx.TE_MULTILINE | wx.TE_READONLY, ) boxsizer.Add(self.apdutextctrl, 1, wx.EXPAND | wx.ALL, 5) self.SetSizer(boxsizer) self.SetAutoLayout(True) self.Bind(wx.EVT_TEXT_MAXLEN, self.OnMaxLength, self.apdutextctrl) def OnMaxLength(self, evt): """Reset text buffer when max length is reached.""" self.apdutextctrl.SetValue("") evt.Skip() def update(self, cardconnection, ccevent): """CardConnectionObserver callback.""" apduline = "" if "connect" == ccevent.type: apduline += "connecting to " + cardconnection.getReader() elif "disconnect" == ccevent.type: apduline += "disconnecting from " + cardconnection.getReader() elif "command" == ccevent.type: apduline += "> " + toHexString(ccevent.args[0]) elif "response" == ccevent.type: if [] == ccevent.args[0]: apduline += "< %-2X %-2X" % tuple(ccevent.args[-2:]) else: apduline += ( "< " + toHexString(ccevent.args[0]) + "%-2X %-2X" % tuple(ccevent.args[-2:]) ) self.apdutextctrl.AppendText(apduline + "\n") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/CardAndReaderTreePanel.py0000644000076500000240000003630314677317744023001 0ustar00rousseaustaff"""wxPython panel display cards/readers as a TreeCtrl. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # smartcard imports from threading import RLock # wxPython GUI modules (https://www.wxpython.org/) import wx import smartcard.wx.SimpleSCardApp from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.Exceptions import CardConnectionException, NoCardException from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver from smartcard.util import toHexString from smartcard.wx import ICO_READER, ICO_SMARTCARD class BaseCardTreeCtrl(wx.TreeCtrl): """Base class for the smart card and reader tree controls.""" def __init__( self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None, ): """Constructor. Initializes a smartcard or reader tree control.""" wx.TreeCtrl.__init__( self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS ) self.clientpanel = clientpanel self.parent = parent isz = (16, 16) il = wx.ImageList(isz[0], isz[1]) self.capindex = il.Add( wx.ArtProvider.GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, isz) ) self.fldrindex = il.Add( wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz) ) self.fldropenindex = il.Add( wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz) ) if None != ICO_SMARTCARD: self.cardimageindex = il.Add(wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO)) if None != ICO_READER: self.readerimageindex = il.Add(wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO)) self.il = il self.SetImageList(self.il) def Repaint(self): self.Refresh() class CardTreeCtrl(BaseCardTreeCtrl): """The CardTreeCtrl monitors inserted cards and notifies the application client dialog of any card activation.""" def __init__( self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None, ): """Constructor. Create a smartcard tree control.""" BaseCardTreeCtrl.__init__( self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel ) self.root = self.AddRoot("Smartcards") self.SetItemData(self.root, None) self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) self.Expand(self.root) def OnAddCards(self, addedcards): """Called when a card is inserted. Adds a smart card to the smartcards tree.""" parentnode = self.root for cardtoadd in addedcards: childCard = self.AppendItem(parentnode, toHexString(cardtoadd.atr)) self.SetItemText(childCard, toHexString(cardtoadd.atr)) self.SetItemData(childCard, cardtoadd) self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Normal) self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Expanded) self.Expand(childCard) self.Expand(self.root) self.EnsureVisible(self.root) self.Repaint() def OnRemoveCards(self, removedcards): """Called when a card is removed. Removes a card from the tree.""" parentnode = self.root for cardtoremove in removedcards: (childCard, cookie) = self.GetFirstChild(parentnode) while childCard.IsOk(): if self.GetItemText(childCard) == toHexString(cardtoremove.atr): self.Delete(childCard) (childCard, cookie) = self.GetNextChild(parentnode, cookie) self.Expand(self.root) self.EnsureVisible(self.root) self.Repaint() class ReaderTreeCtrl(BaseCardTreeCtrl): """The ReaderTreeCtrl monitors inserted cards and readers and notifies the application client dialog of any card activation.""" def __init__( self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None, ): """Constructor. Create a reader tree control.""" BaseCardTreeCtrl.__init__( self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel ) self.mutex = RLock() self.root = self.AddRoot("Smartcard Readers") self.SetItemData(self.root, None) self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) self.Expand(self.root) def AddATR(self, readernode, atr): """Add an ATR to a reader node.""" capchild = self.AppendItem(readernode, atr) self.SetItemData(capchild, None) self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Normal) self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Expanded) self.Expand(capchild) return capchild def GetATR(self, reader): """Return the ATR of the card inserted into the reader.""" atr = "no card inserted" try: if not type(reader) is str: connection = reader.createConnection() connection.connect() atr = toHexString(connection.getATR()) connection.disconnect() except NoCardException: pass except CardConnectionException: pass return atr def OnAddCards(self, addedcards): """Called when a card is inserted. Adds the smart card child to the reader node.""" self.mutex.acquire() try: parentnode = self.root for cardtoadd in addedcards: (childReader, cookie) = self.GetFirstChild(parentnode) found = False while childReader.IsOk() and not found: if self.GetItemText(childReader) == str(cardtoadd.reader): (childCard, cookie2) = self.GetFirstChild(childReader) self.SetItemText(childCard, toHexString(cardtoadd.atr)) self.SetItemData(childCard, cardtoadd) found = True else: (childReader, cookie) = self.GetNextChild(parentnode, cookie) # reader was not found, add reader node # this happens when card monitoring thread signals # added cards before reader monitoring thread signals # added readers if not found: childReader = self.AppendItem(parentnode, str(cardtoadd.reader)) self.SetItemData(childReader, cardtoadd.reader) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Normal ) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Expanded ) childCard = self.AddATR(childReader, toHexString(cardtoadd.atr)) self.SetItemData(childCard, cardtoadd) self.Expand(childReader) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnAddReaders(self, addedreaders): """Called when a reader is inserted. Adds the smart card reader to the smartcard readers tree.""" self.mutex.acquire() try: parentnode = self.root for readertoadd in addedreaders: # is the reader already here? found = False (childReader, cookie) = self.GetFirstChild(parentnode) while childReader.IsOk() and not found: if self.GetItemText(childReader) == str(readertoadd): found = True else: (childReader, cookie) = self.GetNextChild(parentnode, cookie) if not found: childReader = self.AppendItem(parentnode, str(readertoadd)) self.SetItemData(childReader, readertoadd) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Normal ) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Expanded ) self.AddATR(childReader, self.GetATR(readertoadd)) self.Expand(childReader) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnRemoveCards(self, removedcards): """Called when a card is removed. Removes the card from the tree.""" self.mutex.acquire() try: parentnode = self.root for cardtoremove in removedcards: (childReader, cookie) = self.GetFirstChild(parentnode) found = False while childReader.IsOk() and not found: if self.GetItemText(childReader) == str(cardtoremove.reader): (childCard, cookie2) = self.GetFirstChild(childReader) self.SetItemText(childCard, "no card inserted") found = True else: (childReader, cookie) = self.GetNextChild(parentnode, cookie) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnRemoveReaders(self, removedreaders): """Called when a reader is removed. Removes the reader from the smartcard readers tree.""" self.mutex.acquire() try: parentnode = self.root for readertoremove in removedreaders: (childReader, cookie) = self.GetFirstChild(parentnode) while childReader.IsOk(): if self.GetItemText(childReader) == str(readertoremove): self.Delete(childReader) else: (childReader, cookie) = self.GetNextChild(parentnode, cookie) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() class CardAndReaderTreePanel(wx.Panel): """Panel containing the smart card and reader tree controls.""" class _CardObserver(CardObserver): """Inner CardObserver. Gets notified of card insertion removal by the CardMonitor.""" def __init__(self, cardtreectrl): self.cardtreectrl = cardtreectrl def update(self, observable, handlers): """CardObserver callback that is notified when cards are added or removed.""" addedcards, removedcards = handlers self.cardtreectrl.OnRemoveCards(removedcards) self.cardtreectrl.OnAddCards(addedcards) class _ReaderObserver(ReaderObserver): """Inner ReaderObserver. Gets notified of reader insertion/removal by the ReaderMonitor.""" def __init__(self, readertreectrl): self.readertreectrl = readertreectrl def update(self, observable, handlers): """ReaderObserver callback that is notified when readers are added or removed.""" addedreaders, removedreaders = handlers self.readertreectrl.OnRemoveReaders(removedreaders) self.readertreectrl.OnAddReaders(addedreaders) def __init__(self, parent, appstyle, clientpanel): """Constructor. Create a smartcard and reader tree control on the left-hand side of the application main frame. @param parent: the tree panel parent @param appstyle: a combination of the following styles (bitwise or |) - TR_SMARTCARD: display a smartcard tree panel - TR_READER: display a reader tree panel - default is TR_DEFAULT = TR_SMARTCARD @param clientpanel: the client panel to notify of smartcard and reader events """ wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) sizer = wx.BoxSizer(wx.VERTICAL) # create the smartcard tree if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: self.cardtreectrl = CardTreeCtrl(self, clientpanel=clientpanel) # create the smartcard insertion observer self.cardtreecardobserver = self._CardObserver(self.cardtreectrl) # register as a CardObserver; we will ge # notified of added/removed cards self.cardmonitor = CardMonitor() self.cardmonitor.addObserver(self.cardtreecardobserver) sizer.Add(self.cardtreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) # create the reader tree if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: self.readertreectrl = ReaderTreeCtrl(self, clientpanel=clientpanel) # create the reader insertion observer self.readertreereaderobserver = self._ReaderObserver(self.readertreectrl) # register as a ReaderObserver; we will ge # notified of added/removed readers self.readermonitor = ReaderMonitor() self.readermonitor.addObserver(self.readertreereaderobserver) # create the smartcard insertion observer self.readertreecardobserver = self._CardObserver(self.readertreectrl) # register as a CardObserver; we will get # notified of added/removed cards self.cardmonitor = CardMonitor() self.cardmonitor.addObserver(self.readertreecardobserver) sizer.Add(self.readertreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) self.SetSizer(sizer) self.SetAutoLayout(True) def OnDestroy(self, event): """Called on panel destruction.""" # deregister observers if hasattr(self, "cardmonitor"): self.cardmonitor.deleteObserver(self.cardtreecardobserver) if hasattr(self, "readermonitor"): self.readermonitor.deleteObserver(self.readertreereaderobserver) self.cardmonitor.deleteObserver(self.readertreecardobserver) event.Skip() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/ReaderToolbar.py0000644000076500000240000000704714677317744021312 0ustar00rousseaustaff"""wxPython toolbar with reader icons implementing ReaderObserver. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import wx from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver from smartcard.wx import ICO_READER, ICO_SMARTCARD class ReaderComboBox(wx.ComboBox, ReaderObserver): def __init__(self, parent): """Constructor. Registers as ReaderObserver to get notifications of reader insertion/removal.""" wx.ComboBox.__init__( self, parent, wx.NewId(), size=(170, -1), style=wx.CB_DROPDOWN | wx.CB_SORT, choices=[], ) # register as a ReaderObserver; we will get # notified of added/removed readers self.readermonitor = ReaderMonitor() self.readermonitor.addObserver(self) def update(self, observable, handlers): """Toolbar ReaderObserver callback that is notified when readers are added or removed.""" addedreaders, removedreaders = handlers for reader in addedreaders: item = self.Append(str(reader)) self.SetClientData(item, reader) for reader in removedreaders: item = self.FindString(str(reader)) if wx.NOT_FOUND != item: self.Delete(item) selection = self.GetSelection() # if wx.NOT_FOUND == selection: # self.SetSelection(0) class ReaderToolbar(wx.ToolBar): """ReaderToolbar. Contains controls to select a reader from a listbox and connect to the cards.""" def __init__(self, parent): """Constructor, creating the reader toolbar.""" wx.ToolBar.__init__( self, parent, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SIMPLE_BORDER | wx.TB_HORIZONTAL | wx.TB_FLAT | wx.TB_TEXT, name="Reader Toolbar", ) # create bitmaps for toolbar tsize = (16, 16) if None != ICO_READER: bmpReader = wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO) else: bmpReader = wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, tsize) if None != ICO_SMARTCARD: bmpCard = wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO) else: bmpCard = wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, tsize) self.readercombobox = ReaderComboBox(self) # create and add controls self.AddSimpleTool( 10, bmpReader, "Select smart card reader", "Select smart card reader" ) self.AddControl(self.readercombobox) self.AddSeparator() self.AddSimpleTool(20, bmpCard, "Connect to smartcard", "Connect to smart card") self.AddSeparator() self.Realize() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/SimpleSCardApp.py0000644000076500000240000000606314677317744021371 0ustar00rousseaustaff"""Simple wxPython wxApp for smartcard. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import wx from smartcard.wx.SimpleSCardAppFrame import SimpleSCardAppFrame TR_SMARTCARD = 0x001 TR_READER = 0x002 TB_SMARTCARD = 0x004 TB_READER = 0x008 PANEL_APDUTRACER = 0x010 TR_DEFAULT = TR_SMARTCARD class SimpleSCardApp(wx.App): """The SimpleSCardApp class represents the smart card application. SimpleSCardApp is a subclass of wx.App. """ def __init__( self, appname="", apppanel=None, appstyle=TR_DEFAULT, appicon=None, pos=(-1, -1), size=(-1, -1), ): r"""Constructor for simple smart card application. @param appname: the application name @param apppanel: the application panel to display in the application frame @param appicon: the application icon file; the default is no icon @param appstyle: a combination of the following styles (bitwise or |) - TR_SMARTCARD: display a smartcard tree panel - TR_READER: display a reader tree panel - TB_SMARTCARD: display a smartcard toolbar - TB_SMARTCARD: display a reader toolbar - PANEL_APDUTRACER: display an APDU tracer panel - default is TR_DEFAULT = TR_SMARTCARD @param pos: the application position as a (x,y) tuple; default is (-1,-1) @param size: the application window size as a (x,y) tuple; default is (-1,-1) Example: C{app = SimpleSCardApp( appname = 'A simple smartcard application', apppanel = testpanel.MyPanel, appstyle = TR_READER | TR_SMARTCARD, appicon = 'resources\mysmartcard.ico')} """ self.appname = appname self.apppanel = apppanel self.appstyle = appstyle self.appicon = appicon self.pos = pos self.size = size wx.App.__init__(self, False) def OnInit(self): """Create and display application frame.""" self.frame = SimpleSCardAppFrame( self.appname, self.apppanel, self.appstyle, self.appicon, self.pos, self.size, ) self.frame.Show(True) self.SetTopWindow(self.frame) return True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/SimpleSCardAppEventObserver.py0000644000076500000240000000412614677317744024101 0ustar00rousseaustaff"""Smartcard event observer. __author__ = "gemalto https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ class SimpleSCardAppEventObserver: """This interface defines the event handlers called by the SimpleSCardApp.""" def __init__(self): self.selectedcard = None self.selectedreader = None # callbacks from SimpleCardAppFrame controls def OnActivateCard(self, card): """Called when a card is activated in the reader tree control or toolbar.""" self.selectedcard = card def OnActivateReader(self, reader): """Called when a reader is activated in the reader tree control or toolbar.""" self.selectedreader = reader def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" pass def OnDeselectCard(self, card): """Called when a card is selected in the reader tree control or toolbar.""" self.selectedcard = None def OnSelectCard(self, card): """Called when a card is selected in the reader tree control or toolbar.""" self.selectedcard = card def OnSelectReader(self, reader): """Called when a reader is selected in the reader tree control or toolbar.""" self.selectedreader = reader ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/SimpleSCardAppFrame.py0000644000076500000240000003123714677317744022345 0ustar00rousseaustaff"""Simple wxpython frame for smart card application. __author__ = "gemalto https://www.gemalto.com/" __date__ = "November 2006" __version__ = "1.4.0" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os.path import wx import smartcard import smartcard.wx from smartcard.wx import APDUTracerPanel, CardAndReaderTreePanel, ReaderToolbar from smartcard.wx.SimpleSCardAppEventObserver import SimpleSCardAppEventObserver [ wxID_SIMPLESCARDAPP_FRAME, ] = [wx.NewId() for x in range(1)] class BlankPanel(wx.Panel, SimpleSCardAppEventObserver): """A blank panel in case no panel is provided to SimpleSCardApp.""" def __init__(self, parent): wx.Panel.__init__(self, parent, -1) sizer = wx.GridSizer(1, 1, 0) self.SetSizer(sizer) self.SetAutoLayout(True) class TreeAndUserPanelPanel(wx.Panel): """The panel that contains the Card/Reader TreeCtrl and the user provided Panel.""" def __init__(self, parent, apppanelclass, appstyle): """ Constructor. Creates the panel with two panels: - the left-hand panel is holding the smartcard and/or reader tree - the right-hand panel is holding the application dialog @param apppanelclass: the class of the panel to instantiate in the L{SimpleSCardAppFrame} @param appstyle: a combination of the following styles (bitwise or |) - TR_SMARTCARD: display a smartcard tree panel - TR_READER: display a reader tree panel - TB_SMARTCARD: display a smartcard toolbar - TB_SMARTCARD: display a reader toolbar - default is TR_DEFAULT = TR_SMARTCARD """ wx.Panel.__init__(self, parent, -1) self.parent = parent self.selectedcard = None boxsizer = wx.BoxSizer(wx.HORIZONTAL) # create user dialog if None != apppanelclass: self.dialogpanel = apppanelclass(self) else: self.dialogpanel = BlankPanel(self) # create card/reader tree control if ( appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD or appstyle & smartcard.wx.SimpleSCardApp.TR_READER ): self.readertreepanel = CardAndReaderTreePanel.CardAndReaderTreePanel( self, appstyle, self.dialogpanel ) boxsizer.Add(self.readertreepanel, 1, wx.EXPAND | wx.ALL, 5) boxsizer.Add(self.dialogpanel, 2, wx.EXPAND | wx.ALL) if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateReader, self.readertreepanel.readertreectrl, ) self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectReader, self.readertreepanel.readertreectrl, ) self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnReaderRightClick, self.readertreepanel.readertreectrl, ) self.Bind( wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.readertreepanel.readertreectrl, ) if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateCard, self.readertreepanel.cardtreectrl, ) self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectCard, self.readertreepanel.cardtreectrl, ) self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnCardRightClick, self.readertreepanel.cardtreectrl, ) self.SetSizer(boxsizer) self.SetAutoLayout(True) def ActivateCard(self, card): """Activate a card.""" if not hasattr(card, "connection"): card.connection = card.createConnection() if None != self.parent.apdutracerpanel: card.connection.addObserver(self.parent.apdutracerpanel) card.connection.connect() self.dialogpanel.OnActivateCard(card) def DeactivateCard(self, card): """Deactivate a card.""" if hasattr(card, "connection"): card.connection.disconnect() if None != self.parent.apdutracerpanel: card.connection.deleteObserver(self.parent.apdutracerpanel) delattr(card, "connection") self.dialogpanel.OnDeactivateCard(card) def OnActivateCard(self, event): """Called when the user activates a card in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.ActivateCard(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) def OnActivateReader(self, event): """Called when the user activates a reader in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.ActivateCard(itemdata) elif isinstance(itemdata, smartcard.reader.Reader.Reader): self.dialogpanel.OnActivateReader(itemdata) event.Skip() def OnItemCollapsed(self, event): item = event.GetItem() self.readertreepanel.readertreectrl.Expand(item) def OnCardRightClick(self, event): """Called when user right-clicks a node in the card tree control.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.selectedcard = itemdata if not hasattr(self, "connectID"): self.connectID = wx.NewId() self.disconnectID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID) self.Bind(wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID) menu = wx.Menu() if not hasattr(self.selectedcard, "connection"): menu.Append(self.connectID, "Connect") else: menu.Append(self.disconnectID, "Disconnect") self.PopupMenu(menu) menu.Destroy() def OnReaderRightClick(self, event): """Called when user right-clicks a node in the reader tree control.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.selectedcard = itemdata if not hasattr(self, "connectID"): self.connectID = wx.NewId() self.disconnectID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID) self.Bind(wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID) menu = wx.Menu() if not hasattr(self.selectedcard, "connection"): menu.Append(self.connectID, "Connect") else: menu.Append(self.disconnectID, "Disconnect") self.PopupMenu(menu) menu.Destroy() def OnConnect(self, event): if isinstance(self.selectedcard, smartcard.Card.Card): self.ActivateCard(self.selectedcard) def OnDisconnect(self, event): if isinstance(self.selectedcard, smartcard.Card.Card): self.DeactivateCard(self.selectedcard) def OnSelectCard(self, event): """Called when the user selects a card in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.dialogpanel.OnSelectCard(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) def OnSelectReader(self, event): """Called when the user selects a reader in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemData(item) if isinstance(itemdata, smartcard.Card.Card): self.dialogpanel.OnSelectCard(itemdata) elif isinstance(itemdata, smartcard.reader.Reader.Reader): self.dialogpanel.OnSelectReader(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) class SimpleSCardAppFrame(wx.Frame): """The main frame of the simple smartcard application.""" def __init__( self, appname, apppanelclass, appstyle, appicon, pos=(-1, -1), size=(-1, -1), ): """ Constructor. Creates the frame with two panels: - the left-hand panel is holding the smartcard and/or reader tree - the right-hand panel is holding the application dialog @param appname: name of the application @param apppanelclass: the class of the panel to instantiate in the L{SimpleSCardAppFrame} @param appstyle: a combination of the following styles (bitwise or |) - TR_SMARTCARD: display a smartcard tree panel - TR_READER: display a reader tree panel - TB_SMARTCARD: display a smartcard toolbar - TB_SMARTCARD: display a reader toolbar - PANEL_APDUTRACER: display an APDU tracer panel - default is TR_DEFAULT = TR_SMARTCARD @param pos: the application position as a (x,y) tuple; default is (-1,-1) @param size: the application window size as a (x,y) tuple; default is (-1,-1) """ wx.Frame.__init__( self, None, wxID_SIMPLESCARDAPP_FRAME, appname, pos=pos, size=size, style=wx.DEFAULT_FRAME_STYLE, ) if appicon: _icon = wx.Icon(appicon, wx.BITMAP_TYPE_ICO) self.SetIcon(_icon) elif os.path.exists(smartcard.wx.ICO_SMARTCARD): _icon = wx.Icon(smartcard.wx.ICO_SMARTCARD, wx.BITMAP_TYPE_ICO) self.SetIcon(_icon) boxsizer = wx.BoxSizer(wx.VERTICAL) self.treeuserpanel = TreeAndUserPanelPanel(self, apppanelclass, appstyle) boxsizer.Add(self.treeuserpanel, 3, wx.EXPAND | wx.ALL) # create a toolbar if required if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD: self.toolbar = ReaderToolbar.ReaderToolbar(self) self.SetToolBar(self.toolbar) else: self.toolbar = None # create an apdu tracer console if required if appstyle & smartcard.wx.SimpleSCardApp.PANEL_APDUTRACER: self.apdutracerpanel = APDUTracerPanel.APDUTracerPanel(self) boxsizer.Add(self.apdutracerpanel, 1, wx.EXPAND | wx.ALL) else: self.apdutracerpanel = None self.SetSizer(boxsizer) self.SetAutoLayout(True) self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD: self.Bind( wx.EVT_COMBOBOX, self.OnReaderComboBox, self.toolbar.readercombobox ) def OnCloseFrame(self, evt): """Called when frame is closed, i.e. on wx.EVT_CLOSE""" evt.Skip() def OnExit(self, evt): """Called when frame application exits.""" self.Close(True) evt.Skip() def OnReaderComboBox(self, event): """Called when the user activates a reader in the toolbar combo box.""" cb = event.GetEventObject() reader = cb.GetClientData(cb.GetSelection()) if isinstance(reader, smartcard.reader.Reader.Reader): self.treeuserpanel.dialogpanel.OnActivateReader(reader) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/src/smartcard/wx/__init__.py0000644000076500000240000000322614677317744020317 0ustar00rousseaustaff"""wxpython smartcard utility module. __author__ = "https://www.gemalto.com/" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com This file is part of pyscard. pyscard is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. pyscard is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyscard; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import os.path import sys def main_is_frozen(): return hasattr(sys, "frozen") or hasattr(sys, "importers") ICO_SMARTCARD = None ICO_READER = None # running from a script, i.e. not running from standalone exe built with py2exe if not main_is_frozen(): ICO_SMARTCARD = os.path.join( os.path.dirname(__file__), "resources", "smartcard.ico" ) ICO_READER = os.path.join(os.path.dirname(__file__), "resources", "reader.ico") # running from a standalone exe built with py2exe # resources expected images directory else: if os.path.exists(os.path.join("images", "smartcard.ico")): ICO_SMARTCARD = os.path.join("images", "smartcard.ico") if os.path.exists(os.path.join("images", "reader.ico")): ICO_READER = os.path.join("images", "reader.ico") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1736693378.6859083 pyscard-2.2.1/src/smartcard/wx/resources/0000755000076500000240000000000014740753203020176 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/wx/resources/reader.ico0000644000076500000240000000047614674316735022156 0ustar00rousseaustaff(( `ff`p38`x p`xppxxppxpxxxxpxpxp @?././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727110621.0 pyscard-2.2.1/src/smartcard/wx/resources/smartcard.ico0000644000076500000240000000047614674316735022674 0ustar00rousseaustaff(( 333s333{wwwwwws{s{swwwwsw{ww{w{swwwws{s{sww{wwws{{././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1736693378.693113 pyscard-2.2.1/test/0000755000076500000240000000000014740753203013736 5ustar00rousseaustaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727888197.0 pyscard-2.2.1/test/conftest.py0000644000076500000240000000040714677275505016153 0ustar00rousseaustaffimport pytest import smartcard.reader.ReaderGroups @pytest.fixture(autouse=True) def reset_reader_groups(): """Reader group instances must be reset at the beginning of each test.""" smartcard.reader.ReaderGroups.readergroups.instance = None yield ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729456542.0 pyscard-2.2.1/test/test_ATR.py0000644000076500000240000003015114705264636016005 0ustar00rousseaustaffimport re import textwrap import pytest from smartcard.ATR import ATR from smartcard.Exceptions import SmartcardException from smartcard.util import toBytes def test_atr1(capsys): atr = [0x3F, 0x65, 0x25, 0x00, 0x2C, 0x09, 0x69, 0x90, 0x00] data_out = textwrap.dedent( """\ TB1: 25 TC1: 0 supported protocols T=0 T=0 supported: True T=1 supported: False \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 50 \tprogramming voltage: 30 \tguard time: 0 nb of interface bytes: 2 nb of historical bytes: 5 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out def test_atr2(capsys): atr = [0x3F, 0x65, 0x25, 0x08, 0x93, 0x04, 0x6C, 0x90, 0x00] data_out = textwrap.dedent( """\ TB1: 25 TC1: 8 supported protocols T=0 T=0 supported: True T=1 supported: False \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 50 \tprogramming voltage: 30 \tguard time: 8 nb of interface bytes: 2 nb of historical bytes: 5 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out def test_atr3(capsys): atr = [0x3B, 0x16, 0x94, 0x7C, 0x03, 0x01, 0x00, 0x00, 0x0D] data_out = textwrap.dedent( """\ TA1: 94 supported protocols T=0 T=0 supported: True T=1 supported: False \tclock rate conversion factor: 512 \tbit rate adjustment factor: 8 \tmaximum programming current: 50 \tprogramming voltage: 5 \tguard time: None nb of interface bytes: 1 nb of historical bytes: 6 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out def test_atr4(capsys): atr = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] data_out = textwrap.dedent( """\ TB1: 0 TC1: 0 supported protocols T=0 T=0 supported: True T=1 supported: False \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 25 \tprogramming voltage: 5 \tguard time: 0 nb of interface bytes: 2 nb of historical bytes: 5 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out def test_atr5(capsys): atr = [0x3B, 0xE3, 0x00, 0xFF, 0x81, 0x31, 0x52, 0x45, 0xA1, 0xA2, 0xA3, 0x1B] data_out = textwrap.dedent( """\ TB1: 0 TC1: ff TD1: 81 TD2: 31 TA3: 52 TB3: 45 supported protocols T=1 T=0 supported: False T=1 supported: True checksum: 27 \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 25 \tprogramming voltage: 5 \tguard time: 255 nb of interface bytes: 6 nb of historical bytes: 3 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out def test_atr6(capsys): atr = [0x3B, 0xE5, 0x00, 0x00, 0x81, 0x21, 0x45, 0x9C, 0x10, 0x01, 0x00, 0x80, 0x0D] data_out = textwrap.dedent( """\ TB1: 0 TC1: 0 TD1: 81 TD2: 21 TB3: 45 supported protocols T=1 T=0 supported: False T=1 supported: True checksum: 13 \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 25 \tprogramming voltage: 5 \tguard time: 0 nb of interface bytes: 5 nb of historical bytes: 5 """ ) a = ATR(atr) with pytest.warns(DeprecationWarning, match=re.escape("print(ATR.render())")): a.dump() stdout, _ = capsys.readouterr() assert stdout == data_out @pytest.mark.parametrize( "ts", ( pytest.param("0x42", id="numeric"), pytest.param("0xaa", id="lowercase"), pytest.param("0x00", id="zero padding"), ), ) def test_invalid_ts(ts: str): atr = [int(ts[2:], 16), 0x00] with pytest.raises(SmartcardException, match=f"invalid TS {ts}"): ATR(atr) def test_atr_get(): atr = "3B F2 95 12 34 01 36 06" a = ATR(toBytes(atr)) assert a.getTA1() == 0x95 assert a.getTB1() == 0x12 assert a.getTC1() == 0x34 assert a.getTD1() == 0x01 assert a.getHistoricalBytes(), [0x36 == 0x06] assert a.isT15Supported() is False assert str(a) == atr @pytest.mark.parametrize( "field, expected_length", ( ("clockrateconversion", 16), ("bitratefactor", 16), ), ) def test_map_lengths(field, expected_length): """Verify ATR class fields have expected lengths. This doesn't validate values, but simply ensures the lengths match expectations. """ assert len(getattr(ATR, field)) == expected_length @pytest.mark.parametrize( "atr,", ( pytest.param([], id="ATR is too short (0 bytes)"), pytest.param([0x3B], id="ATR is too short (1 byte, valid TS)"), ), ) def test_invalid_atr_lengths(atr: list[int]): """Verify that short ATRs raise exceptions.""" with pytest.raises(SmartcardException, match="at least 2 bytes"): ATR(atr) @pytest.mark.parametrize("ts", (0x3B, 0x3F)) def test_2_bytes(ts): """Verify that a completely empty ATR parses well.""" atr = ATR([ts, 0b0000_0000]) # |||| `-- no historical bytes # |||`-- no TA # ||`-- no TB # |`-- no TC # `-- no TD assert atr.getTA1() is None assert atr.getTB1() is None assert atr.II is None assert atr.PI1 is None assert atr.getTC1() is None assert atr.getTD1() is None assert atr.getChecksum() is None assert atr.getGuardTime() is None assert atr.getHistoricalBytesCount() == 0 assert atr.getHistoricalBytes() == [] assert atr.getInterfaceBytesCount() == 0 # Default values assert atr.getBitRateFactor() == 1 assert atr.getClockRateConversion() == 372 assert atr.getProgrammingCurrent() == 50 assert atr.getProgrammingVoltage() == 5 # Protocols assert len(atr.getSupportedProtocols()) == 1 assert "T=0" in atr.getSupportedProtocols() assert atr.isT0Supported() is True assert atr.isT1Supported() is False assert atr.isT15Supported() is False # Rendering expected_rendering = textwrap.dedent( """\ supported protocols T=0 T=0 supported: True T=1 supported: False \tclock rate conversion factor: 372 \tbit rate adjustment factor: 1 \tmaximum programming current: 50 \tprogramming voltage: 5 \tguard time: None nb of interface bytes: 0 nb of historical bytes: 0 """.rstrip() ) assert atr.render() == expected_rendering # Warnings with pytest.warns(DeprecationWarning, match="ATR.TA"): assert atr.hasTA == [False] with pytest.warns(DeprecationWarning, match="ATR.TB"): assert atr.hasTB == [False] with pytest.warns(DeprecationWarning, match="ATR.TC"): assert atr.hasTC == [False] with pytest.warns(DeprecationWarning, match="ATR.TD"): assert atr.hasTD == [False] def test_only_ta1(): """Verify that TA1 can be conveyed standalone.""" atr = ATR([0x3B, 0b0001_0000, 0xA7]) # `-- only enable TA assert atr.TA == [0xA7] assert "TA1: a7\n" in atr.render() with pytest.warns(DeprecationWarning, match="ATR.TA"): assert atr.hasTA == [True] # TA1 affects these values assert atr.getClockRateConversion() == 768 assert atr.getBitRateFactor() == 64 # Sanity check assert atr.TB == atr.TC == atr.TD == [None] assert atr.N is None assert atr.getInterfaceBytesCount() == 1 assert atr.getHistoricalBytesCount() == 0 assert atr.hasChecksum is False assert atr.checksumOK is None assert atr.getChecksum() is None def test_only_tb1(): """Verify that TB1 can be conveyed standalone. TB1 and TB2 are deprecated in ISO 7816-3 2006, so no values are checked here. """ atr = ATR([0x3B, 0b0010_0000, 0b0_10_11111]) # `-- only enable TB assert atr.TB == [0b0_10_11111] assert "TB1: 5f\n" in atr.render() with pytest.warns(DeprecationWarning, match="ATR.TB"): assert atr.hasTB == [True] # TB1 affects these values assert atr.II == 0b10 assert atr.PI1 == 0b11111 assert atr.getProgrammingVoltage() != 5 assert atr.getProgrammingCurrent() != 50 # Sanity check assert atr.TA == atr.TC == atr.TD == [None] assert atr.N is None assert atr.getInterfaceBytesCount() == 1 assert atr.getHistoricalBytesCount() == 0 assert atr.hasChecksum is False assert atr.checksumOK is None assert atr.getChecksum() is None def test_only_tc1(): """Verify that TC1 can be conveyed standalone.""" atr = ATR([0x3B, 0b0100_0000, 0xC1]) # `-- only enable TC assert atr.TC == [0xC1] assert "TC1: c1\n" in atr.render() with pytest.warns(DeprecationWarning, match="ATR.TC"): assert atr.hasTC == [True] # TC1 affects these values assert atr.N == 0xC1 # Sanity check assert atr.TA == atr.TB == atr.TD == [None] assert atr.getInterfaceBytesCount() == 1 assert atr.getHistoricalBytesCount() == 0 assert atr.hasChecksum is False assert atr.checksumOK is None assert atr.getChecksum() is None def test_only_td1(): """Verify that TD1 can be conveyed standalone.""" atr = ATR([0x3B, 0b1000_0000, 0x00]) # `-- only enable TD assert atr.TD == [0x00, None] assert atr.isT0Supported() is True assert atr.isT1Supported() is False assert atr.isT15Supported() is False assert "TD1: 0\n" in atr.render() with pytest.warns(DeprecationWarning, match="ATR.TD"): assert atr.hasTD == [True, False] # Sanity check assert atr.TA == atr.TB == atr.TC == [None, None] assert atr.N is None assert atr.getHistoricalBytesCount() == 0 assert atr.hasChecksum is False assert atr.checksumOK is None assert atr.getChecksum() is None def test_historical_bytes(): """Verify that historical bytes can be conveyed standalone.""" atr = ATR([0x3B, 0x0F, *list(range(15))]) # `-- indicate 15 historical bytes assert atr.K == 15 assert atr.getHistoricalBytesCount() == 15 assert atr.getHistoricalBytes() == list(range(15)) # Sanity check assert atr.TA == atr.TB == atr.TC == atr.TD == [None] assert atr.N is None assert atr.hasChecksum is False assert atr.checksumOK is None assert atr.getChecksum() is None @pytest.mark.parametrize("ts", (0x3B, 0x3F)) @pytest.mark.parametrize("atr_bytes", ([0x00, 0x00], [0x1, 0xFE, 0xFF])) def test_valid_checksums(ts, atr_bytes): """Verify behavior of valid checksums.""" atr = ATR([ts] + atr_bytes) assert atr.hasChecksum is True assert atr.checksumOK is True assert atr.getChecksum() == atr_bytes[-1] assert f"checksum: {atr_bytes[-1]}\n" in atr.render() @pytest.mark.parametrize("ts", (0x3B, 0x3F)) @pytest.mark.parametrize("atr_bytes", ([0x00, 0x01], [0x01, 0xFE, 0x0])) def test_invalid_checksums(ts, atr_bytes): """Verify behavior of invalid checksums.""" atr = ATR([ts] + atr_bytes) assert atr.hasChecksum is True assert atr.checksumOK is False assert atr.getChecksum() == atr_bytes[-1] assert f"checksum: {atr_bytes[-1]:x}\n" in atr.render() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727637539.0 pyscard-2.2.1/test/test_Exceptions.py0000644000076500000240000001072214676324043017476 0ustar00rousseaustaffimport platform import pytest from smartcard.Exceptions import * from smartcard.scard import * def test_hresult_value(): exc = SmartcardException() assert exc.hresult == -1 def test_list_readers_exception(): exc = ListReadersException(-1) assert str(exc) == "Failed to list readers" exc = ListReadersException(0) assert exc.hresult == 0 text = str(exc) if platform.system() == "Windows": expected = ( "Failed to list readers: " "The operation completed successfully. (0x00000000)" ) else: expected = "Failed to list readers: Command successful. (0x00000000)" assert text == expected exc = ListReadersException(0x42) assert exc.hresult == 0x42 text = str(exc) if platform.system() != "Windows": expected = "Failed to list readers: Unknown error: 0x00000042 (0x00000042)" macos_bug_expected = expected.replace("Unknown", "Unkown") assert text in (expected, macos_bug_expected) exc = ListReadersException(SCARD_S_SUCCESS) assert exc.hresult == 0 exc = ListReadersException(SCARD_E_NO_SERVICE) assert exc.hresult == SCARD_E_NO_SERVICE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to list readers: " "The Smart Card Resource Manager is not running. (0x8010001D)" ) else: expected = "Failed to list readers: Service not available. (0x8010001D)" assert text == expected exc = ListReadersException(SCARD_E_NOT_TRANSACTED) if platform.system() == "Windows": expected = ( "Failed to list readers: " "An attempt was made to end a non-existent transaction. (0x80100016)" ) else: expected = "Failed to list readers: Transaction failed. (0x80100016)" assert str(exc) == expected def test_no_readers_exception(): exc = NoReadersException() assert exc.hresult == -1 text = str(exc) assert text == "No reader found" def test_invalid_reader_exception(): exc = InvalidReaderException("foobar") assert exc.hresult == -1 text = str(exc) assert text == "Invalid reader: foobar" def test_card_connection_exception(): exc = CardConnectionException() assert exc.hresult == -1 text = str(exc) assert text == "" exc = CardConnectionException("foo", SCARD_W_REMOVED_CARD) assert exc.hresult == SCARD_W_REMOVED_CARD text = str(exc) if platform.system() == "Windows": expected = ( "foo: The smart card has been removed, " "so that further communication is not possible. (0x80100069)" ) else: expected = "foo: Card was removed. (0x80100069)" assert text == expected def test_hresult(): hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult == SCARD_S_SUCCESS: hresult, _, _ = SCardConnect( hcontext, "INVALID READER NAME", SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY ) assert hresult == SCARD_E_UNKNOWN_READER else: assert hresult == SCARD_E_NO_SERVICE @pytest.mark.parametrize("arg", ([0], "foo")) def test_wrong_type(arg): # SCardEstablishContext() argument should be int with pytest.raises(TypeError): SCardEstablishContext(arg) def test_card_request_timeout_exception(): exc = CardRequestTimeoutException() assert str(exc) == "Time-out during card request" exc = CardRequestTimeoutException(SCARD_E_NOT_TRANSACTED) if platform.system() == "Windows": expected = ( "Time-out during card request: " "An attempt was made to end a non-existent transaction. (0x80100016)" ) else: expected = "Time-out during card request: Transaction failed. (0x80100016)" assert str(exc) == expected exc = CardRequestTimeoutException(hresult=SCARD_E_NOT_TRANSACTED) assert str(exc) == expected def test_invalid_atr_mask_length_exception(): exc = InvalidATRMaskLengthException("3B 00") assert str(exc) == "Invalid ATR mask length: 3B 00" def test_no_card_exception(): exc = NoCardException("foo bar", -1) assert str(exc) == "foo bar" exc = NoCardException("foo bar", SCARD_E_NOT_TRANSACTED) if platform.system() == "Windows": expected = ( "foo bar: " "An attempt was made to end a non-existent transaction. (0x80100016)" ) else: expected = "foo bar: Transaction failed. (0x80100016)" assert str(exc) == expected ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727637539.0 pyscard-2.2.1/test/test_PCSC.py0000644000076500000240000000101514676324043016100 0ustar00rousseaustafffrom smartcard.scard import * def test_low_level(): hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) assert hresult in (SCARD_S_SUCCESS, SCARD_E_NO_SERVICE) if hresult == SCARD_E_NO_SERVICE: return hresult, _ = SCardListReaders(hcontext, []) assert hresult in (SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE) # the computer we are using may not have a reader connected # so we can't do much hresult = SCardReleaseContext(hcontext) assert hresult == SCARD_S_SUCCESS ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727637539.0 pyscard-2.2.1/test/test_PCSCExceptions.py0000644000076500000240000001225614676324043020153 0ustar00rousseaustaffimport platform from smartcard.pcsc.PCSCExceptions import * from smartcard.scard import * def test_list_readers_exception(): exc = ListReadersException(0) assert exc.hresult == 0 text = str(exc) if platform.system() == "Windows": expected = ( "Failed to list readers: " "The operation completed successfully. (0x00000000)" ) else: expected = "Failed to list readers: Command successful. (0x00000000)" assert text == expected exc = ListReadersException(0x42) assert exc.hresult == 0x42 text = str(exc) if platform.system() == "Windows": expected = ( "Failed to list readers: " "The network resource type is not correct. (0x00000042)" ) else: expected = "Failed to list readers: Unknown error: 0x00000042 (0x00000042)" macos_bug_expected = expected.replace("Unknown", "Unkown") assert text in (expected, macos_bug_expected) exc = ListReadersException(SCARD_S_SUCCESS) assert exc.hresult == 0 exc = ListReadersException(SCARD_E_NO_SERVICE) assert exc.hresult == SCARD_E_NO_SERVICE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to list readers: " "The Smart Card Resource Manager is not running. (0x8010001D)" ) else: expected = "Failed to list readers: Service not available. (0x8010001D)" assert text == expected def test_establish_context_exception(): exc = EstablishContextException(SCARD_E_NO_SERVICE) assert exc.hresult == SCARD_E_NO_SERVICE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to establish context: " "The Smart Card Resource Manager is not running. (0x8010001D)" ) else: expected = "Failed to establish context: Service not available. (0x8010001D)" assert text == expected def test_introduce_reader_exception(): exc = IntroduceReaderException(SCARD_E_DUPLICATE_READER, "foobar") assert exc.hresult == SCARD_E_DUPLICATE_READER text = str(exc) if platform.system() == "Windows": expected = ( "Failed to introduce a new reader: foobar: " "The reader driver did not produce a unique reader name. (0x8010001B)" ) else: expected = ( "Failed to introduce a new reader: foobar: " "Reader already exists. (0x8010001B)" ) assert text == expected def test_remove_reader_from_group_exception(): exc = RemoveReaderFromGroupException( SCARD_E_INVALID_HANDLE, "readername", "readergroup" ) assert exc.hresult == SCARD_E_INVALID_HANDLE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to remove reader: readername from group: readergroup: " "The supplied handle was invalid. (0x80100003)" ) else: expected = ( "Failed to remove reader: readername from group: readergroup: " "Invalid handle. (0x80100003)" ) assert text == expected def test_add_reader_to_group_exception(): exc = AddReaderToGroupException(SCARD_E_INVALID_HANDLE, "reader", "group") assert exc.hresult == SCARD_E_INVALID_HANDLE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to add reader: reader to group: group: " "The supplied handle was invalid. (0x80100003)" ) else: expected = ( "Failed to add reader: reader to group: group: " "Invalid handle. (0x80100003)" ) assert text == expected def test_release_context_exception(): exc = ReleaseContextException(SCARD_E_INVALID_HANDLE) assert exc.hresult == SCARD_E_INVALID_HANDLE text = str(exc) if platform.system() == "Windows": expected = ( "Failed to release context: The supplied handle was invalid. (0x80100003)" ) else: expected = "Failed to release context: Invalid handle. (0x80100003)" assert text == expected def test_base_scard_exception(): exc = BaseSCardException(SCARD_E_UNKNOWN_READER) assert exc.hresult == SCARD_E_UNKNOWN_READER text = str(exc) if platform.system() == "Windows": expected = ( "scard exception: " "The specified reader name is not recognized. (0x80100009)" ) else: expected = "scard exception: Unknown reader specified. (0x80100009)" assert text == expected exc = BaseSCardException(hresult=-1) assert exc.hresult == -1 text = str(exc) expected = "scard exception" assert text == expected exc = BaseSCardException(hresult=-1, message="foo bar") assert exc.hresult == -1 text = str(exc) expected = "foo bar" assert text == expected exc = BaseSCardException(message="foo", hresult=SCARD_E_NOT_TRANSACTED) assert exc.hresult == SCARD_E_NOT_TRANSACTED text = str(exc) if platform.system() == "Windows": expected = "An attempt was made to end a non-existent transaction. " else: expected = "Transaction failed." expected = "foo: " + expected + " (0x80100016)" assert text == expected ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727637539.0 pyscard-2.2.1/test/test_SCardGetErrorMessage.py0000644000076500000240000000134114676324043021325 0ustar00rousseaustaffimport platform from smartcard.scard import ( SCARD_F_INTERNAL_ERROR, SCARD_S_SUCCESS, SCardGetErrorMessage, ) def test_scard_get_error_message(): res = SCardGetErrorMessage(SCARD_S_SUCCESS) # do not test on Windows # the error messages are different and localized if platform.system() == "Windows": return expected = "Command successful." assert res == expected res = SCardGetErrorMessage(SCARD_F_INTERNAL_ERROR) expected = "Internal error." assert res == expected res = SCardGetErrorMessage(1) expected = "Unknown error: 0x00000001" # macOS bug not yet fixed macos_bug_expected = "Unkown error: 0x00000001" assert res in (expected, macos_bug_expected) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727897572.0 pyscard-2.2.1/test/test_guid.py0000644000076500000240000000077614677317744016330 0ustar00rousseaustafffrom smartcard.guid import GUIDToStr, strToGUID def test_roundtrip_string(): string = "{AD4F1667-EA75-4124-84D4-641B3B197C65}" assert GUIDToStr(strToGUID(string)) == string def test_roundtrip_list_of_ints(): list_of_ints = [ 103, 22, 79, 173, 117, 234, 36, 65, 132, 212, 100, 27, 59, 25, 124, 101, ] assert strToGUID(GUIDToStr(list_of_ints)) == list_of_ints ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1729025142.0 pyscard-2.2.1/test/test_observer.py0000644000076500000240000001233414703552166017205 0ustar00rousseaustaffimport unittest.mock import pytest import smartcard.Observer def test_state_changes(): """Verify that the "changed" state can be set and cleared.""" # Base state observable = smartcard.Observer.Observable() assert not observable.hasChanged(), "Observable must not start in a changed state" # Set observable.setChanged() assert observable.hasChanged(), ".setChanged() must *set* the state" observable.setChanged() assert observable.hasChanged(), ".setChanged() must not *toggle* the state" # Clear observable.clearChanged() assert not observable.hasChanged(), ".clearChanged() must *clear* the state" observable.clearChanged() assert not observable.hasChanged(), ".clearChanged() must not *toggle* the state" @pytest.mark.parametrize( "unbound_method", ( # Observer management methods smartcard.Observer.Observable.addObserver, smartcard.Observer.Observable.countObservers, smartcard.Observer.Observable.deleteObserver, smartcard.Observer.Observable.deleteObservers, smartcard.Observer.Observable.notifyObservers, # State management methods smartcard.Observer.Observable.clearChanged, smartcard.Observer.Observable.hasChanged, smartcard.Observer.Observable.setChanged, ), ) def test_synchronization(unbound_method): """Verify that all Observable methods are synchronized. The `.mutex` attribute is mocked and is confirmed to be acquired and released. The test implementation here doesn't necessarily make valid method calls; it relies on the knowledge that most Observable methods are decorated and that the lock is acquired before the underlying method is called (and thus, before Python realizes that required method parameters are unfilled and raises a TypeError). """ mutex = unittest.mock.MagicMock() # Ensure the context manager protocol is functional. mutex.__enter__.return_value = mutex observable = smartcard.Observer.Observable() observable.mutex = mutex try: # Call the unbound Observable method, passing *observable* as `self`. unbound_method(observable) # noqa except TypeError: # Ignore TypeErrors caused by missing mandatory method arguments. pass mutex.__enter__.assert_called_once() mutex.__exit__.assert_called_once() def test_registered_observers_are_always_notified(): """Verify all observers are notified, even if the observer list changes.""" class JealousObserver(smartcard.Observer.Observer): update_count = 0 def update(self, observable, _): # Try to prevent all other observers from receiving an update. for other_observer in observers - {self}: try: observable.deleteObserver(other_observer) except ValueError: pass # Track the number of times an update was received. JealousObserver.update_count += 1 jealous_observer_count = 10 observers = {JealousObserver() for _ in range(jealous_observer_count)} # Create a fair observable and notify the observers of a change. fair_observable = smartcard.Observer.Observable() [fair_observable.addObserver(observer) for observer in observers] fair_observable.setChanged() fair_observable.notifyObservers() # Confirm that the observers have all erased each other from the list of observers. assert fair_observable.countObservers() == 0 # Confirm that the observers were all updated, despite their jealous efforts. assert JealousObserver.update_count == jealous_observer_count def test_double_observer_additions(): """Verify that an observer cannot be added twice.""" observer = smartcard.Observer.Observer() observable = smartcard.Observer.Observable() observable.addObserver(observer) observable.addObserver(observer) assert observable.countObservers() == 1 def test_double_observer_removals(): """Verify that an observer cannot be removed twice.""" observer = smartcard.Observer.Observer() observable = smartcard.Observer.Observable() observable.addObserver(observer) observable.deleteObserver(observer) with pytest.raises(ValueError, match="x not in list"): observable.deleteObserver(observer) def test_no_notifications_when_no_changes(): """Verify that no notifications are sent when no changes are detected.""" class Observer(smartcard.Observer.Observer): def update(self, *_, **__): raise RuntimeError("no updates were expected") observable = smartcard.Observer.Observable() observable.addObserver(Observer()) # Attempt to send a notification when no changes have been made. # Nothing needs to be asserted here; # the lack of a RuntimeError during test execution demonstrates the test passed. observable.notifyObservers() def test_default_observer_updates(): """Call the default Observer.update() method. This test exists solely for the purposes of reaching 100% test coverage. It can be removed if Observer becomes an abstract base class. """ observable = smartcard.Observer.Observable() assert smartcard.Observer.Observer().update(observable, "arg") is None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727888197.0 pyscard-2.2.1/test/test_readergroups.py0000644000076500000240000000633214677275505020072 0ustar00rousseaustaffimport pytest import smartcard.reader.ReaderGroups import smartcard.ulist def test_reader_groups_acts_like_a_singleton(): """Verify that the target class *acts* like a singleton.""" instance_1 = smartcard.reader.ReaderGroups.readergroups() instance_2 = smartcard.reader.ReaderGroups.readergroups() assert instance_1.instance is instance_2.instance def test_reader_groups_method_calls(): reader_group = smartcard.reader.ReaderGroups.readergroups() assert len(reader_group.instance) == 0, "No reader groups should be pre-defined" list.append(reader_group.instance, "a") assert len(reader_group.instance) == 1, "Unable to add a reader group" reader_group.addreadergroup("a") assert len(reader_group.instance) == 1, "Reader groups must be unique" with pytest.raises(smartcard.reader.ReaderGroups.BadReaderGroupException): reader_group.addreadergroup(1) with pytest.raises(smartcard.reader.ReaderGroups.BadReaderGroupException): reader_group.removereadergroup(1) # .__iter__() assert len(list(reader_group.instance)) == 1 # No-op calls reader_group.addreadertogroup("no-op", "bogus") reader_group.removereaderfromgroup("no-op", "bogus") # ------------------------------------------------------------------------------------ # The tests below this line demonstrate serious behavioral problems with readergroups. @pytest.mark.xfail(reason="readergroups is not actually a singleton", strict=True) def test_reader_groups_is_a_singleton(): """Verify that readergroups is a singleton.""" instance_1 = smartcard.reader.ReaderGroups.readergroups() instance_2 = smartcard.reader.ReaderGroups.readergroups() assert instance_1 is instance_2 @pytest.mark.xfail(reason="initlist parameters may be silently ignored", strict=True) def test_demonstrate_initlist_values_may_be_silently_ignored(): """Demonstrate that `initlist` parameters may be silently ignored.""" smartcard.reader.ReaderGroups.readergroups(["a"]) reader_group = smartcard.reader.ReaderGroups.readergroups(["b"]) assert "b" in reader_group.instance def test_demonstrate_adding_is_impossible(): """Demonstrate that `.addreadergroup()` cannot be called.""" reader_group = smartcard.reader.ReaderGroups.readergroups() with pytest.raises(RecursionError, match="maximum recursion depth exceeded"): reader_group.addreadergroup("a") def test_demonstrate_removing_is_impossible(): """Demonstrate that `.removereadergroup()` cannot be called. `.removereadergroup()` recurses twice. It successfully removes the value, then fails to find it the second time. """ reader_group = smartcard.reader.ReaderGroups.readergroups() list.append(reader_group.instance, "a") assert reader_group.instance == ["a"] with pytest.raises(ValueError, match="x not in list"): reader_group.removereadergroup("a") assert reader_group.instance == [] def test_demonstrate_getting_is_impossible(): """Demonstrate that `.getreadergroups()` returns hard-coded values.""" reader_group = smartcard.reader.ReaderGroups.readergroups() list.append(reader_group.instance, "a") assert reader_group.instance == ["a"] assert reader_group.getreadergroups() == [] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1728938524.0 pyscard-2.2.1/test/test_synchronization.py0000644000076500000240000000625614703301034020607 0ustar00rousseaustafffrom __future__ import annotations import pytest import smartcard.Synchronization @pytest.mark.parametrize( "defined_methods, names, modified_methods", ( # Nothing should be wrapped (str version) pytest.param(set(), "", set(), id="wrap nothing (str)"), pytest.param({"a"}, "", set(), id="wrap nothing (a, str)"), pytest.param({"a", "b"}, "", set(), id="wrap nothing (a+b, str)"), # Nothing should be wrapped (iterable version) pytest.param(set(), [], set(), id="wrap nothing (list)"), pytest.param({"a"}, [], set(), id="wrap nothing (a, list)"), pytest.param({"a", "b"}, [], set(), id="wrap nothing (a+b, list)"), # Everything should be wrapped pytest.param(set(), None, set(), id="wrap all"), pytest.param({"a"}, None, {"a"}, id="wrap all (a)"), pytest.param({"a", "b"}, None, {"a", "b"}, id="wrap all (a+b)"), # Only "a" should be wrapped (str version) pytest.param({"a"}, "a", {"a"}, id="wrap a only (a, str)"), pytest.param({"a", "b"}, "a", {"a"}, id="wrap a only (a+b, str)"), # Only "a" should be wrapped (list version) pytest.param({"a"}, ["a"], {"a"}, id="wrap a only (a, list)"), pytest.param({"a", "b"}, ["a"], {"a"}, id="wrap a only (a+b, list)"), ), ) def test_synchronize( defined_methods: set[str], names: None | str | list[str], modified_methods: set[str], ): """Verify synchronize() wraps class methods as expected.""" method_map = {method: lambda self: None for method in defined_methods} class_ = type("A", (object,), method_map) smartcard.Synchronization.synchronize(class_, names) for modified_method in modified_methods: assert getattr(class_, modified_method) is not method_map[modified_method] for unmodified_method in defined_methods - modified_methods: assert getattr(class_, unmodified_method) is method_map[unmodified_method] def test_synchronization_reentrant_lock(): """Verify Synchronization mutex locks are re-entrant by default.""" class A(smartcard.Synchronization.Synchronization): def level_1(self): self.level_2() def level_2(self): return self smartcard.Synchronization.synchronize(A) instance = A() # If the synchronization lock is NOT re-entrant by default, # the test suite will hang when it reaches this line. instance.level_1() def test_synchronization_wrapping(): """Verify synchronized functions have correct names and docstrings.""" class A(smartcard.Synchronization.Synchronization): def apple(self): """KEEP ME""" smartcard.Synchronization.synchronize(A) assert A.apple.__name__ == "apple" assert "KEEP ME" in A.apple.__doc__ def test_synchronization_kwargs(): """Verify synchronized functions support arguments and keyword arguments.""" class A(smartcard.Synchronization.Synchronization): def positional_only(self, positional, /): return positional def keyword_only(self, *, keyword): return keyword smartcard.Synchronization.synchronize(A) A().positional_only(True) A().keyword_only(keyword=True) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727886541.0 pyscard-2.2.1/test/test_ulist.py0000644000076500000240000000542214677272315016523 0ustar00rousseaustaffimport pytest import smartcard.ulist def test_demonstrate_ulist_cannot_be_instantiated(): """ulist() cannot be instantiated without an argument.""" with pytest.raises(TypeError, match="'NoneType' object is not iterable"): smartcard.ulist.ulist() @pytest.mark.xfail(reason="order should be ['x', 1, 2] not [1, 2, 'x']", strict=True) def test_demonstrate_order_is_not_respected(): """Order is not strictly respected.""" instance = smartcard.ulist.ulist([1, 2]) new_instance = ["x"] + instance assert new_instance == ["x", 1, 2] @pytest.mark.xfail(reason="not all list methods are overwritten", strict=True) def test_demonstrate_non_unique_behavior(): """ulist.extend() breaks uniqueness guarantees.""" instance = smartcard.ulist.ulist([1, 2]) instance.extend([1, 2, 3]) assert instance == [1, 2] # actually, it's [1, 2, 1, 2, 3] def test_ulist_methods(): """This broadly tests the ulist implementation. It can be removed when ulist is removed. """ smartcard.ulist.ulist([]) smartcard.ulist.ulist([1]) smartcard.ulist.ulist([1, 1]) instance = smartcard.ulist.ulist([1]) original_id = id(instance) assert instance assert len(instance) == 1 assert instance == [1] assert id(instance) == original_id instance.append(1) assert instance assert len(instance) == 1 assert instance == [1] assert id(instance) == original_id instance.append(2) assert instance assert len(instance) == 2 assert instance == [1, 2] assert id(instance) == original_id new_instance = instance + [3] assert new_instance is not instance assert new_instance == [1, 2, 3] assert instance == [1, 2] assert id(instance) == original_id new_instance = instance + [1, 2] assert new_instance is not instance assert new_instance == [1, 2] assert instance == [1, 2] assert id(instance) == original_id new_instance = [1, 2] + instance assert new_instance is not instance assert new_instance == [1, 2] assert instance == [1, 2] assert id(instance) == original_id instance += 2 assert instance == [1, 2] assert id(instance) == original_id instance.insert(0, 0) assert len(instance) == 3 assert instance == [0, 1, 2] instance.insert(10_000, 0) assert len(instance) == 3 assert instance == [0, 1, 2] value = instance.pop() assert value == 2 assert instance == [0, 1] value = instance.pop(0) assert value == 0 assert instance == [1] instance.pop() instance.append(0) instance.remove(0) with pytest.raises(ValueError): instance.remove(0) my_pristine_list = [0, 1, 2, 0, 1, 2, 0, 1, 2] instance += my_pristine_list assert my_pristine_list == [0, 1, 2, 0, 1, 2, 0, 1, 2] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1727637539.0 pyscard-2.2.1/test/test_util.py0000644000076500000240000001070014676324043016326 0ustar00rousseaustaffimport pytest from smartcard.util import * def test_to_bytes(): data_in = "3B 65 00 00 9C 11 01 01 03" data_out = [59, 101, 0, 0, 156, 17, 1, 1, 3] assert toBytes(data_in) == data_out data_in = "3B6500009C11010103" assert toBytes(data_in) == data_out data_in = "3B6500 009C1101 0103" assert toBytes(data_in) == data_out data_in = """ 3B 65 00 00 9C 11 01 01 03 """ assert toBytes(data_in) == data_out data_in = "zz" with pytest.raises(TypeError): toBytes(data_in) def test_padd(): data_in = toBytes("3B 65 00 00 9C 11 01 01 03") old_data_in = list(data_in) data_out = [ 0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] assert padd(data_in, 16) == data_out assert data_in == old_data_in assert padd(data_in, 4) == data_in def test_to_ascii_bytes(): data_in = "Number 101" data_out = [0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31] assert toASCIIBytes(data_in) == data_out def test_to_ascii_string(): data_in = [0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31] data_out = "Number 101" assert toASCIIString(data_in) == data_out data_in = [0x01, 0x20, 0x80, 0x7E, 0xF0] data_out = ". .~." assert toASCIIString(data_in) == data_out def test_to_gsm3_38_bytes(): data_in = "@Pascal" data_out = [0x00, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C] assert toGSM3_38Bytes(data_in) == data_out data_in = "@ùPascal" data_out = [0x00, 0x06, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C] assert toGSM3_38Bytes(data_in) == data_out data_in = "@ùPascal".encode("iso8859-1") data_out = [0x00, 0x06, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C] assert toGSM3_38Bytes(data_in) == data_out data_in = "1234" data_out = [0x31, 0x32, 0x33, 0x34] assert toGSM3_38Bytes(data_in) == data_out def test_to_hex_string(): data_in = [] data_out = "" assert toHexString(data_in) == data_out data_in = 42 with pytest.raises(TypeError): toHexString(data_in) data_in = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] data_out = "3B 65 00 00 9C 11 01 01 03" assert toHexString(data_in) == data_out data_out = "3B, 65, 00, 00, 9C, 11, 01, 01, 03" assert toHexString(data_in, COMMA) == data_out data_out = "0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03" assert toHexString(data_in, HEX) == data_out data_out = "0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03" assert toHexString(data_in, HEX | COMMA) == data_out data_out = "0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03" assert toHexString(data_in, HEX | UPPERCASE) == data_out data_out = "0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03" assert toHexString(data_in, HEX | UPPERCASE | COMMA) == data_out data_out = "3B6500009C11010103" assert toHexString(data_in, PACK) == data_out data_out = "3B,65,00,00,9C,11,01,01,03" assert toHexString(data_in, COMMA | PACK) == data_out data_out = "0x3B0x650x000x000x9C0x110x010x010x03" assert toHexString(data_in, HEX | PACK) == data_out data_out = "0x3B,0x65,0x00,0x00,0x9C,0x11,0x01,0x01,0x03" assert toHexString(data_in, HEX | COMMA | PACK) == data_out data_out = "0X3B0X650X000X000X9C0X110X010X010X03" assert toHexString(data_in, HEX | UPPERCASE | PACK) == data_out data_out = "0X3B,0X65,0X00,0X00,0X9C,0X11,0X01,0X01,0X03" assert toHexString(data_in, HEX | UPPERCASE | COMMA | PACK) == data_out with pytest.raises(TypeError): toHexString("foo") def test_hex_list_to_bin_string(): data_in = [1, 2, 3] data_out = "\x01\x02\x03" with pytest.warns(DeprecationWarning): assert HexListToBinString(data_in) == data_out def test_bin_string_to_hex_list(): data_in = "\x01\x02\x03" data_out = [1, 2, 3] with pytest.warns(DeprecationWarning): assert BinStringToHexList(data_in) == data_out def test_hl2bs(): data_in = [78, 117, 109, 98, 101, 114, 32, 49, 48, 49] data_out = "Number 101" with pytest.warns(DeprecationWarning): assert hl2bs(data_in) == data_out def test_bs2hl(): data_in = "Number 101" data_out = [78, 117, 109, 98, 101, 114, 32, 49, 48, 49] with pytest.warns(DeprecationWarning): assert bs2hl(data_in) == data_out