PyKCS11, a Python wrapper for the PKCS#11 API

Copyright (C) 2004 Midori (http:/www.paipai.net/)
Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

Contents:

 

Foreword

This wrapper has been generated with the help of the SWIG compiler, a wrapper generator.
Just differences from original PKCS#11 API are documented. Anything not documented here can be found on the PKCS#11 specification.
Please don't think about this documentation as a replacement for the PKCS#11 manual :)

The PKCS#11 API is very C oriented, so a C++ wrapper over the original PKCS#11 API has been created
This C++ wrapper exports the interface of some PKCS#11 function in a more "Python oriented" way (using stl collections, that are well wrapped by SWIG and are easy to use with Python because are very similar to Lists and Tuples).
The C++ has been chosen as wrapping language because SWIG supports it very well.

 

About this documentation

This document ISN'T A PKCS#11 API reference replacement. You NEED to know most of the PKCS#11 API you need if you want to use PyKCS11.
The PKCS#11 reference contained in this document just shows differences between PyKCS11 and the original PKCS#11 API.
Please don't ask us how to use the PKCS#11 API, consult instead the original RSA PKCS#11 documentation:
http://www.rsasecurity.com/rsalabs
http://www.rsasecurity.com/rsalabs/node.asp?id=2133
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf

 

Basic principles used to write this wrapper


1) Since most PKCS#11 structures are read only, strings located inside such a structure (i.e. a fixed length string padded with space character, not null terminated) is not accessed directly, but using an accessor function named GetTheOriginalNameOfTheStringVar(), that convert the PKCS#11 padded string to a Python string.

Example:
typedef struct CK_INFO {
CK_VERSION cryptokiVersion;
unsigned char manufacturerID[32];
unsigned long flags;
unsigned char libraryDescription[32];
CK_VERSION libraryVersion;
} CK_INFO;

The manufacturerID field is accessed using the GetManufacturerID() method of a CK_INFO instance.
The libraryDescription field is accessed using the GetLibraryDescription() method of a CK_INFO instance.

ckInfo = PyKCS11.CK_INFO()
...
print "Manufacturer is: ", ckInfo.GetManufacturerID()


2) Any string input parameter passed as array/length pair is wrapped as Python string

In example, the C_Login function:
C_Login's original prototype: C_Login(CK_SESSION_HANDLE hSession, CK_CHAR* pPin, CK_ULONG ulPinLen)
C_Login's prototype in PyKCS11: C_Login(CK_SESSION_HANDLE hSession, String Pin)

So in a Python script:

p11Lib = PyKCS11.CPKCS11Lib()
# ... other P11 calls ...
Pin = "123456"
rv = p11Lib.C_Login(PyKCS11.CKU_USER, Pin)
print "C_Login returned ", rv

3) All input and output bytes array parameters are passed as ckbytelist type, instead of array/length pair.
The ckbytelist  is much like a Python list.
The PKCS#11 API uses a convention to retrieve unknown length data; usually this convention is leaved unchanged (an exception is the C_GetSlotList function).
Why that? This wrapper does not have the purpose to simplify the usage of the PKCS#11 API inside Python. It just is a tool to call the PKCS#11 in the way you would do using C (that is, the extension is designed to be a PKCS#11 testing tool to create test script in a simpler way).
So, to retrieve unknown length byte array you should create an empty ckbytelist object; then you should call the PKCS#11 function a first time: this first call just returns the data length; now you should call the function again using exactly same parameters to retrieve actual data.

4) PKCS#11 Templates (CK_ATTRIBUTE arrays) are passed as ckattrlist type. The ckattrlist is much like a Python list.
ckattrlist is a list of CK_ATTRIBUTE_SMART structures, a CK_ATTRIBUTE extension; CK_ATTRIBUTE_SMART has some helper method that let you set and get values using Python basic types.
Additional notes about the C_GetAttributeValue() function, the only one that uses attribute templates as output. This function should be called twice, once to know the values' length and another time to retrieve actual values.

