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