[Python-modules-commits] [pykcs11] 01/03: New upstream version 1.4.4

Ludovic Rousseau rousseau at moszumanska.debian.org
Wed Oct 11 13:56:53 UTC 2017


This is an automated email from the git hooks/post-receive script.

rousseau pushed a commit to branch master
in repository pykcs11.

commit ec1a373715c53a9e3e0be65c08fa55a5171063d0
Author: Ludovic Rousseau <rousseau at debian.org>
Date:   Wed Oct 11 14:41:21 2017 +0200

    New upstream version 1.4.4
---
 MANIFEST                                |  12 +++
 Makefile                                |   1 +
 PKG-INFO                                |   2 +-
 PyKCS11/__init__.py                     |  46 +++++++---
 README.md                               |  11 +++
 run_test.py                             |  38 ++++++++
 samples/dumpit.py                       |  10 ++-
 samples/encrypt.py                      |   6 +-
 samples/generate.py                     |   2 +-
 samples/genkeypair_import_cert.py       |   2 +
 samples/getinfo.py                      |  10 ++-
 samples/modulus.py                      |   4 +-
 samples/{generate.py => rsa_encrypt.py} |  18 ++--
 samples/signature.py                    |   6 +-
 samples/unblock.py                      |   2 +-
 setup.py                                |   4 +-
 src/opensc/pkcs11.h                     |   2 +-
 tests/__init__.py                       |   0
 tests/test_CK.py                        |  23 +++++
 tests/test_asymetric.py                 | 154 ++++++++++++++++++++++++++++++++
 tests/test_ckbytelist.py                |  84 +++++++++++++++++
 tests/test_digest.py                    |  38 ++++++++
 tests/test_exception.py                 |  42 +++++++++
 tests/test_info.py                      |  43 +++++++++
 tests/test_random.py                    |  27 ++++++
 tests/test_symetric.py                  |  97 ++++++++++++++++++++
 tox.ini                                 |  16 ++++
 27 files changed, 661 insertions(+), 39 deletions(-)

diff --git a/MANIFEST b/MANIFEST
index 254e192..7a38e8b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -14,6 +14,7 @@ samples/generate.py
 samples/genkeypair_import_cert.py
 samples/getinfo.py
 samples/modulus.py
+samples/rsa_encrypt.py
 samples/signature.py
 samples/unblock.py
 samples/LowLevel/dumpit.py
@@ -23,6 +24,7 @@ samples/LowLevel/test.py
 samples/LowLevel/test1.py
 PyKCS11/LowLevel.py
 PyKCS11/__init__.py
+run_test.py
 src/ck_attribute_smart.cpp
 src/ck_attribute_smart.h
 src/dyn_generic.h
@@ -41,3 +43,13 @@ src/utility.cpp
 src/utility.h
 src/opensc/pkcs11.h
 src/pykcs11_wrap.cpp
+tests/__init__.py
+tests/test_CK.py
+tests/test_asymetric.py
+tests/test_ckbytelist.py
+tests/test_digest.py
+tests/test_exception.py
+tests/test_info.py
+tests/test_random.py
+tests/test_symetric.py
+tox.ini
diff --git a/Makefile b/Makefile
index 1bb07bb..50f5f20 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ doc: build
 	epydoc --verbose PyKCS11
 
 doc-upload: doc
+	rm -r api
 	mv html api
 	scp -r api ludov at web.sourceforge.net:/home/project-web/pkcs11wrap/htdocs
 
diff --git a/PKG-INFO b/PKG-INFO
index 8b383cc..2acc375 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyKCS11
-Version: 1.4.3
+Version: 1.4.4
 Summary: A Full PKCS#11 wrapper for Python
 Home-page: https://github.com/LudovicRousseau/PyKCS11
 Author: Ludovic Rousseau
diff --git a/PyKCS11/__init__.py b/PyKCS11/__init__.py
index a2eda95..eae812b 100644
--- a/PyKCS11/__init__.py
+++ b/PyKCS11/__init__.py
@@ -116,7 +116,7 @@ class ckbytelist(PyKCS11.LowLevel.ckbytelist):
         return the representation of a tuple
         the __str__ method will use it also
         """
-        rep = [elt for elt in self]
+        rep = [int(elt) for elt in self]
         return repr(rep)
 
 
@@ -441,10 +441,15 @@ class PyKCS11Error(Exception):
         The text representation of a PKCS#11 error is something like:
         "CKR_DEVICE_ERROR (0x00000030)"
         """
-        if (self.value < 0):
-            return CKR[self.value] + " (%s)" % self.text
+        if self.value in CKR:
+            if self.value < 0:
+                return CKR[self.value] + " (%s)" % self.text
+            else:
+                return CKR[self.value] + " (0x%08X)" % self.value
+        elif self.value & CKR_VENDOR_DEFINED:
+            return "Vendor error (0x%08X)" % (self.value & 0xffffffff & ~CKR_VENDOR_DEFINED)
         else:
