Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Review, and followup on ledger integration #176

Merged
merged 17 commits into from
Feb 20, 2019
Merged
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
command: |
rustc --version
cargo --version
cargo test --all --all-features
cargo test --all --features "default softsign yubihsm yubihsm-mock"
- run:
name: audit
command: |
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ tmkms.toml

# Ignore VIM swap files
*.swp

\.idea/
87 changes: 86 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ signal-hook = "0.1.7"
signatory = { version = "0.11", features = ["ed25519"] }
signatory-dalek = "0.11"
signatory-yubihsm = { version = "0.11", optional = true }
signatory-ledger-tm = { version = "0.11", optional = true }
subtle-encoding = "0.3"
tendermint = { version = "0.2", path = "tendermint-rs" }

Expand All @@ -43,10 +44,11 @@ tempfile = "3"
rand = "0.6"

[features]
default = ["softsign", "yubihsm"]
default = ["softsign"]
softsign = []
yubihsm = ["signatory-yubihsm/usb"] # USB only for now
yubihsm-mock = ["yubihsm", "signatory-yubihsm/mockhsm"]
ledgertm = ["signatory-ledger-tm"]

# Enable integer overflow checks in release builds for security reasons
[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ mod start;
mod version;
#[cfg(feature = "yubihsm")]
mod yubihsm;

#[cfg(feature = "yubihsm")]
pub use self::yubihsm::YubihsmCommand;

pub use self::{
help::HelpCommand, keygen::KeygenCommand, start::StartCommand, version::VersionCommand,
};
Expand Down
5 changes: 5 additions & 0 deletions src/config/provider/ledgertm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! Configuration for Ledger Tendermint signer

/// Ledger Tendermint signer configuration
#[derive(Clone, Deserialize, Debug)]
pub struct LedgerTendermintConfig {}
9 changes: 9 additions & 0 deletions src/config/provider/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#[cfg(feature = "ledgertm")]
pub mod ledgertm;
#[cfg(feature = "softsign")]
pub mod softsign;
#[cfg(feature = "yubihsm")]
pub mod yubihsm;

#[cfg(feature = "ledgertm")]
use self::ledgertm::LedgerTendermintConfig;
#[cfg(feature = "softsign")]
use self::softsign::SoftSignConfig;
#[cfg(feature = "yubihsm")]
Expand All @@ -20,4 +24,9 @@ pub struct ProviderConfig {
#[cfg(feature = "yubihsm")]
#[serde(default)]
pub yubihsm: Vec<YubihsmConfig>,

/// Map of ledger-tm labels to their configurations
#[cfg(feature = "ledgertm")]
#[serde(default)]
pub ledgertm: Vec<LedgerTendermintConfig>,
}
37 changes: 37 additions & 0 deletions src/keyring/ed25519/ledgertm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Ledger Tendermint signer

use signatory::PublicKeyed;
use signatory_ledger_tm::{self, Ed25519LedgerTmAppSigner};

use crate::{
config::provider::ledgertm::LedgerTendermintConfig,
error::{KmsError, KmsErrorKind::*},
keyring::{ed25519::Signer, KeyRing},
};

pub const LEDGER_TM_PROVIDER_LABEL: &str = "ledgertm";
pub const LEDGER_TM_ID: &str = "ledgertm";

/// Create Ledger Tendermint signer object from the given configuration
pub fn init(
keyring: &mut KeyRing,
ledgertm_configs: &[LedgerTendermintConfig],
) -> Result<(), KmsError> {
if ledgertm_configs.is_empty() {
return Ok(());
}

if ledgertm_configs.len() != 1 {
fail!(
ConfigError,
"expected one [providers.ledgertm] in config, found: {}",
ledgertm_configs.len()
);
}
let provider = Box::new(Ed25519LedgerTmAppSigner::connect()?);
let pk = provider.public_key()?;
// TODO: key_id shouldn't be a constant here (see LEDGER_TM_ID):
let signer = Signer::new(LEDGER_TM_PROVIDER_LABEL, LEDGER_TM_ID.to_string(), provider);
Copy link
Contributor Author

@liamsi liamsi Feb 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jleni Will there be an equivalent to a key_id we can put into the config? e.g. for yubihsm we can have sth like keys = [{ id = "gaia-9000", key = 1 }]. I guess this makes sense here, too?
I'll add a TODO here and merge for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validator app needs to rely on Ledger's crypto API for Ed25519 so in practice there is a Bip32 derivation path. At the moment, this is not exposed in the API but it would be actually possible to have different keys to allow for something like that. Actually, it could be even possible to have both secp256k1 and ed25519 in the same device.

Should we open an issue for this new feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please that would be awesome! Thanks :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created issues for this:
#177
cosmos/ledger-cosmos#108

keyring.add(pk, signer)?;
Ok(())
}
2 changes: 2 additions & 0 deletions src/keyring/ed25519/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub use signatory::ed25519::{PublicKey, Seed, PUBLIC_KEY_SIZE};

#[cfg(feature = "ledgertm")]
pub mod ledgertm;
mod signer;
#[cfg(feature = "softsign")]
pub mod softsign;
Expand Down
5 changes: 5 additions & 0 deletions src/keyring/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::{
error::{KmsError, KmsErrorKind::*},
};

#[cfg(feature = "ledgertm")]
use self::ed25519::ledgertm;
#[cfg(feature = "yubihsm")]
use self::ed25519::yubihsm;
use self::ed25519::{softsign, Signer};
Expand Down Expand Up @@ -42,6 +44,9 @@ impl KeyRing {
#[cfg(feature = "yubihsm")]
yubihsm::init(&mut keyring, &config.yubihsm)?;

#[cfg(feature = "ledgertm")]
ledgertm::init(&mut keyring, &config.ledgertm)?;

if keyring.0.is_empty() {
fail!(ConfigError, "no signing keys configured!")
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ extern crate sha2;
extern crate signal_hook;
extern crate signatory;
extern crate signatory_dalek;
#[cfg(feature = "ledgertm")]
extern crate signatory_ledger_tm;
#[cfg(feature = "yubihsm")]
extern crate signatory_yubihsm;
extern crate subtle_encoding;
Expand Down
2 changes: 1 addition & 1 deletion tendermint-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ sha2 = { version = "0.8", optional = true, default-features = false }
subtle-encoding = { version = "0.3", features = ["bech32-preview"] }
tai64 = { version = "1", optional = true, features = ["chrono"] }
x25519-dalek = { version = "0.4.4", optional = true, default-features = false, features = ["u64_backend"] }
zeroize = { version = "0.4", optional = true }
zeroize = { version = "0.5.2", optional = true }

[features]
default = ["secret-connection", "serializers", "tai64"]
Expand Down
6 changes: 6 additions & 0 deletions tmkms.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ adapter = { type = "usb" }
auth = { key = 1, password = "password" } # Default YubiHSM admin credentials. Change ASAP!
keys = [{ id = "gaia-9000", key = 1 }]
#serial_number = "0123456789" # identify serial number of a specific YubiHSM to connect to

[[providers.ledgertm]]
# note:
# - this will enable a ledger signer
# - currently no other options are supported and
# - the key_id used by signatory internally will be "ledgertm" by default