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...

Friday, April 22, 2011

PyKCS11 provided samples: getinfo.py

I will continue the serie about PyKCS11 I started last year in PyKCS11 introduction. Just to remind you, PyKCS11 is a Python wrapper above the PKCS#11 API.

Setup


In the following I will use a .Net card and the PKCS#11 for .Net cards I blogged about in April 2010.

I generated a X509 certificate using tinyca2 and loaded it on the card using Firefox.

Example codes provided with PyKCS11: getinfo.py


getinfo.py is a short sample code to... get information from the token.

Output


cryptokiVersion: 2.20 
flags:  
libraryDescription: Gemalto .NET PKCS11              
libraryVersion: 2.2 
manufacturerID: Gemalto                          
Available Slots: 5 [0, 1, 2, 3, 4]
Slot n.: 0
 firmwareVersion: 0.00 
 flags: CKF_TOKEN_PRESENT, CKF_REMOVABLE_DEVICE, CKF_HW_SLOT 
 hardwareVersion: 0.00 
 manufacturerID: Unknown                          
 slotDescription: Gemalto GemPC Twin 00 00                                         
 SessionInfo
  flags: CKF_SERIAL_SESSION 
  slotID: 0 
  state: 0 
  ulDeviceError: 0 
 TokenInfo
  firmwareVersion: 0.0 
  flags: CKF_LOGIN_REQUIRED, CKF_TOKEN_INITIALIZED, CKF_USER_PIN_INITIALIZED 
  hardwareVersion: 0.0 
  label: .NET #AFC4963915BE14DB           
  manufacturerID: Gemalto                          
  model: .NET Card        
  serialNumber: AFC4963915BE14DB 
  ulFreePrivateMemory: -1 
  ulFreePublicMemory: -1 
  ulMaxPinLen: 0 
  ulMaxRwSessionCount: 0 
  ulMaxSessionCount: 0 
  ulMinPinLen: 0 
  ulRwSessionCount: 0 
  ulSessionCount: 1 
  ulTotalPrivateMemory: -1 
  ulTotalPublicMemory: -1 
  utcTime:  
  Mechanism list: 
   CKM_RSA_PKCS_KEY_PAIR_GEN 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_HW, CKF_GENERATE_KEY_PAIR 
   CKM_RSA_PKCS 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_ENCRYPT, CKF_HW, CKF_DECRYPT, CKF_SIGN, CKF_VERIFY 
   CKM_RSA_X_509 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_ENCRYPT, CKF_HW, CKF_DECRYPT, CKF_SIGN, CKF_VERIFY 
   CKM_MD5_RSA_PKCS 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_HW, CKF_SIGN, CKF_VERIFY 
   CKM_SHA1_RSA_PKCS 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_HW, CKF_SIGN, CKF_VERIFY 
   CKM_SHA256_RSA_PKCS 
    ulMinKeySize: 512 
    ulMaxKeySize: 2048 
    flags: CKF_HW, CKF_SIGN, CKF_VERIFY 
   CKM_MD5 
    flags: CKF_DIGEST 
   CKM_SHA_1 
    flags: CKF_DIGEST 
   CKM_SHA256 
    flags: CKF_DIGEST 
Slot n.: 1
 firmwareVersion: 0.00 
 flags: CKF_REMOVABLE_DEVICE, CKF_HW_SLOT 
 hardwareVersion: 0.00 
 manufacturerID: Unknown                          
 slotDescription: empty                                                            
 SessionInfo Error: CKR_TOKEN_NOT_PRESENT (0x000000E0)
Slot n.: 2
 firmwareVersion: 0.00 
 flags: CKF_REMOVABLE_DEVICE, CKF_HW_SLOT 
 hardwareVersion: 0.00 
 manufacturerID: Unknown                          
 slotDescription: empty                                                            
 SessionInfo Error: CKR_TOKEN_NOT_PRESENT (0x000000E0)
Slot n.: 3
 firmwareVersion: 0.00 
 flags: CKF_REMOVABLE_DEVICE, CKF_HW_SLOT 
 hardwareVersion: 0.00 
 manufacturerID: Unknown                          
 slotDescription: empty                                                            
 SessionInfo Error: CKR_TOKEN_NOT_PRESENT (0x000000E0)
