Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api/rootfingerprint: add ability to display fingerprint #903

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ customers cannot upgrade their bootloader, its changes are recorded separately.
## Firmware

### [Unreleased]
- Add ability to display the root fingerprint on the device

### 9.10.0 [2022-03-10]
- Bitcoin: add support for BIP-86: receive to taproot addresses and sign transactions with taproot inputs
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ endif()
#
# Versions MUST contain three parts and start with lowercase 'v'.
# Example 'v1.0.0'. They MUST not contain a pre-release label such as '-beta'.
set(FIRMWARE_VERSION "v9.10.0")
set(FIRMWARE_BTC_ONLY_VERSION "v9.10.0")
set(FIRMWARE_VERSION "v9.11.0")
set(FIRMWARE_BTC_ONLY_VERSION "v9.11.0")
set(BOOTLOADER_VERSION "v1.0.4")

find_package(PythonInterp 3.6 REQUIRED)
Expand Down
1 change: 1 addition & 0 deletions messages/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ message PubResponse {
}

message RootFingerprintRequest {
bool display = 1;
}

message RootFingerprintResponse {
Expand Down
3 changes: 3 additions & 0 deletions py/bitbox02/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## [Unreleased]
- Add `display` parameter to `root_fingerprint()`.

## 6.0.0
- Offset the recoverable ID by 27 in the signature returned by `eth_sign_msg()`.
- Rename `BTCOutputExternal.hash` to `BTCOutputExternal.payload`.
Expand Down
2 changes: 1 addition & 1 deletion py/bitbox02/bitbox02/bitbox02/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from __future__ import print_function
import sys

__version__ = "6.0.0"
__version__ = "6.1.0"

if sys.version_info.major != 3 or sys.version_info.minor < 6:
print(
Expand Down
6 changes: 3 additions & 3 deletions py/bitbox02/bitbox02/bitbox02/bitbox02.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,13 +656,13 @@ def remove_sdcard(self) -> None:
)
self._msg_query(request, expected_response="success")

def root_fingerprint(self) -> bytes:
def root_fingerprint(self, display: bool = False) -> bytes:
"""
Get the root fingerprint from the bitbox02
Get the root fingerprint from the bitbox02. If `display` is `True`, the fingerprint is displayed on the device before returning (only from firmware v9.11.0).
"""
# pylint: disable=no-member
request = hww.Request()
request.fingerprint.CopyFrom(common.RootFingerprintRequest())
request.fingerprint.CopyFrom(common.RootFingerprintRequest(display=display))
response = self._msg_query(request, expected_response="fingerprint")
return response.fingerprint.fingerprint

Expand Down
23 changes: 15 additions & 8 deletions py/bitbox02/bitbox02/communication/generated/common_pb2.py

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

5 changes: 5 additions & 0 deletions py/bitbox02/bitbox02/communication/generated/common_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ global___PubResponse = PubResponse

class RootFingerprintRequest(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor = ...
DISPLAY_FIELD_NUMBER: builtins.int
display: builtins.bool = ...
def __init__(self,
*,
display : builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["display",b"display"]) -> None: ...
global___RootFingerprintRequest = RootFingerprintRequest

class RootFingerprintResponse(google.protobuf.message.Message):
Expand Down
1 change: 1 addition & 0 deletions py/send_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ def _remove_sdcard(self) -> None:

def _get_root_fingerprint(self) -> None:
print(f"Root fingerprint: {self._device.root_fingerprint().hex()}")
self._device.root_fingerprint(display=True)

def _display_zpub(self) -> None:
try:
Expand Down
2 changes: 1 addition & 1 deletion src/rust/bitbox02-rust/src/hww/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ async fn process_api(request: &Request) -> Option<Result<Response, Error>> {
#[cfg(not(feature = "app-ethereum"))]
Request::Eth(_) => Some(Err(Error::Disabled)),

Request::Fingerprint(pb::RootFingerprintRequest {}) => Some(rootfingerprint::process()),
Request::Fingerprint(ref request) => Some(rootfingerprint::process(request).await),
request @ Request::BtcPub(_)
| request @ Request::Btc(_)
| request @ Request::BtcSignInit(_) => process_api_btc(request).await,
Expand Down
43 changes: 38 additions & 5 deletions src/rust/bitbox02-rust/src/hww/api/rootfingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@ use pb::response::Response;

use bitbox02::keystore;

use crate::workflow::confirm;

/// Returns the keystore's root fingerprint, which is the first 32
/// bits of the hash160 of the pubkey at the keypath m/.
/// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#key-identifiers
pub fn process() -> Result<Response, Error> {
pub async fn process(request: &pb::RootFingerprintRequest) -> Result<Response, Error> {
let fingerprint = keystore::root_fingerprint()?;
if request.display {
confirm::confirm(&confirm::Params {
body: &format!("Root fingerprint:\n{}", &hex::encode(&fingerprint[..])),
accept_only: true,
..Default::default()
})
.await?;
}
Ok(Response::Fingerprint(pb::RootFingerprintResponse {
fingerprint: fingerprint.to_vec(),
}))
Expand All @@ -33,32 +43,55 @@ pub fn process() -> Result<Response, Error> {
mod tests {
use super::*;

use crate::bb02_async::block_on;
use alloc::boxed::Box;
use bitbox02::keystore::lock;
use bitbox02::testing::mock_unlocked_using_mnemonic;
use bitbox02::testing::{mock, mock_unlocked_using_mnemonic, Data};

#[test]
fn test_process() {
lock();
assert_eq!(process(), Err(Error::Generic));
assert_eq!(
block_on(process(&pb::RootFingerprintRequest { display: false })),
Err(Error::Generic)
);

mock_unlocked_using_mnemonic(
"purity concert above invest pigeon category peace tuition hazard vivid latin since legal speak nation session onion library travel spell region blast estate stay"
);
assert_eq!(
process(),
block_on(process(&pb::RootFingerprintRequest { display: false })),
Ok(Response::Fingerprint(pb::RootFingerprintResponse {
fingerprint: vec![0x02, 0x40, 0xe9, 0x2a],
}))
);

static mut CONFIRM_COUNTER: u32 = 0;
mock(Data {
ui_confirm_create: Some(Box::new(|params| {
match unsafe {
CONFIRM_COUNTER += 1;
CONFIRM_COUNTER
} {
1 => {
assert_eq!(params.title, "");
assert_eq!(params.body, "Root fingerprint:\nf40b469a");
true
}
_ => panic!("too many user confirmations"),
}
})),
..Default::default()
});
mock_unlocked_using_mnemonic(
"small agent wife animal marine cloth exit thank stool idea steel frame",
);
assert_eq!(
process(),
block_on(process(&pb::RootFingerprintRequest { display: true })),
Ok(Response::Fingerprint(pb::RootFingerprintResponse {
fingerprint: vec![0xf4, 0x0b, 0x46, 0x9a],
}))
);
assert_eq!(unsafe { CONFIRM_COUNTER }, 1);
}
}
2 changes: 2 additions & 0 deletions src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ pub struct PubResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RootFingerprintRequest {
#[prost(bool, tag="1")]
pub display: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RootFingerprintResponse {
Expand Down