Resources release in PySCard

With PySCard version 2.2.2 (New version of PySCard: 2.2.2) it is now possible to release/free the PC/SC context used by some objects.

Sample

As see in PCSC sample in Python a typical PySCard code looks like:

#! /usr/bin/env python

from smartcard.System import readers

# define the APDUs used in this script
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62,
    0x03, 0x01, 0x0C, 0x06, 0x01]
COMMAND = [0x00, 0x00, 0x00, 0x00]

# get all the available readers
r = readers()
print "Available readers:", r

reader = r[0]
print "Using:", reader

connection = reader.createConnection()
connection.connect()

data, sw1, sw2 = connection.transmit(SELECT)
print data
print "Select Applet: %02X %02X" % (sw1, sw2)

data, sw1, sw2 = connection.transmit(COMMAND)
print data
print "Command: %02X %02X" % (sw1, sw2)

You can see that a connection is created with connection = reader.createConnection() and then the card is connected with connection.connect(), but the card is never explicitly disconnected and the connection is never released.

It was already possible to use:

connection.disconnect()

It is now also possible to use:

connection.release()

The code becomes (after convertion to Python 3):

#! /usr/bin/env python

from smartcard.System import readers
from smartcard.util import toASCIIString

# define the APDUs used in this script
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62,
    0x03, 0x01, 0x0C, 0x06, 0x01]
COMMAND = [0x00, 0x00, 0x00, 0x00]

# get all the available readers
r = readers()
print("Available readers:", r)

reader = r[0]
print("Using:", reader)

connection = reader.createConnection()
connection.connect()

data, sw1, sw2 = connection.transmit(SELECT)
print(data)
print(f"Select Applet: {sw1:02X} {sw2:02X}")

data, sw1, sw2 = connection.transmit(COMMAND)
print(data)
print(toASCIIString(data))
print(f"Command: {sw1:02X} {sw2:02X}")

connection.disconnect()
connection.release()

Output

Available readers: ['Gemalto PC Twin Reader']
Using: Gemalto PC Twin Reader
[]
Select Applet: 90 00
[72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]
Hello world!
Command: 90 00

If you do not want to explicitly call .disconnect() and .release() you can use a context manager and the Python with statement.

[...]

with reader.createConnection() as connection:
    connection.connect()

    data, sw1, sw2 = connection.transmit(SELECT)
    print(data)
    print(f"Select Applet: {sw1:02X} {sw2:02X}")

    data, sw1, sw2 = connection.transmit(COMMAND)
    print(data)
    print(toASCIIString(data))
    print(f"Command: {sw1:02X} {sw2:02X}")

Or you can also use the del instruction to call the object finalizer.

del connection

CardRequest

You can also use with with a CardRequest object.

#! /usr/bin/env python

from smartcard.CardRequest import CardRequest

print("Insert a card within 10 seconds")
with CardRequest(timeout=10) as req:
    svc = req.waitforcard()
    svc.connection.connect()
    r = svc.connection.transmit([0,0,0,0])
    print(r)
    svc.connection.disconnect()
    svc.connection.release()

Ouput

Insert a card within 10 seconds
([], 109, 0)

CardService

And also with a CardService object.

#! /usr/bin/env python

from smartcard.CardRequest import CardRequest

print("Insert a card within 10 seconds")
with CardRequest(timeout=10) as req:
    with req.waitforcard() as svc:
        svc.connection.connect()
        r = svc.connection.transmit([0,0,0,0])
        print(r)

Traces

It is possible and easy to trace the actions performed by PySCard using an smartcard.Observer object.

#! /usr/bin/env python

from time import sleep
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver

print("Insert a card within 10 seconds")
with CardRequest(timeout=10) as req:
    with req.waitforcard() as svc:
        observer = ConsoleCardConnectionObserver()
        svc.connection.addObserver(observer)

        svc.connection.connect()
        r = svc.connection.transmit([0,0,0,0])
        print(r)