Slot n.: 4
 firmwareVersion: 0.00 
 flags: CKF_REMOVABLE_DEVICE, CKF_HW_SLOT 
 hardwareVersion: 0.00 
 manufacturerID: Unknown                          
 slotDescription: empty                                                            
 SessionInfo Error: CKR_TOKEN_NOT_PRESENT (0x000000E0)

Comments


The PKCS#11 token has 5 virtual slots. Only slot 0 contains information about the card.

The getinfo.py sample code uses colors to display the information.

Source code


A large part of the source code is to manage:
  • command arguments
  • display and colorization

We will see in a future blog article how to use the wrapper in an interactive Python. So a lot of the extra code in the sample will be useless in that case.

#!/usr/bin/env python

#   Copyright (C) 2006-2010 Ludovic Rousseau (ludovic.rousseau@free.fr)
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

import PyKCS11
import platform
import sys


class getInfo(object):
    red = blue = magenta = normal = ""

    def colorize(self, text, arg):
        print self.magenta + text + self.blue, arg, self.normal

    def display(self, obj, indent=""):
        dico = obj.to_dict()
        for key in sorted(dico.keys()):
            type = obj.fields[key]
            left = indent + key + ":"
            if type == "flags":
                self.colorize(left, ", ".join(dico[key]))
            elif type == "pair":
                self.colorize(left, "%d.%d" % dico[key])
            else:
                self.colorize(left, dico[key])

    def __init__(self, lib=None):
        if sys.stdout.isatty() and platform.system().lower() != 'windows':
            self.red = "\x1b[01;31m"
            self.blue = "\x1b[34m"
            self.magenta = "\x1b[35m"
            self.normal = "\x1b[0m"

        self.pkcs11 = PyKCS11.PyKCS11Lib()
        self.pkcs11.load(lib)

    def getSlotInfo(self, slot):
        print "Slot n.:", slot
        self.display(self.pkcs11.getSlotInfo(slot), " ")

    def getTokenInfo(self, slot):
        print " TokenInfo"
        self.display(self.pkcs11.getTokenInfo(slot), "  ")

    def getMechanismInfo(self, slot):
        print "  Mechanism list: "
        m = self.pkcs11.getMechanismList(slot)
        for x in m:
            self.colorize("  ", x)
            i = self.pkcs11.getMechanismInfo(slot, x)
            if not i.flags & PyKCS11.CKF_DIGEST:
                if i.ulMinKeySize != PyKCS11.CK_UNAVAILABLE_INFORMATION:
                    self.colorize("    ulMinKeySize:", i.ulMinKeySize)
                if i.ulMaxKeySize != PyKCS11.CK_UNAVAILABLE_INFORMATION:
                    self.colorize("    ulMaxKeySize:", i.ulMaxKeySize)
            self.colorize("    flags:", ", ".join(i.flags2text()))

    def getInfo(self):
        self.display(self.pkcs11.getInfo())

    def getSessionInfo(self, slot, pin=None):
        print " SessionInfo",
        session = self.pkcs11.openSession(slot)

        if pin:
            print "(using pin: %s)" % pin
            session.login(pin)
        else:
            print

        self.display(session.getSessionInfo(), "  ")

        if pin:
            session.logout()


def usage():
    print "Usage:", sys.argv[0],
    print "[-p pin][--pin=pin]",
    print "[-s slot][--slot=slot]",
    print "[-c lib][--lib=lib]",
    print "[-h][--help]",
    print "[-o][--opensession]"

