diff --git a/.circleci/config.yml b/.circleci/config.yml index 1cfcfbe..5ccd4ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -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: | diff --git a/.gitignore b/.gitignore index 29c953b..f7b95ee 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ tmkms.toml # Ignore VIM swap files *.swp + +\.idea/ diff --git a/Cargo.lock b/Cargo.lock index 4e830c5..5071b32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,6 +360,18 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hidapi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hkdf" version = "0.7.0" @@ -416,6 +428,32 @@ name = "lazy_static" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ledger" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "hidapi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ledger-tendermint" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ledger 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.48" @@ -448,6 +486,23 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" version = "0.1.39" @@ -516,6 +571,11 @@ dependencies = [ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.6.11" @@ -782,6 +842,17 @@ dependencies = [ "signatory 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "signatory-ledger-tm" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ledger-tendermint 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "signatory 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "signatory-yubihsm" version = "0.11.0" @@ -902,7 +973,7 @@ dependencies = [ "subtle-encoding 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "tai64 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "x25519-dalek 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -946,6 +1017,7 @@ dependencies = [ "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "signatory 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "signatory-dalek 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "signatory-ledger-tm 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "signatory-yubihsm 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "subtle-encoding 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -983,6 +1055,11 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -1105,6 +1182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gaunt 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0348d3b5fbd30311ea16ce573f137c689e5a3fb2d7b037eefe0a6384143298b6" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" +"checksum hidapi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2511971f82b321b33b8a7695442f59129e2d9bc302302cbcdb962eb739a78cff" "checksum hkdf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a89c4638cf4e02d9db29750659d2af13d9001b508716f77d4693ec8a1f8bda8" "checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -1112,10 +1190,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum ledger 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efbe806baa1f132478c8428aa17da59092b7a73abab0a11b835d4d0dc0b45bc7" +"checksum ledger-tendermint 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "896b75694fcdeefd516962757d53134e53c4dd0d89694321697913bc89a5f604" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libusb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f990ddd929cbe53de4ecd6cf26e1f4e0c5b9796e4c629d9046570b03738aa53" "checksum libusb-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c53b6582563d64ad3e692f54ef95239c3ea8069e82c9eb70ca948869a7ad767" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" @@ -1124,6 +1206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum prost-amino 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c5c4189b6c3e054c064a0c88d51f9379db268d5f8f6ea6afffd3849aeca1a7" "checksum prost-amino-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6376b995db84c9791ab5d3f7bc3e315f8bc1a55fe139a0a2da24aa24e27de809" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -1154,6 +1237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4" "checksum signatory 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2edc08ebe757a7b45352fa63c75c107fb569cc281779b0db0f8d6a384eaddd8" "checksum signatory-dalek 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5ed7678eaeb98cb23e1efdb5e961021b02d3bd9f8bab4d4e30c53ebb3dd50" +"checksum signatory-ledger-tm 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2633f1e0a241347d31f2031b6053506dd72d9c5dedf06fe231526f049e4d1ed" "checksum signatory-yubihsm 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b494a76142da87e8952f9135ed9a0acf55b93a1b1f504c7a1ab227f84c395ccc" "checksum simplelog 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e95345f185d5adeb8ec93459d2dc99654e294cc6ccf5b75414d8ea262de9a13" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" @@ -1172,6 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index 6d31fb1..f4969c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } @@ -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] diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e016371..decbdeb 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -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, }; diff --git a/src/config/provider/ledgertm.rs b/src/config/provider/ledgertm.rs new file mode 100644 index 0000000..fbe5fab --- /dev/null +++ b/src/config/provider/ledgertm.rs @@ -0,0 +1,5 @@ +//! Configuration for Ledger Tendermint signer + +/// Ledger Tendermint signer configuration +#[derive(Clone, Deserialize, Debug)] +pub struct LedgerTendermintConfig {} diff --git a/src/config/provider/mod.rs b/src/config/provider/mod.rs index dbf577a..2768556 100644 --- a/src/config/provider/mod.rs +++ b/src/config/provider/mod.rs @@ -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")] @@ -20,4 +24,9 @@ pub struct ProviderConfig { #[cfg(feature = "yubihsm")] #[serde(default)] pub yubihsm: Vec, + + /// Map of ledger-tm labels to their configurations + #[cfg(feature = "ledgertm")] + #[serde(default)] + pub ledgertm: Vec, } diff --git a/src/keyring/ed25519/ledgertm.rs b/src/keyring/ed25519/ledgertm.rs new file mode 100644 index 0000000..76cdf4f --- /dev/null +++ b/src/keyring/ed25519/ledgertm.rs @@ -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); + keyring.add(pk, signer)?; + Ok(()) +} diff --git a/src/keyring/ed25519/mod.rs b/src/keyring/ed25519/mod.rs index 77859d1..cce1eab 100644 --- a/src/keyring/ed25519/mod.rs +++ b/src/keyring/ed25519/mod.rs @@ -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; diff --git a/src/keyring/mod.rs b/src/keyring/mod.rs index 5bd4286..c688bea 100644 --- a/src/keyring/mod.rs +++ b/src/keyring/mod.rs @@ -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}; @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index 7fe3e4d..93f96e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/tendermint-rs/Cargo.toml b/tendermint-rs/Cargo.toml index 2e39aa0..93d22d6 100644 --- a/tendermint-rs/Cargo.toml +++ b/tendermint-rs/Cargo.toml @@ -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"] diff --git a/tmkms.toml.example b/tmkms.toml.example index 275c73f..3ed8dfe 100644 --- a/tmkms.toml.example +++ b/tmkms.toml.example @@ -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