yubihsm 0.21.0

Pure Rust client for YubiHSM2 devices with support for HTTP and USB-based access to the device. Supports most HSM functionality including ECDSA, Ed25519, HMAC, and RSA.
Documentation
<img src="https://raw.githubusercontent.com/tendermint/yubihsm-rs/master/img/logo.png" width="150" height="110">

# yubihsm.rs

[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
![MIT/Apache2 licensed][license-image]
[![Build Status][build-image]][build-link]
<img src="https://rustsec.org/assets/img/badges/unsafe/deny.svg" width="88" height="20" alt="unsafe: deny">

[crate-image]: https://img.shields.io/crates/v/yubihsm.svg
[crate-link]: https://crates.io/crates/yubihsm
[docs-image]: https://docs.rs/yubihsm/badge.svg
[docs-link]: https://docs.rs/yubihsm/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[build-image]: https://circleci.com/gh/tendermint/yubihsm-rs.svg?style=shield
[build-link]: https://circleci.com/gh/tendermint/yubihsm-rs

Pure Rust client for [YubiHSM 2] devices from [Yubico].

[Documentation][docs-link]

## About

This is a pure-Rust client library for [YubiHSM 2] devices which implements
most the functionality of the [libyubihsm] C library from Yubico's YubiHSM SDK.
It provides two backends for communicating with YubiHSMs:

- [yubihsm::HttpConnector]: communicate with YubiHSM via the
  `yubihsm-connector` process from the Yubico SDK.
- [yubihsm::UsbConnector]: communicate directly with the YubiHSM over USB using
  the [libusb] crate.

The [yubihsm::Client] type provides access to [HSM commands][command].

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]).

## Prerequisites

This crate builds on Rust 1.31+.

On x86(-64) targets, add the following `RUSTFLAGS` to enable AES-NI to better
secure communication with the YubiHSM:

```
RUSTFLAGS=-Ctarget-feature=+aes,+ssse3`
```

You can configure your `~/.cargo/config` to always pass these flags:

```toml
[build]
rustflags = ["-Ctarget-feature=+aes,+ssse3"]
```

## Supported Commands

**NOTE:** If there's a command on this list you'd like to use which isn't presently
supported, please open an issue requesting support.

| [Command]                      | Impl'd | [MockHSM] | Description |
|--------------------------------|--------|-----------|-------------|
| [Authenticate Session]         ||| Authenticate to HSM with password or encryption key |
| [Blink Device]                 ||| Blink the HSM's LEDs (to identify it) |
| [Close Session]                ||| Terminate an encrypted session with the HSM |
| [Create OTP AEAD]              ||| Create a Yubico OTP AEAD |
| [Create Session]               ||| Initiate a new encrypted session with the HSM |
| [Derive ECDH]                  ||| Compute Elliptic Curve Diffie-Hellman using HSM-backed key |
| [Decrypt OAEP]                 ||| Decrypt data encrypted with RSA-OAEP |
| [Decrypt OTP]                  ||| Decrypt a Yubico OTP, obtaining counters and timer info |
| [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 Key]      ||| Randomly generate new asymmetric key in the HSM |
| [Generate HMAC Key]            ||| Randomly generate HMAC key in the HSM |
| [Generate OTP AEAD Key]        ||| Randomly generate AES key for Yubico OTP authentication |
| [Generate Wrap Key]            ||| Randomly generate AES key for exporting/importing objects |
| [Get Log Entries]              ||| 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 HSM auditing settings |
| [Get Pseudo Random]            ||| Get random data generated by the HSM's internal PRNG |
| [Get Public key]               ||| Get public key for an HSM-backed asymmetric private key |
| [Get Storage Info]             ||| Fetch information about currently free storage |
| [Import Wrapped]               ||| Import an encrypted key into the HSM |
| [List Objects]                 ||| List objects visible from the current session |
| [Put Asymmetric]               ||| Put an existing asymmetric key into the HSM |
| [Put Authentication Key]       ||| Put YubiHSM authentication key into the HSM |
| [Put HMAC Key]                 ||| Put an HMAC key into the HSM |
| [Put Opaque]                   ||| Put an opaque bytestring into the HSM |
| [Put OTP AEAD Key]             ||| Put a Yubico OTP key into the HSM |
| [Put Wrap Key]                 ||| Put an AES keywrapping key into the HSM |
| [Randomize OTP AEAD]           ||| Randomly generate a Yubico OTP AEAD |
| [Reset Device]                 ||| Reset the HSM back to factory default settings |
| [Rewrap OTP AEAD]              ||| Re-wrap a Yubico OTP AEAD from one key to another |
| [Session Message]              ||| Send an encrypted message to the HSM |
| [Set Log Index]                ||| Mark log messages in the HSM as consumed |
| [Set Option]                   ||| Change HSM auditing settings |
| [Sign Attestation Certificate] ||| Create X.509 certificate for asymmetric key |
| [Sign Data ECDSA]              ||| Compute an ECDSA signature using HSM-backed key |
| [Sign Data EdDSA]              ||| Compute an Ed25519 signature using HSM-backed key |
| [Sign HMAC]                    ||| Perform an HMAC operation using an 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 |
| [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              |

## Testing

This crate allows you to run the [integration test] suite in three different ways:

- Live testing against a real YubiHSM2 device:
  - via HTTP
  - via USB
- simulated testing using [MockHSM] which implements some YubiHSM2 functionality

### `cargo test`: test YubiHSM2 live over HTTP via `yubihsm-connector`

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**

### `cargo test --features=usb`: test YubiHSM2 live via USB

Adding the `usb` cargo feature builds `UsbConnector` in addition to
`HttpConnector`, and also runs the test suite live via USB rather than using
the `yubihsm-connector` process.

**ALSO NOTE THAT THESE TESTS ARE DESTRUCTIVE: DO NOT RUN THEM AGAINST A
YUBIHSM2 WHICH CONTAINS KEYS YOU CARE ABOUT**

### `cargo test --features=mockhsm`: simulated tests against a mock HSM

This mode is useful for when you don't have access to physical YubiHSM2
hardware, such as CI environments.

## License

**yubihsm.rs** is distributed under the terms of both the MIT license and
the Apache License (Version 2.0).

See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.

[libyubihsm]: https://github.com/Yubico/yubihsm-shell/blob/master/lib/README.adoc
[YubiHSM 2]: https://www.yubico.com/products/yubihsm/
[Yubico]: https://www.yubico.com/
[yubihsm-connector]: https://developers.yubico.com/YubiHSM2/Component_Reference/yubihsm-connector/
[yubihsm::HttpConnector]: https://docs.rs/yubihsm/latest/yubihsm/connector/http/struct.HttpConnector.html
[yubihsm::UsbConnector]: https://docs.rs/yubihsm/latest/yubihsm/connector/usb/struct.UsbConnector.html
[yubihsm::Client]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html
[command]: https://developers.yubico.com/YubiHSM2/Commands/
[libusb]: https://github.com/dcuddeback/libusb-rs
[thinks it's awesome]: https://twitter.com/Yubico/status/971186516796915712
[YubiHSM2 commands]: https://developers.yubico.com/YubiHSM2/Commands/
[Serde-based message parser]: https://github.com/tendermint/yubihsm-rs/tree/master/src/serialization
[commands]: https://github.com/tendermint/yubihsm-rs/tree/master/src/command
[integration test]:  https://github.com/tendermint/yubihsm-rs/blob/master/tests/integration.rs
[MockHSM]: https://docs.rs/yubihsm/latest/yubihsm/mockhsm/struct.MockHsm.html
[YubiHSM2 SDK]: https://developers.yubico.com/YubiHSM2/Releases/
[yubihsm-shell reset]: https://developers.yubico.com/YubiHSM2/Commands/Reset_Device.html

[Authenticate Session]: https://developers.yubico.com/YubiHSM2/Commands/Authenticate_Session.html
[Blink Device]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.blink_device
[Close Session]: https://developers.yubico.com/YubiHSM2/Commands/Close_Session.html
[Create OTP AEAD]: https://developers.yubico.com/YubiHSM2/Commands/Create_Otp_Aead.html
[Create Session]: https://developers.yubico.com/YubiHSM2/Commands/Create_Session.html
[Derive ECDH]: https://developers.yubico.com/YubiHSM2/Commands/Derive_Ecdh.html
[Decrypt OAEP]: https://developers.yubico.com/YubiHSM2/Commands/Decrypt_Oaep.html
[Decrypt OTP]: https://developers.yubico.com/YubiHSM2/Commands/Decrypt_Otp.html
[Decrypt PKCS1]: https://developers.yubico.com/YubiHSM2/Commands/Decrypt_Pkcs1.html
[Delete Object]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.delete_object
[Device Info]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.device_info
[Echo]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.echo
[Export Wrapped]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.export_wrapped
[Generate Asymmetric Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.generate_asymmetric_key
[Generate HMAC Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.generate_hmac_key
[Generate OTP AEAD Key]: https://developers.yubico.com/YubiHSM2/Commands/Generate_Otp_Aead_Key.html
[Generate Wrap Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.generate_wrap_key
[Get Log Entries]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_log_entries
[Get Object Info]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_object_info
[Get Opaque]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_opaque
[Get Option]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_command_audit_option
[Get Pseudo Random]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_pseudo_random
[Get Public Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.get_pubkey
[Get Storage Info]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.storage_status
[Import Wrapped]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.import_wrapped
[List Objects]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.list_objects
[Put Asymmetric]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_asymmetric_key
[Put Authentication Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_auth_key
[Put HMAC Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_hmac_key
[Put Opaque]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_opaque
[Put OTP AEAD Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_otp_aead_key
[Put Wrap Key]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.put_wrap_key
[Randomize OTP AEAD]: https://developers.yubico.com/YubiHSM2/Commands/Randomize_Otp_Aead.html
[Reset Device]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.reset_device
[Rewrap OTP AEAD]: https://developers.yubico.com/YubiHSM2/Commands/Rewrap_Otp_Aead.html
[Session Message]: https://developers.yubico.com/YubiHSM2/Commands/Session_Message.html
[Set Log Index]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.set_log_index
[Set Option]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.set_audit_option
[Sign Attestation Certificate]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.attest_asymmetric
[Sign Data ECDSA]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.set_log_index
[Sign Data EdDSA]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.sign_ed25519
[Sign HMAC]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.sign_hmac
[Sign Data PKCS1]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.sign_rsa_pkcs1v15_sha256
[Sign Data PSS]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.sign_rsa_pss_sha256
[Unwrap Data]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.unwrap_data
[Verify HMAC]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.verify_hmac
[Wrap Data]: https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.wrap_data