if __name__ == '__main__':
    import getopt

    try:
        opts, args = getopt.getopt(sys.argv[1:], "p:s:c:ho",
            ["pin=", "slot=", "lib=", "help", "opensession"])
    except getopt.GetoptError:
        # print help information and exit:
        usage()
        sys.exit(2)

    slot = None
    lib = None
    pin = None
    open_session = False
    pin_available = False
    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-p", "--pin"):
            pin = a
            pin_available = True
            open_session = True
        if o in ("-s", "--slot"):
            slot = int(a)
        if o in ("-c", "--lib"):
            lib = a
        if o in ("-o", "--opensession"):
            open_session = True

    gi = getInfo(lib)
    gi.getInfo()

    slots = gi.pkcs11.getSlotList()
    print "Available Slots:", len(slots), slots

    if len(slots) == 0:
        sys.exit(2)

    if slot:
        slots = [slots[slot]]

    for slot in slots:
        try:
            gi.getSlotInfo(slot)
            gi.getSessionInfo(slot, pin)
            gi.getTokenInfo(slot)
            gi.getMechanismInfo(slot)
        except PyKCS11.PyKCS11Error, e:
            print "Error:", e

Conclusion

If you have to use a PKCS#11 token and you can choose the programming language you want then you can use Python instead of C.

Flattr this

Wednesday, March 30, 2011

"new" version of libusb

My CCID driver uses libusb-1.0 to talk to USB readers.

libusb evolution stalled


The latest version 1.0.8 of libusb-1.0 was released in May 2010 (nearly a year ago). Since then many bugs have been reported and most have been fixed in the git repository. The problem is that now new stable or 1.0.9 version has been released since May 2010. So if you suffer from a bug in libusb it is not easy to update it.

libusb git snapshot

To ease the use of a more up-to-date version of libusb-1.0 I made a snapshot of the version in the git repository and provide it on my web page of beta versions or http://ludovic.rousseau.free.fr/softwares/pcsc-lite/

The files in the libusb git repository have not evolved in the last 6 months so I do not expect to have to make a new snapshot within the next 6 months. I sent a mail on the libusb mailing list.

Conclusion


So before reporting a bug in libccid first try a newer version of libusb. If the bug is at the communication level it may already be solved in the libusb snapshot version.


Flattr this

Saturday, February 26, 2011

pcscd now uses libudev instead of libhal

pcsc-lite first started (in the previous century) when only serial readers were in use. The serial readers are configured using the /etc/reader.conf file. The problem is that the configuration is static and can't be used with a USB reader.

History of USB plug-n-play mechanism


To detect the insertion or removal of a USB reader different mechanisms have been used in the last 10 years.

Linux


hotplug_linux.c: introduced at least in (or before) version 1.0.2beta2 (20 Dec, 2001).

The problem is that the code is Linux specific.

libusb


hotplug_libusb.c: introduced in version 1.2.0-rc1 (26 August, 2003). From the changelog:
- src/hotplug_libusb.c: Add support of libusb. Allow to use USB readers on
*BSD or any plateform supported by libusb. Thanks to Toni Andjelkovic for
the great job.
The problem of libusb is that pcscd is constantly polling the USB bus to detect reader hotplug.

libhal


hotplug_libhal.c: introduced in version 1.4.100 (23 March 2008). From the changelog:

- add libhal support to avoid polling the USB bus.  libusb is still
  supported but libhal is now the default

The problem is that libhal has been deprecated upstream in May 2008 (2 months after pcscd started using it). Some distributions are actively migrating out of libhal. See Debian bug #587979
"pcscd: uses deprecated HAL" for example. And the wiki page "HALRemoval".

libudev


hotplug_libudev.c: introduced in version 1.6.8 (not yet released as of February 2011).

It looks like libudev is a good choice for the future. I don't know if it is supported by other systems than GNU/Linux. I removed the support of libhal but support of libusb is still present.

Mac OS X


Mac OS X has its own hotplug mechanism in hotplug_macosx.c. Apple maintains its own forked version of pcsc-lite. So I do not plan to change anything Mac OS X specific in pcsc-lite.

Conclusion


The hotplug mechanism is a fast moving target on GNU/Linux. I hope libudev will last at least a few months before I have to move to something else.

Flattr this

Wednesday, February 23, 2011

New version of libccid: 1.4.2

I just released a new version of libccid.

Changelog