sleep(10)
print("end")

Ouput

Insert a card within 10 seconds
connecting to Gemalto PC Twin Reader
> 00 00 00 00
<  [] 6D 00
([], 109, 0)
disconnecting from Gemalto PC Twin Reader
release from Gemalto PC Twin Reader
end

You can see that .disconnect() and .release() methods are called and traced.

The traces are displayed 10 seconds before the "end", i.e. when the two with exit, not when the program ends (and the garbage collector is used to clean each object).

Why

The CardConnection().release() method has been added to release the PC/SC context and allow pcscd (the daemon used in pcsc-lite) to exit automatically before the end of the Python program. See the issue PCSCCardConnection.__del__ method raises exceptions that cannot be easily handled in python code. #223 and in particular this comment https://github.com/LudovicRousseau/pyscard/issues/223#issuecomment-2773120282:

pcscd should not auto exit before all the contexts have been released.

Btw this was indeed the other (only loosely related) issue that I mentioned at the end of initial post.

I.e. that using pyscard in a main process or a thread always holds up pcsc-lite running (unless I missed something, iirc with connection management in C code), and there seem to be no way to say "please close the damn context, time to read cards was gone 10 hours ago, and this silly NFC reader eats up 300 milliamps" :)

So would be nice to have a way to cleanly close such context/connection manually (allowing pcsc-lite to exit too, and without purging pyscard from memory with subprocess) for other reasons as well, but again, probably a separate issue.

And I think context != connection, as latter are managed somewhere in C, not in python, but might be wrong or misremembering.

The problem is that the user has a smart card reader that consumes 300 milliamps even when it's doing "nothing".

So it's a good idea to let pcscd exit so that the USB device will be put in low power thanks to the autosuspend Linux feature.

I haven't checked the behavior on macOS or Windows.

Conclusion

Not all users will need or use the .release() method. If your Python program runs for a long time and you only use the smart card at certain times, it may be a good idea to take a look at your code and update it.

New version of PySCard: 2.2.2

I just released a new version of pyscard. PySCard is a Python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

Changes:

2.2.2 (April 2025)

  • add .release() method to CardConnection & PCSCCardRequest

  • add context manager protocol to CardRequest & CardService

  • fix some parallel execution issues

  • PCSCCardRequest: correctly initialize waitforcardevent()

  • user-guide: Update documentation

  • Minor changes

New version of pcsc-lite: 2.3.3

I just released a new version of pcsc-lite 2.3.3.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Polkit rules was broken. So it was no more possible to give access to remote users for example. See pcsc-lite and polkit.

Thanks to Mike Kazantsev for the very nice bug report in PrivateUsers=yes in systemd sandboxing options prevents polkit rules from getting user/group info.

Changes:

2.3.3: Ludovic Rousseau

2 April 2025

  • Make polkit rules work again (bug introduced in 2.3.2)

Ignore readers using PCSCLITE_IGNORE udev property

Version 2.3.2 of pcsc-lite (New version of pcsc-lite: 2.3.2) introduced a new way to ignore a smart card reader.

The patch included in pcsc-lite is from Valtteri Vuorikoski and I will quote his git commit message in this article.

Use case

"This is similar to the existing filtering support provided by PCSCLITE_FILTER_IGNORE_READER_NAMES (Remove and/or customize PC/SC reader names), but allows using the full range of udev rules to match specific devices. For example, if you have several Yubikeys and one is attached to a specific USB port that is being forwarded to a virtual machine (viz. it should not be touched by programs on the host machine), this facility allows setting a rule to keep pcscd away from that Yubikey. Yubikeys attached to other ports keep working normally."

udev

By default pcsc-lite uses libudev to detect readers events (plug or unplug of a USB reader). The idea is to use a flag set by udev to tell pcsc-lite to ignore a reader.

Example rule that targets a Yubikey attached to a specific USB port and causes pcscd to ignore that device:

