From de394def1041399cd59517765ea856a99743d15b Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 8 Aug 2023 10:59:19 +0100 Subject: [PATCH 01/18] Update test_sessions.py --- tests/test_sessions.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index f9a24e7..9724a8b 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -158,3 +158,20 @@ def test_generate_random(self): self.assertEqual(len(random), 16) # Ensure we didn't get 16 bytes of zeros self.assertTrue(all(c != '\0' for c in random)) + + @Only.softhsm2 + def test_set_pin(self): + old_token_pin = "1234" + new_token_pin = "12345" + + with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session: + self.assertTrue(session.init_pin(old_token_pin)) + + # Open a session with read-write access using the SO PIN + with self.token.open(rw=True, user_pin=old_token_pin) as session: + self.assertTrue(session.set_pin(old_token_pin, new_token_pin)) + + # Open a session with the user PIN set to the temporary token PIN + with self.token.open(user_pin=new_token_pin) as session: + # Check that the session is an instance of pkcs11.Session + self.assertIsInstance(session, pkcs11.Session) From d2da558b2067557566feab2f0347edee6dd605e7 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:01:43 +0100 Subject: [PATCH 02/18] Update _pkcs11.pyx --- pkcs11/_pkcs11.pyx | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index c0e5f44..621399c 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -678,6 +678,30 @@ class Session(types.Session): &length)) return bytes(digest[:length]) + def set_pin(self, old_pin, new_pin): + cdef CK_ULONG old_pin_length + cdef CK_ULONG new_pin_length + cdef CK_OBJECT_HANDLE handle = self._handle + cdef CK_UTF8CHAR *old_pin_data + cdef CK_UTF8CHAR *new_pin_data + + if old_pin is None or new_pin is None: + raise ArgumentsBad("Set `user_pin`") + + pin_old = old_pin.encode('utf-8') + pin_new = new_pin.encode('utf-8') + + if pin_old and pin_new: + old_pin_data = pin_old + new_pin_data = pin_new + old_pin_length = len(pin_old) + new_pin_length = len(pin_new) + + with nogil: + assertRV(_funclist.C_SetPIN(handle, old_pin_data, old_pin_length, new_pin_data, new_pin_length)) + return True + + return False class Object(types.Object): From 59681ac1bbe8138c3b631288ef67ad9b7a2f23fe Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:09:17 +0100 Subject: [PATCH 03/18] Update test_sessions.py --- tests/test_sessions.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 9724a8b..815f948 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -164,14 +164,8 @@ def test_set_pin(self): old_token_pin = "1234" new_token_pin = "12345" - with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session: - self.assertTrue(session.init_pin(old_token_pin)) - - # Open a session with read-write access using the SO PIN with self.token.open(rw=True, user_pin=old_token_pin) as session: self.assertTrue(session.set_pin(old_token_pin, new_token_pin)) - # Open a session with the user PIN set to the temporary token PIN with self.token.open(user_pin=new_token_pin) as session: - # Check that the session is an instance of pkcs11.Session self.assertIsInstance(session, pkcs11.Session) From 0edf06742b4dca2f0ef777b2f1c43b4b49ce5627 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Wed, 9 Aug 2023 09:29:32 +0100 Subject: [PATCH 04/18] Update types.py --- pkcs11/types.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index 34f7678..a4396fd 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -529,8 +529,8 @@ def generate_random(self, nbits): :param int nbits: Number of bits to generate. :rtype: bytes """ - raise NotImplementedError() - + raise NotImplementedError() + def digest(self, data, **kwargs): """ Digest `data` using `mechanism`. @@ -559,7 +559,9 @@ def digest(self, data, **kwargs): data = (data,) return self._digest_generator(data, **kwargs) - + + def set_pin(self, old_pin, new_pin): + pass class Object: """ From 88a8035ce2f0a9eff5d607b327ebdedf7e78f7ff Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:43:24 +0100 Subject: [PATCH 05/18] Update _pkcs11.pyx --- pkcs11/_pkcs11.pyx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index 621399c..61c1dd3 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -684,21 +684,32 @@ class Session(types.Session): cdef CK_OBJECT_HANDLE handle = self._handle cdef CK_UTF8CHAR *old_pin_data cdef CK_UTF8CHAR *new_pin_data - + if old_pin is None or new_pin is None: raise ArgumentsBad("Set `user_pin`") pin_old = old_pin.encode('utf-8') pin_new = new_pin.encode('utf-8') + print("Before altering:") + print(" old_pin =", pin_old, "length =", len(pin_old)) + print(" new_pin =", pin_new, "length =", len(pin_new)) + if pin_old and pin_new: old_pin_data = pin_old new_pin_data = pin_new old_pin_length = len(pin_old) new_pin_length = len(pin_new) - + + print("Before C_SetPIN call") with nogil: assertRV(_funclist.C_SetPIN(handle, old_pin_data, old_pin_length, new_pin_data, new_pin_length)) + print("After C_SetPIN call") + + print("After altering:") + print(" old_pin =", pin_old, "length =", len(pin_old)) + print(" new_pin =", pin_new, "length =", len(pin_new)) + return True return False From 5923c087431b0f6d031c0007e3d9004df55cf6f1 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:43:58 +0100 Subject: [PATCH 06/18] Update types.py --- pkcs11/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index a4396fd..b40c069 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -561,7 +561,7 @@ def digest(self, data, **kwargs): return self._digest_generator(data, **kwargs) def set_pin(self, old_pin, new_pin): - pass + raise NotImplementedError() class Object: """ From aa97873c03b0762df67a1b87fd0eb92a86d05d09 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Wed, 9 Aug 2023 20:30:23 +0100 Subject: [PATCH 07/18] Update _pkcs11.pyx removed the prints --- pkcs11/_pkcs11.pyx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index 61c1dd3..389802f 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -678,6 +678,7 @@ class Session(types.Session): &length)) return bytes(digest[:length]) + def set_pin(self, old_pin, new_pin): cdef CK_ULONG old_pin_length cdef CK_ULONG new_pin_length @@ -690,10 +691,6 @@ class Session(types.Session): pin_old = old_pin.encode('utf-8') pin_new = new_pin.encode('utf-8') - - print("Before altering:") - print(" old_pin =", pin_old, "length =", len(pin_old)) - print(" new_pin =", pin_new, "length =", len(pin_new)) if pin_old and pin_new: old_pin_data = pin_old @@ -701,15 +698,8 @@ class Session(types.Session): old_pin_length = len(pin_old) new_pin_length = len(pin_new) - print("Before C_SetPIN call") with nogil: assertRV(_funclist.C_SetPIN(handle, old_pin_data, old_pin_length, new_pin_data, new_pin_length)) - print("After C_SetPIN call") - - print("After altering:") - print(" old_pin =", pin_old, "length =", len(pin_old)) - print(" new_pin =", pin_new, "length =", len(pin_new)) - return True return False From 05a4df19ff87f545c905a67696088586accce46a Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Thu, 17 Aug 2023 13:15:22 +0100 Subject: [PATCH 08/18] Update types.py --- pkcs11/types.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkcs11/types.py b/pkcs11/types.py index b40c069..adede71 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -562,6 +562,16 @@ def digest(self, data, **kwargs): def set_pin(self, old_pin, new_pin): raise NotImplementedError() + + def init_pin(self, token_label, so_pin): + raise NotImplementedError() + + def login(self, user_pin, user_type=None): + raise NotImplementedError() + + def logout(self): + raise NotImplementedError() + class Object: """ From 82d688da8fd56969390bc7de5aaea535df332381 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 22 Aug 2023 23:13:58 +0100 Subject: [PATCH 09/18] Update _pkcs11.pyx --- pkcs11/_pkcs11.pyx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index 389802f..5ef8809 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -703,6 +703,27 @@ class Session(types.Session): return True return False + + def init_pin(self, user_pin): + cdef CK_OBJECT_HANDLE handle = self._handle + cdef CK_UTF8CHAR *pin_data + cdef CK_ULONG pin_length + + if user_pin is None: + raise ArgumentsBad("Set `user_pin`") + + pin = user_pin.encode('utf-8') + + if pin: + pin_data = pin + pin_length = len(pin) + + with nogil: + assertRV(_funclist.C_InitPIN(handle, pin_data, pin_length)) + + return True + + return False class Object(types.Object): From 54a44110d0fa22db80088cd09a0b6511f5c1c840 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 22 Aug 2023 23:16:52 +0100 Subject: [PATCH 10/18] Update types.py --- pkcs11/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index adede71..4a19c3f 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -563,7 +563,7 @@ def digest(self, data, **kwargs): def set_pin(self, old_pin, new_pin): raise NotImplementedError() - def init_pin(self, token_label, so_pin): + def init_pin(self, user_pin): raise NotImplementedError() def login(self, user_pin, user_type=None): From 25040fafbef66b910e52f5d0ed60ef7c8f9a3d81 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 22 Aug 2023 23:51:28 +0100 Subject: [PATCH 11/18] Update _pkcs11.pyx --- pkcs11/_pkcs11.pyx | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index 5ef8809..d59c0c9 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -724,6 +724,41 @@ class Session(types.Session): return True return False + def logout(self): + cdef CK_OBJECT_HANDLE handle = self._handle + + with nogil: + assertRV(_funclist.C_Logout(handle)) + + return True + + def login(self, user_pin, user_type=None): + cdef CK_OBJECT_HANDLE handle = self._handle + cdef CK_USER_TYPE final_user_type + cdef CK_ULONG pin_len + cdef CK_UTF8CHAR *pin_data + + pin = user_pin.encode("utf-8") + + if pin is not None: + final_user_type = user_type if user_type is not None else CKU_USER + pin_data = pin + pin_len = len(pin) + + print("Attempting login as:", final_user_type) + + with nogil: + assertRV(_funclist.C_Login(handle, final_user_type, pin_data, pin_len)) + + print("Login successful as:", final_user_type) + return True + else: + pin_data = NULL + pin_len = 0 + final_user_type = UserType.NOBODY + + print("Logged in as:", final_user_type) + return False class Object(types.Object): From e5451e1908df3a45996e6f32e151e1b12b92570a Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:30:58 +0100 Subject: [PATCH 12/18] Update types.py Added try catch mechanism to catch the UnicodeDecodeError --- pkcs11/types.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index 4a19c3f..27ef10e 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -32,7 +32,19 @@ def _CK_UTF8CHAR_to_str(data): """Convert CK_UTF8CHAR to string.""" - return data.rstrip(b'\0').decode('utf-8').rstrip() + try: + return data.rstrip(b'\0').decode('utf-8').rstrip() + except UnicodeDecodeError as exc: + print(f"Decoding error: {exc}") + + encoding_info = chardet.detect(data) + detected_encoding = encoding_info['encoding'] + + try: + decoded_data = data.rstrip(b'\0').decode(detected_encoding).rstrip() + print(f"Decoded using {detected_encoding}: {decoded_data}") + except UnicodeDecodeError: + print("Unable to determine the encoding.") def _CK_VERSION_to_tuple(data): From 9416162ba7c0d2b62e4ed68b76f28ed1e0ffec4e Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:31:22 +0100 Subject: [PATCH 13/18] Update dev-requirements.in --- dev-requirements.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev-requirements.in b/dev-requirements.in index 2eb7c06..d6f81ec 100644 --- a/dev-requirements.in +++ b/dev-requirements.in @@ -10,3 +10,5 @@ sphinx sphinx-rtd-theme flake8 + +cardet From cf42006bc3f3a05bb8ddb70101d933de659c0ab9 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:03:43 +0100 Subject: [PATCH 14/18] Update types.py added chardet import --- pkcs11/types.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pkcs11/types.py b/pkcs11/types.py index 27ef10e..2bfe286 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -6,6 +6,7 @@ from threading import RLock from binascii import hexlify +import chardet from cached_property import cached_property From 99082de301a854dd4767302ae36c80c9a982b7cc Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:11:15 +0100 Subject: [PATCH 15/18] Update types.py fixed typo on import name --- pkcs11/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index 2bfe286..7f27538 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -6,7 +6,7 @@ from threading import RLock from binascii import hexlify -import chardet +import cardet from cached_property import cached_property From 0318cecccc83fe7d85004647bc744520204d733c Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:17:07 +0100 Subject: [PATCH 16/18] Update types.py fix 2 import name chardet --- pkcs11/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index 7f27538..2bfe286 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -6,7 +6,7 @@ from threading import RLock from binascii import hexlify -import cardet +import chardet from cached_property import cached_property From 5f0b57a4cc1c22bd34a7f8eee38795528e838d44 Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:39:06 +0100 Subject: [PATCH 17/18] Update types.py added return statement --- pkcs11/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index 2bfe286..c2e6d05 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -44,10 +44,10 @@ def _CK_UTF8CHAR_to_str(data): try: decoded_data = data.rstrip(b'\0').decode(detected_encoding).rstrip() print(f"Decoded using {detected_encoding}: {decoded_data}") + return decoded_data except UnicodeDecodeError: print("Unable to determine the encoding.") - def _CK_VERSION_to_tuple(data): """Convert CK_VERSION to tuple.""" return (data['major'], data['minor']) From b7427818625d10147e1beb4725865f0414874baf Mon Sep 17 00:00:00 2001 From: catarinaferrei <61137065+catarinaferrei@users.noreply.github.com> Date: Mon, 20 Nov 2023 17:15:56 +0000 Subject: [PATCH 18/18] Fix for Decoding issue We reported again a decoding issue in our internal tool using pkcs11 and decided to provide a fix --- pkcs11/types.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkcs11/types.py b/pkcs11/types.py index c2e6d05..a6619a9 100644 --- a/pkcs11/types.py +++ b/pkcs11/types.py @@ -34,20 +34,20 @@ def _CK_UTF8CHAR_to_str(data): """Convert CK_UTF8CHAR to string.""" try: - return data.rstrip(b'\0').decode('utf-8').rstrip() + decoded_data = data.rstrip(b'\0').decode('utf-8').rstrip() + return decoded_data except UnicodeDecodeError as exc: print(f"Decoding error: {exc}") - encoding_info = chardet.detect(data) detected_encoding = encoding_info['encoding'] - try: decoded_data = data.rstrip(b'\0').decode(detected_encoding).rstrip() print(f"Decoded using {detected_encoding}: {decoded_data}") return decoded_data except UnicodeDecodeError: print("Unable to determine the encoding.") - + return "FallbackValue" + def _CK_VERSION_to_tuple(data): """Convert CK_VERSION to tuple.""" return (data['major'], data['minor'])