Skip to content

Commit 1bc3dd6

Browse files
committed
signer: open session in sign method
Asking callers to handle the PyKCS11 session was a crutch to punt the not quite straight-forward decision of how to identify the correct token reader, but is no nice UX. This commit moves session handling to the signer and just uses the first reader slot that has a token. This commit, move the session to the signer also requires loading the pkcs11 library in the hsm module, and to take a login pin (as secrets handler). Signed-off-by: Lukas Puehringer <[email protected]>
1 parent c092766 commit 1bc3dd6

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

securesystemslib/signer/_hsm_signer.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
CRYPTO_IMPORT_ERROR = "'cryptography' required"
1212

1313
PYKCS11_IMPORT_ERROR = None
14+
PYKCS = None
1415
try:
1516
from PyKCS11 import PyKCS11
1617

18+
PYKCS = PyKCS11.PyKCS11Lib()
19+
PYKCS.load()
20+
1721
except ImportError: # pragma: no cover
1822
PYKCS11_IMPORT_ERROR = "'PyKCS11' required"
1923
# pylint: enable=wrong-import-position
@@ -35,8 +39,6 @@ class HSMSigner(Signer):
3539
supports ecdsa on SECG curves secp256r1 (NIST P-256) or secp384r1 (NIST P-384).
3640
3741
Arguments:
38-
hsm_session: An open and logged-in ``PyKCS11.Session`` to the token with the
39-
private key.
4042
hsm_keyid: Key identifier on the token.
4143
public_key: The related public key instance.
4244
@@ -46,10 +48,7 @@ class HSMSigner(Signer):
4648
"""
4749

4850
def __init__(
49-
self,
50-
hsm_session: "PyKCS11.Session",
51-
hsm_keyid: int,
52-
public_key: Key,
51+
self, hsm_keyid: int, public_key: Key, secrets_handler: SecretsHandler
5352
):
5453
if CRYPTO_IMPORT_ERROR:
5554
raise UnsupportedLibraryError(CRYPTO_IMPORT_ERROR)
@@ -67,9 +66,9 @@ def __init__(
6766
raise ValueError(f"unsupported scheme {public_key.scheme}")
6867

6968
self._mechanism = supported_schemes[public_key.scheme]
70-
self.hsm_session = hsm_session
7169
self.hsm_keyid = hsm_keyid
7270
self.public_key = public_key
71+
self.secrets_handler = secrets_handler
7372

7473
@classmethod
7574
def from_priv_key_uri(
@@ -93,9 +92,12 @@ def sign(self, payload: bytes) -> Signature:
9392
Returns:
9493
Signature.
9594
"""
95+
slot_id = PYKCS.getSlotList(tokenPresent=True)[0]
96+
session = PYKCS.openSession(slot_id, PyKCS11.CKF_RW_SESSION)
97+
session.login(self.secrets_handler())
9698

9799
# Search for ecdsa public keys with passed keyid on HSM
98-
keys = self.hsm_session.findObjects(
100+
keys = session.findObjects(
99101
[
100102
(PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY),
101103
(PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_ECDSA),
@@ -107,7 +109,9 @@ def sign(self, payload: bytes) -> Signature:
107109
f"hsm_keyid must identify one {KEY_TYPE_ECDSA} key, found {len(keys)}"
108110
)
109111

110-
signature = self.hsm_session.sign(keys[0], payload, self._mechanism)
112+
signature = session.sign(keys[0], payload, self._mechanism)
113+
session.logout()
114+
session.closeSession()
111115

112116
# The PKCS11 signature octets correspond to the concatenation of the ECDSA
113117
# values r and s, both represented as an octet string of equal length of at

tests/check_hsm_signer.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,7 @@ def _pre_hash(data, scheme):
221221
for hsm_keyid in self.hsm_keyids:
222222
public_key = self._from_hsm(session, hsm_keyid, keyid)
223223

224-
session.login(self.hsm_user_pin) # Login for signing
225-
signer = HSMSigner(session, hsm_keyid, public_key)
224+
signer = HSMSigner(hsm_keyid, public_key, lambda: self.hsm_user_pin)
226225

227226
# NOTE: HSMSigner supports CKM_ECDSA_SHA256 and CKM_ECDSA_SHA384
228227
# mechanisms. But SoftHSM only supports CKM_ECDSA. During testing we

0 commit comments

Comments
 (0)