ACTION!="remove|unbind", SUBSYSTEM=="usb", ATTR{idVendor}=="1050",
ATTR{idProduct}=="0406", KERNEL=="1-2.3", ENV{PCSCLITE_IGNORE}="1"

The KERNEL match targets a USB device attached to port 3 of a hub on port 2 of USB bus 1, and rule sets property PCSCLITE_IGNORE to cause the device to be ignored.

The reader with idVendor=0x1050 and idProduct=0x0406 is the YubiKey FIDO+CCID from Yubico.

Or if you want to ignore any reader connected to USB port 1-3:

ACTION!="remove|unbind", SUBSYSTEM=="usb", KERNEL=="1-3", ENV{PCSCLITE_IGNORE}="1"

You put the above rule is a file /etc/udev/rules.d/foobar.rules and voila.

Config

To know what value for KERNEL= to use you can run udevadm monitor and connect a USB reader. You will get something like:

$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[2022.067560] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
KERNEL[2022.069016] change   /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
KERNEL[2022.069332] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0 (usb)
KERNEL[2022.069416] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.690370] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.695881] change   /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.700310] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0 (usb)
UDEV  [2022.728691] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)

You can see the "1-3" information to use in the .rules file.

Debug

To debug your configuration and check the new field PCSCLITE_IGNORE is correctly set you can use udevadm monitor --property and you get something like:

$ udevadm monitor --property
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[2265.405075] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/001/015
DEVTYPE=usb_device
PRODUCT=8e6/3437/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=015
SEQNUM=4692
MAJOR=189
MINOR=14

[...]

UDEV  [2266.066186] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
ACTION=bind
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/001/015
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=8e6/3437/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=015
SEQNUM=4695
USEC_INITIALIZED=2265405122
ID_BUS=usb
ID_MODEL=USB_SmartCard_Reader
ID_MODEL_ENC=USB\x20SmartCard\x20Reader
ID_MODEL_ID=3437
ID_SERIAL=Gemplus_USB_SmartCard_Reader
ID_VENDOR=Gemplus
ID_VENDOR_ENC=Gemplus
ID_VENDOR_ID=08e6
ID_REVISION=0100
ID_USB_MODEL=USB_SmartCard_Reader
ID_USB_MODEL_ENC=USB\x20SmartCard\x20Reader
ID_USB_MODEL_ID=3437
ID_USB_SERIAL=Gemplus_USB_SmartCard_Reader
ID_USB_VENDOR=Gemplus
ID_USB_VENDOR_ENC=Gemplus
ID_USB_VENDOR_ID=08e6
ID_USB_REVISION=0100
ID_USB_INTERFACES=:0b0000:
ID_VENDOR_FROM_DATABASE=Gemalto (was Gemplus)
ID_MODEL_FROM_DATABASE=GemPC Twin SmartCard Reader
ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:3
ID_PATH=pci-0000:00:14.0-usb-0:3
ID_PATH_TAG=pci-0000_00_14_0-usb-0_3
ID_SMARTCARD_READER=1
ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3
SYSTEMD_WANTS=smartcard.target
SYSTEMD_USER_WANTS=smartcard.target
PCSCLITE_IGNORE=1
MAJOR=189
MINOR=14
TAGS=:uaccess:security-device:seat:systemd:
CURRENT_TAGS=:uaccess:security-device:seat:systemd:

In pcscd logs I get:

04337722 [140613033731776] ../src/hotplug_libudev.c:656:HPEstablishUSBNotifications() USB Device add
00000411 [140613033731776] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x08E6, PID: 0x3437, path: /dev/bus/usb/001/016
00000303 [140613033731776] ../src/hotplug_libudev.c:417:HPAddDevice() Device Gemalto PC Twin Reader at /dev/bus/usb/001/016 (1-3:1.0) has PCSCLITE_IGNORE set: ignored

And I do not see the PC/SC reader with pcsc_scan command:

