A pure-Rust client for YubiHSM2 devices from Yubico.
This is a pure-Rust client library for YubiHSM2 devices which implements most the functionality of the closed-source libyubihsm library from the Yubico SDK. It communicates with the yubihsm-connector service: an HTTP(S) server which sends the commands to the YubiHSM2 hardware device over USB.
Note that this is NOT an official Yubico project and is in no way supported or endorsed by Yubico (although whoever runs their Twitter account thinks it's awesome).
This crate builds on Rust 1.27+ and by default uses SIMD features which require the following RUSTFLAGS:
RUSTFLAGS=-Ctarget-feature=+aes`
You can configure your ~/.cargo/config
to always pass these flags:
[build]
rustflags = ["-Ctarget-feature=+aes"]
NOTE: If there's a command on this list you'd like to use which isn't presently supported, contributing is easy (see below) or open an issue requesting support.
Command | Impl'd | MockHSM | Description |
---|---|---|---|
Attest Asymmetric | ✅ | ⛔ | Create X.509 certificate for asymmetric key |
Authenticate Session | ✅ | ✅ | Authenticate to HSM with password or encryption key |
Blink | ✅ | ✅ | Blink the HSM's LEDs (to identify it) |
Close Session | ✅ | ✅ | Terminate an encrypted session with the HSM |
Create Session | ✅ | ✅ | Initiate a new encrypted session with the HSM |
Decrypt ECDH | ⛔ | ⛔ | Compute Elliptic Curve Diffie-Hellman using HSM-backed key |
Decrypt OAEP | ⛔ | ⛔ | Decrypt data encrypted with RSA-OAEP |
Decrypt PKCS1 | ⛔ | ⛔ | Decrypt data encrypted with RSA-PKCS#1v1.5 |
Device Info | ✅ | ✅ | Get information about the HSM |
Delete Object | ✅ | ✅ | Delete an object of the given ID and type |
Echo | ✅ | ✅ | Echo a message sent to the HSM |
Export Wrapped | ✅ | ✅ | Export an object from the HSM in encrypted form |
Generate Asymmetric | ✅ | ✅ | Randomly generate new asymmetric key in the HSM |
Generate HMAC Key | ✅ | ✅ | Randomly generate HMAC key in the HSM |
Generate OTP Key | ⛔ | ⛔ | Randomly generate AES key for Yubico OTP authentication |
Generate Wrap Key | ✅ | ✅ | Randomly generate AES key for exporting/importing objects |
Get Logs | ✅ | ✅ | Obtain the audit log for the HSM |
Get Object Info | ✅ | ✅ | Get information about an object |
Get Opaque | ✅ | ✅ | Get an opaque bytestring from the HSM |
Get Option | ⛔ | ⛔ | Get information about HSM settings |
Get Pseudo Random | ✅ | ✅ | Get random data generated by the HSM's internal PRNG |
Get Pubkey | ✅ | ✅ | Get public key for an HSM-backed asymmetric private key |
HMAC Data | ✅ | ✅ | Perform an HMAC operation using an HSM-backed key |
Import Wrapped | ✅ | ✅ | Import an encrypted key into the HSM |
List Objects | ✅ | ✅ | List objects visible from the current session |
OTP AEAD Create | ⛔ | ⛔ | Create a Yubico OTP AEAD |
OTP AEAD Random | ⛔ | ⛔ | Randomly generate a Yubico OTP AEAD |
OTP AEAD Rewrap | ⛔ | ⛔ | Re-wrap a Yubico OTP AEAD from one key to another |
OTP Decrypt | ⛔ | ⛔ | Decrypt a Yubico OTP, obtaining counters and timer info |
Put Asymmetric | ✅ | ✅ | Put an existing asymmetric key into the HSM |
Put Auth Key | ✅ | ✅ | Put AES-128x2 preshared authentication key into HSM |
Put HMAC Key | ✅ | ✅ | Put an HMAC key into the HSM |
Put Opaque | ✅ | ✅ | Put an opaque bytestring into the HSM |
Put Option | ⛔ | ⛔ | Change HSM settings |
Put OTP AEAD Key | ✅ | ⛔ | Put a Yubico OTP key into the HSM |
Put Wrap Key | ✅ | ✅ | Put an AES keywrapping key into the HSM |
Reset | ✅ | ✅ | Reset the HSM back to factory default settings |
Session Message | ✅ | ✅ | Send an encrypted message to the HSM |
Set Log Index | ✅ | ✅ | Mark log messages in the HSM as consumed |
Sign Data ECDSA | ✅ | ✅ | Compute an ECDSA signature using HSM-backed key |
Sign Data EdDSA | ✅ | ✅ | Compute an Ed25519 signature using HSM-backed key |
Sign Data PKCS1 | ⛔ | Compute an RSASSA-PKCS#1v1.5 signature using HSM-backed key | |
Sign Data PSS | ⛔ | Compute an RSASSA-PSS signature using HSM-backed key | |
Storage Status | ✅ | ✅ | Fetch information about currently free storage |
Unwrap Data | ✅ | ⛔ | Decrypt data encrypted using a wrap key |
Verify HMAC | ✅ | ✅ | Verify that an HMAC tag for given data is valid |
Wrap Data | ✅ | ⛔ | Encrypt data using a wrap key |
Status | |
---|---|
✅ | Supported |
Partial/Untested Support | |
⛔ | Unsupported |
The following documentation describes the most important parts of this crate's API:
- Session: end-to-end encrypted connection with the YubiHSM. You'll need an active one to do anything.
- commands: commands supported by the YubiHSM2 (i.e. main functionality)
Here is an example of how to create a Session
by connecting to a yubihsm-connector
process, and then performing an Ed25519 signature:
extern crate yubihsm;
use yubihsm::Session;
// Default host, port, auth key ID, and password for yubihsm-connector
let mut session = Session::create_from_password(
"http://127.0.0.1:12345",
1,
b"password",
true
).unwrap();
// Note: You'll need to create this key first. Run the following from yubihsm-shell:
// `generate asymmetric 0 100 ed25519_test_key 1 asymmetric_sign_eddsa ed25519`
let signature = yubihsm::sign_ed25519(&session, 100, "Hello, world!").unwrap();
println!("Ed25519 signature: {:?}", signature);
If there are additional YubiHSM2 commands you would like to use but aren't presently supported, adding them is very easy, and PRs are welcome!
The YubiHSM2 uses a simple, bincode-like message format, which largely consists of fixed-width integers, bytestrings, and bitfields. This crate implements a Serde-based message parser which can automatically parse command/response messages used by the HSM derived from a corresponding Rust struct describing their structure.
Here's a list of steps necessary to implement a new command type:
- Find the command you wish to implement on the YubiHSM2 commands page, and study the structure of the command (i.e. request) and response.
- Create a new module under the commands module which matches the name
of the command and implements the
Command
andResponse
traits. - (Optional) Implement the command in mockhsm/commands.rs and write an integration test.
This crate allows you to run the integration test suite in two different ways: live testing against a real YubiHSM2 device, and simulated testing using a MockHSM service which reimplements some YubiHSM2 functionality in software.
This mode assumes you have a YubiHSM2 hardware device, have downloaded the YubiHSM2 SDK for your platform, and are running a yubihsm-connector process listening on localhost on the default port of 12345.
The YubiHSM2 device should be in the default factory state. To reset it to this state, either use the yubihsm-shell reset command or press on the YubiHSM2 for 10 seconds immediately after inserting it.
You can confirm the tests are running live against the YubiHSM2 by the LED blinking rapidly for 1 second.
NOTE THAT THESE TESTS ARE DESTRUCTIVE: DO NOT RUN THEM AGAINST A YUBIHSM2 WHICH CONTAINS KEYS YOU CARE ABOUT
This mode is useful for when you don't have access to physical YubiHSM2 hardware, such as CI environments.
yubihsm.rs is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE and LICENSE-MIT for details.
-
Generate Asymmetric Key fails when delay is too high (e.g. Generating RSA4096 and sometimes 2048).
-
Cannot Attest EDDSA (ED25519). This is an issue with YubiHSM hardware where this operation.