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.
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.
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.
A large part of the source code is to manage:
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.
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:
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
ConversionConversion EmoticonEmoticon