$ pcsc_scan -r
No reader found.

Conclusion

I am sure you will find other use cases for this new feature.

Thanks to Valtteri Vuorikoski for the patch. If you have ideas of changes or improvements for pcsc-lite do not hesitate to submit them.

New version of pcsc-lite: 2.3.2

I just released a new version of pcsc-lite 2.3.2.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Changes:

2.3.2: Ludovic Rousseau

26 March 2025

  • Hardening systemd pcscd.service file

  • pcscd.service: add missing Requires=polkit.service

  • pcsc-spy: add missing PCSCv2_PART10_PROPERTY_* definitions

  • Support udev PCSCLITE_IGNORE property to filter readers

  • debuglog: force use of colors when --color is used

  • Some other minor improvements

New version of pcsc-tools: 1.7.3

I just released a new version of pcsc-tools, a suite of tools for PC/SC.

Changes:

1.7.3 - 22 March 2025, Ludovic ROUSSEAU

  • 199 new ATRs

  • meson:
    • add Windows support

    • add macOS support

    • add option to set ATRparser

  • minor fixes and improvements

New version of libccid: 1.6.2

I just released version 1.6.2 of libccid the Free Software CCID class smart card reader driver.

Changes:

1.6.2 - 19 March 2025, Ludovic Rousseau

  • Add support of

    • Arculus AuthentiKey

    • BHDC Reader-HHD02

    • CHERRY Smart Terminal 1150

    • HSIC CCID-Reader

    • Ledger Flex

    • SYC USB CCID Reader

    • Thales RF CR2000

    • TOKEN2 FIDO2 Security Key(0026)

  • Give more time to initialize the ACS ACR122U

  • Do not build examples and contrib by default

  • meson: add missing check for pthread_condattr_setclock

  • Don't assume that all notifications are NotifySlotChange

  • Hide unexported functions and variables

  • Some other minor improvements

Results of the blog survey

