Skip to content

Add Set_Pin functionality #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dev-requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ sphinx
sphinx-rtd-theme

flake8

cardet
81 changes: 81 additions & 0 deletions pkcs11/_pkcs11.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,87 @@ 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

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
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):
Expand Down
37 changes: 31 additions & 6 deletions pkcs11/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from threading import RLock
from binascii import hexlify
import chardet

from cached_property import cached_property

Expand All @@ -32,9 +33,21 @@

def _CK_UTF8CHAR_to_str(data):
"""Convert CK_UTF8CHAR to string."""
return data.rstrip(b'\0').decode('utf-8').rstrip()


try:
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'])
Expand Down Expand Up @@ -529,8 +542,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`.
Expand Down Expand Up @@ -559,7 +572,19 @@ def digest(self, data, **kwargs):
data = (data,)

return self._digest_generator(data, **kwargs)


def set_pin(self, old_pin, new_pin):
raise NotImplementedError()

def init_pin(self, user_pin):
raise NotImplementedError()

def login(self, user_pin, user_type=None):
raise NotImplementedError()

def logout(self):
raise NotImplementedError()


class Object:
"""
Expand Down
11 changes: 11 additions & 0 deletions tests/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,14 @@ 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, user_pin=old_token_pin) as session:
self.assertTrue(session.set_pin(old_token_pin, new_token_pin))

with self.token.open(user_pin=new_token_pin) as session:
self.assertIsInstance(session, pkcs11.Session)