Skip to content
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

HSMSigner: Use pre-hashing #548

Merged
merged 1 commit into from
Mar 23, 2023
Merged
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
21 changes: 11 additions & 10 deletions securesystemslib/signer/_hsm_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from securesystemslib import KEY_TYPE_ECDSA
from securesystemslib.exceptions import UnsupportedLibraryError
from securesystemslib.hash import digest
from securesystemslib.keys import _get_keyid
from securesystemslib.signer._key import Key, SSlibKey
from securesystemslib.signer._signature import Signature
Expand Down Expand Up @@ -44,13 +45,6 @@
PYKCS11_IMPORT_ERROR = None
try:
from PyKCS11 import PyKCS11

# TODO: Don't hardcode schemes
_MECHANISM_FOR_SCHEME = {
"ecdsa-sha2-nistp256": PyKCS11.Mechanism(PyKCS11.CKM_ECDSA_SHA256),
"ecdsa-sha2-nistp384": PyKCS11.Mechanism(PyKCS11.CKM_ECDSA_SHA384),
}

except ImportError:
PYKCS11_IMPORT_ERROR = "'PyKCS11' required"

Expand Down Expand Up @@ -141,10 +135,12 @@ def __init__(
if PYKCS11_IMPORT_ERROR:
raise UnsupportedLibraryError(PYKCS11_IMPORT_ERROR)

if public_key.scheme not in _MECHANISM_FOR_SCHEME:
if public_key.scheme not in [
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
]:
raise ValueError(f"unsupported scheme {public_key.scheme}")

self._mechanism = _MECHANISM_FOR_SCHEME[public_key.scheme]
self.hsm_keyid = hsm_keyid
self.token_filter = token_filter
self.public_key = public_key
Expand Down Expand Up @@ -367,13 +363,18 @@ def sign(self, payload: bytes) -> Signature:
Returns:
Signature.
"""

hasher = digest(algorithm=f"sha{self.public_key.scheme[-3:]}")
hasher.update(payload)

pin = self.pin_handler(self.SECRETS_HANDLER_MSG)
with self._get_session(self.token_filter) as session:
session.login(pin)
key = self._find_key(
session, self.hsm_keyid, PyKCS11.CKO_PRIVATE_KEY
)
signature = session.sign(key, payload, self._mechanism)
mechanism = PyKCS11.Mechanism(PyKCS11.CKM_ECDSA)
signature = session.sign(key, hasher.digest(), mechanism)
session.logout()

# The PKCS11 signature octets correspond to the concatenation of the ECDSA
Expand Down
20 changes: 0 additions & 20 deletions tests/test_hsm_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import shutil
import tempfile
import unittest
from unittest.mock import patch

from asn1crypto.keys import ( # pylint: disable=import-error
ECDomainParameters,
Expand All @@ -15,32 +14,13 @@
from PyKCS11 import PyKCS11

from securesystemslib.exceptions import UnverifiedSignatureError
from securesystemslib.hash import digest
from securesystemslib.signer import HSMSigner, Signer
from securesystemslib.signer._hsm_signer import PYKCS11LIB

_orig_sign = HSMSigner.sign


def _sign(self, data):
"""Wraps HSMSigner sign method for testing

HSMSigner supports CKM_ECDSA_SHA256 and CKM_ECDSA_SHA384 mechanisms. But SoftHSM
only supports CKM_ECDSA. For testing we patch the HSMSigner mechanism attribute and
pre-hash the data.
"""
self._mechanism = PyKCS11.Mechanism( # pylint: disable=protected-access
PyKCS11.CKM_ECDSA
)
hasher = digest(algorithm=f"sha{self.public_key.scheme[-3:]}")
hasher.update(data)
return _orig_sign(self, hasher.digest())


@unittest.skipUnless(
os.environ.get("PYKCS11LIB"), "set PYKCS11LIB to SoftHSM lib path"
)
@patch.object(HSMSigner, "sign", _sign)
class TestHSM(unittest.TestCase):
"""Test HSMSigner with SoftHSM

Expand Down