Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Saturday, September 4, 2010

pcscd auto start

The problem


pcsc-lite is composed of two parts:
  1. a daemon pcscd
  2. The daemon job is to access/send commands to the readers, through reader drivers.
  3. a library libpcsclite.so.1
  4. The library provides the PC/SC API to the application to talk to the pcscd daemon using an internal protocol.

Traditionally the daemon is started when the system starts and is running until the system is shut down.

Using the dependencies relation of packages in modern distributions you may install a package that, in some cases, uses PC/SC and then is linked with libpcsclite and then pcscd is also installed and running all the time for nothing.

The solution


The idea is to start pcscd only when needed. It is possible since the first PC/SC call is always SCardEstablishContext(). So SCardEstablishContext() must check if pcscd is already running and launch it if not.

The implementation details


pcscd exit


It is also possible to exit pcscd when no more client is using it. This is possible since the last PC/SC call is always SCardReleaseContext().

When all the contexts open with SCardEstablishContext() have been closed by SCardReleaseContext() it is possible to exit pcscd. To avoid restarting pcscd just after exiting it, pcscd exits only after 60 seconds of inactivity. It is configurable using:
#define TIME_BEFORE_SUICIDE 60

Reader devices access rights


By default (on GNU/Linux) USB devices are accessible (for write accesses) by root processes only. If pcscd is started during the system start up the process is executed as root so has the correct permissions to access the USB devices. But if now pcscd is started by a process of a normal user it will be started with the access rights of this normal user.

pcscd then needs to gain extra access rights. This is the perfect use of the suid/sgid mechanism. In pcsc-lite 1.6.x (with x < 5) the file /usr/sbin/pcscd was suid root. So the process was running as root. It does work but programs running as root are always "suspicious" for a security aware administrator. And it is even more important if the program is suid root, as it was the case.

To be conform to the principle of least privilege a better approach has been implemented. The access rights of the devices are changed to be accessible in read and write to a process in the group "pcscd", and pcscd is now a sgid program in the group "pcscd". So when pcscd is started by a normal user it will gain access to files in the group "pcscd".

The group "pcscd" should be used only by pcsc-lite so only pcscd has access to smart card readers. The pcscd process has only gained the minimum rights needed to do its job (instead of gaining root access).

udev rule


To change the access rights of a USB devices the solution on a GNU/Linux system is to write a udev rule file.

The CCID driver provides such a udev rule file.

The main part of the file is:
# If not adding the device, go away
ACTION!="add", GOTO="pcscd_ccid_rules_end"
SUBSYSTEM!="usb", GOTO="pcscd_ccid_rules_end"
ENV{DEVTYPE}!="usb_device", GOTO="pcscd_ccid_rules_end"

# generic CCID device
ATTRS{bInterfaceClass}=="0b", RUN+="/bin/chgrp pcscd $root/$parent"

# All done
LABEL="pcscd_ccid_rules_end"

If a device has an interface with the field bInterfaceClass set to 0x0b (11 in decimal) then it is a CCID device according to the CCID specification. In that case run the command chgrp to set the group to pcscd to the parent device.

udev has a GROUP= action to change the group of a device but it looks like I can't use that. The rule matches a field of an interface but GROUP= works when matching a device (the parent of an interface).

Reader driver impacts


The reader drivers have to provide a udev rule to change the group ownership of the device supported by the driver. If they do not the devices will not be accessible unless pcscd is run as root (as before).

For example the ifd-gempc driver will have to provide a udev rule for the 3 USB devices supported.

Something like:
# udev rules to set the access rights of GemPC smart card readers
# so they can be used by pcscd

# If not adding the device, go away
ACTION!="add", GOTO="pcscd_ifd_gempc_rules_end"
SUBSYSTEM!="usb", GOTO="pcscd_ifd_gempc_rules_end"

# GemPC 430, 432 & 435 USB readers
ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="0430", GROUP="pcscd"
ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="0432", GROUP="pcscd"
ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="0435", GROUP="pcscd"

# All done
LABEL="pcscd_ifd_gempc_rules_end"

The file is easy to generate since you just have to reuse the information from the Info.plist file of the driver.

The rule file for the CCID driver is a bit different since I used the fact that CCID devices all have the same USB class (bInterfaceClass).

Security aspects


Possible security vulnerability in pcscd


I know no security vulnerability in pcscd. But pcscd is not immune. See pcsc-lite security advisory CVE-2010-0407 for example.

If a new security vulnerability in pcscd is found the impact will be much lower now that pcscd run as a simple user in group "pcscd". An attacker would not gain root access.

Multi user systems


What will happen on a system with users A and B that both want to use PC/SC?

Suppose A starts a PC/SC program and then starts the pcscd daemon. pcscd will run as user A with the group set to pcscd.

Then B starts a PC/SC program. pcscd is already running so it will not be restarted.

B could try to inject code in the pcscd process and run the code with the access rights of A. This should not be possible. See the previous chapter about possible vulnerability in pcscd.

User A could run pcscd in debug mode (using the --debug and --apdu option of pcscd) and see all the PC/SC commands and APDU used by the application run by B. Such APDU could contain the pincode of B for example. This attack is not possible. pcscd contains a check to disable the --apdu option if it has been launched using the sgid mechanism.

Conclusion


The auto start mechanism introduced in pcsc-lite 1.6.0 allows to limit the number of running processes (when a smart card is not used).

The sgid mechanism introduced in pcsc-lite 1.6.5 greatly limits the security implication by just using a special group instead of running pcscd as root.