1.4.2 - 22 February 2011, Ludovic Rousseau

  • Add support of Feitian SCR310 reader (also known as 301v2), ACS
    APG8201 PINhandy 1, Oberthur ID-ONE TOKEN SLIM v2, new Neowave
    Weneo token, Vasco DIGIPASS KEY 860, Vasco DIGIPASS KEY 200,
    Xiring Leo v2, Xiring MyLeo, Aktiv Rutoken lite readers
  • Add back support of "bogus" Oz776, REINER SCT and BLUDRIVE II
  • Ease detection of OpenCT by pcsc-lite
  • disable use of interrupt card events for multi slots readers (the
    algorithm is bogus and can't be used)
  • fix minor problems detected by the clang tool
  • some minor bugs removed

New version of pcsc-lite: 1.6.7

I just released new version of pcsc-lite 1.6.7.

pcsc-lite-1.6.7: Ludovic Rousseau
22 February 2011
  • better Mac OS X support
  • Fix Alioth bug [#312960] "SCardDisconnect when other context has transaction"
  • add a API tracing feature in the client side (#define DO_TRACE)
  • allow the use of tracing and profiling features from different
    application threads
  • fix a problem with a multi-slots reader
  • fix minor problems detected by the clang tool
  • some other minor improvements and bug corrections

The next version of pcsc-lite should use libudev instead of the deprecated libhal.

Monday, February 7, 2011

pcsc-lite: arbitrary code execution

LWN published a message about "pcsc-lite: arbitrary code execution":

pcsc-lite: arbitrary code execution


Package(s):pcsc-lite CVE #(s):CVE-2010-4531
Created:January 14, 2011 Updated:February 3, 2011
Description: From the Red Hat bugzilla:
A stack-based buffer overflow flaw was found in the way
PC/SC Lite smart card framework decoded certain attribute
values of the Answer-to-Reset (ATR) message, received back
from the card after connecting. A local attacker could
use this flaw to execute arbitrary code with the privileges
of the user running the pcscd daemon, via a malicious smart
card inserted to the system USB port.
Alerts:
Fedora FEDORA-2011-0164 2011-01-05
Fedora FEDORA-2011-0123 2011-01-05
Mandriva MDVSA-2011:015 2011-01-20
Debian DSA-2156-1 2011-01-31
openSUSE openSUSE-SU-2011:0092-1 2011-02-02
Pardus 2011-24 2011-02-02


The description of the bug is correct (this time). But I am not sure it would be possible to execute arbitrary code. The ATR is still limited to MAX_ATR_SIZE=33 bytes.

The bug was fixed on 3rd November 2010 in revision 5370 more than a month before MWR published a InfoSecurity Security Advisory PCSC-Lite: pcscd ATR Handler Buffer Overflow on 13th December 2010.

Debian 6.0 was released just yesterday. The pcscd package in this version contains the fix.


Flattr this

ccid: arbitrary code execution

LWN published a message about "ccid: arbitrary code execution":

ccid: arbitrary code execution


Package(s):ccid CVE #(s):CVE-2010-4530
Created:January 14, 2011 Updated:February 3, 2011
Description: From the Red Hat bugzilla:
An integer overflow, leading to array index error was found
in the way USB CCID (Chip/Smart Card Interface Devices) driver
processed certain values of card serial number. A local attacker
could use this flaw to execute arbitrary code, with the privileges
of the user running the pcscd daemon, via a malicious smart card
with specially-crafted value of its serial number, inserted to
the system USB port.
Alerts:
Fedora FEDORA-2011-0162 2011-01-05
Fedora FEDORA-2011-0143 2011-01-05
Mandriva MDVSA-2011:014 2011-01-20
openSUSE openSUSE-SU-2011:0092-1 2011-02-02
Pardus 2011-22 2011-02-02

The description of the problem is not exact. The problem is present in file ccid/src/ccid_serial.c and only impacts the GemPC Twin connected to a serial port.

The bug was fixed on 5th November 2010 in revisions 5381 and 5382, more than a month before MWR published a InfoSecurity Security Advisory PCSC-Lite: libccid Buffer Overflow on 13th December 2010.

Debian 6.0 was released just yesterday. The libccid package in this version contains the fix. Debian did not released a Debian Security Advisory because the bug is minor.


Flattr this