Skip to content

Commit 1ff2114

Browse files
Dominikus GierlachMatthiasValvekens
authored andcommitted
Add PIN management functionality
1 parent bc1b1f3 commit 1ff2114

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

pkcs11/_pkcs11.pyx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,40 @@ cdef class Session(HasFuncList, types.Session):
11481148
op.ingest_chunks(data)
11491149
return op.finish()
11501150

1151+
def set_pin(self, old_pin, new_pin):
1152+
cdef CK_ULONG old_pin_length
1153+
cdef CK_ULONG new_pin_length
1154+
cdef CK_OBJECT_HANDLE handle = self.handle
1155+
cdef CK_UTF8CHAR *old_pin_data
1156+
cdef CK_UTF8CHAR *new_pin_data
1157+
cdef CK_RV retval
1158+
1159+
pin_old = old_pin.encode('utf-8')
1160+
pin_new = new_pin.encode('utf-8')
1161+
1162+
old_pin_data = pin_old
1163+
new_pin_data = pin_new
1164+
old_pin_length = len(pin_old)
1165+
new_pin_length = len(pin_new)
1166+
1167+
with nogil:
1168+
retval = self.funclist.C_SetPIN(handle, old_pin_data, old_pin_length, new_pin_data, new_pin_length)
1169+
assertRV(retval)
1170+
1171+
def init_pin(self, pin):
1172+
cdef CK_OBJECT_HANDLE handle = self.handle
1173+
cdef CK_UTF8CHAR *pin_data
1174+
cdef CK_ULONG pin_length
1175+
cdef CK_RV retval
1176+
1177+
pin = pin.encode('utf-8')
1178+
1179+
pin_data = pin
1180+
pin_length = len(pin)
1181+
1182+
with nogil:
1183+
retval = self.funclist.C_InitPIN(handle, pin_data, pin_length)
1184+
assertRV(retval)
11511185

11521186
cdef class ObjectHandleWrapper(HasFuncList):
11531187
"""

pkcs11/types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,19 @@ def digest(self, data, **kwargs):
576576

577577
return self._digest_generator(data, **kwargs)
578578

579+
def set_pin(self, old_pin, new_pin):
580+
"""Change the user pin."""
581+
raise NotImplementedError()
582+
583+
def init_pin(self, pin):
584+
"""
585+
Initializes the user PIN.
586+
587+
Differs from set_pin in that it sets the user PIN for the first time.
588+
Once set, the pin can be changed using set_pin.
589+
"""
590+
raise NotImplementedError()
591+
579592
def _digest(self, data, mechanism=None, mechanism_param=None):
580593
raise NotImplementedError()
581594

tests/test_sessions.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
PKCS11Error,
1212
)
1313
from pkcs11.attributes import AttributeMapper, handle_bool, handle_str
14+
from pkcs11.exceptions import PinIncorrect, PinLenRange
1415

1516
from . import TOKEN_PIN, TOKEN_SO_PIN, Not, Only, TestCase, requires
1617

@@ -291,3 +292,52 @@ def _handler(self, key):
291292
bool_read = key[Attribute.ID]
292293
self.assertIsInstance(bool_read, bool)
293294
self.assertFalse(bool_read, False)
295+
296+
@Only.softhsm2
297+
def test_set_pin(self):
298+
old_token_pin = TOKEN_PIN
299+
new_token_pin = f"{TOKEN_PIN}56"
300+
301+
with self.token.open(rw=True, user_pin=old_token_pin) as session:
302+
session.set_pin(old_token_pin, new_token_pin)
303+
304+
with self.token.open(user_pin=new_token_pin) as session:
305+
self.assertIsInstance(session, pkcs11.Session)
306+
307+
with self.token.open(rw=True, user_pin=new_token_pin) as session:
308+
session.set_pin(new_token_pin, old_token_pin)
309+
310+
with self.token.open(user_pin=old_token_pin) as session:
311+
self.assertIsInstance(session, pkcs11.Session)
312+
313+
with self.token.open(rw=True, user_pin=old_token_pin) as session:
314+
with self.assertRaises(AttributeError):
315+
session.set_pin(None, new_token_pin)
316+
with self.assertRaises(AttributeError):
317+
session.set_pin(old_token_pin, None)
318+
with self.assertRaises(PinLenRange):
319+
session.set_pin(old_token_pin, "")
320+
with self.assertRaises(PinIncorrect):
321+
session.set_pin("", new_token_pin)
322+
323+
@Only.softhsm2
324+
def test_init_pin(self):
325+
new_token_pin = f"{TOKEN_PIN}56"
326+
327+
with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session:
328+
session.init_pin(new_token_pin)
329+
330+
with self.token.open(rw=True, user_pin=new_token_pin) as session:
331+
self.assertIsInstance(session, pkcs11.Session)
332+
333+
with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session:
334+
session.init_pin(TOKEN_PIN)
335+
336+
with self.token.open(rw=True, user_pin=TOKEN_PIN) as session:
337+
self.assertIsInstance(session, pkcs11.Session)
338+
339+
with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session:
340+
with self.assertRaises(AttributeError):
341+
session.init_pin(None)
342+
with self.assertRaises(PinLenRange):
343+
session.init_pin("")

0 commit comments

Comments
 (0)