From db1fa598232f0698d942cc974f481b5d888ac080 Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Sat, 29 Jun 2024 15:42:04 -0600 Subject: [PATCH] feat: get ledger app version (#623) --- Cargo.lock | 7 +++++++ starknet-signers/Cargo.toml | 3 ++- starknet-signers/src/ledger.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a46c8dd0..aa130718 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1782,6 +1782,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.203" @@ -2116,6 +2122,7 @@ dependencies = [ "eth-keystore", "getrandom", "rand", + "semver", "starknet-core", "starknet-crypto", "thiserror", diff --git a/starknet-signers/Cargo.toml b/starknet-signers/Cargo.toml index 9a378f45..d0515adf 100644 --- a/starknet-signers/Cargo.toml +++ b/starknet-signers/Cargo.toml @@ -21,6 +21,7 @@ thiserror = "1.0.40" crypto-bigint = { version = "0.5.1", default-features = false } rand = { version = "0.8.5", features = ["std_rng"] } coins-bip32 = { version = "0.11.1", optional = true } +semver = { version = "1.0.23", optional = true } # Using a fork until https://github.com/summa-tx/coins/issues/137 is fixed coins-ledger = { git = "https://github.com/xJonathanLEI/coins", rev = "0e3be5db0b18b683433de6b666556b99c726e785", default-features = false, optional = true } @@ -37,4 +38,4 @@ wasm-bindgen-test = "0.3.34" [features] default = [] -ledger = ["coins-bip32", "coins-ledger"] +ledger = ["coins-bip32", "coins-ledger", "semver"] diff --git a/starknet-signers/src/ledger.rs b/starknet-signers/src/ledger.rs index beca1775..e86ae90d 100644 --- a/starknet-signers/src/ledger.rs +++ b/starknet-signers/src/ledger.rs @@ -5,6 +5,7 @@ use coins_ledger::{ APDUAnswer, APDUCommand, Ledger, }; use crypto_bigint::{ArrayEncoding, U256}; +use semver::Version; use starknet_core::{crypto::Signature, types::Felt}; use crate::{Signer, VerifyingKey}; @@ -19,6 +20,7 @@ const EIP_2645_PURPOSE: u32 = 0x80000a55; const EIP_2645_PATH_LENGTH: usize = 6; +const VERSION_SIZE: usize = 3; const PUBLIC_KEY_SIZE: usize = 65; const SIGNATURE_SIZE: usize = 65; @@ -49,6 +51,9 @@ pub enum LedgerError { UnexpectedResponseLength { expected: usize, actual: usize }, } +/// The `GetPubKey` Ledger command. +struct GetVersion; + /// The `GetPubKey` Ledger command. struct GetPubKeyCommand { display: bool, @@ -126,6 +131,21 @@ impl LedgerStarknetApp { Ok(Self { transport }) } + /// Gets the Ledger app version. + pub async fn get_version(&self) -> Result { + let response = self.transport.exchange(&GetVersion.into()).await?; + + let data = get_apdu_data(&response)?; + if data.len() != VERSION_SIZE { + return Err(LedgerError::UnexpectedResponseLength { + expected: VERSION_SIZE, + actual: data.len(), + }); + } + + Ok(Version::new(data[0] as u64, data[1] as u64, data[2] as u64)) + } + /// Gets a public key from the app for a particular derivation path, with optional on-device /// confirmation for extra security. /// @@ -242,6 +262,19 @@ impl From for LedgerError { } } +impl From for APDUCommand { + fn from(_value: GetVersion) -> Self { + Self { + cla: CLA_STARKNET, + ins: 0x00, + p1: 0x00, + p2: 0x00, + data: APDUData::new(&[]), + response_len: None, + } + } +} + impl From for APDUCommand { fn from(value: GetPubKeyCommand) -> Self { let path = value