Skip to content
Closed
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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ For macOS:
brew install libusb
```

For Windows:
```
# Install Visual Studio Build Tools with Windows 10 SDK and C++ CMake tools
# Install OpenSSL development libraries
```

## Install

```
Expand Down Expand Up @@ -77,6 +83,26 @@ All output will be in JSON form and sent to `stdout`.
Additional information or prompts will be sent to `stderr` and will not necessarily be in JSON.
This additional information is for debugging purposes.

### PKCS11 Token Support

HWI supports PKCS11 tokens (HSMs) with secp256k1 curve support. To use a PKCS11 token:

1. Set the required environment variables:
```bash
# Windows
$env:PKCS11_LIB_PATH = "C:\path\to\your\pkcs11\library.dll"
$env:PKCS11_TOKEN_LABEL = "YourTokenLabel"

# Unix-like
export PKCS11_LIB_PATH=/path/to/your/pkcs11/library.so
export PKCS11_TOKEN_LABEL=YourTokenLabel
```

2. Use the token with HWI:
```bash
hwi --device-type pkcs11 --path /path/to/library.so getmasterxpub
```

To see a complete list of available commands and global parameters, run
`./hwi.py --help`. To see options specific to a particular command,
pass the `--help` parameter after the command name; for example:
Expand Down
124 changes: 124 additions & 0 deletions docs/devices/pkcs11.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
PKCS#11 Token
=============

The PKCS#11 Token device implementation allows HWI to interact with PKCS#11-compliant Hardware Security Modules (HSMs) that support the secp256k1 curve.

Requirements
------------

- A PKCS#11-compliant HSM with secp256k1 curve support
- The PKCS#11 library for your HSM
- The ``python-pkcs11`` Python package

Windows-specific Requirements
---------------------------

On Windows, you'll need:

1. Visual Studio Build Tools with C++ support
- Download from: https://visualstudio.microsoft.com/visual-cpp-build-tools/
- Select "Desktop development with C++"
- Make sure to include the Windows 10 SDK

2. OpenSSL development headers
- Download from: https://slproweb.com/products/Win32OpenSSL.html
- Choose the "Win64 OpenSSL" version
- During installation, select "Copy OpenSSL DLLs to Windows system directory"

3. The PKCS#11 library for your HSM (usually a .dll file)
- Place the .dll file in a system path (e.g., C:\Windows\System32)
- Or specify its path using the PKCS11_LIB_PATH environment variable

Installation Steps for Windows:

1. Install the prerequisites in the order listed above

2. Install python-pkcs11:
.. code-block:: powershell

pip install python-pkcs11

If you get a "Failed building wheel" error:
- Make sure Visual Studio Build Tools are installed
- Ensure OpenSSL is installed and in your PATH
- Try running the command in a new terminal after installing the prerequisites

Configuration
------------

The following environment variables can be used to configure the PKCS#11 device:

- ``PKCS11_LIB_PATH``: Path to the PKCS#11 library (required)
- ``PKCS11_TOKEN_LABEL``: Label of the token to use (default: "Bitcoin")

Usage
-----

1. Set up your environment variables:

.. code-block:: powershell

# On Windows (PowerShell):
$env:PKCS11_LIB_PATH = "C:\path\to\your\pkcs11\library.dll"
$env:PKCS11_TOKEN_LABEL = "YourTokenLabel"

# On Linux/macOS:
export PKCS11_LIB_PATH=/path/to/your/pkcs11/library.so
export PKCS11_TOKEN_LABEL=YourTokenLabel

2. Initialize your HSM with a master key:

- Create a master key with label "MASTER_KEY"
- Ensure the key uses the secp256k1 curve
- Set appropriate access controls

3. Use HWI with your PKCS#11 token:

.. code-block:: bash

hwi enumerate # List available devices
hwi --device-type pkcs11 --path /path/to/library.so getmasterxpub

Security Considerations
---------------------

- The PKCS#11 token must be properly configured with appropriate access controls
- The master key should be protected with a strong PIN/password
- The PKCS#11 library should be from a trusted source
- The token should be physically secured

