diff --git a/pkcs11/_pkcs11.pyx b/pkcs11/_pkcs11.pyx index fbc0cd3..75307d6 100644 --- a/pkcs11/_pkcs11.pyx +++ b/pkcs11/_pkcs11.pyx @@ -524,23 +524,28 @@ cdef class Token(HasFuncList, types.Token): pin = None c_user_type = CKU_USER_NOBODY + if (so_pin is PROTECTED_AUTH or user_pin is PROTECTED_AUTH) and \ + not self.flags & TokenFlag.PROTECTED_AUTHENTICATION_PATH: + raise ArgumentsBad("Protected authentication is not supported by loaded module") + with nogil: retval = self.funclist.C_OpenSession(slot_id, flags, NULL, NULL, &handle) assertRV(retval) if so_pin is PROTECTED_AUTH or user_pin is PROTECTED_AUTH: - if self.flags & TokenFlag.PROTECTED_AUTHENTICATION_PATH: - with nogil: - retval = self.funclist.C_Login(handle, c_user_type, NULL, 0) - assertRV(retval) - else: - raise ArgumentsBad("Protected authentication is not supported by loaded module") + with nogil: + retval = self.funclist.C_Login(handle, c_user_type, NULL, 0) elif pin is not None: pin_data = pin pin_length = len(pin) with nogil: retval = self.funclist.C_Login(handle, c_user_type, pin_data, pin_length) + + if retval != CKR_OK: + # Raise the login error, not a C_CloseSession error. + with nogil: + self.funclist.C_CloseSession(handle) assertRV(retval) return Session.make( diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 41aa2c9..f66db85 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -11,7 +11,7 @@ PKCS11Error, ) from pkcs11.attributes import AttributeMapper, handle_bool, handle_str -from pkcs11.exceptions import PinIncorrect, PinLenRange +from pkcs11.exceptions import ArgumentsBad, PinIncorrect, PinLenRange from . import TOKEN_PIN, TOKEN_SO_PIN, Not, Only, TestCase, requires @@ -34,6 +34,22 @@ def test_open_session_and_login_so(self): with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session: self.assertIsInstance(session, pkcs11.Session) + @Only.softhsm2 + def test_failed_login_does_not_leak_session(self): + with self.assertRaises(PinIncorrect): + self.token.open(user_pin="not the user pin") + + with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session: + self.assertIsInstance(session, pkcs11.Session) + + @Only.softhsm2 + def test_unsupported_protected_auth_does_not_leak_session(self): + with self.assertRaises(ArgumentsBad): + self.token.open(user_pin=pkcs11.PROTECTED_AUTH) + + with self.token.open(rw=True, so_pin=TOKEN_SO_PIN) as session: + self.assertIsInstance(session, pkcs11.Session) + @requires(pkcs11.Mechanism.AES_KEY_GEN) def test_generate_key(self): with self.token.open(user_pin=TOKEN_PIN) as session: