Skip to content

Commit 69fd06d

Browse files
committed
Add PKCS11 token support with tests and documentation
1 parent 5f533aa commit 69fd06d

File tree

9 files changed

+616
-2
lines changed

9 files changed

+616
-2
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ sudo yum -y install python3-devel libusbx-devel systemd-devel
2626
For macOS:
2727
```
2828
brew install libusb
29+
30+
```
31+
32+
For Windows:
33+
```
34+
# Install Visual Studio Build Tools with Windows 10 SDK and C++ CMake tools
35+
# Install OpenSSL development libraries
2936
```
3037

3138
## Install
@@ -77,6 +84,26 @@ All output will be in JSON form and sent to `stdout`.
7784
Additional information or prompts will be sent to `stderr` and will not necessarily be in JSON.
7885
This additional information is for debugging purposes.
7986

87+
### PKCS11 Token Support
88+
89+
HWI supports PKCS11 tokens (HSMs) with secp256k1 curve support. To use a PKCS11 token:
90+
91+
1. Set the required environment variables:
92+
```bash
93+
# Windows
94+
$env:PKCS11_LIB_PATH = "C:\path\to\your\pkcs11\library.dll"
95+
$env:PKCS11_TOKEN_LABEL = "YourTokenLabel"
96+
97+
# Unix-like
98+
export PKCS11_LIB_PATH=/path/to/your/pkcs11/library.so
99+
export PKCS11_TOKEN_LABEL=YourTokenLabel
100+
```
101+
102+
2. Use the token with HWI:
103+
```bash
104+
hwi --device-type pkcs11 --path /path/to/library.so getmasterxpub
105+
```
106+
80107
To see a complete list of available commands and global parameters, run
81108
`./hwi.py --help`. To see options specific to a particular command,
82109
pass the `--help` parameter after the command name; for example:

docs/devices/pkcs11.rst

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
PKCS#11 Token
2+
=============
3+
4+
The PKCS#11 Token device implementation allows HWI to interact with PKCS#11-compliant Hardware Security Modules (HSMs) that support the secp256k1 curve.
5+
6+
Requirements
7+
------------
8+
9+
- A PKCS#11-compliant HSM with secp256k1 curve support
10+
- The PKCS#11 library for your HSM
11+
- The ``python-pkcs11`` Python package
12+
13+
Windows-specific Requirements
14+
---------------------------
15+
16+
On Windows, you'll need:
17+
18+
1. Visual Studio Build Tools with C++ support
19+
- Download from: https://visualstudio.microsoft.com/visual-cpp-build-tools/
20+
- Select "Desktop development with C++"
21+
- Make sure to include the Windows 10 SDK
22+
23+
2. OpenSSL development headers
24+
- Download from: https://slproweb.com/products/Win32OpenSSL.html
25+
- Choose the "Win64 OpenSSL" version
26+
- During installation, select "Copy OpenSSL DLLs to Windows system directory"
27+
28+
3. The PKCS#11 library for your HSM (usually a .dll file)
29+
- Place the .dll file in a system path (e.g., C:\Windows\System32)
30+
- Or specify its path using the PKCS11_LIB_PATH environment variable
31+
32+
Installation Steps for Windows:
33+
34+
1. Install the prerequisites in the order listed above
35+
36+
2. Install python-pkcs11:
37+
.. code-block:: powershell
38+
pip install python-pkcs11
39+
If you get a "Failed building wheel" error:
40+
- Make sure Visual Studio Build Tools are installed
41+
- Ensure OpenSSL is installed and in your PATH
42+
- Try running the command in a new terminal after installing the prerequisites
43+
44+
Configuration
45+
------------
46+
47+
The following environment variables can be used to configure the PKCS#11 device:
48+
49+
- ``PKCS11_LIB_PATH``: Path to the PKCS#11 library (required)
50+
- ``PKCS11_TOKEN_LABEL``: Label of the token to use (default: "Bitcoin")
51+
52+
Usage
53+
-----
54+
55+
1. Set up your environment variables:
56+
57+
.. code-block:: powershell
58+
# On Windows (PowerShell):
59+
$env:PKCS11_LIB_PATH = "C:\path\to\your\pkcs11\library.dll"
60+
$env:PKCS11_TOKEN_LABEL = "YourTokenLabel"
61+
# On Linux/macOS:
62+
export PKCS11_LIB_PATH=/path/to/your/pkcs11/library.so
63+
export PKCS11_TOKEN_LABEL=YourTokenLabel
64+
2. Initialize your HSM with a master key:
65+
66+
- Create a master key with label "MASTER_KEY"
67+
- Ensure the key uses the secp256k1 curve
68+
- Set appropriate access controls
69+
70+
3. Use HWI with your PKCS#11 token:
71+
72+
.. code-block:: bash
73+
hwi enumerate # List available devices
74+
hwi --device-type pkcs11 --path /path/to/library.so getmasterxpub
75+
Security Considerations
76+
---------------------
77+
78+
- The PKCS#11 token must be properly configured with appropriate access controls
79+
- The master key should be protected with a strong PIN/password
80+
- The PKCS#11 library should be from a trusted source
81+
- The token should be physically secured
82+
83+
Limitations
84+
----------
85+
86+
- Only supports secp256k1 curve
87+
- Requires the token to be pre-initialized with a master key
88+
- May not support all HWI features depending on the token's capabilities
89+
90+
Troubleshooting
91+
--------------
92+
93+
If you encounter issues:
94+
95+
1. Verify your PKCS#11 library is properly installed
96+
2. Check that your token supports the secp256k1 curve
97+
3. Ensure the master key exists and is accessible
98+
4. Check the token's logs for any error messages
99+
5. Verify the environment variables are set correctly
100+
101+
Windows-specific Troubleshooting:
102+
103+
1. If you get a "Failed building wheel" error:
104+
- Make sure Visual Studio Build Tools are installed
105+
- Ensure OpenSSL is installed and in your PATH
106+
- Try running the command in a new terminal after installing the prerequisites
107+
108+
2. If the library is not found:
109+
- Check if the .dll file is in a system path
110+
- Verify the PKCS11_LIB_PATH environment variable is set correctly
111+
- Try running as Administrator
112+
113+
3. If you get a "DLL load failed" error:
114+
- Check if all required dependencies are installed
115+
- Verify the architecture matches (32-bit vs 64-bit)
116+
- Try installing the Visual C++ Redistributable
117+
- Make sure OpenSSL DLLs are in your system PATH

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
sphinxcontrib-autoprogram>=0.1.5
22
sphinx>=3.2.1
33
sphinx_rtd_theme>=1.0.0
4+
python-pkcs11>=0.7.0