Limitations
----------

- Only supports secp256k1 curve
- Requires the token to be pre-initialized with a master key
- May not support all HWI features depending on the token's capabilities

Troubleshooting
--------------

If you encounter issues:

1. Verify your PKCS#11 library is properly installed
2. Check that your token supports the secp256k1 curve
3. Ensure the master key exists and is accessible
4. Check the token's logs for any error messages
5. Verify the environment variables are set correctly

Windows-specific Troubleshooting:

1. If you get a "Failed building wheel" error:
- Make sure Visual Studio Build Tools are installed
- Ensure OpenSSL is installed and in your PATH
- Try running the command in a new terminal after installing the prerequisites

2. If the library is not found:
- Check if the .dll file is in a system path
- Verify the PKCS11_LIB_PATH environment variable is set correctly
- Try running as Administrator

3. If you get a "DLL load failed" error:
- Check if all required dependencies are installed
- Verify the architecture matches (32-bit vs 64-bit)
- Try installing the Visual C++ Redistributable
- Make sure OpenSSL DLLs are in your system PATH
52 changes: 52 additions & 0 deletions hwilib/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
Union,
)

import pkcs11
from pkcs11 import Mechanism, ObjectClass, KeyType


py_enumerate = enumerate

Expand Down Expand Up @@ -590,3 +593,52 @@ def install_udev_rules(source: str, location: str) -> Dict[str, bool]:
from .udevinstaller import UDevInstaller
return {"success": UDevInstaller.install(source, location)}
raise NotImplementedError("udev rules are not needed on your platform")

class PKCS11Client(HardwareWalletClient):
def __init__(self, path: str, password: Optional[str] = None, expert: bool = False, chain: Chain = Chain.MAIN) -> None:
super(PKCS11Client, self).__init__(path, password, expert, chain)

# Initialize PKCS11 library and token
self.lib = pkcs11.lib(path) # path should point to the PKCS11 library
self.token = self.lib.get_token(token_label='YOUR_TOKEN_LABEL')
self.session = self.token.open(user_pin=password)

# Find the master key
self.master_key = self.session.get_key(
object_class=ObjectClass.PRIVATE_KEY,
key_type=KeyType.EC,
label='MASTER_KEY'
)

def get_pubkey_at_path(self, bip32_path: str) -> ExtendedKey:
# Implement BIP32 path derivation and get public key
# You'll need to implement BIP32 path derivation logic
# and use the PKCS11 token to get the public key
pass

def sign_tx(self, psbt: PSBT) -> PSBT:
# Implement PSBT signing using the PKCS11 token
# You'll need to:
# 1. Parse the PSBT
# 2. For each input that needs signing:
# - Get the appropriate key from the token
# - Sign the transaction
# 3. Return the signed PSBT
pass

def sign_message(self, message: Union[str, bytes], keypath: str) -> str:
# Implement message signing using the PKCS11 token
# You'll need to:
# 1. Get the key at the specified path
# 2. Sign the message
# 3. Return the signature
pass

def get_master_fingerprint(self) -> bytes:
# Get the master key's fingerprint
# This is typically the first 4 bytes of the hash160 of the master public key
pass

def close(self) -> None:
# Close the PKCS11 session
self.session.close()
22 changes: 20 additions & 2 deletions hwilib/devices/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
"""
Devices
*******

This module contains all of the device implementations.
Each device implementation is a subclass of :class:`~hwilib.hwwclient.HardwareWalletClient`.
"""

from .trezor import TrezorClient
from .ledger import LedgerClient
from .keepkey import KeepkeyClient
from .jade import JadeClient
from .coldcard import ColdcardClient
from .digitalbitbox import DigitalbitboxClient
from .bitbox02 import Bitbox02Client
from .pkcs11 import PKCS11Client

__all__ = [
'trezor',
'ledger',
'keepkey',
'digitalbitbox',
'jade',
'coldcard',
'digitalbitbox',
'bitbox02',
'jade'
'pkcs11',
]
Loading