aboutsummaryrefslogtreecommitdiff
path: root/cryptech/py11/mutex.py
diff options
context:
space:
mode:
Diffstat (limited to 'cryptech/py11/mutex.py')
-rw-r--r--cryptech/py11/mutex.py89
1 files changed, 89 insertions, 0 deletions
diff --git a/cryptech/py11/mutex.py b/cryptech/py11/mutex.py
new file mode 100644
index 0000000..da2123c
--- /dev/null
+++ b/cryptech/py11/mutex.py
@@ -0,0 +1,89 @@
+"""
+Optional Python mutex implementation for cryptech.py11 library,
+using the threading.Lock primitive to provide the mutex itself.
+
+Most of the code in this module has to do with mapping between the
+Python and PKCS #11 APIs.
+
+If you just want locking, it's probably simpler to let the C code
+handle it, by passing CKF_OS_LOCKING_OK to C_Initialize().
+
+The main reason for having a complete implementation in Python is to
+test the API.
+
+Sample usage:
+
+ from cryptech.py11 import *
+ from cryptech.py11.mutex import MutexDB
+
+ p11 = PKCS11()
+ mdb = MutexDB()
+ p11.C_Initialize(0, mdb.create, mdb.destroy, mdb.lock, mdb.unlock)
+
+"""
+
+from struct import pack, unpack
+from .types import *
+from .exceptions import *
+
+# This controls how big our mutex handles are.
+encoded_format = "=L"
+
+# These are all determined by encoded_format, don't touch.
+
+encoded_length = len(pack(encoded_format, 0))
+encoded_type = CK_BYTE * encoded_length
+handle_max = unpack(encoded_format, chr(0xff) * encoded_length)[0]
+
+class Mutex(object):
+
+ def __init__(self, handle):
+ from threading import Lock
+ self.encoded = encoded_type(*handle)
+ self.lock = Lock()
+
+def p11_callback(func):
+ from threading import ThreadError
+ def wrapper(self, arg):
+ try:
+ func(self, arg)
+ except ThreadError, e:
+ print "Failed: %s" % e
+ return CKR_MUTEX_NOT_LOCKED.ckr_code
+ except Exception, e:
+ print "Failed: %s" % e
+ return CKR_FUNCTION_FAILED.ckr_code
+ else:
+ return CKR_OK
+ return wrapper
+
+class MutexDB(object):
+
+ def __init__(self):
+ self.mutexes = {}
+ self.next_handle = 0
+
+ def find_free_handle(self):
+ if len(self.mutexes) > handle_max:
+ raise RuntimeError
+ while self.next_handle in self.mutexes:
+ self.next_handle = (self.next_handle + 1) & handle_max
+ return pack(encoded_format, self.next_handle)
+
+ @p11_callback
+ def create(self, handle_ptr):
+ handle = self.find_free_handle()
+ self.mutexes[handle] = Mutex(handle)
+ handle_ptr[0] = self.mutexes[handle].encoded
+
+ @p11_callback
+ def destroy(self, handle):
+ del self.mutexes[handle[:encoded_length]]
+
+ @p11_callback
+ def lock(self, handle):
+ self.mutexes[handle[:encoded_length]].lock.acquire()
+
+ @p11_callback
+ def unlock(self, handle):
+ self.mutexes[handle[:encoded_length]].lock.release()