-            return CKR[self.value] + " (0x%08X)" % self.value
+            return "Unknown error (0x%08X)" % self.value
 
 
 class PyKCS11Lib(object):
@@ -962,7 +967,7 @@ class Session(object):
         @param mecha: the digesting mechanism to be used
         @type mecha: L{Mechanism} instance or L{MechanismSHA1}
         for CKM_SHA_1
-        @return: A DigestSession object
+        @return: A L{DigestSession} object
         @rtype: DigestSession
         """
         return DigestSession(self.lib, self.session, mecha)
@@ -981,6 +986,8 @@ class Session(object):
 
         @note: the returned value is an istance of L{ckbytelist}.
         You can easly convert it to a binary string with::
+            bytes(ckbytelistDigest)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistDigest)
 
         """
@@ -1016,6 +1023,8 @@ class Session(object):
 
         @note: the returned value is an instance of L{ckbytelist}.
         You can easly convert it to a binary string with::
+            bytes(ckbytelistSignature)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistSignature)
 
         """
@@ -1081,6 +1090,8 @@ class Session(object):
 
         @note: the returned value is an instance of L{ckbytelist}.
         You can easly convert it to a binary string with::
+            bytes(ckbytelistEncrypted)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistEncrypted)
 
         """
@@ -1116,6 +1127,8 @@ class Session(object):
 
         @note: the returned value is an instance of L{ckbytelist}.
         You can easly convert it to a binary string with::
+            bytes(ckbytelistData)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistData)
 
         """
@@ -1151,6 +1164,8 @@ class Session(object):
 
         @note: the returned value is an instance of L{ckbytelist}.
         You can easily convert it to a binary string with::
+            bytes(ckbytelistData)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistData)
 
         """
@@ -1377,9 +1392,12 @@ class Session(object):
 
         @note: if allAsBinary is True the function do not convert results to
         Python types (i.e.: CKA_TOKEN to Bool, CKA_CLASS to int, ...).
+
         Binary data is returned as L{ckbytelist} type, usable
         as a list containing only bytes.
         You can easly convert it to a binary string with::
+            bytes(ckbytelistVariable)
+        or, for Python 2::
             ''.join(chr(i) for i in ckbytelistVariable)
 
         """
@@ -1388,8 +1406,8 @@ class Session(object):
             valTemplate[x].SetType(attr[x])
         # first call to get the attribute size and reserve the memory
         rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate)
-        if rv == CKR_ATTRIBUTE_TYPE_INVALID \
-           or rv == CKR_ATTRIBUTE_SENSITIVE:
+        if rv in (CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_SENSITIVE,
+                  CKR_ARGUMENTS_BAD):
             return self.getAttributeValue_fragmented(obj_id, attr, allAsBinary)
 
         if rv != CKR_OK:
@@ -1401,7 +1419,7 @@ class Session(object):
 
         res = []
         for x in range(len(attr)):
-            if (allAsBinary):
+            if allAsBinary:
                 res.append(valTemplate[x].GetBin())
             elif valTemplate[x].IsNum():
                 res.append(valTemplate[x].GetNum())
@@ -1434,8 +1452,8 @@ class Session(object):
             valTemplate[0].SetType(attr[x])
             # first call to get the attribute size and reserve the memory
             rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate)
-            if rv == CKR_ATTRIBUTE_TYPE_INVALID \
-               or rv == CKR_ATTRIBUTE_SENSITIVE:
+            if rv in (CKR_ATTRIBUTE_TYPE_INVALID,
+                      CKR_ATTRIBUTE_SENSITIVE, CKR_ARGUMENTS_BAD):
                 # append an empty value
                 res.append(None)
                 continue
@@ -1447,7 +1465,7 @@ class Session(object):
             if rv != CKR_OK:
                 raise PyKCS11Error(rv)
 
-            if (allAsBinary):
+            if allAsBinary:
                 res.append(valTemplate[0].GetBin())
             elif valTemplate[0].IsNum():
                 res.append(valTemplate[0].GetNum())
@@ -1469,9 +1487,7 @@ class Session(object):
         @param seed: seed material
         @type seed: iterable
         """
-        low_seed = ckbytelist(len(seed))
-        for c in range(len(seed)):
-            low_seed.append(seed[c])
+        low_seed = ckbytelist(seed)
         rv = self.lib.C_SeedRandom(self.session, low_seed)
         if rv != CKR_OK:
             raise PyKCS11Error(rv)
@@ -1485,6 +1501,8 @@ class Session(object):
 
         @note: the returned value is an instance of L{ckbytelist}.
         You can easly convert it to a binary string with::