hwilib/commands.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
Union,
6767
)
6868

69+
import pkcs11
70+
from pkcs11 import Mechanism, ObjectClass, KeyType
6971

7072
py_enumerate = enumerate
7173

@@ -590,3 +592,52 @@ def install_udev_rules(source: str, location: str) -> Dict[str, bool]:
590592
from .udevinstaller import UDevInstaller
591593
return {"success": UDevInstaller.install(source, location)}
592594
raise NotImplementedError("udev rules are not needed on your platform")
595+
596+
class PKCS11Client(HardwareWalletClient):
597+
def __init__(self, path: str, password: Optional[str] = None, expert: bool = False, chain: Chain = Chain.MAIN) -> None:
598+
super(PKCS11Client, self).__init__(path, password, expert, chain)
599+
600+
# Initialize PKCS11 library and token
601+
self.lib = pkcs11.lib(path) # path should point to the PKCS11 library
602+
self.token = self.lib.get_token(token_label='YOUR_TOKEN_LABEL')
603+
self.session = self.token.open(user_pin=password)
604+
605+
# Find the master key
606+
self.master_key = self.session.get_key(
607+
object_class=ObjectClass.PRIVATE_KEY,
608+
key_type=KeyType.EC,
609+
label='MASTER_KEY'
610+
)
611+
612+
def get_pubkey_at_path(self, bip32_path: str) -> ExtendedKey:
613+
# Implement BIP32 path derivation and get public key
614+
# You'll need to implement BIP32 path derivation logic
615+
# and use the PKCS11 token to get the public key
616+
pass
617+
618+
def sign_tx(self, psbt: PSBT) -> PSBT:
619+
# Implement PSBT signing using the PKCS11 token
620+
# You'll need to:
621+
# 1. Parse the PSBT
622+
# 2. For each input that needs signing:
623+
# - Get the appropriate key from the token
624+
# - Sign the transaction
625+
# 3. Return the signed PSBT
626+
pass
627+
628+
def sign_message(self, message: Union[str, bytes], keypath: str) -> str:
629+
# Implement message signing using the PKCS11 token
630+
# You'll need to:
631+
# 1. Get the key at the specified path
632+
# 2. Sign the message
633+
# 3. Return the signature
634+
pass
635+
636+
def get_master_fingerprint(self) -> bytes:
637+
# Get the master key's fingerprint
638+
# This is typically the first 4 bytes of the hash160 of the master public key
639+
pass
640+
641+
def close(self) -> None:
642+
# Close the PKCS11 session
643+
self.session.close()

hwilib/devices/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
1+
"""
2+
Devices
3+
*******
4+
This module contains all of the device implementations.
5+
Each device implementation is a subclass of :class:`~hwilib.hwwclient.HardwareWalletClient`.
6+
"""
7+
8+
from .trezor import TrezorClient
9+
from .ledger import LedgerClient
10+
from .keepkey import KeepkeyClient
11+
from .jade import JadeClient
12+
from .coldcard import ColdcardClient
13+
from .digitalbitbox import DigitalbitboxClient
14+
from .bitbox02 import Bitbox02Client
15+
from .pkcs11 import PKCS11Client
116
__all__ = [
217
'trezor',
318
'ledger',
419
'keepkey',
520
'digitalbitbox',
621
'coldcard',
722
'bitbox02',
8-
'jade'
23+
'jade',
24+
'pkcs11'
925
]

0 commit comments

Comments
 (0)