5) PKCS#11 wrapped functions returns the PKCS#11 error codes unchanged. No exceptions are thrown while a PKCS#11 error is returned, you should check return value for errors exactly as you would do in C.

6) All PKCS#11 defines (return codes, attribute types, mechanism types, etc) are declared as constants in the PyKCS11 module. The name of each constant is exactly the C define name (i.e. CKR_OK, CKA_LABEL, CKM_RSA_PKCS, CKU_USER, etc.)

 

PyKCS11 Reference

How to call PyKCS11

PyKCS11 is composed by 2 Python modules, _PyKCS11.dll (or .so, or any other Dynamic Library extension your OS uses) and PyKCS11.py.
_PyKCS11.dll is the native code wrapper, a native Python module that calls the PKCS#11 API. PyKCS11.py is a pure-Python helper module that just encapsulates _PyKCS11.dll functions inside nice Python objects (that is, _PyKCS11.dll interface is not object oriented, while PyKCS11.py does).

To call PyKCS11, you should place_PyKCS11.dll and PyKCS11.py files inside the Python's libraries folder or in the script folder, then you should import the PyKCS11 module in your script, i.e. like this:

import PyKCS11

 

PyKCS11 Objects and Types

PyKCS11 module defines some custom data type, used i.e. to return session and object handles, list of slots and binary data.
There is also a group of wrappers for all PKCS#11 structures, such as CK_SESSION_INFO.

ck[...]list

The ck[...]list types are used by PyKCS11 to receive or return collections of data. i.e. the ckintlist is used to get or pass list of numeric values, while ckbytelist is just like a byte array and is used to pass or get binary data.
Each ck[...]list type has a really similar interface. You can use them as Python lists, using them in iterations or accessing it with []:

Example 1:
slotList = PyKCS11.ckintlist()
p11Lib.C_GetSlotList(0, slotList)
for x in range(len(slotList)):
     print "SlotID:", slotList[x]

Example 2:
ToBeSignedBuffer = PyKCS11.ckintlist(1024)
SignatureBuffer = PyKCS11.ckintlist()
[...]
rv = p11Lib.C_Sign(Session, ToBeSignedBuffer, SignatureBuffer)
rv = p11Lib.C_Sign(Session, ToBeSignedBuffer, SignatureBuffer)
[...]

There is also some other method, as size() and clear(). Usually you don't need to call that methods while using this types with PyKCS11, so they are not documented (you can see them in the PyKCS11.py file)

ckintlist

A list of numeric values. Is used to pass or get lists of numeric value; i.e. is used by C_GetSlotList() to return a list of available slots (as a list of SlotIDs).

ckbytelist Represents an array of bytes; is used every time a binary buffer should be passed to a PKCS#11 function. Can be used as a list, so you can iterate on it like this:

Note: to avoid the double call mechanism you can use the ckintlist's method reserve(new_list_len) or you can specify an initial length when you create the ckintlist instance:

ToBeSignedBuffer = PyKCS11.ckbytelist(1024)
SignatureBuffer = PyKCS11.ckbytelist()
# fills the ToBeSignedBuffer
SignatureBuffer.reserve(128)
rv = p11Lib.C_Sign(Session,ToBeSignedBuffer, SignatureBuffer)
[...]

ckattrlist Represents an array of CK_ATTRIBUTE_SMART objects. Is used every time a PKCS#11 Template is involved. The C_GetAttributeValue() function is the only one that use this type as output.
CK_ATTRIBUTE_SMART

Is an extension for the PKCS#11 structure CK_ATTRIBUTE. The CK_ATTRIBUTE structure (se also PKCS#11 templates) is widely used in the PKCS#11 API to set or get Object's attributes or while creating objects or generating keys. A CK_ATTRIBUTE can contain any type of value as internally it is stored ad a byte array.
Since CK_ATTRUBUTE structure is very C oriented, this wrapper was created to let assign or get variables in a more friendly way; it extends the CK_ATTRIBUTE type adding some helper function that let you set or get the internal CK_ATTRIBUTE value using Python basic types, such as numeric, string and tuple.
Please see next paragraph for a complete CK_ATTRIBUTE_SMART interface reference.

