Production-ready Python host for MASTR protocol communication with hardware security tokens.
The MASTR Host implements a secure communication protocol between a host computer and a hardware security token (RP2040 + ATECC608A). It provides:
✅ Mutual Authentication via ECDH key exchange
✅ AES-128-GCM Encryption for all communications
✅ Integrity Verification with cryptographic attestation
✅ Pluggable Crypto Backends (File-based or TPM2)
✅ Automatic Key Provisioning for first-time setup
✅ Clean Logging with color-coded output
✅ Type-Safe with comprehensive type hints
- Permanent keys use P-256 ECDSA
- Session keys derived via HKDF-SHA256
- All data encrypted with AES-128-GCM
- Hardware RNG for IV generation
- Firmware integrity attestation
# 1. Connect your MASTR token via USB
# 2. Run with --provision flag
python -m host.main /dev/ttyACM0 --provision
# This will:
# ✓ Generate host keypair
# ✓ Exchange keys with token
# ✓ Set up golden hash for integrity checks
# ✓ Perform full authenticationOutput:
============================================================
MASTR Host - Production Protocol Implementation
============================================================
Port: /dev/ttyACM0
Crypto: NaiveCrypto
=== Connecting to Token ===
✓ Connected to /dev/ttyACM0
=== Phase 0: Key Loading ===
[INFO] Provision mode: Regenerating keypair...
✓ Generated new host keypair
=== Auto-Provisioning Token Key ===
...
✓ Keys provisioned successfully!
=== Phase 1: Mutual Authentication (ECDH) ===
...
✓ Session key: c8c2f188ffa06388c56ed44454b6309a
=== Channel Verification ===
...
✓ Pong sent
============================================================
✅ Secure channel established!
============================================================
=== Phase 2: Integrity Verification ===
...
✓ Token sent BOOT_OK - integrity verification passed!
============================================================
✅ Integrity verification complete!
============================================================
# Just run normally - keys are loaded from disk
python -m host.main /dev/ttyACM0- Python 3.8+
- pySerial for serial communication
- cryptography library for crypto operations
# From project root
cd host/
pip install -r requirements.txtOr manually:
pip install pyserial cryptographyLinux:
# Add user to dialout group for serial access
sudo usermod -a -G dialout $USER
# Log out and back in for changes to take effectmacOS:
# No special setup needed
# Devices appear as /dev/tty.usbmodemXXXXWindows:
# Devices appear as COM3, COM4, etc.
# No special setup neededpython -m host.main <port> [options]| Option | Description | Default |
|---|---|---|
port |
Serial port (e.g., /dev/ttyACM0, COM3) | Required |
-b, --baudrate |
Baud rate | 115200 |
-v, --verbose |
Enable verbose output | False |
--crypto |
Crypto backend: naive or tpm2 |
naive |
--provision |
Auto-provision keys and golden hash | False |
Basic usage:
python -m host.main /dev/ttyACM0Verbose mode:
python -m host.main /dev/ttyACM0 -vDifferent baud rate:
python -m host.main /dev/ttyACM0 -b 9600Windows:
python -m host.main COM3With TPM2 backend (when implemented):
python -m host.main /dev/ttyACM0 --crypto=tpm2Automatic (with --provision):
python -m host.main /dev/ttyACM0 --provisionGenerates:
host_permanent_privkey.pem- Host's private key (ECDSA, keep secret!)host_permanent_pubkey.bin- Host's public key (64 bytes, X||Y)token_permanent_pubkey.bin- Token's public key (64 bytes, X||Y)golden_hash.bin- Expected firmware hash (32 bytes, SHA-256)
Manual (existing keys):
python -m host.main /dev/ttyACM0Loads keys from disk automatically.
What happens:
- Host generates ephemeral P-256 keypair
- Host signs ephemeral pubkey with permanent key
- Host sends
H2T_ECDH_SHARE(pubkey + signature) - Token verifies signature, generates its own ephemeral keypair
- Token sends
T2H_ECDH_SHARE(pubkey + signature) - Both sides compute ECDH shared secret
- Both sides derive AES-128 session key via HKDF-SHA256
- Encryption enabled (state → 0x22)
Security:
- Mutual authentication prevents MITM attacks
- Ephemeral keys provide forward secrecy
- ECDSA signatures ensure authenticity
What happens:
- Token sends encrypted "ping" challenge
- Host decrypts and verifies
- Host sends encrypted "pong" response
- Token verifies response
- Channel established (state → 0x24)
Purpose:
- Confirms both sides have same session key
- Detects key derivation errors
- Required before integrity verification
What happens:
- Token sends 4-byte random nonce (encrypted)
- Host loads golden hash from disk
- Host signs
(golden_hash || nonce)with permanent key - Host sends
H2T_INTEGRITY_RESPONSE(hash + signature, encrypted) - Token verifies signature and compares hash
- If valid: Token sends
T2H_BOOT_OK(encrypted) - Host acknowledges with
H2T_BOOT_OK_ACK - Ready for operations (state → 0x34)
Purpose:
- Proves host firmware integrity
- Prevents unauthorized/modified hosts
- Token enforces this before allowing operations
Planned:
- Periodic encrypted heartbeats every 5 seconds
- Detects disconnection or tampering
- Automatic shutdown on timeout
host/
├── main.py # MASTRHost class - state machine
├── logger.py # Centralized logging
├── crypto_interface.py # Abstract crypto interface
├── crypto.py # NaiveCrypto implementation
├── protocol.py # Message type definitions
├── serial_handler.py # Serial communication
├── parser.py # Frame parsing
├── ARCHITECTURE.md # Detailed architecture docs
└── README.md # This file
┌──────────────┐
│ main.py │ ← Protocol state machine
│ (MASTRHost) │ Frame routing
└──────┬───────┘
│
┌───┴────────────────┐
│ │
┌──▼───────┐ ┌──────▼──────┐
│logger.py │ │crypto_ │
│ │ │interface.py │
│Logger │ │ │
│methods │ │NaiveCrypto │
└──────────┘ │TPM2Crypto │
└──────┬──────┘
│
┌──────▼──────┐
│serial_ │
│handler.py │
│ │
│Background │
│RX thread │
└──────┬──────┘
│
┌──────▼──────┐
│parser.py │
│ │
│Frame │
│extraction │
└──────┬──────┘
│
▼
Serial Port
User Command
│
├──> MASTRHost.run()
│ │
│ ├──> Load/Generate Keys (Phase 0)
│ │ │
│ │ └──> CryptoInterface methods
│ │
│ ├──> ECDH Handshake (Phase 1)
│ │ │
│ │ ├──> SerialHandler.send_frame()
│ │ │ │
│ │ │ └──> Byte stuffing
│ │ │ Encryption
│ │ │ Serial TX
│ │ │
│ │ └──> Wait for response
│ │ │
│ │ └──> FrameParser
│ │ on_frame_received()
│ │ Route to handler
│ │
│ ├──> Channel Verify (Phase 1.5)
│ │
│ └──> Integrity Verify (Phase 2)
│
└──> Keep connection open
# Clone repository
git clone <repo-url>
cd MASTR-NEW/host/
# Install dependencies
pip install -r requirements.txt
# Run tests (if available)
python -m pytest1. Define in protocol.py:
class MessageType(IntEnum):
H2T_MY_REQUEST = 0x60
T2H_MY_RESPONSE = 0x612. Add handler in main.py:
def _handle_my_response(self, payload: bytes) -> None:
"""Handle T2H_MY_RESPONSE"""
Logger.info(f"Got response: {payload.hex()}")
# Process...3. Register in on_frame_received():
elif frame.msg_type == MessageType.T2H_MY_RESPONSE:
self._handle_my_response(payload)4. Implement token-side in C:
// In src/protocol.c
case H2T_MY_REQUEST:
// Handle request
send_message(T2H_MY_RESPONSE, data, len);
break;1. Implement CryptoInterface:
from host.crypto_interface import CryptoInterface
class MyCustomCrypto(CryptoInterface):
def __init__(self) -> None:
super().__init__()
# Your initialization
def load_permanent_keys(self) -> bool:
# Your implementation
pass
# ... implement all abstract methods2. Use your backend:
from host.crypto_mycustom import MyCustomCrypto
host = MASTRHost(
port="/dev/ttyACM0",
crypto=MyCustomCrypto()
)from host.logger import Logger
# Success messages (green checkmark)
Logger.success("Operation completed")
# Errors (red X)
Logger.error("Operation failed")
# Info (cyan)
Logger.info("Processing...")
# Warnings (yellow)
Logger.warning("Deprecated feature")
# Debug (orange)
Logger.debug("TAG", "Debug message")
# Sections (cyan header)
Logger.section("Phase 1: Authentication")
# Steps (numbered)
Logger.step(1, "Generating keypair...")
Logger.substep("Details about this step...")Causes:
- Device not plugged in
- Wrong port name
- Permission denied (Linux)
Solutions:
# Linux: Check devices
ls -l /dev/ttyACM*
ls -l /dev/ttyUSB*
# Add user to dialout group
sudo usermod -a -G dialout $USER
# Log out and back in
# macOS: Check devices
ls -l /dev/tty.usbmodem*
# Windows: Check Device Manager
# Look under "Ports (COM & LPT)"Cause: First-time run without --provision
Solution:
python -m host.main /dev/ttyACM0 --provisionCauses:
- Token not responding
- Token firmware issue
- Wrong baud rate
Solutions:
# Reset token (unplug/replug)
# Try different baud rate
python -m host.main /dev/ttyACM0 -b 9600
# Check token is running correct firmwareCauses:
- Mismatched keys between host and token
- Corrupted key files
Solutions:
# Re-provision from scratch
rm host_permanent_*.pem host_permanent_*.bin token_permanent_*.bin
python -m host.main /dev/ttyACM0 --provisionCause: Integrity verification requires golden hash
Solution:
# Provision includes golden hash setup
python -m host.main /dev/ttyACM0 --provision0x00: T2H_ERROR- Error from token0x01: T2H_NACK- Negative acknowledgment
0x20: H2T_ECDH_SHARE- Host ephemeral pubkey + signature0x21: T2H_ECDH_SHARE- Token ephemeral pubkey + signature0x22: T2H_CHANNEL_VERIFY_REQUEST- Encrypted ping0x23: H2T_CHANNEL_VERIFY_RESPONSE- Encrypted pong
0x30: T2H_INTEGRITY_CHALLENGE- Nonce challenge0x31: H2T_INTEGRITY_RESPONSE- Hash + signature0x32: T2H_BOOT_OK- Integrity check passed0x33: T2H_INTEGRITY_FAIL_HALT- Integrity check failed0x34: H2T_BOOT_OK_ACK- Host acknowledges BOOT_OK
0x40: H2T_HEARTBEAT- Periodic heartbeat0x41: T2H_HEARTBEAT_ACK- Heartbeat acknowledgment
0xFE: DEBUG_MSG- UTF-8 debug text0xFD: H2T_TEST_RANDOM_REQUEST- Request random number0xFC: T2H_TEST_RANDOM_RESPONSE- Random number (32 bytes)0xFB: H2T_DEBUG_SET_HOST_PUBKEY- Set host public key0xFA: T2H_DEBUG_GET_TOKEN_PUBKEY- Get token public key0xF9: H2T_DEBUG_SET_GOLDEN_HASH- Set golden hash
- ARCHITECTURE.md - Detailed architecture documentation
- Protocol Diagrams - Visual protocol flow diagrams
- C Implementation - Token-side firmware
- Protocol Specification - Full protocol spec
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Code Style:
- Follow PEP 8
- Use type hints
- Add docstrings
- Use Logger for output
See LICENSE.TXT in project root.
After successful setup, you can:
-
Integrate into your application:
from host.main import MASTRHost from host.crypto import NaiveCrypto host = MASTRHost(port="/dev/ttyACM0", crypto=NaiveCrypto()) exit_code = host.run()
-
Implement custom message handlers for your use case
-
Deploy to production with TPM2 crypto backend (when available)
-
Add application-specific phases after Phase 2
Questions? Check ARCHITECTURE.md for detailed technical information.
Last Updated: 2024-10-26
Version: 2.0 (Post Phase 1 Cleanup)