aboutsummaryrefslogtreecommitdiff
path: root/cryptech/py11/attributes.py
diff options
context:
space:
mode:
Diffstat (limited to 'cryptech/py11/attributes.py')
-rw-r--r--cryptech/py11/attributes.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/cryptech/py11/attributes.py b/cryptech/py11/attributes.py
new file mode 100644
index 0000000..56473ad
--- /dev/null
+++ b/cryptech/py11/attributes.py
@@ -0,0 +1,101 @@
+# An attempt at a Python interface to PKCS 11 using the scary ctypes
+# module from the Python standard library.
+
+from struct import pack, unpack
+from ctypes import *
+from .types import *
+from .constants import *
+
+class Attribute(object):
+
+ @classmethod
+ def new(cls, attribute_name, type_name):
+ from . import constants
+ from . import types
+ assert attribute_name.startswith("CKA_")
+ attribute_number = getattr(constants, attribute_name)
+ type_class = getattr(types, type_name, str)
+ if type_class is CK_BBOOL:
+ cls = Attribute_CK_BBOOL
+ elif type_class is CK_ULONG:
+ cls = Attribute_CK_ULONG
+ elif type_name == "biginteger":
+ cls = Attribute_biginteger
+ return cls(attribute_name, attribute_number, type_name, type_class)
+
+ def __init__(self, attribute_name, attribute_number, type_name, type_class):
+ assert attribute_name.startswith("CKA_")
+ self.name = attribute_name
+ self.code = attribute_number
+ self.type_name = type_name
+ self.type_class = type_class
+
+ def encode(self, x): return x
+ def decode(self, x): return x
+
+class Attribute_CK_BBOOL(Attribute):
+ def encode(self, x): return chr(int(x))
+ def decode(self, x): return bool(ord(x))
+
+class Attribute_CK_ULONG(Attribute):
+ def encode(self, x): return pack("L", x)
+ def decode(self, x): return unpack("L", x)[0]
+
+class Attribute_biginteger(Attribute):
+ def encode(self, x): return "\x00" if x == 0 else ("%0*x" % (((x.bit_length() + 7) / 8) * 2, x)).decode("hex")
+ def decode(self, x): return long(x.encode("hex"), 16)
+
+
+class AttributeDB(object):
+
+ def __init__(self):
+ from .attribute_map import attribute_map
+ self.db = {}
+ for attribute_name, type_name in attribute_map.iteritems():
+ a = Attribute.new(attribute_name, type_name)
+ self.db[a.name] = a
+ self.db[a.code] = a
+
+ def encode(self, k, v):
+ return self.db[k].encode(v) if k in self.db else v
+
+ def decode(self, k, v):
+ return self.db[k].decode(v) if k in self.db else v
+
+ def getvalue_create_template(self, attributes):
+ attributes = tuple(self.db[a].code for a in attributes)
+ template = (CK_ATTRIBUTE * len(attributes))()
+ for i in xrange(len(attributes)):
+ template[i].type = attributes[i]
+ template[i].pValue = None
+ template[i].ulValueLen = 0
+ return template
+
+ def getvalue_allocate_template(self, template):
+ for t in template:
+ t.pValue = create_string_buffer(t.ulValueLen)
+
+ def from_ctypes(self, template):
+ return dict((t.type, self.decode(t.type, t.pValue[:t.ulValueLen]))
+ for t in template)
+
+ def to_ctypes(self, attributes):
+ attributes = tuple(attributes.iteritems()
+ if isinstance(attributes, dict) else
+ attributes)
+ template = (CK_ATTRIBUTE * len(attributes))()
+ for i, kv in enumerate(attributes):
+ k, v = kv
+ if k in self.db:
+ a = self.db[k]
+ k, v = a.code, a.encode(v)
+ template[i].type = k
+ template[i].pValue = create_string_buffer(v)
+ template[i].ulValueLen = len(v)
+ return template
+
+ def attribute_name(self, code):
+ return self.db[code].name
+
+ def attribute_code(self, name):
+ return self.db[name].code