CK_VERSION See the PKCS#11 API reference
CK_INFO The manufacturerID and libraryDescription fields can be accessed using GetManufacturerID() and GetLibraryVersion() methods. For more details about this structure please consult the PKCS#11 API reference.
CK_SLOT_INFO The manufacturerID, slotDescription, hardwareVersion and firmwareVersion fields can be accessed using GetManufacturerID(), GetSlotDescription(), GetHardwareVersion() and GetFirmwareVersion() methods. For more details about this structure please consult the PKCS#11 API reference.
CK_TOKEN_INFO The manufacturerID, model and firmwareVersion fields can be accessed using GetManufacturerID(), GetModel() and GetFirmwareVersion() methods. For more details about this structure please consult the PKCS#11 API reference.
CK_SESSION_INFO See the PKCS#11 API reference
CK_DATE The year, month and day fields can be accessed using GetYear(), GetMonth() and GetDay() methods. For more details about this structure please consult the PKCS#11 API reference.
CK_MECHANISM See the PKCS#11 API reference
CK_MECHANISM_INFO See the PKCS#11 API reference



CK_ATTRIBUTE_SMART Reference

CK_ATTRIBUTE_SMART Methods:

Reset() Make the object instance empty: reset the value and the type
ResetValue() Just make the value empty, leaving the type unchanged.
Reserve(numeric len) Allocates enough space to store a number of bytes specified in the len parameter.
GetType() Returns the Attribute Type (look for CK_ATTRIBUTE_TYPE in the PKCS#11 API Reference)
SetType() Set the Attribute Type
GetLen() Get the Attribute size expressed in bytes
IsString() Returns true if the value contained is a string (the type contained is detected using the Attribute Type value)
IsBool() Returns true if the value contained is boolean (the type contained is detected using the Attribute Type value)
IsNum() Returns true if the value contained is numeric (the type contained is detected using the Attribute Type value)
IsBin() Returns true if the value contained isn't boolean, string or numeric (equivalent to not IsNum() and not IsBool() and not IsString() )
GetString() Returns the contained value as string (no conversion is performed: if the value contained is not a PKCS#11 string, invalid data may be returned)
SetString(string new_value) Set the Attribute value to the string new_value
GetNum() Returns the contained value as Numeric. Note that if the Attribute doesn't contains a numeric value, always 0 is returned.
SetNum(numeric new_value) Set the Attribute value to the numeric new_value
GetBool() Returns the contained value as Boolean. Note that if the Attribute doesn't contains a Boolean value, always false is returned.
SetBool() Set the Attribute value to the boolean new_value
GetBin() Return the raw Attribute Value, as a tuple of byte (returns a ckbytelist object)
SetBin(list/tuple new_value) Set the Attribute value to the raw new_value. The new_value should be a list or tuple

 

CPKCS11Lib Reference

CPKCS11Lib represents a PKCS#11 library instance. It almost exposes the complete PKCS#11 interface and some additional methods as Load() and Unload().


Example of use:


import PyKCS11

p11Lib = PyKCS11.CPKCS11Lib() # creates a CPKCS11Lib instance
lib_path = "PKCS11Lib.dll"
info = PyKCS11.CK_INFO() # creates a CK_INFO instance
slotInfo = PyKCS11.CK_SLOT_INFO() # creates a CK_SLOT_INFO instance
slotList = PyKCS11.ckintlist() # creates a ckintlist instance to store the SlotList
rv = p11Lib.Load(lib_path, 1)
print "Load():", rv
rv = p11Lib.C_GetInfo(info)
print "C_GetInfo():", rv
print "manufacturerID:", info.GetManufacturerID()
del info
rv = p11Lib.C_GetSlotList(0, slotList)
print "C_GetSlotList():", rv
print "\tAvailable Slots: " + str(len(slotList))

 

CPKCS11Lib specific methods (loading and unloading a PKCS#11 module)

bool CPKCS11Lib.Load(string szLib, bool bAutoCallInitialize)

Loads a PKCS#11 Library.

szLib The library to load (name or full path)
bAutoCallInitialize Automatically calls C_Initialize(), if needed
Returns True if the load succeeded

bool CPKCS11Lib.Unload()

Unloads a PKCS#11 Library.

Returns Nothing

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
...
if bLoadResult: p11.Unload()

Notes on loading same Library more than once inside the same process

Abstract of what follows: PKCS#11 API is not designed to be used by different modules that runs inside a single process, if that modules doesn't are aware of each other presence!

PyKCS11 is able to load same PKCS#11 Library more than once in a transparent way if you pass the bAutoCallInitialize parameter as true.
PKCS#11 API says that the C_Initialize() MUST be called only once by a single process; if you call it more than once, an error is reported; but this is not the problem.
Problems begins when C_Finalize() is called! The library became unusable when C_Finalize() is called, so if you load same library more than once the C_Finalize() MUST be called only when there is no more code that needs to use the Library.
So, if you call the Load() method using the bAutoCallInitialize parameter set to true, the C_Finalize() is called only when the last CPKCS11Lib instance is deleted.
Some issue still exists:

  1. Some "other code" in the process loads a library and calls C_Initialize() BEFORE PyKCS11 does. PyKCS11 would detect this scenario and never calls the C_Finalize(), that should be called by that "other code".
    If that "other code" calls C_Finalize() while PyKCS11 is using the library, PyKCS11 detects this and calls C_Initialize() automatically. This avoids the invalidation of ALL PyKCS11 instances, but can't avoid the invalidation of all sessions and object handles (that is, all sessions are closed and all objects must be searched again or recreated).
  2. Some "other code" in the process loads a library and calls C_Initialize() AFTER PyKCS11 did. This "other code" should get an error calling C_Initialize() and in most cases it just doesn't works. If that "other code" expected this error and so continue working fine, it can make a call to C_Finalize() while PyKCS11 is using the library. PyKCS11 detects this and calls C_Initialize() automatically. This avoids the invalidation of ALL PyKCS11 instances, but can't avoid the invalidation of all sessions and object handles (that is, all sessions are closed and all objects must be searched again or recreated).

General purpose Methods

CK_RV CPKCS11Lib.C_Initialize()
Initializes the loaded library. Doesn't take any parameter (the original PKCS#11 takes void* parameter; NULL will be passed to the PKCS#11 library)

CK_RV CPKCS11Lib.C_Finalize()
Finalize the loaded library. Doesn't take any parameter (the original PKCS#11 takes void* parameter; NULL will be passed to the PKCS#11 library)

CK_RV CPKCS11Lib.C_GetInfo(CK_INFO Info)
Get Library information. Can be used to detect if the library is Initialized (CKR_CRYPTOKI_NOT_INITIALIZED is returned if C_Initialize needs to be called)
Takes a CK_INFO instance as parameter.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
info = PyKCS11.CK_INFO()
rv = p11.C_GetInfo(info)

 

Slot management Methods


CK_RV CPKCS11Lib.C_GetSlotList (bool TokenPresent, ckintlist slotList)
Get a list of available slots. The list is placed inside the slotList parameter. The function can be called passing a slotList instance of any length: it would be resized to contain the actual slot list size (this is an exception to the normal behavior)
slotList parameter is used instead of the pair CK_SLOT_ID* pSlotList and CK_UNLOG uCount PKCS#11 original parameters.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
slotList = PyKCS11.ckintlist()
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
print "C_GetSlotList():", rv
print "\tAvailable Slots: " + str(len(slotList))


CK_RV CPKCS11Lib.C_GetSlotInfo ( int slotID, CK_SLOT_INFO pInfo )

Get information about a slot. Accept a slot id (see C_GetSlotList() function, a value contained in the slotList parameter), and a CK_SLOT_INFO instance.

Example of use:
import PyKCS11
SlotInfos = PyKCS11.CK_SLOT_INFO()
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
print "C_GetSlotList():", rv
print "\tAvailable Slots: " + str(len(slotList))
rv = p11.C_GetSlotInfo(
slotList[0], SlotInfos)
print "\tSlot ", slotList[0], " name:", SlotInfos.GetSlotDescription()

Token management Methods


CK_RV CPKCS11Lib.C_GetTokenInfo ( int slotID, CK_Token_INFO Info )

Get information about a Token placed in a slot. Accept a slot id (see C_GetSlotList() function, a value contained in the slotList parameter), and a CK_TOKEN_INFO instance.

Example of use:
import PyKCS11
TokenInfos = PyKCS11.CK_TOKEN_INFO()
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
print "C_GetSlotList():", rv
print "\tAvailable Slots: " + str(len(slotList))
rv = p11.C_GetTokenInfo(
slotList[0], TokenInfos)
print "\tSlot ", slotList[0], " name:", TokenInfos.GetSlotDescription()

CK_RV CPKCS11Lib.C_InitToken(int slotID, string Pin, string Label)
Initialize a Token. Accept a slot id (see C_GetSlotList() function, a value contained in the slotList parameter), a Pin and a token Label.
The original PKCS#11 function takes a pair "CK_CHAR* pPin, CK_ULONG uPunLen", that became a Python string, passed as Pin parameter; and another parameter "CK_CHAR Label[32]", a fixed length string padded with the blanks (ASCII space character, 0x20), that became a Python string passed as Label parameter. Label length can be between 0 and 32.

CK_RV CPKCS11Lib.C_InitPIN (CK_SESSION_HANDLE hSession, string Pin)
Initialize or reset the user Pin. Accept a session handle as first parameter (hSession), and a new Pin.
The original PKCS#11 function takes a pair "CK_CHAR* pPin, CK_ULONG uPunLen", that became a Python string, passed as Pin parameter.

CK_RV CPKCS11Lib.C_SetPIN (CK_SESSION_HANDLE hSession, string OldPin, string NewPin )
Changes a Pin. Accept a session handle as first parameter (hSession) and the strings OldPin and the NewPin.
The original PKCS#11 function takes a pair "CK_CHAR* pOldPin, CK_ULONG uOldPunLen", that became a Python string, passed as OldPin parameter; and takes a pair "CK_CHAR* pNewPin, CK_ULONG uNewPunLen", that became a Python string, passed as NewPin parameter.

Session management Methods

CK_RV CPKCS11Lib.C_OpenSession (int slotID, int flags, CK_SESSION_HANDLE newhSession )

Open a new session on a Token. In the original prototype the newhSession parameter was a CK_SESSION_HANDLE pointer.

CK_RV CPKCS11Lib.C_CloseSession( CK_SESSION_HANDLE hSession )

Closes a session opened using C_OpenSession.

CK_RV CPKCS11Lib.C_CloseAllSessions ( int slotID )

Closes all session opened on a Token.

CK_RV CPKCS11Lib.C_Login (CK_SESSION_HANDLE hSession, int userType, string Pin )

Login a user on all sessions open on a Token. Accept a session handle obtained calling the C_OpenSession function, the type of user to login and the Pin to use.

CK_RV CPKCS11Lib.C_Logout ( CK_SESSION_HANDLE hSession )

Logout all sessions open on a Token. Accept a session handle obtained calling the C_OpenSession.

CK_RV CPKCS11Lib.C_GetSessionInfo ( CK_SESSION_HANDLE hSession, CK_SESSION_INFO Info )

Get some information about the specified session and copy them in the Info object. In the original prototype the Info was a CK_SESSION_INFO pointer.


Example of use:
import PyKCS11
TokenInfos = PyKCS11.CK_TOKEN_INFO()
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)

session = PyKCS11.CK_SESSION_HANDLE()
sessionInfo = PyKCS11.CK_SESSION_INFO()
rv = p11.C_OpenSession(
slotList[0], PyKCS11.CKF_SERIAL_SESSION, session)
rv = p11.C_Login(session, PyKCS11.CKU_USER, "123456")
rv = p11.C_GetSessionInfo(session, sessionInfo)
rv = p11.C_Logout(
session)
rv = p11.C_CloseSession(

Object management Methods

CK_RV CPKCS11Lib.C_CreateObject ( CK_SESSION_HANDLE hSession, vectorattr Template, CK_OBJECT_HANDLE outhObject )

This method can be used to create a new object. The Object template (that is, object's attributes) is passed using the Template argument, while the object handle is placed in the outhObject argument. In the original prototype, Template was a pair of arguments: a CK_TEMPLATE array and a numeric length of array, while outhObject was a CK_OBJECT_HANDLE pointer.
Template is a vectorattr object type, a list of CK_ATTRIBUTE_SMART objects.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
session = PyKCS11.CK_SESSION_HANDLE()
sessionInfo = PyKCS11.CK_SESSION_INFO()
rv = p11.C_OpenSession(slotList[0], PyKCS11.CKF_SERIAL_SESSION, session)
rv = p11.C_Login(session, PyKCS11.CKU_USER, "123456")
objTemplate = PyKCS11.vectorattr(4)
objValues = PyKCS11.vectorattr(2)
newObjValues = PyKCS11.vectorattr(1)
hObject = PyKCS11.CK_OBJECT_HANDLE()
objTemplate(0).SetBool(PyKCS11.CKA_TOKEN, 1)
objTemplate(1).SetNum(PyKCS11.CKA_CLASS, PyKCS11.CKO_DATA)
objTemplate(2).SetString(PyKCS11.CKA_LABEL, "TestDataObject")
objTemplate(3).SetString(PyKCS11.CKA_VALUE, "This is a sample Data Object")
rv = p11.C_CreateObject(session, objTemplate, hObject)
objValues(0).SetType(PyKCS11.CKA_MODIFIABLE)
objValues(1).SetType(PyKCS11.CKA_PRIVATE)
rv = p11.C_GetAttributeValue(session, hObject, objValues) # first call: just get sizes
rv = p11.C_GetAttributeValue(session, hObject, objValues) # second call: get actual data
newObjValues(0).SetString(PyKCS11.CKA_APPLICATION, "Test")
rv = p11.C_SetAttributeValue(session, hObject, newObjValues)
rv = p11.C_DestroyObject(session, hObject)
rv = p11.C_Logout(session)
rv = p11.C_CloseSession(session)

CK_RV CPKCS11Lib.C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)

This function destroys an object. You specify the object to destroy passing an object handle previously obtained by C_FindObjects() or any object creation function, such as C_CreateObject().

Example of use: see C_CreateObject().

CK_RV CPKCS11Lib.C_GetObjectSize (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, int outulSize)

Return the size of an object. The object's size is returned in the outulSize argument. In the original prototype the outulSize was a pointer to an unsigned long.

Example of use: see C_CreateObject().

CK_RV CPKCS11Lib.C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, vectorattr outTemplate)

Get object's attributes. outTemplate is a vectorattr object type, a list of CK_ATTRIBUTE_SMART objects. In the original prototype outTemplate was a pair of arguments: a CK_TEMPLATE array and a numeric length of that array.

Example of use: see C_CreateObject().


CK_RV CPKCS11Lib.C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, vectorattr Template )

Assign new values to object's attributes. Template is a vectorattr object type, a list of CK_ATTRIBUTE_SMART objects. In the original prototype outTemplate was a pair of arguments: a CK_TEMPLATE array and a numeric length of that array.

Example of use: see C_CreateObject().

CK_RV CPKCS11Lib.C_FindObjectsInit( CK_SESSION_HANDLE hSession, vectorattr Template )

Begin a search on a session using Template as search filter. In the original prototype Template was a pair of arguments: a CK_TEMPLATE array and a numeric length of that array.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
session = PyKCS11.CK_SESSION_HANDLE()
rv = p11.C_OpenSession(slotList[0], PyKCS11.CKF_SERIAL_SESSION, session)
rv = p11.C_Login(session, PyKCS11.CKU_USER, "123456")
SearchResult = PyKCS11.ckintlist(10)
searchTemplate = PyKCS11.vectorattr(2)
searchTemplate[0].SetBool(PyKCS11.CKA_TOKEN, 1)
searchTemplate[1].SetNum(PyKCS11.CKA_CLASS, PyKCS11.CKO_CERTIFICATE)
rv = p11.C_FindObjectsInit(session, searchTemplate)
rv = p11.C_FindObjects(session, SearchResult)
rv = p11.C_FindObjectsFinal(session)
for x in SearchResult:
   print "object " + hex(x)
   valTemplate = PyKCS11.ckattrlist(1)
   valTemplate[0].SetType(PyKCS11.CKA_LABEL)
   rv = p11.C_GetAttributeValue(session, x, valTemplate)
   print "CKA_LABEL: ", valTemplate[0].GetString()

 

CK_RV CPKCS11Lib.C_FindObjects( CK_SESSION_HANDLE hSession, ckintlist outObjectsList )

Continue a search operation started by C_FindObjectsInit() on a session. Returns a list of object handles in the outObjectsList argument. In the original prototype outObjectsList was a pair of arguments: an array of CK_OBJECT_HANDLE and a numeric length of that array.

Example of use: see C_FindObjectsInit().

CK_RV CPKCS11Lib.C_FindObjectsFinal( CK_SESSION_HANDLE hSession )

Ends a search started on a session by C_FindObjectsInit().

Example of use: see C_FindObjectsInit().

 

CK_RV CPKCS11Lib.C_GenerateKeyPair( CK_SESSION_HANDLE hSession, CK_MECHANISM Mechanism, ckattrlist PublicKeyTemplate, ckattrlist PrivateKeyTemplate, CK_OBJECT_HANDLE outhPublicKey,
CK_OBJECT_HANDLE outhPrivateKey )

Generate a new key pair using the specified templates for private and public keys. The generated object handles are placed in outhPublicKey and outhPrivateKey.
In the original prototype PublicKeyTemplate/PrivateKeyTemplate was a pair of arguments: an array of CK_ATTRIBUTE and a numeric length of that array. While outhPublicKey/outhPrivateKey was a CK_OBJECT_HANDLE pointer.

Example of use: the use of this function is very similar to C_CreateObject().

 

Cryptographic Methods

CK_RV CPKCS11Lib.C_SignInit( CK_SESSION_HANDLE hSession, CK_MECHANISM Mechanism, CK_OBJECT_HANDLE hKey )

Start a signature on a session using the specified key.

Example of use: see C_Sign().

CK_RV CPKCS11Lib.C_Sign( CK_SESSION_HANDLE hSession, ckbytelist inData, ckbytelist outSignature )

Perform a signature operation. inData contains the data to sign; after a successful call outSignature should contain the signed data.
In the original prototype inData was a pair of arguments: an array of CK_BYTE and a numeric length of that array; while outSignature was another pair of arguments: an array of CK_BYTE and a numeric length of that array used to pass array size and to get actual data length.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
session = PyKCS11.CK_SESSION_HANDLE()
rv = p11.C_OpenSession(slotList[0], PyKCS11.CKF_SERIAL_SESSION, session)
rv = p11.C_Login(session, PyKCS11.CKU_USER, "123456")
SearchResult = PyKCS11.ckintlist(10)
searchTemplate = PyKCS11.vectorattr(2)
searchTemplate[0].SetBool(PyKCS11.CKA_TOKEN, 1)
searchTemplate[1].SetNum(PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY)
rv = p11.C_FindObjectsInit(session, searchTemplate)
rv = p11.C_FindObjects(session, SearchResult)
rv = p11.C_FindObjectsFinal(session)
DataToSign = PyKCS11.ckbytelist(5)
Signature = PyKCS11.ckbytelist()
DataToSign[0] = 1
DataToSign[1] = 2
DataToSign[2] = 3
DataToSign[3] = 4
DataToSign[4] = 5
Mechanism = PyKCS11.CK_MECHANISM()
Mechanism.mechanism = PyKCS11.CKM_RSA_PKCS
for x in SearchResult:
   rv = p11.C_SignInit(session, Mechanism, x)
   rv = p11.C_Sign(session, DataToSign, Signature) # first call get size
   rv = p11.C_Sign(session, DataToSign, Signature) # second call get the signature

CK_RV CPKCS11Lib.C_DecryptInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM Mechanism, CK_OBJECT_HANDLE hKey)

