# An attempt at a Python interface to PKCS 11 using the scary ctypes
# module from the Python standard library.
from ctypes import *
from .types import *
from .exceptions import *
# This code is derived from the RSA PKCS #11 C header files, which say:
#
# License to copy and use this software is granted provided that it is
# identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
# (Cryptoki)" in all material mentioning or referencing this software.
#
# License is also granted to make and use derivative works provided that
# such works are identified as "derived from the RSA Security Inc. PKCS #11
# Cryptographic Token Interface (Cryptoki)" in all material mentioning or
# referencing the derived work.
#
# RSA Security Inc. makes no representations concerning either the
# merchantability of this software or the suitability of this software for
# any particular purpose. It is provided "as is" without express or implied
# warranty of any kind.
# This is not a complete set of PKCS #11 types, because the full set
# with all the optional mechanisms is tediously long and each
# structure type requires hand conversion. Goal at the moment is to
# cover stuff we care about in the base specification. Add other
# mechanism-specific stuff later as needed.
# Mapping beween C and Python at the lowest level isn't perfect
# because characters are integer types in C while they're strings in
# Python. It looks like we want the string handling in most cases
# other than CK_BBOOL and CK_VERSION, map lowest-level PKCS #11 types
# accordingly.
CK_BYTE = c_char
CK_CHAR = CK_BYTE
CK_UTF8CHAR = CK_BYTE
CK_BBOOL = c_ubyte
CK_ULONG = c_ulong
CK_LONG = c_long
CK_FLAGS = CK_ULONG
CK_VOID_PTR = POINTER(c_char)
CK_BYTE_PTR = POINTER(CK_BYTE)
CK_CHAR_PTR = POINTER(CK_CHAR)
CK_UTF8CHAR_PTR = POINTER(CK_UTF8CHAR)
CK_ULONG_PTR = POINTER(CK_ULONG)
CK_VOID_PTR_PTR = POINTER(CK_VOID_PTR)
class CK_VERSION (Structure):
_fields_ = [("major", c_ubyte),
("minor", c_ubyte)]
CK_VERSION_PTR = POINTER(CK_VERSION)
class CK_INFO (Structure):
_fields_ = [("cryptokiVersion", CK_VERSION),
("manufacturerID", CK_UTF8CHAR * 32),
("flags", CK_FLAGS),
("libraryDescription", CK_UTF8CHAR * 32),
("libraryVersion", CK_VERSION)]
CK_INFO_PTR = POINTER(CK_INFO)
CK_NOTIFICATION = CK_ULONG
CK_SLOT_ID = CK_ULONG
CK_SLOT_ID_PTR = POINTER(CK_SLOT_ID)
class CK_SLOT_INFO (Structure):
_fields_ = [("slotDescription", CK_UTF8CHAR * 64),
("manufacturerID", CK_UTF8CHAR * 32),
("flags", CK_FLAGS),
("hardwareVersion", CK_VERSION),
("firmwareVersion", CK_VERSION)]
CK_SLOT_INFO_PTR = POINTER(CK_SLOT_INFO)
class CK_TOKEN_INFO (Structure):
_fields_ = [("label", CK_UTF8CHAR * 32),
("manufacturerID", CK_UTF8CHAR * 32),
("model", CK_UTF8CHAR * 16),
("serialNumber", CK_CHAR * 16),
("flags", CK_FLAGS),
("ulMaxSessionCount", CK_ULONG),
("ulSessionCount", CK_ULONG),
("ulMaxRwSessionCount", CK_ULONG),
("ulRwSessionCount", CK_ULONG),
("ulMaxPinLen", CK_ULONG),
("ulMinPinLen", CK_ULONG),
("ulTotalPublicMemory", CK_ULONG),
("ulFreePublicMemory", CK_ULONG),
("ulTotalPrivateMemory",CK_ULONG),
("ulFreePrivateMemory", CK_ULONG),
("hardwareVersion", CK_VERSION),
("firmwareVersion", CK_VERSION),
("utcTime", CK_CHAR * 16)]
CK_TOKEN_INFO_PTR = POINTER(CK_TOKEN_INFO)
CK_SESSION_HANDLE = CK_ULONG
CK_SESSION_HANDLE_PTR = POINTER(CK_SESSION_HANDLE)
CK_USER_TYPE = CK_ULONG
CK_STATE = CK_ULONG
class CK_SESSION_INFO (Structure):
_fields_ = [("slotID", CK_SLOT_ID),
("state", CK_STATE),
("flags", CK_FLAGS),
("ulDeviceError", CK_ULONG)]
CK_SESSION_INFO_PTR = POINTER(CK_SESSION_INFO)
CK_OBJECT_HANDLE = CK_ULONG
CK_OBJECT_HANDLE_PTR = POINTER(CK_OBJECT_HANDLE)
CK_OBJECT_CLASS = CK_ULONG
CK_OBJECT_CLASS_PTR = POINTER(CK_OBJECT_CLASS)
CK_HW_FEATURE_TYPE = CK_ULONG
CK_KEY_TYPE = CK_ULONG
CK_CERTIFICATE_TYPE = CK_ULONG
CK_ATTRIBUTE_TYPE = CK_ULONG
class CK_ATTRIBUTE (Structure):
_fields_ = [("type", CK_ATTRIBUTE_TYPE),
("pValue", CK_VOID_PTR),
("ulValueLen", CK_ULONG)]
CK_ATTRIBUTE_PTR = POINTER(CK_ATTRIBUTE)
class CK_DATE (Structure):
_fields_ = [("year", CK_CHAR * 4),
("month", CK_CHAR * 2),
("day", CK_CHAR * 2)]
CK_MECHANISM_TYPE = CK_ULONG
CK_MECHANISM_TYPE_PTR = POINTER(CK_MECHANISM_TYPE)
class CK_MECHANISM (Structure):
_fields_ = [("mechanism", CK_MECHANISM_TYPE),
("pParameter", CK_VOID_PTR),
("ulParameterLen", CK_ULONG)]
CK_MECHANISM_PTR = POINTER(CK_MECHANISM)
class CK_MECHANISM_INFO (Structure):
_fields_ = [("ulMinKeySize", CK_ULONG),
("ulMaxKeySize", CK_ULONG),
("flags", CK_FLAGS)]
CK_MECHANISM_INFO_PTR = POINTER(CK_MECHANISM_INFO)
CK_RV = CK_ULONG
CK_NOTIFY = CFUNCTYPE(CK_RV, CK_SESSION_HANDLE, CK_NOTIFICATION, CK_VOID_PTR)
CK_CREATEMUTEX = CFUNCTYPE(CK_RV, CK_VOID_PTR_PTR)
CK_DESTROYMUTEX = CFUNCTYPE(CK_RV, CK_VOID_PTR)
CK_LOCKMUTEX = CFUNCTYPE(CK_RV, CK_VOID_PTR)
CK_UNLOCKMUTEX = CFUNCTYPE(CK_RV, CK_VOID_PTR)
class CK_C_INITIALIZE_ARGS (Structure):
_fields_ = [("CreateMutex", CK_CREATEMUTEX),
("DestroyMutex", CK_DESTROYMUTEX),
("LockMutex", CK_LOCKMUTEX),
("UnlockMutex", CK_UNLOCKMUTEX),
("flags", CK_FLAGS),
("pReserved", CK_VOID_PTR)]
CK_C_INITIALIZE_ARGS_PTR = POINTER(CK_C_INITIALIZE_ARGS)
# Prototypes for the PKCS #11 public functions.
#
# These used to be a separate module, but the forward references
# needed to implement CK_FUNCTION_LIST are enough fun without adding a
# gratuitous Python module loop too.
class CK_FUNCTION_LIST (Structure):
pass
CK_FUNCTION_LIST_PTR = POINTER(CK_FUNCTION_LIST)
CK_FUNCTION_LIST_PTR_PTR = POINTER(CK_FUNCTION_LIST_PTR)
Prototypes = (
("C_Initialize", [CK_VOID_PTR]),
("C_Finalize", [CK_VOID_PTR]),
("C_GetInfo", [CK_INFO_PTR]),
("C_GetFunctionList", [CK_FUNCTION_LIST_PTR_PTR]),
("C_GetSlotList", [CK_BBOOL, CK_SLOT_ID_PTR, CK_ULONG_PTR]),
("C_GetSlotInfo", [CK_SLOT_ID, CK_SLOT_INFO_PTR]),
("C_GetTokenInfo", [CK_SLOT_ID, CK_TOKEN_INFO_PTR]),
("C_GetMechanismList", [CK_SLOT_ID, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR]),
("C_GetMechanismInfo", [CK_SLOT_ID, CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR]),
("C_InitToken", [CK_SLOT_ID, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR]),
("C_InitPIN", [CK_SESSION_HANDLE, CK_UTF8CHAR_PTR, CK_ULONG]),
("C_SetPIN", [CK_SESSION_HANDLE, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR, CK_ULONG]),
("C_OpenSession", [CK_SLOT_ID, CK_FLAGS, CK_VOID_PTR, CK_NOTIFY, CK_SESSION_HANDLE_PTR]),
("C_CloseSession", [CK_SESSION_HANDLE]),
("C_CloseAllSessions", [CK_SLOT_ID]),
("C_GetSessionInfo", [CK_SESSION_HANDLE, CK_SESSION_INFO_PTR]),
("C_GetOperationState", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_SetOperationState", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE]),
("C_Login", [CK_SESSION_HANDLE, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG]),
("C_Logout", [CK_SESSION_HANDLE]),
("C_CreateObject", [CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR]),
("C_CopyObject", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR]),
("C_DestroyObject", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE]),
("C_GetObjectSize", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR]),
("C_GetAttributeValue", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG]),
("C_SetAttributeValue", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG]),
("C_FindObjectsInit", [CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG]),
("C_FindObjects", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE_PTR, CK_ULONG, CK_ULONG_PTR]),
("C_FindObjectsFinal", [CK_SESSION_HANDLE]),
("C_EncryptInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_Encrypt", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_EncryptUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_EncryptFinal", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DecryptInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_Decrypt", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DecryptUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DecryptFinal", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DigestInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR]),
("C_Digest", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DigestUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_DigestKey", [CK_SESSION_HANDLE, CK_OBJECT_HANDLE]),
("C_DigestFinal", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_SignInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_Sign", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_SignUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_SignFinal", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_SignRecoverInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_SignRecover", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_VerifyInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_Verify", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG]),
("C_VerifyUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_VerifyFinal", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_VerifyRecoverInit", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE]),
("C_VerifyRecover", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DigestEncryptUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DecryptDigestUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_SignEncryptUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_DecryptVerifyUpdate", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR]),
("C_GenerateKey", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR]),
("C_GenerateKeyPair", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR]),
("C_WrapKey", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE,
CK_BYTE_PTR, CK_ULONG_PTR]),
("C_UnwrapKey", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR]),
("C_DeriveKey", [CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR]),
("C_SeedRandom", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_GenerateRandom", [CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG]),
("C_GetFunctionStatus", [CK_SESSION_HANDLE]),
("C_CancelFunction", [CK_SESSION_HANDLE]),
("C_WaitForSlotEvent", [CK_FLAGS, CK_SLOT_ID_PTR, CK_VOID_PTR]))
CK_FUNCTION_LIST._fields_ = ([("version", CK_VERSION)] +
[(_name, CFUNCTYPE(*([CK_RV] + _args)))
for _name, _args in Prototypes])