From 386b1c9ec5d3fa690b1fdaf232f85793e7e12ed2 Mon Sep 17 00:00:00 2001 From: edouardparis Date: Tue, 5 Dec 2023 16:43:44 +0100 Subject: [PATCH 1/3] Add coldcard device to supported hws --- gui/Cargo.lock | 259 +++++++++++++++++++++++++++++++++++++++++++++++-- gui/Cargo.toml | 2 +- gui/src/hw.rs | 54 ++++++++++- 3 files changed, 302 insertions(+), 13 deletions(-) diff --git a/gui/Cargo.lock b/gui/Cargo.lock index 4b889c27..8e5caf65 100644 --- a/gui/Cargo.lock +++ b/gui/Cargo.lock @@ -77,10 +77,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", - "cipher", + "cipher 0.4.4", "cpufeatures", ] +[[package]] +name = "aes-ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7729c3cde54d67063be556aeac75a81330d802f0259500ca40cb52967f975763" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", + "ctr 0.6.0", +] + [[package]] name = "aes-gcm" version = "0.10.3" @@ -89,12 +101,32 @@ checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", "aes", - "cipher", - "ctr", + "cipher 0.4.4", + "ctr 0.9.2", "ghash", "subtle", ] +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + [[package]] name = "ahash" version = "0.7.6" @@ -175,13 +207,13 @@ dependencies = [ [[package]] name = "async-hwi" version = "0.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1d739fac959bf5e332425995a1892f99d94f39acd8acf36fe6c212f9583e0c" +source = "git+https://github.com/wizardsardine/async-hwi?branch=coldcard#b146735976c867e9c53b37b77ab48977d4913f36" dependencies = [ "async-trait", "base64 0.13.1", "bitbox-api", "bitcoin", + "coldcard", "futures", "hidapi", "ledger-apdu", @@ -225,12 +257,24 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base32" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "base64" version = "0.13.1" @@ -252,6 +296,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bdk_coin_select" version = "0.1.1" @@ -491,7 +541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if", - "cipher", + "cipher 0.4.4", "cpufeatures", ] @@ -503,7 +553,7 @@ checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ "aead", "chacha20", - "cipher", + "cipher 0.4.4", "poly1305", "zeroize", ] @@ -529,6 +579,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + [[package]] name = "cipher" version = "0.4.4" @@ -631,6 +690,20 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "coldcard" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78618b6a41c7f3d1797f1a83d8ccedd7a94a8e0b47b54c06702e560148298254" +dependencies = [ + "aes-ctr", + "base58", + "bitcoin_hashes 0.12.0", + "hidapi", + "k256", + "rand", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -643,6 +716,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + [[package]] name = "const-random" version = "0.1.15" @@ -823,6 +902,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -833,13 +924,22 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] + [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher", + "cipher 0.4.4", ] [[package]] @@ -971,6 +1071,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5" +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "digest" version = "0.10.7" @@ -978,6 +1088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1072,12 +1183,45 @@ dependencies = [ "wio", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "either" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encase" version = "0.3.0" @@ -1221,6 +1365,16 @@ dependencies = [ "log", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.5" @@ -1499,6 +1653,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1758,6 +1913,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "guillotiere" version = "0.6.2" @@ -1901,6 +2067,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.9" @@ -2324,6 +2499,20 @@ dependencies = [ "serde_json", ] +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + [[package]] name = "kamadak-exif" version = "0.5.5" @@ -3357,6 +3546,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.26" @@ -3787,6 +3986,16 @@ dependencies = [ "usvg-text-layout", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rgb" version = "0.8.36" @@ -3995,6 +4204,20 @@ dependencies = [ "tiny-skia 0.7.0", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.27.0" @@ -4141,6 +4364,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-adler32" version = "0.3.5" @@ -4272,6 +4505,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 7831f633..77a2f0e1 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -14,7 +14,7 @@ name = "liana-gui" path = "src/main.rs" [dependencies] -async-hwi = "0.0.13" +async-hwi = { git = "https://github.com/wizardsardine/async-hwi", branch = "coldcard"} liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false, features = ["nonblocking_shutdown"] } liana_ui = { path = "ui" } backtrace = "0.3" diff --git a/gui/src/hw.rs b/gui/src/hw.rs index f67757e2..1151f086 100644 --- a/gui/src/hw.rs +++ b/gui/src/hw.rs @@ -8,7 +8,7 @@ use std::{ use crate::app::{settings, wallet::Wallet}; use async_hwi::{ bitbox::{api::runtime, BitBox02, PairingBitbox02}, - ledger, specter, DeviceKind, Error as HWIError, Version, HWI, + coldcard, ledger, specter, DeviceKind, Error as HWIError, Version, HWI, }; use liana::miniscript::bitcoin::{bip32::Fingerprint, hashes::hex::FromHex, Network}; use serde::{Deserialize, Serialize}; @@ -484,7 +484,7 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { still.push(id); continue; } - if let Ok(device) = device_info.open_device(api) { + if let Ok(device) = device_info.open_device(&api) { if let Ok(device) = PairingBitbox02::connect( device, Some(Box::new(settings::global::PersistedBitboxNoiseConfig::new( @@ -502,8 +502,44 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { } } } + if device_info.vendor_id() == coldcard::api::COINKITE_VID + && device_info.product_id() == coldcard::api::CKCC_PID + { + let id = format!( + "coldcard-{:?}-{}-{}", + device_info.path(), + device_info.vendor_id(), + device_info.product_id() + ); + if state.connected_supported_hws.contains(&id) { + still.push(id); + continue; + } + if let Some(sn) = device_info.serial_number() { + if let Ok((cc, _)) = + coldcard::api::Coldcard::open(AsRefWrap { inner: api }, sn, None) + { + match HardwareWallet::new( + id, + if let Some(wallet) = &state.wallet { + coldcard::Coldcard::from(cc) + .with_wallet_name(wallet.name.clone()) + .into() + } else { + coldcard::Coldcard::from(cc).into() + }, + Some(&state.keys_aliases), + ) + .await + { + Err(e) => tracing::error!("Failed to connect to coldcard: {}", e), + Ok(hw) => hws.push(hw), + }; + } + } + } } - for detected in ledger::Ledger::::enumerate(api) { + for detected in ledger::Ledger::::enumerate(&api) { let id = format!( "ledger-{:?}-{}-{}", detected.path(), @@ -514,7 +550,7 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { still.push(id); continue; } - match ledger::Ledger::::connect(api, detected) { + match ledger::Ledger::::connect(&api, detected) { Ok(mut device) => match device.get_master_fingerprint().await { Ok(fingerprint) => { let version = device.get_version().await.ok(); @@ -612,6 +648,16 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { ) } +struct AsRefWrap<'a, T> { + inner: &'a T, +} + +impl<'a, T> AsRef for AsRefWrap<'a, T> { + fn as_ref(&self) -> &T { + self.inner + } +} + fn ledger_version_supported(version: Option<&Version>) -> bool { if let Some(version) = version { if version.major >= 2 { From 0f7a89db6423532f17b0a5337327ec656f7edd15 Mon Sep 17 00:00:00 2001 From: edouardparis Date: Tue, 16 Jan 2024 15:15:33 +0100 Subject: [PATCH 2/3] gui: use async-hwi:master --- gui/Cargo.lock | 6 ++---- gui/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/gui/Cargo.lock b/gui/Cargo.lock index 8e5caf65..0d738567 100644 --- a/gui/Cargo.lock +++ b/gui/Cargo.lock @@ -207,10 +207,9 @@ dependencies = [ [[package]] name = "async-hwi" version = "0.0.13" -source = "git+https://github.com/wizardsardine/async-hwi?branch=coldcard#b146735976c867e9c53b37b77ab48977d4913f36" +source = "git+https://github.com/wizardsardine/async-hwi?branch=master#d49673778bf5e8f907686f71888db9cf92c85038" dependencies = [ "async-trait", - "base64 0.13.1", "bitbox-api", "bitcoin", "coldcard", @@ -693,8 +692,7 @@ dependencies = [ [[package]] name = "coldcard" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78618b6a41c7f3d1797f1a83d8ccedd7a94a8e0b47b54c06702e560148298254" +source = "git+https://github.com/darosior/rust-coldcard.git?branch=2401_api_feature_msrv#d817bd970995e7994c8d468f460c31141c47f7c6" dependencies = [ "aes-ctr", "base58", diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 77a2f0e1..b21bf381 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -14,7 +14,7 @@ name = "liana-gui" path = "src/main.rs" [dependencies] -async-hwi = { git = "https://github.com/wizardsardine/async-hwi", branch = "coldcard"} +async-hwi = { git = "https://github.com/wizardsardine/async-hwi", branch = "master"} liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false, features = ["nonblocking_shutdown"] } liana_ui = { path = "ui" } backtrace = "0.3" From 07eba96ebf1c4a9c520c4686602fc3a56cf262c7 Mon Sep 17 00:00:00 2001 From: edouardparis Date: Tue, 16 Jan 2024 16:17:29 +0100 Subject: [PATCH 3/3] fix clippy error --- gui/src/hw.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/src/hw.rs b/gui/src/hw.rs index 1151f086..e2a8f048 100644 --- a/gui/src/hw.rs +++ b/gui/src/hw.rs @@ -484,7 +484,7 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { still.push(id); continue; } - if let Ok(device) = device_info.open_device(&api) { + if let Ok(device) = device_info.open_device(api) { if let Ok(device) = PairingBitbox02::connect( device, Some(Box::new(settings::global::PersistedBitboxNoiseConfig::new( @@ -539,7 +539,7 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { } } } - for detected in ledger::Ledger::::enumerate(&api) { + for detected in ledger::Ledger::::enumerate(api) { let id = format!( "ledger-{:?}-{}-{}", detected.path(), @@ -550,7 +550,7 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) { still.push(id); continue; } - match ledger::Ledger::::connect(&api, detected) { + match ledger::Ledger::::connect(api, detected) { Ok(mut device) => match device.get_master_fingerprint().await { Ok(fingerprint) => { let version = device.get_version().await.ok();