Start a decryption on a session using the specified key.

Example of use: see C_Decrypt().

CK_RV CPKCS11Lib.C_Decrypt ( CK_SESSION_HANDLE hSession, ckbytelist inEncryptedData, ckbytelist outData )

Perform a decryption on the specified session. inEncryptedData is the data to decrypt, outData is where the decrypted data would be placed.
In the original prototype inEncryptedData was a pair of arguments: an array of CK_BYTE and a numeric length of that array; while outData was another pair of arguments: an array of CK_BYTE and a numeric length of that array used to pass array size and to get actual data length.

Example of use:
import PyKCS11
p11 = PyKCS11.CPKCS11Lib() #create a lib instance
bLoadResult = p11.Load("p11lib.dll", true) #load a lib and calls C_Initialize.
rv = p11.C_GetSlotList(0, slotList)
session = PyKCS11.CK_SESSION_HANDLE()
rv = p11.C_OpenSession(slotList[0], PyKCS11.CKF_SERIAL_SESSION, session)
rv = p11.C_Login(session, PyKCS11.CKU_USER, "123456")
SearchResult = PyKCS11.ckintlist(10)
searchTemplate = PyKCS11.vectorattr(2)
searchTemplate[0].SetBool(PyKCS11.CKA_TOKEN, 1)
searchTemplate[1].SetNum(PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY)
rv = p11.C_FindObjectsInit(session, searchTemplate)
rv = p11.C_FindObjects(session, SearchResult)
rv = p11.C_FindObjectsFinal(session)
DataToDecrypt = PyKCS11.ckbytelist(128)
DecryptedData = PyKCS11.ckbytelist()
# ... fill the DataToDecrypt variable
Mechanism = PyKCS11.CK_MECHANISM()
Mechanism.mechanism = PyKCS11.CKM_RSA_PKCS
for x in SearchResult:
   rv = p11.C_DecryptInit(session, Mechanism, x)
   rv = p11.C_Decrypt(session, DataToDecrypt, DecryptedData) # first call get the size
   rv = p11.C_Decrypt(session, DataToDecrypt, DecryptedData) # second call get the data
CK_RV CPKCS11Lib.C_EncryptInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM Mechanism, CK_OBJECT_HANDLE hKey )

Start an encryption on a session using the specified key.

Example of use: see C_Encrypt().

 

CK_RV CPKCS11Lib.C_Encrypt ( CK_SESSION_HANDLE hSession, ckbytelist inData, ckbytelist outEncryptedData )

Perform an encryption on the specified session. inData is the data to decrypt, outEncryptedData is where the decrypted data would be placed.
In the original prototype inData was a pair of arguments: an array of CK_BYTE and a numeric length of that array; while outEncryptedData was another pair of arguments: an array of CK_BYTE and a numeric length of that array used to pass array size and to get actual data length.

Example of use: the usage is very similar to C_Encrypt().

 

Other Methods

This reference ends here.
We think that the above documentation is enough to understand how to use all function of this wrapper; if you need to know how to use other methods, please see the basic principles used to create this wrapper and the official PKCS#11 manual from RSA.

 

Copyright (C) 2004 Midori (http:/www.paipai.net/)
Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.