+            bytes(random)
+        or, for Python 2::
             ''.join(chr(i) for i in random)
         """
         low_rand = ckbytelist(size)
diff --git a/README.md b/README.md
index 1aa4014..725ac73 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,17 @@ that doesn't come with the standard distribution.
 History
 =======
 
+1.4.4 - October 2017, Ludovic Rousseau
+   - getAttributeValue(): handle CKR_ARGUMENTS_BAD error
+   - seedRandom: fix the seed convertion
+   - Add vendor errors support to PyKCS11Error
+   - samples/getinfo & dumpit: list only slots with a token present by default
+   - run_test: add support of OpenSC PKCS#11 spy
+   - ckbytelist: update __repr__()
+   - include tests files in the archive
+   - dumpit: display the error if getAttributeValue() fails
+   - some minor improvements
+
 1.4.3 - June 2017, Ludovic Rousseau
    - Add support of CKM_RSA_PKCS_PSS mechanism
    - fix CKM_AES_CBC issue with Python 3
diff --git a/run_test.py b/run_test.py
new file mode 100755
index 0000000..c4504aa
--- /dev/null
+++ b/run_test.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+# use:
+# ./run_test.py
+# ./run_test.py test_ckbytelist.py
+
+from __future__ import print_function
+
+import unittest
+import os
+import sys
+
+pattern = "test*.py"
+if len(sys.argv) > 1:
+    pattern = sys.argv[1]
+
+if "PKCS11SPY" in os.environ:
+    # use OpenSC PKCS#11 spy if PKCS11SPY is defined
+    LIBS = ["/usr/local/lib/pkcs11/pkcs11-spy.so",  # macOS or local build
+            "/usr/lib/x86_64-linux-gnu/pkcs11-spy.so"]  # Debian amd64
+else:
+    # use SoftHSM2 or SoftHSM1
+    LIBS = ["/usr/local/lib/softhsm/libsofthsm2.so",  # macOS or local build
+            "/usr/lib/softhsm/libsofthsm2.so",  # Debian libsofthsm2
+            "/usr/lib/softhsm/libsofthsm.so",  # Debian libsofthsm
+            "/usr/lib/libsofthsm.so"]  # Ubuntu 12.04 libsofthsm
+
+for lib in LIBS:
+    if os.path.isfile(lib):
+        print("Using lib:", lib)
+        os.environ['PYKCS11LIB'] = lib
+        break
+
+tl = unittest.TestLoader()
+suite = tl.discover("tests", pattern=pattern)
+result = unittest.TextTestRunner(verbosity=2).run(suite)
+if result.errors or result.failures:
+    sys.exit(1)
diff --git a/samples/dumpit.py b/samples/dumpit.py
index 374d7ab..8e1335c 100755
--- a/samples/dumpit.py
+++ b/samples/dumpit.py
@@ -55,6 +55,7 @@ def dump(src, length=16):
 
 def usage():
     print("Usage:", sys.argv[0], end=' ')
+    print("[-a][--all]", end=' ')
     print("[-p pin][--pin=pin] (use --pin=NULL for pinpad)", end=' ')
     print("[-c lib][--lib=lib]", end=' ')
     print("[-S][--sign]", end=' ')
@@ -64,7 +65,8 @@ def usage():
     print()
 
 try:
-    opts, args = getopt.getopt(sys.argv[1:], "p:c:Sdhs:", ["pin=", "lib=", "sign", "decrypt", "slot=", "help"])
+    opts, args = getopt.getopt(sys.argv[1:], "p:c:Sdhs:a",
+       ["pin=", "lib=", "sign", "decrypt", "slot=", "help", "all"])
 except getopt.GetoptError:
     # print help information and exit:
     usage()
@@ -74,6 +76,7 @@ pin_available = False
 decrypt = sign = False
 lib = None
 slot = None
+token_present = True
 for o, a in opts:
     if o in ("-h", "--help"):
         usage()
@@ -92,6 +95,8 @@ for o, a in opts:
         decrypt = True
     elif o in ("-s", "--slot"):
         slot = int(a)
+    if o in ("-a", "--all"):
+        token_present = False
 
 red = blue = magenta = normal = ""
 if sys.stdout.isatty() and platform.system().lower() != 'windows':
@@ -109,7 +114,7 @@ pkcs11.load(lib)
 info = pkcs11.getInfo()
 print("Library manufacturerID:", info.manufacturerID)
 
-slots = pkcs11.getSlotList()
+slots = pkcs11.getSlotList(token_present)
 print("Available Slots:", len(slots), slots)
 
 if slot is not None:
@@ -165,6 +170,7 @@ for s in slots:
             try:
                 attributes = session.getAttributeValue(o, all_attributes)
             except PyKCS11.PyKCS11Error as e:
+                print(e)
                 continue
             attrDict = dict(list(zip(all_attributes, attributes)))
             if attrDict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_PRIVATE_KEY \
diff --git a/samples/encrypt.py b/samples/encrypt.py
index 11240d9..316dc88 100755
--- a/samples/encrypt.py
+++ b/samples/encrypt.py
@@ -25,7 +25,7 @@ pkcs11 = PyKCS11Lib()
 pkcs11.load()  # define environment variable PYKCS11LIB=YourPKCS11Lib
 
 # get 1st slot
-slot = pkcs11.getSlotList()[0]
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 
 session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
 session.login("1234")
@@ -40,8 +40,8 @@ enc = session.encrypt(pubKey, binascii.unhexlify(message))
 dec = session.decrypt(privKey, enc)
 
 print("\nmessage: " + message)
-print("\nencrypted: " + binascii.hexlify(bytearray(enc)))
-print("\ndecrypted: " + bytearray(dec))
+print("\nencrypted: {}".format(binascii.hexlify(bytearray(enc))))
+print("\ndecrypted: {}".format(bytearray(dec)))
 
 # logout
 session.logout()
diff --git a/samples/generate.py b/samples/generate.py
index 3c3508c..f35ebec 100755
--- a/samples/generate.py
+++ b/samples/generate.py
@@ -22,7 +22,7 @@ pkcs11 = PyKCS11Lib()
 pkcs11.load()  # define environment variable PYKCS11LIB=YourPKCS11Lib
 
 # get 1st slot
-slot = pkcs11.getSlotList()[0]
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 
 session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
 session.login("1234")
diff --git a/samples/genkeypair_import_cert.py b/samples/genkeypair_import_cert.py
index eaf00ba..43d409a 100755
--- a/samples/genkeypair_import_cert.py
+++ b/samples/genkeypair_import_cert.py
@@ -111,6 +111,8 @@ cert_template = [
     (PyKCS11.CKA_ID, key_id)  # must be set, and DER see Table 24, X.509 Certificate Object Attributes
     ]
 
+# create the certificate object
+session.createObject(cert_template)
 
 # logout
 session.logout()
diff --git a/samples/getinfo.py b/samples/getinfo.py
index 70d17ef..0b7be92 100755
--- a/samples/getinfo.py
+++ b/samples/getinfo.py
@@ -96,6 +96,7 @@ class getInfo(object):
 
 def usage():
     print("Usage:", sys.argv[0], end=' ')
+    print("[-a][--all]", end=' ')
     print("[-p pin][--pin=pin] (use 'NULL' for pinpad)", end=' ')
     print("[-s slot][--slot=slot]", end=' ')
     print("[-c lib][--lib=lib]", end=' ')
@@ -105,8 +106,8 @@ if __name__ == '__main__':
     import getopt
 
     try:
-        opts, args = getopt.getopt(sys.argv[1:], "p:s:c:ho",
-            ["pin=", "slot=", "lib=", "help", "opensession"])
+        opts, args = getopt.getopt(sys.argv[1:], "p:s:c:hoa",
+            ["pin=", "slot=", "lib=", "help", "opensession", "all"])
     except getopt.GetoptError:
         # print help information and exit:
         usage()
@@ -115,6 +116,7 @@ if __name__ == '__main__':
     slot = None
     lib = None
     pin = ""
+    token_present = True
     for o, a in opts:
         if o in ("-h", "--help"):
             usage()
@@ -127,11 +129,13 @@ if __name__ == '__main__':
             slot = int(a)
         if o in ("-c", "--lib"):
             lib = a
+        if o in ("-a", "--all"):
+            token_present = False
 
     gi = getInfo(lib)
     gi.getInfo()
 
-    slots = gi.pkcs11.getSlotList()
+    slots = gi.pkcs11.getSlotList(token_present)
     print("Available Slots:", len(slots), slots)
 
     if len(slots) == 0:
diff --git a/samples/modulus.py b/samples/modulus.py
index 716ec90..2e9cd24 100755
--- a/samples/modulus.py
+++ b/samples/modulus.py
@@ -25,7 +25,7 @@ pkcs11 = PyKCS11Lib()
 pkcs11.load()  # define environment variable PYKCS11LIB=YourPKCS11Lib
 
 # get 1st slot
-slot = pkcs11.getSlotList()[0]
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 
 session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
 session.login("1234")
@@ -36,7 +36,7 @@ keyID = (0x22,)
 # find public key and print modulus
 pubKey = session.findObjects([(CKA_CLASS, CKO_PUBLIC_KEY), (CKA_ID, keyID)])[0]
 modulus = session.getAttributeValue(pubKey, [CKA_MODULUS])[0]
-print("\nmodulus: " + binascii.hexlify(bytearray(modulus)))
+print("\nmodulus: {}".format(binascii.hexlify(bytearray(modulus))))
 
 # logout
 session.logout()
diff --git a/samples/generate.py b/samples/rsa_encrypt.py
similarity index 78%
copy from samples/generate.py
copy to samples/rsa_encrypt.py
index 3c3508c..269d945 100755
--- a/samples/generate.py
+++ b/samples/rsa_encrypt.py
@@ -22,7 +22,7 @@ pkcs11 = PyKCS11Lib()
 pkcs11.load()  # define environment variable PYKCS11LIB=YourPKCS11Lib
 
 # get 1st slot
-slot = pkcs11.getSlotList()[0]
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 
 session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
 session.login("1234")
@@ -31,14 +31,14 @@ pubTemplate = [
     (CKA_CLASS, CKO_PUBLIC_KEY),
     (CKA_TOKEN, CK_TRUE),
     (CKA_PRIVATE, CK_FALSE),
-    (CKA_MODULUS_BITS, 0x0400),
+    (CKA_MODULUS_BITS, 2048),
     (CKA_PUBLIC_EXPONENT, (0x01, 0x00, 0x01)),
     (CKA_ENCRYPT, CK_TRUE),
     (CKA_VERIFY, CK_TRUE),
     (CKA_VERIFY_RECOVER, CK_TRUE),
     (CKA_WRAP, CK_TRUE),
-    (CKA_LABEL, "My Public Key"),
-    (CKA_ID, (0x22,))
+    (CKA_LABEL, "Encryption key"),
+    (CKA_ID, (0x43,))
 ]
 
 privTemplate = [
@@ -49,11 +49,17 @@ privTemplate = [
     (CKA_SIGN, CK_TRUE),
     (CKA_SIGN_RECOVER, CK_TRUE),
     (CKA_UNWRAP, CK_TRUE),
-    (CKA_ID, (0x22,))
+    (CKA_ID, (0x43,))
 ]
 
 (pubKey, privKey) = session.generateKeyPair(pubTemplate, privTemplate)
 
-# logout
+PLAINTEXT = "A test string"
+mech = RSAOAEPMechanism(CKM_SHA_1, CKG_MGF1_SHA1)
+ciphertext = session.encrypt(pubKey, PLAINTEXT, mech)
+decrypted = "".join([chr(i) for i in session.decrypt(privKey, ciphertext, mech)])
+assert decrypted == PLAINTEXT
+
 session.logout()
 session.closeSession()
+print("That's all folks!")
diff --git a/samples/signature.py b/samples/signature.py
index 22931cb..1d43dab 100755
--- a/samples/signature.py
+++ b/samples/signature.py
@@ -24,8 +24,8 @@ import binascii
 pkcs11 = PyKCS11Lib()
 pkcs11.load()  # define environment variable PYKCS11LIB=YourPKCS11Lib
 
-# get 3rd slot
-slot = pkcs11.getSlotList()[0]
+# get 1st slot
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 
 session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
 session.login("1234")
@@ -39,7 +39,7 @@ toSign = "48656c6c6f20776f726c640d0a"
 # find private key and compute signature
 privKey = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY), (CKA_ID, keyID)])[0]
 signature = session.sign(privKey, binascii.unhexlify(toSign), Mechanism(CKM_SHA1_RSA_PKCS, None))
-print("\nsignature: " + binascii.hexlify(bytearray(signature)))
+print("\nsignature: {}".format(binascii.hexlify(bytearray(signature))))
 
 # find public key and verify signature
 pubKey = session.findObjects([(CKA_CLASS, CKO_PUBLIC_KEY), (CKA_ID, keyID)])[0]
diff --git a/samples/unblock.py b/samples/unblock.py
index 65eeaaf..6c54ae4 100755
--- a/samples/unblock.py
+++ b/samples/unblock.py
@@ -25,7 +25,7 @@ puk = "1234"
 
 pkcs11 = PyKCS11.PyKCS11Lib()
 pkcs11.load()
-slot = pkcs11.getSlotList()[0]
+slot = pkcs11.getSlotList(tokenPresent=True)[0]
 session = pkcs11.openSession(slot, PyKCS11.CKF_RW_SESSION)
 session.login(puk, PyKCS11.CKU_SO)
 session.initPin(pin)
diff --git a/setup.py b/setup.py
index 3ea780d..c19ba48 100755
--- a/setup.py
+++ b/setup.py
@@ -46,7 +46,7 @@ if (platform.system().lower() == 'windows'):
     source_files.append("src/dyn_win32.c")
     source_files.append("pykcs11.rc")
     libraries_val = ["python%d%d" % pyver[:2]]
-    extra_compile_args = ["/Fdvc70.pdb", "/Zi", "/GR"]
+    extra_compile_args = ["/Fdvc70.pdb", "/Zi", "/GR", "/EHsc"]
     extra_link_args = ["/DEBUG", "/PDB:_LowLevel.pdb", "/SUBSYSTEM:WINDOWS", "/OPT:REF", "/OPT:ICF"]
 else:
     source_files.append("src/dyn_unix.c")
@@ -55,7 +55,7 @@ else:
     libraries_val = []
 
 setup(name="PyKCS11",
-    version="1.4.3",
+    version="1.4.4",
     description="A Full PKCS#11 wrapper for Python",
     keywords="crypto,pki,pkcs11,c++",
     classifiers=classifiers,
diff --git a/src/opensc/pkcs11.h b/src/opensc/pkcs11.h
index 02c7419..aabf144 100644
--- a/src/opensc/pkcs11.h
+++ b/src/opensc/pkcs11.h
@@ -707,7 +707,7 @@ struct ck_rsa_pkcs_oaep_params {
   unsigned long source_data_len;
 } ;
 
-typedef struct ck_rsa_pkcs_pss_params {
+struct ck_rsa_pkcs_pss_params {
   unsigned long hashAlg;
   unsigned long mgf;
   unsigned long sLen;
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_CK.py b/tests/test_CK.py
new file mode 100644
index 0000000..216bc39
--- /dev/null
+++ b/tests/test_CK.py
@@ -0,0 +1,23 @@
+#! /usr/bin/env python
+
+# execute using:
+# python tests/CK_test.py
+
+import unittest
+import PyKCS11
+
+
+class TestUtil(unittest.TestCase):
+
+    def test_CKM(self):
+        self.assertEqual(PyKCS11.CKM_RSA_PKCS_KEY_PAIR_GEN, 0x00000000)
+        self.assertEqual(PyKCS11.CKM[PyKCS11.CKM_RSA_PKCS_KEY_PAIR_GEN],
+                         'CKM_RSA_PKCS_KEY_PAIR_GEN')
+
+        self.assertEqual(PyKCS11.CKM_VENDOR_DEFINED, 0x80000000)
+
+    def test_CKR(self):
+        self.assertEqual(PyKCS11.CKR_VENDOR_DEFINED, 0x80000000)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_asymetric.py b/tests/test_asymetric.py
new file mode 100644
index 0000000..c206bad
--- /dev/null
+++ b/tests/test_asymetric.py
@@ -0,0 +1,154 @@
+import unittest
+from PyKCS11 import PyKCS11
+
+
+class TestUtil(unittest.TestCase):
+
+    def setUp(self):
+        self.pkcs11 = PyKCS11.PyKCS11Lib()
+        self.pkcs11.load()
+        self.slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
+        self.session = self.pkcs11.openSession(self.slot,
+                                               PyKCS11.CKF_SERIAL_SESSION |
+                                               PyKCS11.CKF_RW_SESSION)
+        self.session.login("1234")
+
+        keyID = (0x22,)
+        pubTemplate = [
+            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PUBLIC_KEY),
+            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
+            (PyKCS11.CKA_MODULUS_BITS, 0x0400),
+            (PyKCS11.CKA_PUBLIC_EXPONENT, (0x01, 0x00, 0x01)),
+            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_VERIFY, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_VERIFY_RECOVER, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_WRAP, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_LABEL, "My Public Key"),
+            (PyKCS11.CKA_ID, keyID)
+        ]
+
+        privTemplate = [
+            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY),
+            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_SIGN, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_SIGN_RECOVER, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_UNWRAP, PyKCS11.CK_TRUE),
+            (PyKCS11.CKA_ID, keyID)
+        ]
+
+        (self.pubKey, self.privKey) = self.session.generateKeyPair(pubTemplate, privTemplate)
+        self.assertIsNotNone(self.pubKey)
+        self.assertIsNotNone(self.privKey)
+
+    def tearDown(self):
+        self.session.destroyObject(self.pubKey)
+        self.session.destroyObject(self.privKey)
+
+        self.session.logout()
+        self.pkcs11.closeAllSessions(self.slot)
+        del self.pkcs11
+
+    def test_sign_PKCS(self):
+        toSign = "Hello world"
+
+        # sign/verify
+        signature = self.session.sign(self.privKey, toSign,
+                PyKCS11.Mechanism(PyKCS11.CKM_SHA1_RSA_PKCS, None))
+
+        result = self.session.verify(self.pubKey, toSign, signature,
+                PyKCS11.Mechanism(PyKCS11.CKM_SHA1_RSA_PKCS, None))
+
+        self.assertTrue(result)
+
+    def test_sign_X509(self):
+        toSign = "Hello world"
+
+        # sign/verify
+        try:
+            signature = self.session.sign(self.privKey, toSign,
+                    PyKCS11.Mechanism(PyKCS11.CKM_RSA_X_509, None))
+
+            result = self.session.verify(self.pubKey, toSign, signature,
+                    PyKCS11.Mechanism(PyKCS11.CKM_RSA_X_509, None))
+
+            self.assertTrue(result)
+        except PyKCS11.PyKCS11Error as e:
+            # RSA X509 is not supported by SoftHSM1
+            if not e.value == PyKCS11.CKR_MECHANISM_INVALID:
+                raise
+
+    def test_encrypt_PKCS(self):
+        # encrypt/decrypt using CMK_RSA_PKCS (default)
+        dataIn = "Hello world"
+        encrypted = self.session.encrypt(self.pubKey, dataIn)
+        decrypted = self.session.decrypt(self.privKey, encrypted)
+
+        # convert in a string
+        text = "".join(map(chr, decrypted))
+
+        self.assertEqual(dataIn, text)
+
+    def test_encrypt_X509(self):
+        # encrypt/decrypt using CKM_RSA_X_509
+        dataIn = "Hello world!"
+        mecha = PyKCS11.Mechanism(PyKCS11.CKM_RSA_X_509, None)
+        try:
+            encrypted = self.session.encrypt(self.pubKey, dataIn, mecha=mecha)
+            decrypted = self.session.decrypt(self.privKey, encrypted, mecha=mecha)
+
+            # remove padding NUL bytes
+            padding_length = 0
+            for e in decrypted:
+                if e != 0:
+                    break
+                padding_length += 1
+            decrypted = list(decrypted)[padding_length:]
+
+            # convert in a string
+            text = "".join(map(chr, decrypted))
+
+            self.assertEqual(dataIn, text)
+        except PyKCS11.PyKCS11Error as e:
+            # RSA X509 is not supported by SoftHSM1
+            if not e.value == PyKCS11.CKR_MECHANISM_INVALID:
+                raise
+
+    def test_RSA_OAEP(self):
+        # RSA OAEP
+        plainText = "A test string"
+
+        mech = PyKCS11.RSAOAEPMechanism(PyKCS11.CKM_SHA_1, PyKCS11.CKG_MGF1_SHA1)
+        try:
+            cipherText = self.session.encrypt(self.pubKey, plainText, mech)
+            decrypted = self.session.decrypt(self.privKey, cipherText, mech)
+
+            text = "".join(map(chr, decrypted))
+
+            self.assertEqual(text, plainText)
+        except PyKCS11.PyKCS11Error as e:
+            # RSA OAEP is not supported by SoftHSM1
+            if not e.value == PyKCS11.CKR_MECHANISM_INVALID:
+                raise
+
+    def test_RSA_PSS(self):
+        # RSA PSS
+        plainText = "A test string"
+
+        mech = PyKCS11.RSA_PSS_Mechanism(PyKCS11.CKM_SHA384, PyKCS11.CKG_MGF1_SHA384, 48)
+        try:
+            cipherText = self.session.encrypt(self.pubKey, plainText, mech)
+            decrypted = self.session.decrypt(self.privKey, cipherText, mech)
+            text = "".join(map(chr, decrypted))
+
+            self.assertEqual(text, plainText)
+        except PyKCS11.PyKCS11Error as e:
+            # RSA PSS is not yet supported by SoftHSM2
+            if not e.value == PyKCS11.CKR_MECHANISM_INVALID:
+                raise
+
+        # test CK_OBJECT_HANDLE.__repr__()
+        text = str(self.pubKey)
+        self.assertIsNotNone(text)
diff --git a/tests/test_ckbytelist.py b/tests/test_ckbytelist.py
new file mode 100644
index 0000000..82fdca8
--- /dev/null
+++ b/tests/test_ckbytelist.py
@@ -0,0 +1,84 @@
+import unittest
+import PyKCS11
+
+
+class Testutil(unittest.TestCase):
+
+    def test_empty(self):
+        ck = PyKCS11.ckbytelist()
+        self.assertSequenceEqual(ck, [])
+
+    def test_resize(self):
+        ck = PyKCS11.ckbytelist()
+        ck.resize(5)
+        self.assertSequenceEqual(ck, [0, 0, 0, 0, 0])
+
+    def test_data(self):
+        ck = PyKCS11.ckbytelist(5)
+        for index in range(5):
+            ck[index] = index
+        self.assertSequenceEqual(ck, [0, 1, 2, 3, 4])
+
+    def test_append(self):
+        ck = PyKCS11.ckbytelist()
+        for index in range(5):
+            ck.append(index)
+        self.assertSequenceEqual(ck, [0, 1, 2, 3, 4])
+
+    def test_length0(self):
+        ck = PyKCS11.ckbytelist()
+        self.assertEqual(len(ck), 0)
+
+    def test_length5(self):
+        ck = PyKCS11.ckbytelist(5)
+        self.assertEqual(len(ck), 5)
+
+    def test_string(self):
+        ck = PyKCS11.ckbytelist()
+        ck.resize(5)
+        for index in range(5):
+            ck[index] = index
+        self.assertEqual(str(ck), "[0, 1, 2, 3, 4]")
+
+    def test_init_list0(self):
+        ck = PyKCS11.ckbytelist([])
+        self.assertSequenceEqual(ck, [])
+
+    def test_init_list1(self):
+        ck = PyKCS11.ckbytelist([1])
+        self.assertSequenceEqual(ck, [1])
+
+    def test_init_list5(self):
+        ck = PyKCS11.ckbytelist([0, 1, 2, 3, 4])
+        self.assertSequenceEqual(ck, [0, 1, 2, 3, 4])
+
+    def test_init_str(self):
+        ck = PyKCS11.ckbytelist("ABC")
+        self.assertSequenceEqual(ck, [65, 66, 67])
+
+    def test_init_bytes(self):
+        ck = PyKCS11.ckbytelist(b"ABC")
+        self.assertSequenceEqual(ck, [65, 66, 67])
+
+    def test_init_ckbytelist(self):
+        ck1 = PyKCS11.ckbytelist(b"ABC")
+        ck2 = PyKCS11.ckbytelist(ck1)
+        self.assertSequenceEqual(ck2, [65, 66, 67])
+
+    def test_unknown_format(self):
+        with self.assertRaises(PyKCS11.PyKCS11Error) as cm:
+            PyKCS11.ckbytelist(dict())
+
+        the_exception = cm.exception
+        self.assertEqual(the_exception.value, -3)
+        import sys
+        if sys.version_info[0] >= 3:
+            # Python 3 and later
+            expected = "Unknown format (<class 'dict'>)"
+        else:
+            # Python 2
+            expected = "Unknown format (<type 'dict'>)"
+        self.assertEqual(str(the_exception), expected)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_digest.py b/tests/test_digest.py
new file mode 100644
index 0000000..25d1f94
--- /dev/null
+++ b/tests/test_digest.py
@@ -0,0 +1,38 @@
+#! /usr/bin/env python
+
+# execute using:
+# python tests/CK_test.py
+
+import unittest
+from PyKCS11 import PyKCS11
+
+# SHA1 of "abc"
+SHA1_abc = [0xa9, 0x99, 0x3e, 0x36, 0x47, 0x6, 0x81, 0x6a, 0xba, 0x3e,
+            0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d]
+
+
+class TestUtil(unittest.TestCase):
+
+    def setUp(self):
+        self.pkcs11 = PyKCS11.PyKCS11Lib()
+        self.pkcs11.load()
+        self.slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
+        self.session = self.pkcs11.openSession(self.slot,
+                                               PyKCS11.CKF_SERIAL_SESSION)
+
+    def tearDown(self):
+        self.pkcs11.closeAllSessions(self.slot)
+        del self.pkcs11
+
+    def test_digest(self):
+        digest = self.session.digest("abc")
+        self.assertSequenceEqual(digest, SHA1_abc)
+
+    def test_digestSession(self):
+        digestSession = self.session.digestSession()
+        digestSession.update("abc")
+        digest = digestSession.final()
+        self.assertSequenceEqual(digest, SHA1_abc)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_exception.py b/tests/test_exception.py
new file mode 100644
index 0000000..15866e9
--- /dev/null
+++ b/tests/test_exception.py
@@ -0,0 +1,42 @@
+import unittest
+import PyKCS11
+
+
+class Testutil(unittest.TestCase):
+
+    def test_empty(self):
+        e = PyKCS11.PyKCS11Error(0)
+        self.assertEqual(e.value, 0)
+
+    def test_CKR_OK(self):
+        e = PyKCS11.PyKCS11Error(PyKCS11.CKR_OK)
+        self.assertEqual(e.value, 0)
+        self.assertEqual(str(e), "CKR_OK (0x00000000)")
+
+    def test_CKR_PIN_INVALID(self):
+        e = PyKCS11.PyKCS11Error(PyKCS11.CKR_PIN_INVALID)
+        self.assertEqual(e.value, 0xa1)
+        self.assertEqual(str(e), "CKR_PIN_INVALID (0x000000A1)")
+
+    def test_Load(self):
+        e = PyKCS11.PyKCS11Error(-1, "Pouet")
+        self.assertEqual(e.value, -1)
+        self.assertEqual(str(e), "Load (Pouet)")
+
+    def test_raise(self):
+        with self.assertRaises(PyKCS11.PyKCS11Error):
+            raise PyKCS11.PyKCS11Error(0)
+
+    def test_unknown(self):
+        e = PyKCS11.PyKCS11Error(PyKCS11.CKR_VENDOR_DEFINED - 1)
+        self.assertEqual(str(e), "Unknown error (0x7FFFFFFF)")
+
+    def test_vendor0(self):
+        e = PyKCS11.PyKCS11Error(PyKCS11.CKR_VENDOR_DEFINED, "Pouet")
+        self.assertEqual(e.value, PyKCS11.CKR_VENDOR_DEFINED)
+        self.assertEqual(str(e), "Vendor error (0x00000000)")
+
+    def test_vendor10(self):
+        e = PyKCS11.PyKCS11Error(PyKCS11.CKR_VENDOR_DEFINED + 10)
+        self.assertEqual(e.value, PyKCS11.CKR_VENDOR_DEFINED + 10)
+        self.assertEqual(str(e), "Vendor error (0x0000000A)")
diff --git a/tests/test_info.py b/tests/test_info.py
new file mode 100644
index 0000000..ff968e7
--- /dev/null
+++ b/tests/test_info.py
@@ -0,0 +1,43 @@
+import unittest
+from PyKCS11 import PyKCS11
... 199 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pykcs11.git



More information about the Python-modules-commits mailing list