One month ago I proposed a survey (Survey about my blog: https://blog.apdu.fr/) to know more about you, the readers of my blog https://blog.apdu.fr/.

I now have 42 answers. I think 42 is a good number.

My survey had 4 open questions. Some of you entered very specific and personal information. I will try to not include personal information in the results. But I am very thankful for your confidence and the details you shared with me.

Since how long do you use smart cards?

Since how long do you use smart cards?

#

< 1 year

4

1 to 5 years

7

6 to 10 years

10

11 to 15 years

4

16 to 20 years

5

> 20 years

11

/images/2025/03/survey_1.png

I am surprised to have so many users of smart cards for such a long time.

Maybe I should have been more explicit in my question. I have been using smart cards myself since around 1990 with French public phone cards and bank cards as a normal user. My question was more, since when do you use smart cards as a professional?.

It is interesting to see very experienced smart card users and also all the possible groups of experiences.

Since how long do you read my blog?

Since how long do you read my blog?

#

< 1 year

10

1 to 5 years

8

6 to 10 years

10

11 to 15 years

10

> 16 years

3

/images/2025/03/survey_2.png

This question has a trap. My blog started in 2000, so the oldest article is 15 years old. It is not possible to read it since more than 16 years.

The distribution of results is fairly even.

What is your activity?

What is your activity?

#

%

developer

32

78,0 %

Other

10

24,4 %

project manager

5

12,2 %

sales

1

2,4 %

CEO

1

2,4 %

/images/2025/03/survey_3.png

With no real surprise, the vast majority of my readers are developers. This is not surprising since the majority of the blog content is about programs and programming interfaces.

In the "other" category, we have:

  • sysadmin

  • manufacturer

  • functional and technical expert

  • driver packager

How do you read/find my blog?

How do you read/find my blog?

#

%

Redirected by a search engine

17

41,5 %

Redirected by an email

13

31,7 %

RSS feed

9

22,0 %

Redirected from a web page

9

22,0 %

Other

5

12,2 %

/images/2025/03/survey_4.png

Many readers find the articles using a search engine. I guess it's the normal way to find a solution to a problem or some documentation.

I will continue to include references to my blog articles in the emails I send. I find that writing a blog article is a good way to not write again and again the same thing.

Few readers are using the RSS feed (but see RSS feed for my blog).

In the "other" category, we have:

  • bookmark

  • redirected by a colleague

  • Firefox Update Scanner (maybe the RSS feed could be used instead?)

What content do you like?

What content do you like?

#

%

technical explanation of a new feature

39

95,1 %

new software release announcement

25

61,0 %

how to use a function

21

51,2 %

sample codes

20

48,8 %

macOS issues

17

41,5 %

Windows issues

13

31,7 %

pictures of my holidays

4

9,8 %

/images/2025/03/survey_5.png

No surprise, with a large part of developers, the main interest is in technical explanations and new software announcements.

I am happy to see that few people are looking for content about Windows issues.

Some people are looking for news about my holidays. That is nice, but I do not plan to share many photos here. Great game contest: Where was the picture below taken?

/images/2025/03/DSC_0919.JPG

Free form

Thanks for your answers in the free forms.

What content would you like to find on my blog?

In no specific order:

  • news about pcsc-lite

  • more details about PC/SC and Smartcard

  • sample code and technical explanations

    Yes, of course.

  • more card specific stuff like reading passport information or discussing a bit about EMV processing

    My expertise lies more in PKI cards. I agree that it's interesting to have more details on common cards like EMV, passport or ID cards.

  • chart of specifics/features/bugs between smartcard readers, cards and OS/driver versions

    You can find a list of readers you can't use at Disabled CCID readers and readers you should not use at Unsupported or partly supported CCID readers.

    I have never seen a really bogus smart card.

  • your history with smart cards

    I started in the smart card industry in 1997. At first, it was difficult to use a smart card on a GNU/Linux system. I started by writing a driver for a serial smart card reader, then submitted patches to pcsc-lite and continued developing different smart card related software.

Conclusion

Do not expect posts about my holidays or my life.

I will continue to publish technical articles. If you know about a subject and want to share your knowledge, I am open to co-author articles. If you wrote a Free Software program or library that uses a smart card, I can take a look and write about it.

In any case you can contact me. My e-mail address is available from About me.

RSS feed for my blog

From the Survey about my blog: https://blog.apdu.fr/ I see that the RSS feed is only the 3rd way to read my blog (20% of my readers).

From Wikipedia https://en.wikipedia.org/wiki/RSS:

RSS (RDF Site Summary or Really Simple Syndication) is a web feed that allows users and applications to access updates to websites in a standardized, computer-readable format. Subscribing to RSS feeds can allow a user to keep track of many different websites in a single news aggregator, which constantly monitors sites for new content, removing the need for the user to manually check them. News aggregators (or "RSS readers") can be built into a browser, installed on a desktop computer, or installed on a mobile device.

If you don't want to miss any article from my blog then RSS is a very good solution for that.

The RSS URL is https://blog.apdu.fr/rss.xml and you can get it from the "RSS feed" link in the page header.

/images/2025/01/rss_feed.png

For example I use NewsBlur to read my different RSS feeds either on my desktop browsers or on my smart phone. NewsBlur manages the status of all the articles so I do not see again an article I have already read.

You can also use RSS Parot (Turn Mastodon into your feed reader) if you want to be notified on your Fediverse account (Mastodon for example) of new publications.

Survey about my blog: https://blog.apdu.fr/

I would like to know you, my readers, a bit more.

I prepared a short survey at blog.apdu.fr readers (thanks to Framasoft for the survey/Framaforms service). Please take a few minutes to answer the survey so I can improve the blog.

I plan to keep the survey open for about one month. After that I will publish a summary here. If you want me to keep your answers private please indicate it.

Survey URL: blog.apdu.fr readers

Thanks for your participation.