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
Previous
Next Post »